uni-app小程序沉浸式導(dǎo)航實現(xiàn)的全過程
1. 開始
項目要在多個頁面上加自定義導(dǎo)航欄,還要有漸變效果,就是隨著頁面上滑,導(dǎo)航欄透明度由0逐漸變?yōu)?。這里面有幾個基本點需要注意下。
2. page的樣式
page 不能是height: 100%,可以設(shè)置height: auto,這樣才可以觸發(fā) onPageScroll。
3. onPageScroll
只有 page 才有 onPageScroll 事件。試驗發(fā)現(xiàn),mixin 和頁面內(nèi)都寫了 onPageScroll 的話,都會觸發(fā)。
如果把它放在 mixin 中,寫成下面這樣,可能會有問題:
data() {
return {
pageScrollTop: 0,
};
},
onPageScroll({ scrollTop }) {
this.pageScrollTop = scrollTop || 0;
},因為自定義導(dǎo)航欄不一定要在頁面級組件上,很多頁面都是寫在子組件里,而 mixin 是各個組件各自維護(hù)了一份data,所以無法傳遞。這也是Vue組件和小程序組件的不同之處。
解決方法有多個:
- 將 onPageScroll 寫在頁面級組件上,然后獲取到 scrollTop 后傳給子組件,這種方法太麻煩
- onPageScroll 依然寫在 mixin 中,保存 scrollTop 到 vuex 的 state 中,然后在頁面或者組件中獲取這個 state
4. 性能問題
這里面還有兩個性能相關(guān)的點要注意下:
- 只有頁面級組件或者個別組件需要用的數(shù)據(jù),不要放在 mixin 的 data/computed 中。因為 mixin 是所有組件的混入,并且 uni-app 中所有 data 和 computed 都會作為渲染依賴(不管用沒用到),可能會引起很多性能開銷。
- onPageScroll 中不要做復(fù)雜邏輯,不要頻繁調(diào)用 setData,在 uni-app 中就是不要頻繁更新 data。因為小程序是雙線程通信,邏輯層更改數(shù)據(jù)要先到 native層,再傳到渲染層,中間可能還有 JSON.stringify 等操作。
5. 方案
綜上,目前采用的方案是:
mixin中,監(jiān)聽 onPageScroll,因為這個在只會在當(dāng)前頁面觸發(fā),子組件會被忽略,所以寫在這里并不影響性能。
vuex 中保存 pageScrollTop、mpHeaderHeight,及一個衍生變量 mpHeaderBg。
然后,需要使用 mpHeaderBg 的頁面,去引用 vuex 中的變量。
如果想要在一個新頁面加上漸變導(dǎo)航,只需要引用 vuex 中的 mpHeaderBg 即可。
6. 代碼
// 某個頁面
<template>
<MatchHeaderMp
:header-bg="mpHeaderBg"
/>
</template>
<script>
computed: {
mpHeaderBg() {
// getMpHeaderBg 方法來自于 mixin
return this.getMpHeaderBg();
},
}
</script>// mixin
export const uniSystemInfoMixin = {
data() {
return {
// page-meta上設(shè)置的根標(biāo)簽字體大小
mixinRootFontSize: 50,
};
},
mounted() {
// 設(shè)置根字體大小
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') {
// 窗體改變大小觸發(fā)事件
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: {},
// 狀態(tài)欄高度
mpHeaderHeight: 44,
}),
mutations: {
setPageScrollTop(state, pageScrollTop = 0) {
const curPageName = getCurPageName();
state.pageScrollTopMap = {
...state.pageScrollTopMap,
[curPageName]: pageScrollTop,
};
},
setMpHeaderHeight(state, mpHeaderHeight) {
state.mpHeaderHeight = mpHeaderHeight;
},
},
};7. 注意事項
- 不要多個頁面共享同一個變量,會存在多個頁面互相影響的可能。
- 小程序重新進(jìn)入某個頁面,都會重新回到頂部,包括
page和所有scroll view,所以要在beforeDestroy中重置pageScrollTop。
總結(jié)
到此這篇關(guān)于uni-app小程序沉浸式導(dǎo)航實現(xiàn)的文章就介紹到這了,更多相關(guān)uni-app小程序沉浸式導(dǎo)航內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript將數(shù)字轉(zhuǎn)化成為貨幣格式字符串
這篇文章主要介紹Javascript將數(shù)字轉(zhuǎn)化成為貨幣格式字符串的方法,通俗易懂,需要的朋友可以參考下。2016-06-06
uniapp和uniCloud開發(fā)中常出現(xiàn)的問題及解決匯總
使用uni 開發(fā)一段時間了,下面這篇文章主要給大家介紹了關(guān)于uniapp和uniCloud開發(fā)中常出現(xiàn)的問題及解決的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
JavaScript函數(shù)apply()和call()用法與異同分析
這篇文章主要介紹了JavaScript函數(shù)apply()和call()用法與異同,結(jié)合實例形式分析了apply()和call()的功能、區(qū)別、使用方法及相關(guān)操作注意事項,需要的朋友可以參考下2018-08-08
.NET微信公眾號開發(fā)之創(chuàng)建自定義菜單
這篇文章主要介紹了.NET微信公眾號開發(fā)之創(chuàng)建自定義菜單的相關(guān)資料,需要的朋友可以參考下2015-07-07
js實現(xiàn)瀏覽器窗口大小被改變時觸發(fā)事件的方法
這篇文章主要介紹了js實現(xiàn)瀏覽器窗口大小被改變時觸發(fā)事件的方法,實例分析了window.onresize方法的使用技巧,需要的朋友可以參考下2015-02-02

