• uniapp实战项目 (仿知识星球App) - - 自定义顶部导航栏和登录弹窗组件


    实战项目名称:仿知识星球App
    技术栈:前端 => uni-app ( 后端:Node.js + Mysql + Apollo + Graphql )
    已实现功能:微信登录,创建星球,内容管理,星球管理
    项目git地址:请点击访问

    项目最终效果图:@点击访问效果图,欢迎关注收藏订阅专栏!!!


    提示:该项目只用于个人实战,不应用于任何商业用途。

    一、今日实战目标

    • 自定义顶部导航栏
    • 自定义登录弹窗

    二、实战步骤

    1.禁用原生顶部导航栏

    • 在page.json中,按下方图片进行配置
    {
    	"path": "pages/index/index",
    	"style": {
    			"navigationStyle": "custom"
    	}
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    2.根据设计图自定义不同的顶部导航栏

    • 如下方图片所示,项目中各页面的导航栏都不一样,我们利用uView框架中的u-navbar组件,实现自定义导航栏
      在这里插入图片描述

    首页的顶部导航栏关键代码如下:

    <u-navbar :placeholder="true" leftIconColor="#fff">
    		//左边显示的内容,字体样式都可以自定义
    		<view class="u-nav-slot both-center" slot="left">
    				<view class="title">
    					兴趣星球
    				</view>
    		</view>
    		//右边的+按钮,只会在app端显示,编译成微信小程序的时候不会有这个按钮
    		<!-- #ifdef APP-PLUS -->
    			<view class="u-nav-slot" slot="right" @click="open()">
    				<view class="relative">
    					<image class="add" src="../../static/svg/add.svg" mode=""></image>
    				</view>
    			</view>
    		<!-- #endif -->
    </u-navbar>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.自定义登录弹窗组件

    • 先看看效果图
      在这里插入图片描述

    • 新建登录弹窗组件

    登录弹窗组件关键代码如下:

    <template>
    	<view>
    		<u-popup :safeAreaInsetBottom="true" :safeAreaInsetTop="true" :mode="popupData.mode" :show="show"
    			:round="popupData.round" :overlay="popupData.overlay" :borderRadius="popupData.borderRadius"
    			:closeable="popupData.closeable" :closeOnClickOverlay="popupData.closeOnClickOverlay" @close="close">
    			<view class="u-popup-slot both-center col">
    				<image class="img" src="../../static/logintip2.png" mode="scaleToFill"></image>
    
    				<!-- #ifdef APP-PLUS -->
    				<view class="green-bnt row both-center " @click="login_weixin()">
    					<image class="wx" src="../../static/svg/wx.svg" mode=""></image>
    					<view class="">
    						微信登录
    					</view>
    				</view>
    				<!-- #endif -->
    					
    				<!-- #ifdef MP-WEIXIN -->
    				<view class="green-bnt row both-center " @click="wxGetUserInfo()">
    					<image class="wx" src="../../static/svg/wx.svg" mode=""></image>
    					<view class="">
    						微信授权登录
    					</view>
    				</view>
    				<!-- #endif -->
    				<view class="row label check-box hor-center">
    					<view class="radio both-center" :class="{'select' : agree}" @click="change()">
    						<image v-if="agree" class="icons" src="../../static/svg/select.svg" mode="scaleToFill"></image>
    					</view>
    					已阅读并同意
    					<view class="main-color">《用户协议》 </view><view class="main-color">《隐私政策》 </view>
    				</view>
    			</view>
    		</u-popup>
    	</view>
    </template>
    
    <script>
    	export default {
    		name: "login-popup",
    		data() {
    			return {
    				agree: false,
    				code: '',
    				popupData: {
    					isshow: false,
    					overlay: true,
    					mode: 'bottom',
    					borderRadius: '',
    					round: '20',
    					closeable: true,
    					closeOnClickOverlay: true
    				}
    			};
    		},
    		props: {
    			show: Boolean
    		},
    		mounted() {
    			this.popupData.isshow = this.show
    		},
    		methods: {
    			change() {
    				this.agree = !this.agree
    			},
    			close() {
    				this.popupData.isshow = false
    				this.$emit("send") //子组件传值父组件
    			},
    		}
    	}
    </script>
    
    <style scoped>
    	.u-popup-slot {
    		height: 280px;
    	}
    
    	.img {
    		/* #ifndef APP-PLUS */
    		margin-top: 5px;
    		/* #endif */
    		/* #ifndef APP-PLUS */
    		margin-top: 25px;
    		/* #endif */
    		width: 140px;
    		height: 111px;
    	}
    
    	.label {
    		font-family: PingFangSC-Regular;
    		font-size: 26px;
    		font-weight: normal;
    		line-height: 40px;
    		letter-spacing: 0px;
    		color: rgba(0, 0, 0, 0.3);
    	}
    
    	/*  */
    	.green-bnt {
    		margin-top: 20px;
    		width: 80%;
    		height: 50px;
    		border-radius: 30px;
    		background: #17B99A;
    		box-shadow: 0 15px 30px #E7F8F5;
    		color: #fff;
    		font-family: PingFangSC-Semibold;
    		font-size: 15px;
    		font-weight: normal;
    		line-height: 20px;
    		letter-spacing: 0px;
    	}
    
    	.wx {
    		width: 24px;
    		height: 24px;
    		margin-right: 6px;
    	}
    
    	.check-box {
    		padding-top: 5px;
    		font-size: 12px;
    	}
    
    	/* check */
    	.radio {
    		margin-right: 5px;
    		width: 15px;
    		height: 15px;
    		border-radius: 50%;
    		border: 1px solid rgba(0, 0, 0, 0.3);
    	}
    
    	.select {
    		border: none;
    	}
    
    	.icons {
    		width: 15px;
    		height: 15px;
    		border-radius: 50%;
    		/* #ifdef APP-PLUS */
    		border: 1px solid #17B99A;
    		/* #endif */
    	}
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 在其他页面中使用该弹窗组件
    ① 先引入组件
    import LoginPopup from '@/components/login-popup/login-popup.vue'
    export default {
    		data() {
    			return {
    			show: false, //默认组件不显示
    			...
    			}
    		},
    		components: {
    			LoginPopup
    		},
    }
    
    ② 将组件添加到首页视图内
      //show控制组件是否显示,@send是点击弹窗组件内的,触发首页相应的methods,这一点跟vue的组件间通信方式一样
    	<LoginPopup :show="show" @send="close" />
    
    ③ 编写关键methods
    methods:{
    	open() {
    		if (uni.getStorageSync('hasLogin')) {
    			uni.navigateTo({
    				url: '../newGroup/newGroup'
    			})
    		} else {
    					this.show = true
    			   }
    	},
    	close() {
    	this.show = false
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    总结

    由于项目目前在对接后台api中,项目git地址:请点击访问,大家可以去clone下来借鉴下;

    • 温馨提示:
    1. 项目仅用于个人实战,设计图和架构是自己基于知识星球APP进行设计的,算得上是入门级的uni-app,后期会更新一个企业级uniapp项目
    2. 我是在空闲中写写博客,并没有很规范,欢迎在评论区留下你的建议与意见。
    3. git项目拷贝下来的代码有不懂的,可以截图私信给我,看到会回复你,希望可以帮助到你了解和开发uniapp。
  • 相关阅读:
    shell脚本之break和continue
    2022 CCF BDCI 返乡发展人群预测 [0.9117+]
    代码随想录算法训练营第25天|216.组合总和III 17.电话号码的字母组合
    2023年亚太杯数学建模思路 - 复盘:光照强度计算的优化模型
    Android 自定义加载动画LoadingView
    爱了爱了,20个好用到爆的 Python 函数
    Webpack插件与Webpack之间的关系
    真无线耳机哪个好?真无线耳机性价比排行榜
    wmware14虚拟机安装麒麟操作系统
    72B大模型分片部署
  • 原文地址:https://blog.csdn.net/weixin_43523043/article/details/126469188