第一部分:swiper + 頂部/底部導航欄實現
這裏的思想與安卓的fragment+viewpager是很類似的,用swiper作爲左右滾動區間,聯動tab導航欄,中間展示內容組件化
導航欄部分大家可以自定義,我整個界面採用的是底部導航欄用position:fixed浮動,swiper部分的current注意是與tab的下標一致,並且注意swiper的高度一定要動態自適應,這個等下滑動衝突會講到。swiper-item內部內容是抽成組件化了,這樣代碼看着更整潔規範,注意內部class一定要寫。
一個簡單的swiper聯動導航欄例子就好了,當然只是簡單的,因爲實際上還有不少問題。
第二部分:滑動衝突處理
如果你按照上面自己敲出來一個demo 你就會發現,如果你的頁面內容過長涉及滾動,你的組件內就根本就不能滾動,原理是這些組件的父組件是swiper這貨,而swiper樣式中本身是不支持上下滑動滴,當然這個也好處理,我們在樣式中加入:
/deep/ uni-swiper .uni-swiper-wrapper {
overflow-y: auto !important;
}
/deep/ uni-swiper-item {
overflow-y: auto !important;
}
加完了滾動以後你就會驚喜的發現頁面滾動上去以後再也下不來了!因爲下拉事件被原生的下拉刷新佔用咯~ 你想着這還不簡單,我加個scrollview還不行麼,那你試試吧真不行嘿嘿!
首先讓我告訴你原理:我們的swiper這貨是必須有高度的, 而由於swiper高度是固定的,導致就算組件內部內容已經過長了,但下拉的時候body其實並沒有過長,因此,無論你是什麼scrollview或者overflow:auto,都會優先觸發body滾動,也就是下拉刷新,這就是造成衝突的主要原因,我可以用一張圖更清晰的解釋:
針對這點,網上一種解決辦法@touch.stop和@touchmove.stop你們可以試一下,反正H5可以,真機上不行,就算真機上可以,但這種方法只會在swiper區域攔截,造成下拉刷新區域很小,用戶體驗也是很差的。所以被我淘汰了。
根據上面的原理圖,我們可以想到,既然swiper內部不能滾動,那就讓swiper自身高度自適應撐起來,這樣就會完美解決問題
所以首先我們需要解決swiper高度自適應問題
這裏給了高度,的確已經解決了初步的問題,但是實際運用中,不可能所有的內容都是一上來就確定的,肯定要有網絡請求在隨時更新內容和高度的,比如有一個列表,那麼上面的代碼就失效了,因爲高度在onReady週期已經定死了。
所以 我們的最後一步 需要隨時更新高度,那麼想到的思路就是子組件中emit通知父組件的swiper更新高度咯,嘗試一下:(我這裏用了個測試box來實驗)
<view style="height: 100px;background-color: #007AFF;" v-show="testShow"></view>
uni.$on('updateSwiperHeight', () => {
console.log('收到通知');
this.getCurrentSwiperHeight('.fragment');
}); //父組件中註冊監聽
父組件在收到通知後會重新獲取子組件高度並更新界面,這是美好的邏輯設想,但實際上獲取dom高度的方法中,此時高度還沒有及時更新,所以我們首先會想到將getCurrentSwiperHeight方法放在this.$nextTick方法中,但是在我的嘗試下 就算包裹在nexttick中,高度也是沒有及時更新,所以我只能使用了最終解決辦法:
使用setTimeout,延遲一段時間再獲取高度,事實證明暫時只有這種方法能獲取到高度。如果大家有什麼更好的辦法,可以留言告訴我謝謝!