国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

BetterScroll:可能是目前最好用的移動(dòng)端滾動(dòng)插件

layman / 2541人閱讀

摘要:是一款重點(diǎn)解決移動(dòng)端各種滾動(dòng)場(chǎng)景需求的開(kāi)源插件地址,有下列功能支持滾動(dòng)列表,下拉刷新,上拉刷新,輪播圖,等功能。為了滿足這些功能,通過(guò)使用慣性滾動(dòng)邊界回彈滾動(dòng)條淡入淡出來(lái)確保滾動(dòng)的流暢。貝瑟爾函數(shù)可以去看看,他讓動(dòng)畫(huà)不再那么突兀。

BetterScroll 是一款重點(diǎn)解決移動(dòng)端各種滾動(dòng)場(chǎng)景需求的開(kāi)源插件(GitHub地址),有下列功能支持滾動(dòng)列表,下拉刷新,上拉刷新,輪播圖,slider等功能。
為了滿足這些功能,better-scroll通過(guò)使用慣性滾動(dòng)、邊界回彈、滾動(dòng)條淡入淡出來(lái)確保滾動(dòng)的流暢。同時(shí)還支持很多API和事件,具體支持的事件可以查看官網(wǎng)講的非常詳細(xì)。
由于它基于原生JavaScript 實(shí)現(xiàn),不依賴任何框架,所以既可以原生 JavaScript 引用,也可以與目前前端 MVVM 框架結(jié)合使用,比如,其官網(wǎng)上的示例就是與 Vue 的結(jié)合。

如何使用:

再講如何使用的之前,我們先來(lái)了解一下他的滾動(dòng)原理:在瀏覽器中的滾動(dòng)中,當(dāng)內(nèi)容的高度高于外邊容器的高度的時(shí)候也就出現(xiàn)了滾動(dòng)條,我們可以通過(guò)使用滾動(dòng)條來(lái)看到超出的部分.

better-scroll的原理正是基于這里,內(nèi)容部分的寬度/高度必須大于外部寬度/高度。所以在使用
的時(shí)候外部容器的需要設(shè)置固定寬度,還有一個(gè)問(wèn)題需要設(shè)置overflow:hidden,這是因?yàn)闉榱穗[藏超出部分。然后就是什么時(shí)候?qū)etter-scroll進(jìn)行初始化,這個(gè)有點(diǎn)麻煩,但是所幸,作者已經(jīng)在vue框架下進(jìn)行封裝,我們只需要像個(gè)麻瓜一樣往里邊填東西就行了。但是有一點(diǎn)需要注意:滾動(dòng)的元素只能是第一個(gè)容器的第一個(gè)元素。源碼如下:

  // this.scroller就是滾動(dòng)的內(nèi)容,this.wrapper是容器
    this.scroller = this.wrapper.children[0]

如果我們需要滾動(dòng)多個(gè)內(nèi)容怎么辦呢,就用一個(gè)元素將其包裹住,讓他成為容器的第一個(gè)子元素就行了。如何使用講完了,我們來(lái)講講源碼,畢竟這是一個(gè)源碼解析的文章

核心代碼: 1、scrollTo

scrollTo()函數(shù)是better-scroll非常核心的一個(gè)函數(shù),事實(shí)上我們?cè)谡{(diào)用scrollToElement的
時(shí)候,內(nèi)部進(jìn)行的操作還是scrollTo函數(shù)

   BScroll.prototype.scrollTo = function (x, y, time=0, easing = ease.bounce) {
        // useTransition是否使用css3 transition,isInTransition表示是否在滾動(dòng)過(guò)程中
        // this.x表示translate后的位置或者初始化this.x = 0
        this.isInTransition = this.options.useTransition
        && time > 0 && (x !== this.x || y !== this.y)

        // 如果使用的transition,就調(diào)用一系列transition的設(shè)置,默認(rèn)是true
        if (!time || this.options.useTransition) {
            this._transitionProperty()
            this._transitionTimingFunction(easing.style)
            this._transitionTime(time)
            // 這個(gè)函數(shù)會(huì)更改this.x
            this._translate(x, y)

            // time存在protoType表示不僅在屏幕滑動(dòng)的時(shí)候, momentum 滾動(dòng)動(dòng)畫(huà)運(yùn)行過(guò)程中實(shí)時(shí)派發(fā) scroll 事件
            if (time && this.options.probeType === 3) {
                // 這個(gè)函數(shù)的作用是派發(fā)scroll事件
                this._startProbe()
            }

            // wheel用于picker組件設(shè)置,不用管
            if (this.options.wheel) {
                if (y > 0) {
                    this.selectedIndex = 0
                } else if (y < this.maxScrollY) {
                    this.selectedIndex = this.items.length - 1
                } else {
                    this.selectedIndex = Math.round(Math.abs(y / this.itemHeight))
                }
            } else {
                // 進(jìn)行動(dòng)畫(huà)this._animate
                this._animate(x, y, time, easing.fn)
            }
        }
    };

我們來(lái)依次看看這個(gè)函數(shù),其中簡(jiǎn)單的操作用代碼注明,也就不做太多的描述,其中例如this._transition這種有關(guān)transform的都是改變他的位置而已,這里我需要說(shuō)明一下,我們?cè)谥谱鬏啿D的時(shí)候,別去使用transform這種方法來(lái)做輪播圖,因?yàn)楫?dāng)我們需要獲取transform屬性值的時(shí)候,你會(huì)獲取到的值是一個(gè)非常奇怪的矩陣,得到translateX或者translateY的值是一件非常痛苦的事,可以看看作者是如何獲取transform的值的,

matrix = matrix[style.transform].split(")")[0].split(", ")
            x = +(matrix[12] || matrix[4])
            y = +(matrix[13] || matrix[5])

我是一臉蒙蔽,要是你覺(jué)得你水平很高當(dāng)我沒(méi)說(shuō)。this.options.probeType這個(gè)probeType配置表明的是我們需要在什么情況下派發(fā)scroll事件,在better-scroll的原理中是默認(rèn)阻止瀏覽器的默認(rèn)行為的,那我們是如何派發(fā)事件的呢?

  export function tap(e, eventName) {
        let ev = document.createElement("Event")
        ev.initEvent(eventName, true, true)
        e.target.dispatchEvent(ev)
    }

創(chuàng)建一個(gè)element,然后初始化,然后派發(fā)事件,我們就可以像addEventListener("click", fn, false)這樣的方式來(lái)監(jiān)聽(tīng)事件addEventListener(eventName, fn, false)。這兒有一個(gè)參數(shù)叫easing,我們來(lái)看看easing是什么
下面是一個(gè)easing的一個(gè)選項(xiàng):

 bounce: {
        style: "cubic-bezier(0.165, 0.84, 0.44, 1)",
        fn: function (t) {
            return 1 - (--t * t * t * t)
        }
    }

可以看到easing通過(guò)貝瑟爾函數(shù),和fn讓我們的動(dòng)畫(huà)顯得不是那么僵硬。貝瑟爾函數(shù)可以去看看,他讓動(dòng)畫(huà)不再那么突兀。

2、refresh函數(shù)

在實(shí)際開(kāi)發(fā)中,有時(shí)候從后端請(qǐng)求到數(shù)據(jù)后,我們dom結(jié)構(gòu)發(fā)生變化,所以需要調(diào)用refresh方法,來(lái)看看他是什么玩意

BScroll.prototype.refresh = function () {
    // return getBoundingRect getRect()
    let wrapperRect = getRect(this.wrapper)
    this.wrapperWidth = wrapperRect.width
    this.wrapperHeight = wrapperRect.height

    let scrollerRect = getRect(this.scroller)
    this.scrollerWidth = scrollerRect.width
    this.scrollerHeight = scrollerRect.height

    const wheel = this.options.wheel
    // wheel用于picker組件設(shè)置
    if (wheel) {
        this.items = this.scroller.children
        this.options.itemHeight = this.itemHeight = this.items.length ? this.scrollerHeight / this.items.length : 0
        if (this.selectedIndex === undefined) {
            this.selectedIndex = wheel.selectedIndex || 0
        }
        this.options.startY = -this.selectedIndex * this.itemHeight
        this.maxScrollX = 0
        this.maxScrollY = -this.itemHeight * (this.items.length - 1)
    } else {
        // 允許滑動(dòng)的距離
        this.maxScrollX = this.wrapperWidth - this.scrollerWidth
        this.maxScrollY = this.wrapperHeight - this.scrollerHeight
    }

    // 滾動(dòng)原理容器的寬度小于scroller的寬度
    // scrollX設(shè)置為true表示可以橫向滾動(dòng)
    this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0
    this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0

    // 如果水平不存在的話
    if (!this.hasHorizontalScroll) {
        this.maxScrollX = 0
        this.scrollerWidth = this.wrapperWidth
    }

    if (!this.hasVerticalScroll) {
        this.maxScrollY = 0
        this.scrollerHeight = this.wrapperHeight
    }

    this.endTime = 0
    // 移動(dòng)方向
    this.directionX = 0
    this.directionY = 0
    // return el.offsetLeft
    // el.offsetLeft是距離父容器的距離
    // el.getBoundingClientRect()返回的是距離頁(yè)面的距離
    this.wrapperOffset = offset(this.wrapper)

    // 切換到refresh事件
    this.trigger("refresh")

    // 重置位置
    this.resetPosition()
}

當(dāng)我們的dom結(jié)構(gòu)發(fā)生變化的時(shí)候,我們就需要重新計(jì)算父容器和容器的大小了,這樣就可以重新渲染了,這個(gè)函數(shù)沒(méi)什么太難理解的部分,需要注意的是getBoundingClientRect()方法返回元素的大小及其相對(duì)于視口的位置。他同element.style獲取的有些不同getBoundingClientRect()獲取到的值是相對(duì)視口左上角,意思是說(shuō)在獲取right值的時(shí)候,事實(shí)上是left+element.clientWidth。而且getBoundingClientRect()是只能讀取,而element.style不僅能讀取,還能獲取。el.offsetLeft返回的距離父容器的距離,如果我們需要得到元素距離document的距離的話我們就需要這樣寫(xiě)

export function offset(el) {
    let left = 0
    let top = 0

    while (el) {
        left -= el.offsetLeft
        top -= el.offsetTop
        el = el.offsetParent
    }

    return {
        left,
        top
    }
}

一直找到?jīng)]有父元素的時(shí)候,就找到元素距離document的距離了

3、trigger函數(shù)

在better-scroll的源碼中,多次用到trigger函數(shù),我們來(lái)看看他都做了什么

 BScroll.prototype.trigger = function (type) {
        let events = this._events[type]
        if (!events) {
            return
        }

        let len = events.length
        let eventsCopy = [...events]
        for (let i = 0; i < len; i++) {
            let event = eventsCopy[i]
            let [fn, context] = event
            if (fn) {
                fn.apply(context, [].slice.call(arguments,1))
            }
        }
  }

trigger函數(shù)的作用就是切換到某個(gè)事件中,獲取到事件,然后使用fn進(jìn)行調(diào)用。沒(méi)什么太大難度,這里想到一點(diǎn)能夠體現(xiàn)es6的優(yōu)越性的地方,比如a = [1,2,3] 在es5中如果我們需要獲取a這個(gè)數(shù)組長(zhǎng)度的時(shí)候,我們需要這樣寫(xiě)

 let len = a.length

但是在es6中我們不再需要這樣寫(xiě)了,這樣寫(xiě)就行

let { length } = a

如果需要獲取其他屬性值,就麻瓜式往里邊填。這里還涉及一個(gè)深拷貝的問(wèn)題,數(shù)組和對(duì)象的深拷貝這里不做過(guò)多闡述。上述最重要的我認(rèn)為就是這三個(gè)函數(shù)

總結(jié):

這個(gè)better-scroll的源碼條理清晰,畢竟滴滴D8的段位擺在那兒,非常適合閱讀。還有一些就是我對(duì)源碼分析的文章的看法。在寫(xiě)這個(gè)源碼分析的文章的時(shí)候,我意識(shí)到一個(gè)問(wèn)題,那就是不僅我自己能夠看懂,以前我也寫(xiě)過(guò)vuex的源碼分析,基本就是把代碼全部貼上去,寫(xiě)了大概2萬(wàn)字,我現(xiàn)在覺(jué)得這種方法欠妥,正確的方式應(yīng)該就是把重要的部分提取出來(lái),最重要的引導(dǎo)一個(gè)思路。把代碼整個(gè)貼出來(lái),顯得繁瑣不說(shuō),又相當(dāng)于讀者自己把注釋看了一遍而已,所以我認(rèn)為正確的方式是弄出一個(gè)思路,讀者嘗試讀源碼的時(shí)候,能夠有一個(gè)大概的概念。能夠自己理清思路

至于為什么這個(gè)標(biāo)題不寫(xiě)better-scroll的源碼分析呢,我怕有些人說(shuō)有些源碼分析的文章就是垃圾,所以至少在字面上進(jìn)行改變(逃。。。)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/51570.html

相關(guān)文章

  • BetterScroll可能目前最好用的移動(dòng)滾動(dòng)插件

    摘要:是一款重點(diǎn)解決移動(dòng)端各種滾動(dòng)場(chǎng)景需求的開(kāi)源插件地址,有下列功能支持滾動(dòng)列表,下拉刷新,上拉刷新,輪播圖,等功能。為了滿足這些功能,通過(guò)使用慣性滾動(dòng)邊界回彈滾動(dòng)條淡入淡出來(lái)確保滾動(dòng)的流暢。貝瑟爾函數(shù)可以去看看,他讓動(dòng)畫(huà)不再那么突兀。 BetterScroll 是一款重點(diǎn)解決移動(dòng)端各種滾動(dòng)場(chǎng)景需求的開(kāi)源插件(GitHub地址),有下列功能支持滾動(dòng)列表,下拉刷新,上拉刷新,輪播圖,slide...

    xiaolinbang 評(píng)論0 收藏0
  • 移動(dòng)布局與適配

    摘要:實(shí)戰(zhàn)之微信錢包騰訊服務(wù)界面網(wǎng)格布局是讓開(kāi)發(fā)人員設(shè)計(jì)一個(gè)網(wǎng)格并將內(nèi)容放在這些網(wǎng)格內(nèi)。對(duì)于移動(dòng)端適配,不同的公司不同的團(tuán)隊(duì)有不同的解決方案。柵格系統(tǒng)用于處理頁(yè)面多終端適配的問(wèn)題。 grid實(shí)戰(zhàn)之微信錢包 騰訊服務(wù)界面 CSS3網(wǎng)格布局是讓開(kāi)發(fā)人員設(shè)計(jì)一個(gè)網(wǎng)格并將內(nèi)容放在這些網(wǎng)格內(nèi)。而不是使用浮動(dòng)制作一個(gè)網(wǎng)格,實(shí)際上是你將一個(gè)元素聲明為一個(gè)網(wǎng)格容器,并把元素內(nèi)容置于網(wǎng)格中。 移動(dòng)端頁(yè)面適配—...

    Clect 評(píng)論0 收藏0
  • 常用插件、工具類庫(kù)匯總(上)

    摘要:函數(shù)庫(kù)動(dòng)畫(huà)庫(kù)動(dòng)畫(huà)庫(kù),也是目前最通用的動(dòng)畫(huà)庫(kù)。下拉框級(jí)聯(lián)選擇器移動(dòng)端最好用的的篩選器組件聯(lián)動(dòng)篩選移動(dòng)端最好用的的篩選器組件聯(lián)動(dòng)篩選顏色選擇器時(shí)間選擇器時(shí)間日期處理是一個(gè)解析,驗(yàn)證,操作和顯示日期和時(shí)間的類庫(kù)。 showImg(https://segmentfault.com/img/bVbjpHt?w=900&h=383); 前言 在開(kāi)發(fā)中,我們經(jīng)常會(huì)將一些常用的代碼塊、功能塊進(jìn)行封裝,...

    txgcwm 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<