文章目录
uniapp项目踩坑记
uview2和uview1项目融合时,view1组件升级view2组件时,各组件之间的兼容问题,传参问题
u-tabs
app.vue中使用router-view
1·,在app.vue中使用router-view之后,发现项目中的uni.showToast(),uni.getCurrentPages(),uni.navigateBack()使用失效
 * 2, h = systemInfo?.windowHeight ?? '550') => {
if(String(src).includes(imgprofix)) {
var idx=src.lastIndexOf(".");
var prefix=src.substring(0,idx);
var ext=src.substring(idx+1);
let fulpath = ''
if(ext !== 'webp') {
fulpath = `${prefix}_${w}x${h}.${ext}`
}else {
fulpath = `${prefix}.${ext}`
}
return fulpath;
}
return src;
}
使用时按照下面方式
changeImageSize(url,728,394);
动态路由
场景:当两个不相关的项目需要融合成一个项目时,两组路由需要融合的时候,会产生不必要的工作量,而且会导致文件内容过长,遇到此类场景时,我们可以选择使用动态路由进行改动,可以保证两个项目在一个项目中的相对独立。
pages.json是项目中的路由文件,我们首先需要在pages.json同级编写一个pages.js文件。webpack在启动项目和打包的时候,会将pages.js的内容转成pages.json。所以,在js文件中添加路由之后,需要重启才能生效哦。
pages.js
const moduleRouter = require(`./shoppingMall/pages-config`);//B项目中的路由文件地址
module.exports = (pagesJson, loader) => {
return {
easycom: {
'^u-(.*)': 'uview-ui/components/u-$1/u-$1.vue'
},
globalStyle: {
},
pages:[],
subPackages:[
...moduleRouter.subPackages
],
tabBar:{},
}
}
shoppingMall/pages-config.js
shoppingMall/pages-config.js
module.exports = {
subPackages:[]
}
小程序跳转 h5和小程序之间的跳转
3,小程序跳转 h5和小程序之间的跳转
小程序跳转h5:
var url = 'https://XXX.cn';//h5链接 全路径
var path = '/pages/web/jpjs/jpjs?url=' + encodeURIComponent(url)
wxApi.navigateToMiniProgram({
appId:appId, //要打开的小程序 appId
path: path, //打开的页面路径,如果为空则打开首页
// extraData: params || {}, //需要传递给目标小程序的数据,目标小程序可在 App.onLaunch,App.onShow 中获取到这份数据
envVersion: 'release', //develop:开发版 trial:体验版 release:正式版
success(res) {
console.log(res)
},
fail(res) {
console.log(res)
}
})
h5跳转小程序:
在项目中,目前在h5环境中跳转都是用的window.location.href,打开小程序的方法目前不能正常使用
小程序跳小程序:
wxApi.navigateToMiniProgram("/pages/index 页面相对路径");//跳同小程序页面
wx.navigateToMiniProgram({appId:"小程序appId",url:"页面相对路径"}) //跳其他小程序页面
页面直接改成子组件
4,页面直接改成子组件调用之后,onload,onshow的生命周期不再触发,可以替换成使用vue自带生命周期函数,如:created或者mounted。
但是mounte和created在页面加载时只会触发一次,父页面onShow的时候不再触发。如果我们需要再次触发子组件内的内容,我们可以使用activated替代mounted。
image标签src属性
5,在项目中使用image标签src属性引入的本地图片地址,在打包之后回存在图片加载不出来的问题(该问题不会出现在引用远程图片地址)。但是如果当把同样的图片作为背景图片引入,加载就是正常的。
这样引入本地图片,打包之后依旧能正常展示。
处理方案就是把大部分引用图片打包发送到服务器上,远程引用。或者改成背景引用的方式。
h5项目中判断小程序环境
if (window.__wxjs_environment == "miniprogram") {
// 小程序环境
}else{
//h5环境
}
npm install 报错
npm install uni-simple-router
h5项目打包成小程序项目
(1)写一个小程序app的壳子,内部用web-view跳转h5项目内部
<web-view src=""></web-view>
链接参考web-view
参考链接:h5一键打包小程序
h5内部的一些分享,支付需要添加小程序环境的判断,当为小程序的时候,走小程序的逻辑。
具体步骤:一:新建一个app项目:miniprogram
我们需要配置小程序的主页面,并且在主页面中使用web-view
这样我们就可以在打开小程序的时候,进入h5项目内部。
tips:
1,在公司实行过程中,此方案比方法(2)更易维护一些。像作者一直是编写h5,但是微信小程序上手也比较简单,所以能保证项目既能保持h5的运行方式,也能以小程序的方式运行;
2,修改h5项目内容之后,只需要重新打包发版h5项目,不需要再走小程序审核。h5项目内容即改即生效。
(2)h5项目打包成小程序项目
使用命令直接打包成小程序
打包命令为:
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --minimize",
打包遇到问题:
问题一:报错提示不明显
采用排除法,最后发现是项目中写法有问题
问题二:报错提示明显
https://blog.csdn.net/dt1991524/article/details/87983421/
问题三:打包成功之后运行出错
1,
[ app.json 文件内容错误] app.json: ["subPackages"][21]["root"] 不应该包含 ["subPackages"][2]["root"] ["subPackages"][21]["root"] 不应该包含 ["subPackages"][6]["root"] ["subPackages"][21]["root"] 不应该包含 ["subPackages"][10]["root"](env: Window
解决方案:去检查package.json的路由配置是否含有重复或者包含关系
2,
解决方案:原因之一是因为:key=“‘p’+item.name”,改成:key=“item.name”
3,
4,
解决方案:勾选上这个圈中部分
5,
处理方案:虽然不知道为什么,但是确实有效
将vant的全局引用注释
6,
处理方案:
7,
后续使用了方案一之后,此方案暂停。
返回上一级页面的不同场景
在项目中,我们会有一级页面,二级页面,三街页面。我们常常会有一个返回上一页面组件。
上面这两种都是常见的快速返回上一个路径的组件。
但是我们不乏会遇到A项目一级页面,跳转到B项目中的二级页面,此时点击二级页面的返回组件,我们还能正常返回到A项目中吗?
B项目:
back.vue组件
<view class="goback-content" @tap.stop="goback">
goback(){
let pages = getCurrentPages()
let beforePage = pages[pages.length - 2]
if(!beforePage) {
uni.switchTab({
url: `/pages/home/index`
})
} else {
uni.navigateBack()
}
}
文件back.vue在B项目中运行时没有任何问题,都能正常后退,但是在上诉情况下时,我们会发现,点击返回组件之后,返回的是B组件的首页,也就是‘/pages/home/index’页面,需要返回到A项目中我们只需要修改代码为:
goback(){
let pages = getCurrentPages()
let beforePage = pages[pages.length - 2]
if(!beforePage) {
history.back()
} else {
uni.navigateBack()
}
}
此时我们发现在A项目跳转B项目的情况,还是B项目内部跳转的情况都能正常后退到上一个路径。
拨打电话
uni.makePhoneCall({
phoneNumber: tel, // 电话号码
success(e) {
console.log(e)
},
fail(e) {
console.log(e)
}
})
导航
const jweixin = require('jweixin-module') `
jweixin.openLocation(params)
ios安全距离兼容
我们在项目中常常会遇到一些定位悬浮按钮。那么在处理多个悬浮按钮的时候就不可避免的会接触到ios的兼容问题。比如在长场景中,底部u-tarbar的宽度为100rpx。按钮的bottom为120rpx。本应呈现出来这样的效果
但是在ios中却是这样呈现的。很明显能看到按钮被遮挡了一部分,这是由于ios的安全距离问题。
方案一:
我们可以将按钮的bottom从120rpx修改为180rpx,调整按钮不被底部tarbar遮挡
方案二:
在<meta>中添加content="width=device-width, initial-scale=1.0, viewport-fit=cover"
然后在按钮的样式中加入
margin-bottom: constant(safe-area-inset-bottom);//兼容 IOS<11.2
margin-bottom: env(safe-area-inset-bottom);//兼容 IOS>11.
字符串添加空格
在项目中我们会遇到这样的情况,当我们使用一个方法计算出来这块内容时,它是在
直接+’\xa0’,成功,需要几个空格就拼接几个’\xa0’
轮播时数据量过大时优化
在项目中常会遇到使用swiper轮播的场景,当数据量比较大的时候,比如此时请求出来数据700+。我们可以看到页面渲染图片时变得延迟,左右滑动时动画也比较卡顿。对用户体验感极不友好。而且如果当你使用的指示点时也会发现指示点直接超出屏幕很多。
根据上面的情况,从两个方面入手优化用户体验,首先是渲染轮播的时候怎么将速度提升,第二点怎么优化超出屏幕的指示点(上图是优化此点之后的截图)。
第一点:提升渲染速度,我们必须要将700+数据分批渲染,我们采用的是首次渲染三组swiper-item。
//定义一组变量
contentList: [], // 内容轮播区域,源数组
swiperList: [], // 要渲染到swiper-item的数组
currentIndex: 0, // 当前展示的item在总轮播数据里面的索引值
swiperIndex: 0, //当前展示的item在swiper里面的索引值
/**
* @description 轮播切换事件
*/
swiperChane(e) {
const currentItem = e.detail.current
// 如果两者的差为2或者-1则是向后滑动
if (this.swiperIndex - currentItem === 2 || this.swiperIndex - currentItem === -1) {
this.currentIndex =
this.currentIndex + 1 === this.contentList.length ? 0 : this.currentIndex + 1
this.swiperIndex = this.swiperIndex + 1 === 3 ? 0 : this.swiperIndex + 1
}
// 如果两者的差为-2或者1则是向前滑动
else if (this.swiperIndex - currentItem === -2 || this.swiperIndex - currentItem === 1) {
this.currentIndex =
this.currentIndex - 1 === -1 ? this.contentList.length - 1 : this.currentIndex - 1
this.swiperIndex = this.swiperIndex - 1 === -1 ? 2 : this.swiperIndex - 1
}
this.upDateSwiperList()
},
/**
* @description 更新swiperList数组,用于在contentList数据中切换需要展示的数据
* */
upDateSwiperList() {
const swiperList = []
swiperList[this.swiperIndex] = this.contentList[this.currentIndex]
swiperList[this.swiperIndex - 1 === -1 ? 2 : this.swiperIndex - 1] =
this.contentList[
this.currentIndex - 1 === -1 ? this.contentList.length - 1 : this.currentIndex - 1
]
swiperList[this.swiperIndex + 1 === 3 ? 0 : this.swiperIndex + 1] =
this.contentList[
this.currentIndex + 1 === this.contentList.length ? 0 : this.currentIndex + 1
]
this.swiperList = swiperList
}
第二点:考虑将指示点优化为索引展示。
自定义微信分享内容不生效
h5项目需要自定义用户分享给朋友的内容格式,像下面一样
【准备工作】
引入js文件或者安装包
<script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js" type="text/javascript"></script>
或者
package.json
"jweixin-module": "^1.6.0",
//utils.js
import wx from 'weixin-js-sdk' //用uniapp在项目根目录下npm i weixin-js-sdk
export const WXAPI = [
'getLocation',
'openLocation',
'chooseWXPay',
'updateAppMessageShareData',
'updateTimelineShareData',
'scanQRCode'
] // 需要调用的微信api列表
// wxApi.js
import { WXAPI } from './config'
const jweixin = require('jweixin-module')
async initJssdk(methods, callback) {
try {
let results
if (wxSdk) {
results = await wx.getWechatSign({
url: window.location.href.split('#')[0],
rentId: wxSdk
// url: 'https://iwzs.ghxtcom.com/yjy/' // 待改
})
results = results.results
} else {
results = await wx.getWxSDk({
url: window.location.href.split('#')[0]
// rentId: wxSdk
// url: 'https://iwzs.ghxtcom.com/yjy/' // 待改
})
results = results.data
}
const { appId, nonceStr, signature, timestamp } = results
jweixin.config({
debug: false, // 待改
appId,
timestamp,
nonceStr,
signature,
jsApiList: WXAPI
})
jweixin.ready(() => {
this.isRegister = true
this[methods](callback)
})
jweixin.error(res => {
console.error(res)
})
} catch (e) {
console.warn(e)
}
},
首先我们需要分享出来是这种格式而不是一个链接,需要收藏这个项目页面路径,然后从我的收藏里面点进去,再分享出来才是这种。或者需要h5的链接挂在公众号的自定义菜单下才可以实现微信中分享朋友圈及朋友以卡片形式展现。
我们分享会使用到微信api
// 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
updateAppMessageShareData(callback, options)
// 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
updateTimelineShareData(callback, options)
我们可以定义一个方法shareToWeixin,在我们需要自定义分享内容的页面触发这个方法。主要代码如下
// 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
updateAppMessageShareData(callback, options) {
if (!this.isWechat()) return
if (this.isRegister) {
jweixin.updateAppMessageShareData({
title: options.title, // 分享标题
desc: options.desc, // 分享描述
link: options.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: options.imgUrl, // 分享图标名
success(res) {
callback && callback(res)
}
})
} else {
this.initJssdk('updateAppMessageShareData', callback)
}
},
// 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
updateTimelineShareData(callback, options) {
if (!this.isWechat()) return
if (this.isRegister) {
jweixin.updateTimelineShareData({
title: options.title, // 分享标题
link: options.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: options.imgUrl, // 分享图标名
success(res) {
callback && callback(res)
}
})
} else {
this.initJssdk('updateTimelineShareData', callback)
}
},
shareToWeixin(options) {
this.updateAppMessageShareData(() => {}, {
title: options.title, // 分享标题
desc: options.desc, // 分享描述
link: options.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: options.imgUrl // 分享图标
})
this.updateTimelineShareData(() => {}, {
title: options.title, // 分享标题
link: options.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: options.imgUrl // 分享图标
})
},
【问题一】在使用这两个api方法时,我们需要注意的问题是,当项目初始化的时候,会主动触发一次updateAppMessageShareData和updateTimelineShareData,此时options 为空,也就是如果你需要在初始页面需要自定义分享内容,此时就很容易出现不生效的情况。这里我们有两种方案用于处理这种情况(欢迎大家补充)
【方案一】谨慎的选择页面的生命周期或者方法用于触发shareToWeixin方法,如果该方法触发于主动触发之后,自定义内容依旧能生效
【方案二】既然只有在初始化项目的时候才会自主触发一次,我们或许可以给options一个默认的数据,让它在自主触发的时候,自定义我们默认的分享内容
const optionsDefalut = {
title: 'XXXX',
desc: 'XXXXX',
imgUrl: 'https://XXXXXXXX',
link: encodeURI(window.location.href) // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
}
updateAppMessageShareData(callback, options = optionsDefalut){
.....
}
updateTimelineShareData(callback, options = optionsDefalut) {
......
}
【问题二】A,B页面均有自定义分享内容,A页面在onShow,onLoad生命周期触发shareToWeixin方法。
A页面跳转到B页面uni.navigateTo({url: ‘B’})。随即B页面跳转A页面uni.switchTab({url: ‘A’}。我们此时在A页面分享,会发现分享内容是B页面的自定义内容,从B页面跳回A页面之后,没有重新触发shareToWeixin方法。
【方案一】在switchTab增加success方法。
uni.switchTab({
url: 'A',
success: res => {
// A页面的自定义分享内容
}
})
使用uview2 slider组件完成人机识别校验滑块
主要是修改组件样式,关键代码
<u-slider
v-model="sliderValue"
min="0"
max="100"
height="1000rpx"
block-width="1000px"
active-color="#24c371"
block-color="#f9f9f9"
@change="change"
></u-slider>
sliderValue: 0.01,
//值改变事件
change(e) {
if (e === 100) {
// 通过校验之后的方法
} else {
//校验失败之后的方法
}
},
css:
.slider-content {
width: 500rpx;
.slider-title {
font-size: 32rpx;
font-weight: bold;
color: #000;
text-align: center;
height: 100rpx;
line-height: 100rpx;
border-bottom: 1px solid #eee;
}
.slider-desc {
font-size: 28rpx;
color: #333;
text-align: center;
height: 60rpx;
line-height: 60rpx;
}
}
::v-deep .uni-slider-track {
height: 60rpx;
}
::v-deep .uni-slider-handle-wrapper {
height: 60rpx;
position: relative;
&:after {
content: '鎸変綇婊戝潡锛屾嫋鍔ㄥ埌鍙宠竟';
position: absolute;
font-size: 24rpx;
top: 0;
color: #333;
top: 6px;
display: inline-block;
width: 100%;
text-align: center;
}
}
::v-deep .uni-slider-thumb {
width: 56rpx !important;
height: 56rpx !important;
margin-top: -28rpx !important;
}
富文本加载图片出错问题
我们常常会遇到前端需要用富文本展示内容丰富的详情内容,公告内容时,常常会使用到
u-parse,rich-text,v-html等几种方法,但是有时候会遇到我们加载图片的时候,会展示成如下效果
这时候我只需要在index.html页面添加如下代码就阔以解决
<meta name="referrer" content="no-referrer">
遮罩层穿透滚动
项目中常见的功能,比如列表的筛选项,或者简介内容弹窗时,这时候滑动遮罩层会发现列表页面能滑动。虽然一般来说不影响功能,但是有很多时候,从用户交互方面出发确有一点奇怪。如果需要优化处理这种情况的话,我们可以有下面的解决方案。
// 是否阻止滚动,当弹窗出现的时候,组织页面穿透滚动
stopSoll(flag){
if(flag){
this.sollPosition = document.documentElement.scrollTop || document.body.scrollTop;
document.getElementById('container').style.position = "fixed";
document.getElementById('container').style.top = "-" + this.sollPosition + 'px';
document.getElementById('container').style.overflow = "hidden";
}else{
document.getElementById('container').style.position = "";
document.getElementById('container').style.top = "";
document.getElementById('container').style.overflow = "visible";
window.scrollTo(0,this.sollPosition);
}
},
// 使用时
this.stopSoll(false);// 未禁止滚动
this.stopSoll(true);// 禁止滚动
// html 需要将页面最外层设置为目标id:container
在小程序内部需要跳转外链时
首先我们需要根据参数特征判断当前时外链还是内部跳转。
if (url.includes("http") {
// 当发现目标参数判断为全连接时,我们可以初步认为时外链
// 再判断当前的环境是h5环境还是小程序环境,小程序环境需要借助web-view
// #ifdef H5
window.location.href = url
// #endif
// #ifdef MP-WEIXIN
uni.navigateTo({
url: `/webview?url=${iurl}`
})
// #endif
return;
}
uni.navigateTo({
url,//跳转内部连接
});
webview页面
<view>
<!-- url为要跳转外链的地址-->
<web-view :src="url" @message="bindGetMsg"></web-view>
</view>
bindGetMsg(e) {
this.shareObj = e.detail.data[e.detail.data.length - 1];
},
城市索引列表
首先我们需要确定场景是我们点击城市选项的时候,弹出这个城市索引出来,在代码结构上我们选择合适的ui组件完成动画效果。
此时我们还需要准备一套城市的数据,要满足索引需要的数据格式
代码如下:
<!-- 索引城市搜索部分 -->
<u-popup v-model="cityShow" mode="right">
<view class="city-list-box">
<!-- 搜索栏 -->
<view class="sreach-box">
<view class="back-icon" @click="cityBack"
><u-icon name="arrow-left"></u-icon>返回</view
>
<view class="city-sreach">
<text class="ddm-wc icon-sousuo sousuo-ms"></text>
<u-input
v-model.trim="citySearchValue"
placeholder="搜索城市"
clearable
@confirm="citySearch"
/>
</view>
</view>
<!-- 我的位置 -->
<view class="local-box">
<view class="local-title">我的位置</view>
<view
class="local-address"
@click="getAddresssF(lnglat[0], lnglat[1])"
><u-icon name="map-fill" color="#5FC970"></u-icon
>{{ localAddress }}</view
>
<view
:class="[
'local-address',
'all-address',
stagingAddress ? '' : 'active-all',
]"
@click="getAll"
>全部</view
>
</view>
<!-- 索引列表 -->
<scroll-view
scroll-y="true"
class="scroll-Y scroll-box"
:scroll-top="scrollTop"
:show-scrollbar="true"
@scroll="onScroll"
>
<u-index-list
active-color="#5FC970"
:scrollTop="scrollTop"
:offsetTop="offsetTop"
:index-list="areaCity.alphabet"
@select="selectList"
:sticky="false"
>
<view v-for="(item, index) in areaCity.cityList" :key="index">
<u-index-anchor
:index="item.idx"
v-if="item.cities.length > 0 && !citySearchValue"
></u-index-anchor>
<template v-for="(cell, indexs) in item.cities">
<view
v-if="cell.name.includes(citySearchValue)"
class="list-cell"
@click="citylistClick(cell)"
:key="indexs"
>
{{ cell.name }}
</view>
</template>
</view>
</u-index-list>
</scroll-view>
</view>
</u-popup>
area-city.js
我们需要注意这个文件的格式,几个重点的属性值需要写出来。
不过我们需要注意,右侧的索引位置点击的时候内容是否会滚动到对应区域,不准确的情况下我们需要对滚动条位置进行微调。
// 城市索引右侧的快捷选择列表点击事件,点击之后滚动到列表对应描点,会触发滚动事件
selectList(index, scollTop) {
this.scrollTop = scollTop - 130;
},
// 监听城市索引列表滚动事件
onScroll(e) {
this.scrollTop = e.detail.scrollTop;
},
复杂的下拉筛选组件和交互
使用场景,我们在一些场景中,需要对筛选列表的筛选项进行远程获取,并且可能是多选或者单选的情况。还需要将选中的数据隐射在列表页面上,列表页面上的快速选择也能映射到筛选项中。能看出来我们的筛选项目前分为两种模式,一种是正常的列数据筛选,一种是自定义的数据筛选。如下面两图
下拉框内容我们提取一个组件
<my-dropdown
ref="myDropdown"
:findAwayArr.sync="findAwayArr"
:getRegAttrContent.sync="getRegAttrContent"
:moreFiltering.sync="moreFiltering"
@optionClick="optionClick"
/>
my-dropdown组件
<template>
<view :class="[dropdownShow ? 'dropdown100vh' : 'dropdown']">
<view class="dropdown-box">
<view
v-for="(item, index) in dropdownList"
:key="index"
:class="[
'dropdown-item',
activeCode === item.code ? 'item-active' : '',
]"
@click="dropdownClick(item, index)"
>
<text> {{ item.title }} </text>
<u-icon
v-if="activeCode === item.code"
:name="'arrow-up-fill'"
:class="['item-icon', 'item-icon-active']"
color="#5FC970"
size="8rpx"
></u-icon>
<u-icon
v-else
:name="'arrow-down-fill'"
:class="['item-icon']"
color="#B7B7B7"
size="8rpx"
></u-icon>
</view>
</view>
<template v-if="dropdownShow">
<!-- 展示筛选项区域 -->
<view class="content-box" v-if="type == 'radio'">
<view class="content">
<template v-for="(item, index) in listCode[activeCode]">
<item-radio
v-if="!item.hidden"
ref="radioRef"
:key="index"
:title="item.title"
:typeCode="item.typeCode"
:type="item.type"
:data="item"
:labelList.sync="item.list"
@radioChange='radioChange'
/>
</template>
</view>
<view class="btn-box">
<view class="btn btn-reset" @click="resetBtn()">重置</view>
<view class="btn btn-confirm" @click="confirmBtn()">确定</view>
</view>
</view>
<!-- 下拉数据展示区 -->
<view class="content-box" v-else>
<view class="line-box">
<template v-for="(item, index) in listCode[activeCode]">
<view
:class="[
'line-item',
lineOptionIndex === index ? 'line-item-active' : '',
]"
:key="index"
@click="lineOPtionClick(item, index)"
>
<text class="u-line-1">{{ item.name }} </text>
<u-icon
v-if="lineOptionIndex === index"
name="checkbox-mark"
color="#5FC970"
size="15rpx"
></u-icon>
</view>
</template>
</view>
</view>
<view class="u-mask" @click="closeMask"> </view>
</template>
</view>
</template>
methods: {
/**
* @description 筛选项点击切换事件
*/
dropdownClick(item, index) {
if (this.activeCode == item.code) {
this.activeCode = "";
this.closeMask();
return false;
}
this.activeCode = item.code;
this.type = item.type;
this.$emit("dropdownClick", item);
if(!this.dropdownShow){
this.openMask();
}
},
}
项目中某些模块需要单独提供链接访问
业务背景:项目A中,点击底部导航栏c加载模块C,C中加载了很多应用入口,其中有应用D。现需求如下:提供一个链接,直接访问D,未登录情况下需要跳转登录页面(登录页面只保留部分功能),正常登录/注册-登录之后,再直接跳转回D。
了解新需求之后,我们目前有两种方案:
1,方案一:基于项目A复制项目B出来,在项目B中只保留新需求中需要展示得应用D模块和登录/注册模块。再根据需求进行内容的删减展示。
问题:这种方法可以很快的部署出来一个项目并拿到单独访问D的链接,但是此时D的剥离,意味着之后D的需求更新,我们可能需要同时维护A和B中的D模块代码,维护成本增加。
2,方案二:不重新复制项目,单独访问应用D时,我们在访问路由后面添加一个变量标识,标志着是新需求的访问链接。可以解决方案一中后期维护问题。
问题:变量标识如果存取。登录页面需要根据变量标识进行展示内容的判断。
方案二的问题关于变量的存取,第一冒出来的想法使用uni.setStorageSync存放在浏览器中。定义变量source="officialAccount"为新需求的跳转路由标识,在D模块加载时,将source使用uni.setStorageSync进行存放。
D模块代码
onLoad(options) {
this.source = options.source || '';
if(this.source=="officialAccount"){
uni.setStorageSync("source", this.source);
}
login/index.vue 登录页面
onLoad() {
this.source =uni.$getStorageSync("source");
if (this.source) {
// 判断当前时处于单独访问D中,对应展示内容和判断
}
}
根据以上代码,我们完成了标识的存取和使用,看起来没有什么问题。
但是考虑到部署时是在同一个域名下,那么在特定的场景下,比如我们通过同一个浏览器先访问了新需求下的D应用,再访问正常情况下的项目A。如果都进入登录页面,此时登录页面是展示的单独访问D这个需求下的展示内容还是正常情况下的展示内容呢?这里就涉及到关于浏览器对于同源域名的缓存处理。此时回出现缓存的共存。除非你手动清除缓存内容,但是什么时候清除呢?
手动清除source 的缓存时机不太好找,但是又实在不愿意恢复到方案一,于是再次重新考虑保留方案二的思路,那么D理由上的标识是必须要保留的。那么问题就是怎么合理的运用这个标识。既然缓存不行,那么我们考虑使用路由拦截器。
router.js页面
router.beforeEach(async (to, from, next) => {
//检查当前路由是否携带source = 'officialAccount'的标识,如果携带,则需要传递给待跳转的下一个路由
if (from.query.source == 'officialAccount' || from.params.source == 'officialAccount') {
if (!to.query.source) {
to.query.source = 'officialAccount';
to.params.source = 'officialAccount';
if (to.fullPath.includes("?")) {
to.fullPath += "&source=officialAccount"
} else {
to.fullPath += "?source=officialAccount"
}
next(to.fullPath)
return false;
}
}
login/index.vue 登录页面
onLoad() {
this.source = this.$route.query?.source;
if (this.source) {
// 判断当前时处于单独访问D中,对应展示内容和判断
}
}
//登录事件
login(){
//登录成功之后需要再判断一下source的值,如果符合只访问D的需求,需要定向跳转到D页面去,形成一个闭环
if (this.source) {
uni.navigateTo({
url: this.$getStorageSync('/D?source=officialAccount'),
});
}
}