!!!!产品需求描述:
1、所有接口请求时把当前版本号和这个接口是否检查更新参数等加上,后端拿到数据后与当前数据库存储的最新版本号是否一致,不一致则抛错并带有最新版本信息。
2、前端在拦截器中进入判断弹窗弹出流程,(h5页面使用全局组件注册即可,当时以为在App上也可以正常显示,哪知道不行),随即使用subNVue原生子窗体实现。过程中遇到一些问题如下。
!!!!开发过程中问题描述:
1、因在拦截器中做处理,会存在多个请求发出,所以需要定义一个弹窗是否已经显示过弹窗,第一个接口触发版本不对时,未弹起过,则唤起弹窗。反之后面的接口触发版本不对则不再弹起弹窗。
2、注意在index文件中无法获取到最新的vuex内容无法实时更新,所以改用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
3、subNVue原生子窗体,在每次onLaunch时都会初始化,所以在里面使用vuex数据也是不可靠的。得使用uni.getStorageSync()和uni.setStorageSync(),获取最新的值或内容。
4、2,3条建议用来缓存实现一些不重要比较,变化不频繁的数据。
5、具体更新传递弹窗页面信息,使用页面通信,uni.$on(),uni.$emit()。来实现弹窗内容是最新版本信息。若使用uni.getStorageSync()和uni.setStorageSync(),会导致显示更新内容滞后,显示的其实是上一次的。
此文为实现需求的具体实现思路
1.新建原生子窗体目录文件
a.配置 nvue 文件路径,nvue 文件需放置到使用 subNvue 的页面文件目录下,
b.创建文件,文件路径:pages/subNVue/popup.nvue
2.subNVue 子窗体的 pages.json 配置,建议直接配置在首页路径下,其他配置注意事项查看官方文档
{
"pages": [{
"path": "pages/index/index", //首页
"style": {
"app-plus": {
"subNVues":[{
"id": "concat", // 唯一标识
"path": "pages/index/subnvue/concat", // 页面路径
/*"type": "popup", 这里不需要*/
"style": {
"position": "absolute",
"dock": "right",
"width": "100rpx",
"height": "150rpx",
"background": "transparent" //实测在为transparent时,tabbar页面唤起自带遮罩,
}
}]
}
}
},
//放在tabar路径后面
// #ifdef APP-PLUS
{
"path": "pages/subnvue/popup",
"style": {
"navigationBarTitleText": "",
"disableScroll": true,
"bounce":"none",
"navigationStyle": "custom"
}
},
// #endif
]
}
3.在App.vue页面配置,页面注册事件监听方法
onShow: function() {
console.log('App Show')
// 获取用户信息if
// #ifdef APP-PLUS || APP-NVUE
// app每次onshow先关闭之前注册的事件监听,然后重新注册
uni.$off('popup')
// 用于接收原生子窗体页面发出的页面通信事件,用于关闭全局弹窗
uni.$on('popup', (data) => {
if (!data.isShow) {
const subNVue = uni.getSubNVueById('popup');
subNVue.hide('popup', 300)
}
})
// #endif
// #ifdef APP-PLUS
hotUpdate.versionAutoUpdate(this.versionCode)//热更新方法
// #endif
},
4. 拦截器中接口校验到新版本抛错
if (res.statusCode == 412) {
// 用于判断是否已经弹过弹窗
const isShowPromptPopup = uni.getStorageSync('isShowPromptPopup')
// 为第一次检验到,且没有弹过窗走一下校验
if (!isShowPromptPopup) {
// #ifdef H5
setTimeout(() => {
promptPopup.open({
show: true
})
}, 1000)
// #endif
// #ifdef APP-PLUS || APP-NVUE
// 处理弹窗title,更新内容
let showInfo = {
title:'',
arr:[],
setBac:false
}
let descCn = res.data.error.desc.split(';')[0]
let descEn = res.data.error.desc.split(';')[1]
showInfo.title = res.data.error.title
if (uni.getStorageSync("lang") == 'ch') {
showInfo.arr = descCn.split(',')
} else {
showInfo.arr = descEn.split(',')
}
// 在 subNVue/vue 页面触发事件
if (store.state.whiteList.findIndex(item => item == route) != -1) {
//因为路由白名单为固定内容,所以可以使用vuex数据,当前路由通过uni的api获取。
// 判断路由白名单是否显示遮罩,使用原生子窗体,挂载在tabbar页面的话只能在tabbar页面显示遮罩,这时需要手动控制其他页面额外手动设置遮罩
showInfo.setBac = false
uni.$emit('subPromptmsg', showInfo);
} else {
showInfo.setBac = true
uni.$emit('subPromptmsg', showInfo);
}
setTimeout(() => {
const subNVue = uni.getSubNVueById('popup');
subNVue.show('slide-in-center', 200, () => {})
}, 1000)
// #endif
}
uni.setStorageSync('isShowPromptPopup', true)
return
}
5.原生子窗体页面
<template>
<view style="flex-direction: column;align-items: center;justify-content: center;" @click.stop="" :style="setBac?'background-color: rgba(0, 0, 0, 0.5);':''">
<view style="width: 540rpx;height: 790rpx;border-radius: 24rpx;" class="">
<view style="width: 540rpx;height: 379rpx;">
<image style="width: 540rpx;height: 379rpx;" src="../../static/imgs/upDataModel.png"></image>
</view>
<view
style="width: 540rpx;height: 411rpx; background-color: #FFFFFF;border-radius: 0rpx 0rpx 24rpx 24rpx;position: relative;">
<view class="" style="flex-direction: row; justify-content: center;">
<view class="title">{{lang == 'ch'?errorInfo.title:'New Version'}}</view>
<view style="width: 32rpx;height: 32rpx;margin-left: 4rpx;">
<image style="width: 32rpx;height: 32rpx;" src="../../static/imgs/upDataTips.png"></image>
</view>
</view>
<view class="" style="margin-top: 35rpx; padding-left: 50rpx; padding-right: 50rpx;">
<view style="flex-direction: row; width: 440rpx;" v-for="(item,index) in errorInfo.arr" :key="index">
<text class="decs-text" style="width: 18rpx;">{{index 1}}</text>
<text class="decs-text">、</text>
<text class="decs-text" style="width: 400rpx;">{{item}}</text>
</view>
</view>
<view class="flex_c_m" style="position: absolute;bottom: 40rpx;width: 540rpx;height: max-content;">
<view class="bg-ebuy flex_c_m" style="width: 440rpx; height: 80rpx; border-radius: 10rpx;"
@click="confirmprint">
<text class="btn">{{lang == 'ch'?'立即更新':'Update Now'}}</text>
</view>
<text class="fs-22 pa-t12 fc-999">{{lang == 'ch'?"建议连接wifi更快哦":"It's faster to connect to wifi"}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapState
} from 'vuex';
import hotUpdate from '@/js_sdk/hot-update.js'
export default {
data() {
return {
setBac:false,
errorInfo:{
title:'',
arr:[]
}
}
},
computed: {
...mapState({
lang: 'lang',
}),
},
created() {
// 在 subNVue/vue 页面注册事件监听方法
// $on(eventName, callback)
// 使用 uni.$off 移除之前事件监听器。
uni.$off('subPromptmsg', () => {})
// 用于接收拦截器发出的页面通信事件,用于接受拦截器发出的最新版本信息
uni.$on('subPromptmsg', (data) => {
this.setBac = data.setBac
this.errorInfo = data
})
},
methods: {
closeShowPopup() {
uni.$emit('popup', {
isShow: false,
});
},
//确认更新
confirmprint() {
uni.showLoading({
title: this.lang == 'ch' ? '更新中...' : 'updating...'
})
uni.$emit('popup', {
isShow: false,
});
hotUpdate.versionAutoUpdate(this.versionCode)
}
}
}
</script>
<style>
.btn {
font-size: 32rpx;
font-weight: 500;
color: #FFFFFF;
line-height: 45rpx;
}
.title {
font-size: 40rpx;
font-weight: 600;
color: #000000;
line-height: 56rpx;
/* #ifndef APP-NVUE */
letter-spacing: 4rpx;
/* #endif */
}
.decs-text {
font-size: 24rpx;
font-weight: 500;
color: #666666;
line-height: 40rpx;
}
</style>
仅为个人实现需求的方法,如有不对之处。欢迎大家进行审查和指正,并尽可能给出一些反馈和建议,以便改进代码的质量和可用性。
3 个评论
要回复文章请先登录或注册
w***@gmail.com (作者)
z***@hrbyulong.com
x***@163.com