1. 开始

项目要在多个页面上加自定义导航栏,还要有渐变效果,就是随着页面上滑,导航栏透明度由0逐渐变为1。这里面有几个基本点需要注意下。

2. page的样式

page 不能是height: 100%,可以设置height: auto,这样才可以触发 onPageScroll。

3. onPageScroll

只有 page 才有 onPageScroll 事件。试验发现,mixin 和页面内都写了 onPageScroll 的话,都会触发。

如果把它放在 mixin 中,写成下面这样,可能会有问题:

data() {
return {
pageScrollTop: 0,
};
},
onPageScroll({ scrollTop }) {
this.pageScrollTop = scrollTop || 0;
},

因为自定义导航栏不一定要在页面级组件上,很多页面都是写在子组件里,而 mixin 是各个组件各自维护了一份data,所以无法传递。这也是Vue组件和小程序组件的不同之处。

解决方法有多个:

4. 性能问题

这里面还有两个性能相关的点要注意下:

5. 方案

综上,目前采用的方案是:

6. 代码

// 某个页面
<template>
<MatchHeaderMp
:header-bg="mpHeaderBg"
/>
</template>
<script>
computed: {
mpHeaderBg() {
// getMpHeaderBg 方法来自于 mixin
return this.getMpHeaderBg();
},
}
</script>
// mixin
export const uniSystemInfoMixin = {
data() {
return {
// page-meta上设置的根标签字体大小
mixinRootFontSize: 50,
};
},
mounted() {
// 设置根字体大小
this.onSetFontSize();
},
onPageScroll({ scrollTop }) {
const mpHeaderHeight = this.$store.state.wxHeader.mpHeaderHeight || 44;
const pageScrollTop =  this.$store.getters.['wxHeader/pageScrollTop'] || 44;
const parsedScrollTop = scrollTop > mpHeaderHeight ? mpHeaderHeight : scrollTop;
// 如果滑动值大于 mpHeaderHeight,就不再更新 data
if (parsedScrollTop === mpHeaderHeight && pageScrollTop === mpHeaderHeight) {
return;
}
this.$store.commit('wxHeader/setPageScrollTop', parsedScrollTop);
},
beforeDestroy() {
if (this.mpType === 'page') {
this.$store.commit('wxHeader/setPageScrollTop', 0);
}
},
methods: {
getMpHeaderBg() {
const pageScrollTop = this.getMpPageScrollTop();
const mpHeaderHeight = this.$store.state.wxHeader.mpHeaderHeight || 44;
return `rgba(255, 255, 255, ${Math.min(1, pageScrollTop / mpHeaderHeight)})`;
},
getMpPageScrollTop() {
const curPageName = this.getCurPageName();
const pageScrollTopMap = this.$store.state.wxHeader.pageScrollTopMap || {};
return pageScrollTopMap[curPageName] || 0;
},
getCurPageName() {
const pages = getCurrentPages();
return pages[pages.length - 1].route;
},
onSetFontSize() {
// 宽度 375 时(iphone6),rootFontSize为50,则一份为 375/50=7.5
const screenNumber = 7.5;
const that = this ;
if (that.mpType === 'page') {
// 窗体改变大小触发事件
uni.onWindowResize((res) => {
if (res.size.windowWidth) {
that.mixinRootFontSize = parseFloat(res.size.windowWidth) / screenNumber;
}
});
// 打开获取屏幕大小
uni.getSystemInfo({
success(res) {
const fontsize = res.screenWidth / screenNumber;
that.mixinRootFontSize = fontsize;
const mpHeaderHeight = res.statusBarHeight + 44;
that.$store.commit('wxHeader/setMpHeaderHeight', mpHeaderHeight);
},
});
}
},
},
};
// store/modules/wx-header.js
const wxHeaderStore = {
namespaced: true,
state: () => ({
// 存放多个页面的pageScrollTop
pageScrollTopMap: {},
// 状态栏高度
mpHeaderHeight: 44,
}),
mutations: {
setPageScrollTop(state, pageScrollTop = 0) {
const curPageName = getCurPageName();
state.pageScrollTopMap = {
...state.pageScrollTopMap,
[curPageName]: pageScrollTop,
};
},
setMpHeaderHeight(state, mpHeaderHeight) {
state.mpHeaderHeight = mpHeaderHeight;
},
},
};

7. 注意事项

总结

到此这篇关于uni-app小程序沉浸式导航实现的文章就介绍到这了,更多相关uni-app小程序沉浸式导航内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

发表回复