因爲最近一個移動端項目中許多地方有滾動需求, 橫向,縱向的都有,因此就基於better-scroll封裝了一個通用的滾動組件,期間也踩了一些坑,有時候會滾動失效,初始化的時候就不能滾動等等...
better-scroll地址: https://ustbhuangyi.github.io...git
<template> <div ref="wrapper"> <slot></slot> </div> </template> <script> import BScroll from "better-scroll"; export default { props: { probeType: { type: Number, // 非實時派發scroll事件和位置參數, 類型由0,1,2,3, default: 1 }, scrollX: { type: Boolean, // 是否橫向滾動 default: false }, scrollY: { type: Boolean, // 是否縱向滾動 default: true }, click: { type: Boolean, // 是否派發點擊事件 default: true }, listenScroll: { type: Boolean, // 監聽滾動 default: false }, data: { type: Array, // 組件數據,可用於從新刷新scroll組件 default: null }, pullup: { type: Boolean, // 上拉加載更多,請求接口 default: false }, beforeScroll: { type: Boolean, // 滾動以前作些什麼 default: false }, refreshDelay: { type: Number, // scroll刷新時間 default: 20 }, eventPassthrough: { type: String, // 支持原生滾動 default: '' }, 不少... }, mounted() { // 也可使用nextTick來初始化 setTimeout(() => { this.initScroll(); }, 20); }, methods: { // 初始化 initScroll() { if (!this.$refs.wrapper) { return; } // 根據本身的需求傳入配置項 this.scroll = new BScroll(this.$refs.wrapper, { probeType: this.probeType, click: this.click, scrollX: this.scrollX }); if (this.listenScroll) { let me = this; this.scroll.on("scroll", pos => { me.$emit("scroll", pos); }); } if (this.pullup) { this.scroll.on("scrollEnd", () => { if (this.scroll.y <= this.scroll.maxScrollY + 50) { this.$emit("scrollToEnd"); } }); } if (this.beforeScroll) { this.scroll.on("beforeScrollStart", () => { this.$emit("beforeScroll"); }); } }, disable() { this.scroll && this.scroll.disable(); }, enable() { this.scroll && this.scroll.enable(); }, refresh() { this.scroll && this.scroll.refresh(); }, scrollTo() { this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments); }, scrollToElement() { this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments); } }, watch: { // 這個能夠設置data來刷新scroll組件 data() { setTimeout(() => { this.refresh(); }, this.refreshDelay); } } }; </script> <style lang="less" scoped> </style>
固然, 咱們還能夠添加更多的配置功能, 這個須要依據你本身的需求來了,詳情配置去better-scroll官網看看github
<scroll ref="scroll" class="main-content" :data="data"> <div> 添加須要滾動的DOM元素: 如ul>li等, 或者多個子組件 </div> </scroll> // 下面是樣式 .main { width: 100%; height: calc(100vh - 52px); background-color: #f7f8fa; .main-content { height: 100%; overflow: hidden; position: relative; } }
縱向滾動主要是要注意的是: scroll下的第一個子元素,它的高度須要讓內容來撐開!!! 不然沒法滾動
圖片中已經標識出來了...瀏覽器
<template> <div class="app-list-wrapper"> <scroll :scrollX="true" :scrollY="false" ref="scroll" class="icon-content"> <div class="icons"> <div v-for="i in 8" :key="i" class="icon"> <appIcon style="margin-right: 16px"></appIcon> </div> </div> </scroll> </div> </template> // 樣式 <style lang="less" scoped> .app-list-wrapper { width: 100%; .icon-content { // scroll容器 width: 100%; overflow: hidden; .icons { // 注意scroll容器下的第一個元素 padding-left: 20px; display: inline-block; white-space: nowrap; // 子元素樣式 .icon { display: inline-block; } } } } </style>
橫向滾動下咱們傳入配置值就好了; 這裏主要是注意樣式的書寫! 也就是scroll下的第一個子元素的寬度要由內容撐寬才能夠...,代碼塊中也標註出來了.app
1.純靜態頁面的滾動less
舉個栗子,我如今寫了一個彈出層,就是靜態數據渲染,可是需求也須要滾動,由於單頁可能顯示不下, 雖然說better-scroll的原理是第一個子元素超出父盒子就能夠實現滾動了, 彈出層只有在點擊彈窗的時候纔會渲染,因此是沒法滾動的, 在彈窗出來後再手動刷新scroll組件; 這裏咱們就能夠經過那個data屬性搞事情了,每次點擊彈窗後,往data中丟個數據,這樣會觸發scroll組件的watch, 而後手動刷新,就能夠實現滾動了...
// 部分代碼示例 <t-aside :data="onOff"></t-aside> // 側邊欄彈出層組件 methods: { showPopup() { this.onOff.push('1'), // 刷新scroll組件 this.$refs.aside.show(); } }
2.scroll容器數據變化致使沒法正常滾動, 可能狀況是:ide
- 初始化的時候就有問題,去檢查一下第一個子元素高度||寬度是不是由其子元素撐開的 - 接口數據還未請求回來就初始化了, 好比圖片,此時初始化就沒算上圖片的高度, 這時候就須要手動調用this.$refs.scroll.refresh()來刷新scroll組件, 矯正滾動高度 - 頁面容器設爲100vh後發現, 沒法觸發上滑隱藏URL框的需求; 消除手機URL欄: 須要知足列表的高度須要設置固定,外層盒子要大於手機視口高度,滑動時才能消除url地址欄 解決:監聽頁面路由事件beforeRouteEnter,先禁止掉scroll插件的滾動。 讓用戶能夠滾動頁面。 window.onscroll事件中拿到想要的scrollTop後(瀏覽器已經隱藏地址欄和工具欄),放開scroll插件滾動。 - 發現better-scroll派發的scroll方法, 在父組件中監聽後獲取位置參數的效果不太好; 必需要手指貼着滑動才能夠... 這個設置 probeType 爲 3 能夠實時派發滾動事件和位置參數
3.其餘坑點待發現...歡迎大佬一塊兒交流工具