新增组件页面: loginProp.vue
<template> <view class="login-box" v-if="loginShow"> <view class="center-box"> <image class="logo" src="../../static/images/logo.png"></image> <view class="close" @tap="closeLogin"> <u-icon name='close' color="#bebebe" size="26"></u-icon> </view> <view class="title">登录即可体验完整功能</view> <view class="btn-group"> <view class="invite-specia" @tap="goLogin"> <u-icon name="weixin-fill" color="#fff" size="30"></u-icon> <view style="margin-left: 20rpx;"> 微信用户一键登录 </view> </view> </view> </view> <uni-popup ref="popup"> <view class="login_phone_box"> <view class="check_box"> <u-radio-group v-model="currentCheck" placement="row"> <u-radio :customStyle="{marginRight: '8px'}" v-for="(item, index) in radiolist" :key="index" activeColor="#fc742a" :label="item.name" :name="item.value" @change="radioChange"> </u-radio> </u-radio-group> </view> <view class="title">为了验证用户登录信息,小程序将获取您的手机号</view> <view class="operate"> <button class="login" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">登录</button> </view> </view> </uni-popup> </view> </template> <script> export default { name: 'login', props: ['loginShow'], data() { return { show: this.loginShow, sessionKey: {}, wxCode: '' } }, mounted() {}, methods: { closeLogin() { this.$emit('closeLogin', this.show); }, goLogin() { let _this = this; uni.login({ provider: "weixin", success: (res) => { // console.log('获取code', res); if (res.errMsg.indexOf("ok") != -1) { this.wxCode = res.code; uni.showModal({ title: '温馨提示', content: '亲,授权微信登录后才能正常使用小程序功能', success(res) { //如果用户点击了确定按钮 if (res.confirm) { uni.getUserProfile({ desc: '获取你的昵称、头像、地区及性别', success: (res) => { // console.log('获取code', res); let _res = _this.$myRequset({ url: "api?operate=normal.user.WxDecode", method: "POST", data: { code: _this.wxCode, encryptedData: res .encryptedData, iv: res.iv, signature: res .signature, rawData: res.rawData }, }).then((res) => { _this.sessionKey = res.data .data; }); _this.$refs.popup.open(); _this.getPhoneNumber(); }, fail: res => { console.log('fail', res); //拒绝授权 uni.showToast({ title: '您拒绝了请求,不能正常使用小程序', icon: 'none', duration: 2000 }); return; } }); } else if (res.cancel) { //如果用户点击了取消按钮 // console.log(3); uni.showToast({ title: '您拒绝了请求,不能正常使用小程序', icon: 'error', duration: 2000 }); uni.switchTab({ url: "../index/index" }); return; } } }); } } }); }, /* 用户授权手机号 */ async getPhoneNumber(e) { let _this = this; try { let _msg = e.detail.errMsg; if (_msg == "getPhoneNumber:ok") { // 获取手机号 _this.$refs.popup.close(); _this.isLogin = true; let _param = { encryptedData: e.detail.encryptedData, iv: e.detail.iv, sessionKey: this.sessionKey.session_key, openid: this.sessionKey.openid, avatarUrl: this.sessionKey.avatarUrl, nickName: this.sessionKey.nickName, gender: this.sessionKey.gender, login_type: this.currentCheck // 登录类型 } let _url = $requestApi.get_phone; console.log('$requestApi', _url); this.$myRequset({ url: _url, method: "POST", data: _param, }).then((res) => { if (res.data.code == 1) { uni.showLoading({ title: '正在登录...' }); _this.updateUserInfo(res.data.data); } else { uni.showToast({ title: '登录失败', icon: 'error', duration: 2000 }); } }).catch((err) => { uni.showToast({ title: '登录请求失败', icon: 'error', duration: 2000 }); console.log("request_err", err); }); } else { // 重新要求授权 } } catch {} }, //更新用户信息 updateUserInfo(_token) { this.$myRequset({ url: "api?operate=normal.user.user_info", method: "POST", data: { token: _token } }).then((_res) => { uni.showLoading({ title: '正在登录...', icon: 'loading' }); if (_res.data.code == 1) { let userInfo = _res.data.data; uni.setStorageSync('userInfo', userInfo); uni.reLaunch({ url: "../index/index" }); } else { uni.showToast({ title: _res.data.msg, icon: "success", }); } }).catch((err) => { console.log("request_err", err); }); }, } } </script> <style scoped lang='scss'> .login-box { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.5); z-index: 9999; & .center-box { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 622rpx; padding: 60rpx 32rpx; border-radius: 16rpx; opacity: 1; background: rgba(255, 255, 255, 1); .logo { position: absolute; top: -24rpx; left: 50%; transform: translateX(-50%); width: 90rpx; height: 100rpx; } .close { position: absolute; top: 24rpx; right: 24rpx; width: 48rpx; height: 48rpx; } .title { margin: 66rpx 0 40rpx; text-align: center; color: rgba(0, 0, 0, 1); font-size: 36rpx; font-weight: 500; font-family: "PingFang SC"; letter-spacing: 0.6rpx; } .content { margin: 40rpx 0; font-size: 30rpx; font-family: "PingFang SC"; letter-spacing: 0.6rpx; color: #212121; text-align: center; text { font-size: 32rpx; letter-spacing: 0.6rpx; color: rgba(69, 108, 255, 1); } } .btn-group { display: flex; justify-content: center; padding: 0 16rpx; .invite-specia { display: flex; align-items: center; justify-content: center; width: 526rpx; height: 88rpx; line-height: 88rpx; border-radius: 16rpx; text-align: center; background: linear-gradient(-46.8deg, #34aa3a 0%, #2d9432 100%); color: #fff; } } } } /* 获取手机号 */ .login_phone_box { padding: 40rpx 30rpx 80rpx; background-color: #fff; border-radius: 12rpx; width: 75%; margin: 0 auto; & .title { font-size: 34rpx; color: #7d7d7d; margin: 0; margin-bottom: 60rpx; letter-spacing: unset; } & .operate { display: flex; } & button { border: none; font-size: 32rpx; color: #000; background-color: #f5f5f5; border-radius: 8rpx; width: 200rpx; padding: 0; height: 80rpx; line-height: 80rpx; border-color: transparent; outline: unset; &.login { background-color: #fc742a; color: #fff; } } } </style>
页面使用:先引入组件,当组件来使用(loginShow决定啥时候显示,啥时候隐藏)
<template> <view class="pages"> <view> <view class="top"> <view class="flex"> <image :src="userInfo.avatar" v-if="userInfo"></image> <image v-else src="../../static/images/default.png"></image> <view class="flex_cloumn" v-if="userInfo"> <text class="title">{{userInfo.name}}</text> </view> <view v-else @tap="goLogin"> <u--text text="登录" size="18"></u--text> </view> </view> </view> <view class="bottom"> <view class="tab_box"> <view class="item" @tap="goPage('info')"> <text class="title">编辑资料</text> <u-icon name="arrow-right" size="24"></u-icon> </view> </view> </view> <view class="operate_box" v-if="userInfo"> <button @tap="toLogout">退出登录</button> </view> </view> <loginProp :loginShow="loginShow" @closeLogin="closeLogin"></loginProp> </view> </template> <script> import loginProp from "../../components/login/loginProp.vue"; export default { name: "personal", components: { loginProp }, data() { return { loginShow:false, //登录弹框 userInfo: {} } }, onShow() { this.userInfo = this.checkLogin(); console.log('userInfo', this.userInfo); }, onPullDownRefresh() { }, onl oad() { this.initData(); }, methods: { closeLogin(){ this.loginShow = false; }, /* 初始化页面数据 */ initData() { }, /* 修改排序 */ changeSort(_index) { this.currentSort = _index; this.$refs.popup_sort.open(); }, /* 修改在线状态 */ goPage(_type) { let _url = ''; switch (_type) { case 'info': // 编辑资料 _url = "../../pageA/myDetail/myDetail"; break; } uni.navigateTo({ url:_url }) }, goLogin(){ this.loginShow = true; }, /* 快速进去会话 */ changeChatin() {}, toLogout() { let _this = this; let context = { loading_title: "正在退出...", content: "确定退出登录吗?", cancel: "取消退出" }; uni.showModal({ title: '温馨提示', content: context.content, success: (res) => { if (res.confirm) { _this.$myRequset({ url: this.$requestApi.logout, data: { token: _this.userInfo.token } }).then((res) => { if (res.data.code == 1) { uni.showLoading({ title: context.loading_title }); setTimeout(function() { uni.removeStorageSync('userInfo'); uni.reLaunch({ url: "../index/index" }); uni.showToast({ title: res.data.msg, icon: "none" }); uni.hideLoading(); }, 2000); } else { uni.showToast({ title: res.data.msg, icon: "error" }); } }).catch((err) => { console.log("request_err", err); }); } else if (res.cancel) { uni.showToast({ title: context.cancel, icon: "none" }) } } }) } } } </script> <style lang="scss"> @import url("personal.css"); </style>
这个只能说是使用公共组件的方式了,网上有解决方案,是使用dom挂载全局的方式,但是不能使用正常js追加dom元素的方式,小程序不支持document.appensChild的方式。
具体实现方式请查看: https://blog.csdn.net/jsmeng626/article/details/125338447,这个方式是没办法全局挂载的,目前我没找到解决方案。。。如果有大佬能有更好的解决方案麻烦评论区告知下哦,互相交流,谢谢!