better-scroll在vue中的使用
一、介紹
關於better-scroll的原文詳細介紹請參考,這裡只做總結
黃老師的文章《當 better-scroll 遇見 Vue》的詳細介紹
better-scroll的api:點選
better-scroll的滾動原理
<div class="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
</div>
綠色部分為 wrapper,也就是父容器,它會有固定的高度。黃色部分為 content,它是父容器的第一個子元素,它的高度會隨著內容的大小而撐高。那麼,當 content 的高度不超過父容器的高度,是不能滾動的,而它一旦超過了父容器的高度,我們就可以滾動內容區了,這就是 better-scroll 的滾動原理。
better-scroll 的初始化時機很重要,因為它在初始化的時候,會計算父元素和子元素的高度和寬度,來決定是否可以縱向和橫向滾動。因此,我們在初始化它的時候,必須確保父元素和子元素的內容已經正確渲染了。如果子元素或者父元素 DOM 結構發生改變的時候,必須重新呼叫 scroll.refresh()
二、better-scroll在vue中的使用
Vue.js 提供了我們一個獲取 DOM 物件的介面—— vm.$refs
。在這裡,我們通過了 this.$refs.wrapper
訪問到了這個 DOM 物件,並且我們在 mounted 這個鉤子函式裡,this.$nextTick
的回撥函式中初始化 better-scroll 。因為這個時候,wrapper 的 DOM 已經渲染了,我們可以正確計算它以及它內層 content 的高度,以確保滾動正常。
這裡的 this.$nextTick
setTimeout(fn, 0)
。其實我們在這裡把 this.$nextTick
替換成 setTimeout(fn, 20)
也是可以的(20 ms 是一個經驗值,每一個 Tick 約為 17 ms),對使用者體驗而言都是無感知的。
這裡從今日頭條擷取獲取後臺資料鏈接,用vue-jsonp來非同步獲取資料。
安裝vue-jsonp
npm install vue-jsonp --save-dev
在元件單獨使用
import Vue from 'vue' import VueJsonp from 'vue-jsonp' Vue.use(VueJsonp)
詳細請參考 vue-jsonp的npm地址:點選
<template> <div> <nav class="nav"> <ul> <li>推薦</li> </ul> </nav> <div class="wrapper" ref="wrapper"> <div class="content" > <section class="has_action" v-for="item in data" :key="item.datetime"> <div class="item-detail"> <h3 class="dotdot">{{item.title}}</h3> <div class="item-info"> <div> <span class="stick_label space">{{item.label}}</span> <span class="src space">{{item.media_name}}</span> <span class="cmt space">評論{{item.comment_count}}</span> <span class="time space" title="2018-11-05 19:23">{{item.datetime}}</span> </div> </div> </div> </section> </div> </div> </div> </template>
<script> import Vue from 'vue' import VueJsonp from 'vue-jsonp' import BScroll from 'better-scroll' Vue.use(VueJsonp) export default { name: 'myscroll', data() { return { data: [] } }, created() { this._getData().then(json => { this.data = json.data this.$nextTick(() => { this.scroll = new BScroll(this.$refs.wrapper,{}) }) }) }, methods: { // 或者頁面資料,跳用今日頭條資料介面 _getData() { return this.$jsonp('https://m.toutiao.com/list',{ tag: '__all__', ac: 'wap', count: 20, format: 'json_raw', as: 'A1B57B7E600F6A7', cp: '5BE0AFC5FDAEAE1', min_behot_time: 1541469897, _signature: 'A6d5hAAAWEyp4NHR.YRHRAOneZ', i: 1541469650 }) } } } </script>
注意:nav和wrapper這兩個class的css定位屬性
<style scoped lang="stylus"> .nav z-index: 999 position: fixed display: block box-sizing: border-box height: 74px width: 100% text-align: center line-height: 74px font-size: 20px color: #f85959 background: #f4f5f6 .wrapper position: fixed top: 74px left: 0 bottom: 0 right: 0 overflow: hidden .content list-style: none .has_action position: relative margin: 0 30px border-bottom: 1px solid rgba(221, 221, 221, 0.6) .item-detail padding: 32px 0px; .dotdot overflow: hidden text-overflow: ellipsis line-height: 42px font-size: 34px font-weight: normal color: #222 .item-info margin-top: 12px overflow: hidden font-size: 0 color: #999 .space display: inline-block margin-right: 10px vertical-align: middle line-height: 30px font-size: 28px .stick_label border-radius: 4px border: 1PX solid rgba(248,89,89,.5) width: 60px text-align: center color: #f85959 </style>
結果如下: