uni-app小程序沉浸式導(dǎo)航實(shí)現(xiàn)的全過程
1. 開始
項(xiàng)目要在多個(gè)頁面上加自定義導(dǎo)航欄,還要有漸變效果,就是隨著頁面上滑,導(dǎo)航欄透明度由0逐漸變?yōu)?。這里面有幾個(gè)基本點(diǎn)需要注意下。
2. page的樣式
page 不能是height: 100%
,可以設(shè)置height: auto
,這樣才可以觸發(fā) onPageScroll。
3. onPageScroll
只有 page 才有 onPageScroll 事件。試驗(yàn)發(fā)現(xiàn),mixin 和頁面內(nèi)都寫了 onPageScroll 的話,都會觸發(fā)。
如果把它放在 mixin 中,寫成下面這樣,可能會有問題:
data() { return { pageScrollTop: 0, }; }, onPageScroll({ scrollTop }) { this.pageScrollTop = scrollTop || 0; },
因?yàn)樽远x導(dǎo)航欄不一定要在頁面級組件上,很多頁面都是寫在子組件里,而 mixin 是各個(gè)組件各自維護(hù)了一份data,所以無法傳遞。這也是Vue組件和小程序組件的不同之處。
解決方法有多個(gè):
- 將 onPageScroll 寫在頁面級組件上,然后獲取到 scrollTop 后傳給子組件,這種方法太麻煩
- onPageScroll 依然寫在 mixin 中,保存 scrollTop 到 vuex 的 state 中,然后在頁面或者組件中獲取這個(gè) state
4. 性能問題
這里面還有兩個(gè)性能相關(guān)的點(diǎn)要注意下:
- 只有頁面級組件或者個(gè)別組件需要用的數(shù)據(jù),不要放在 mixin 的 data/computed 中。因?yàn)?mixin 是所有組件的混入,并且 uni-app 中所有 data 和 computed 都會作為渲染依賴(不管用沒用到),可能會引起很多性能開銷。
- onPageScroll 中不要做復(fù)雜邏輯,不要頻繁調(diào)用 setData,在 uni-app 中就是不要頻繁更新 data。因?yàn)樾〕绦蚴请p線程通信,邏輯層更改數(shù)據(jù)要先到 native層,再傳到渲染層,中間可能還有 JSON.stringify 等操作。
5. 方案
綜上,目前采用的方案是:
mixin中,監(jiān)聽 onPageScroll,因?yàn)檫@個(gè)在只會在當(dāng)前頁面觸發(fā),子組件會被忽略,所以寫在這里并不影響性能。
vuex 中保存 pageScrollTop、mpHeaderHeight,及一個(gè)衍生變量 mpHeaderBg。
然后,需要使用 mpHeaderBg 的頁面,去引用 vuex 中的變量。
如果想要在一個(gè)新頁面加上漸變導(dǎo)航,只需要引用 vuex 中的 mpHeaderBg 即可。
6. 代碼
// 某個(gè)頁面 <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 時(shí)(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: () => ({ // 存放多個(gè)頁面的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. 注意事項(xiàng)
- 不要多個(gè)頁面共享同一個(gè)變量,會存在多個(gè)頁面互相影響的可能。
- 小程序重新進(jìn)入某個(gè)頁面,都會重新回到頂部,包括
page
和所有scroll view
,所以要在beforeDestroy
中重置pageScrollTop
。
總結(jié)
到此這篇關(guān)于uni-app小程序沉浸式導(dǎo)航實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)uni-app小程序沉浸式導(dǎo)航內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js實(shí)現(xiàn)Form欄顯示全格式時(shí)間時(shí)鐘效果代碼
這篇文章主要介紹了js實(shí)現(xiàn)Form欄顯示全格式時(shí)間時(shí)鐘效果代碼,可讀取當(dāng)前的完整時(shí)間并實(shí)時(shí)顯示,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-08-08逐行分析鴻蒙系統(tǒng)的 JavaScript 框架(推薦)
鴻蒙系統(tǒng)使用 JavaScript 開發(fā) GUI 是一種類似于微信小程序、輕應(yīng)用的模式。這篇文章給大家?guī)砹酥鹦蟹治鲽櫭上到y(tǒng)的 JavaScript 框架的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧2020-09-09Ant Design Pro 下實(shí)現(xiàn)文件下載的實(shí)現(xiàn)代碼
這篇文章主要介紹了Ant Design Pro 下實(shí)現(xiàn)文件下載的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12bootstrapfileinput實(shí)現(xiàn)文件自動上傳
這篇文章主要介紹了bootstrapfileinput實(shí)現(xiàn)文件自動上傳,bootstrap fileinput插件對多種類型的文件提供文件預(yù)覽,并且提供了多選等功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11原生JS版和jquery版實(shí)現(xiàn)checkbox的全選/全不選/點(diǎn)選/行內(nèi)點(diǎn)選(Mr.Think)
腳本之家小編之前整理不少checkbox全選全不選這方便的文章,但看了這篇以后發(fā)現(xiàn)實(shí)現(xiàn)方法更好2016-10-10JavaScript獲取當(dāng)前運(yùn)行腳本文件所在目錄的方法
這篇文章主要介紹了JavaScript獲取當(dāng)前運(yùn)行腳本文件所在目錄的方法,涉及JavaScript文件目錄操作的相關(guān)技巧,需要的朋友可以參考下2016-02-02使用javascript實(shí)現(xiàn)頁面加載loading動畫(附完整源碼)
由于項(xiàng)目中多處要給ajax提交的時(shí)候增加等待動畫效果,所以就寫了一個(gè)簡單的通用js方法,這篇文章主要給大家介紹了關(guān)于如何使用javascript實(shí)現(xiàn)頁面加載loading動畫的相關(guān)資料,需要的朋友可以參考下2024-06-06修改源碼來解決el-select值不匹配導(dǎo)致回顯id的問題
el-select數(shù)據(jù)的回顯是根據(jù)id去匹配值的,最近項(xiàng)目出現(xiàn)了回顯id的情況,一查是沒有匹配數(shù)據(jù)的問題,于是就想怎么處理(針對單選的情況),本文小編給大家介紹了用修改源碼來解決el-select值不匹配導(dǎo)致回顯id的問題,需要的朋友可以參考下2024-09-09