vue無(wú)縫滾動(dòng)的插件開(kāi)發(fā)填坑分享

寫插件的初衷

1.項(xiàng)目經(jīng)常需要無(wú)縫滾動(dòng)效果缴罗,當(dāng)時(shí)寫jq的時(shí)候用用msClass這個(gè)老插件,相對(duì)不上很好用虱颗。

2.后來(lái)轉(zhuǎn)向vue在vue-awesome沒(méi)有找到好的無(wú)縫滾動(dòng)插件晶伦,除了配置swiper可以實(shí)現(xiàn)但是相對(duì)來(lái)說(shuō)太重了闸衫,于是自己造了個(gè)輪子献丑。

3.在這分享下末捣,當(dāng)時(shí)寫這個(gè)插件的坑,自己也復(fù)習(xí)下,如果代碼上有瑕疵歡迎指出创橄。

源碼參考 vue-seamless-scroll

1.簡(jiǎn)單的實(shí)現(xiàn)上下滾動(dòng)基本版(最初版)

html

1.solt提供默認(rèn)插槽位來(lái)放置父組件傳入的html

<template>
    <div @mouseenter="enter" @mouseleave="leave">
        <div ref="wrapper" :style="pos">
            <slot></slot>
       </div>
    </div>
</template>

javascript

1.animationFrame 動(dòng)畫api兼容處理

2.arrayEqual 判斷數(shù)組是否相等 來(lái)監(jiān)聽(tīng)data的變化來(lái)實(shí)現(xiàn)更新無(wú)縫滾動(dòng)

<script>

  require('comutils/animationFrame')  //requestAnimationFrame api
  const arrayEqual = require('comutils/arrayEqual')
  export default {
    data () {
      return {
        yPos: 0,
        reqFrame: null
      }
    },
    props: {
      data: { // data 數(shù)據(jù)
        type: Array,
        default: []
      },
      classOption: { //參數(shù)
        type: Object,
        default: {}
      }
    },
    computed: {
      pos () {
        // 給父元素的style
        return {transform: `translate(0,${this.yPos}px)`}
      },
      defaultOption () {
        return {
          step: 1, //步長(zhǎng)
          limitMoveNum: 5, //啟動(dòng)無(wú)縫滾動(dòng)最小數(shù)據(jù)數(shù)
          hoverStop: true, //是否啟用鼠標(biāo)hover控制
          direction: 1 //1 往上 0 往下
        }
      },
      options () {
        // 合并參數(shù)
        return Object.assign({}, this.defaultOption, this.classOption)
      }
      ,
      moveSwitch () {
      //判斷傳入的初始滾動(dòng)值和data的length來(lái)控制是否滾動(dòng)
        return this.data.length < this.options.limitMoveNum
      }
    },
    methods: {
      enter () {
        if (!this.options.hoverStop || this.moveSwitch) return
        cancelAnimationFrame(this.reqFrame)
      },
      leave () {
        if (!this.options.hoverStop || this.moveSwitch) return
        this._move()
      },
      _move () {
        //滾動(dòng)
        this.reqFrame = requestAnimationFrame(
          () => {
            let h = this.$refs.wrapper.offsetHeight / 2
            let direction = this.options.direction
            if (direction === 1) {
              if (Math.abs(this.yPos) >= h) this.yPos = 0
            } else {
              if (this.yPos >= 0) this.yPos = h * -1
            }
            if (direction === 1) {
              this.yPos -= this.options.step
            } else {
              this.yPos += this.options.step
            }
            this._move()
          }
        )
      },
      _initMove () {
        if (this.moveSwitch) {
          cancelAnimationFrame(this.reqFrame)
          this.yPos = 0
        } else {
          this.$emit('copyData') //需要copy復(fù)制一份 emit到父元素  后期版本這里已經(jīng)優(yōu)化
          if (this.options.direction !== 1) {
            setTimeout(() => {
              this.yPos = this.$refs.wrapper.offsetHeight / 2 * -1
            }, 20)
          }
          this._move()
        }
      }
    },
    mounted () {
      this._initMove()
    },
    watch: {
      //監(jiān)聽(tīng)data的變化
      data (newData, oldData) {
        if (!arrayEqual(newData, oldData.concat(oldData))) {
          cancelAnimationFrame(this.reqFrame)
          this._initMove()
        }
      }
    }
  }
</script>

1.1 優(yōu)化1: 新增配置openWatch 是否開(kāi)啟data監(jiān)控實(shí)時(shí)刷新

有興趣可以看本次commit記錄 myClass.vue的更改

1.2 優(yōu)化2: 新增配置singleHeight waitTime參數(shù) 控制是否單步滾動(dòng)

commit記錄

1.3 優(yōu)化3:添加對(duì)移動(dòng)端touch事件滾動(dòng)列表支持

commit記錄

1.4 優(yōu)化4: 去掉了emit回調(diào)(簡(jiǎn)化初始化)

//原本組件調(diào)用
<my-class :data="listData" :class-option="classOption" @copy-data="listData = listData.concat(listData)">
//簡(jiǎn)化后組件調(diào)用
<my-class :data="listData" :class-option="classOption" class="warp">
用js的來(lái)復(fù)制一份innerHtml來(lái)代替之前的做法簡(jiǎn)化使用
//this.$emit('copyData')

 timer = setTimeout(() => { //20ms延遲 作用保證能取到最新的html
   this.copyHtml = this.$refs.slotList.innerHTML
 }, 20)
 // template
 <template>
    <div @mouseenter="enter" @mouseleave="leave" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
        <div ref="wrap" :style="pos">
            <div ref="slotList" :style="float">
                <slot></slot>
            </div>
            <div v-html="copyHtml" :style="float"></div>
        </div>
    </div>
</template>

commit記錄

1.5 bug1: 解決ie9下animationFrame報(bào)錯(cuò)的bug

這個(gè)問(wèn)題的原因查了比較久最后發(fā)現(xiàn)是當(dāng)時(shí)沒(méi)有加return沒(méi)有取到定時(shí)器id

BVX}H{RC`{80TLA4}1A6XQL.png

1.6 優(yōu)化5:添加左右無(wú)縫滾動(dòng)

類似上下可以查看commit

1.7 Vue.use() 提供install全局注冊(cè)

import vueMyCLass from './components/myClass.vue'

let myScroll

const defaultComponentName = 'vue-seamless-scroll'

// expose component to global scope
if (typeof window !== 'undefined' && window.Vue) {
  Vue.component('vue-seamless-scroll', vueMyCLass)
} else {
  myScroll = {
    install: function (Vue, options = {}) {
      Vue.component(options.componentName || defaultComponentName, vueMyCLass)
    }
  }

}

export default myScroll

1.8 bug 解決了touchMove頻繁快速操作導(dǎo)致單步滾動(dòng)失效bug 和部分代碼優(yōu)化

//1.封裝多次調(diào)用的取消動(dòng)畫方法

_cancle: function _cancle() {
     cancelAnimationFrame(this.reqFrame || '');
    },

//2.touchMove頻繁快速操作導(dǎo)致滾動(dòng)錯(cuò)亂bug

 _move () {
    this._cancle() //進(jìn)入move立即先清除動(dòng)畫 防止頻繁touchMove導(dǎo)致多動(dòng)畫同時(shí)進(jìn)行
    }    

//3.生命周期結(jié)束前取消動(dòng)畫

 beforeDestroy () {
      this._cancle()
}

//4.修復(fù)不傳參數(shù)報(bào)警告的bug

 props: {
      data: {
        type: Array,
        default: () => {
          return []
        }
      },
      classOption: {
        type: Object,
        default: () => {
          return {}
        }
      }
    }

//5.Fixing a bug. add a overflow:hidden on the child element

部分人喜歡用margin-top如果沒(méi)有overflow等限制會(huì)導(dǎo)致我里面計(jì)算高度和實(shí)際有些許差距導(dǎo)致最后效果到臨界位置有輕微抖動(dòng)
//默認(rèn)加上了overflow: 'hidden'

computed: {
      float () {
        return this.options.direction > 1 ? {float: 'left', overflow: 'hidden'} : {overflow: 'hidden'}
      },
      pos () {
        return {
          transform: `translate(${this.xPos}px,${this.yPos}px)`,
          transition: `all ease-in ${this.delay}ms`,
          overflow: 'hidden'
        }
      }
}

//6.新增單步滾動(dòng)也能hover停止的功能

之前因?yàn)閱尾綕L動(dòng)內(nèi)置了延遲執(zhí)行this._move()默認(rèn)單步限制了鼠標(biāo)懸停停止無(wú)縫滾動(dòng),后來(lái)通過(guò)給this._move()加上開(kāi)關(guān)達(dá)到效果。

commit

TKS

如果對(duì)原生js實(shí)現(xiàn)類似的無(wú)縫滾動(dòng)有興趣可以留言莽红,我抽空也可以寫下seamless-scroll

vue-seamless-scroll發(fā)現(xiàn)bug或者有什么不足望指點(diǎn),感覺(jué)不錯(cuò)點(diǎn)個(gè)star吧妥畏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邦邦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子醉蚁,更是在濱河造成了極大的恐慌燃辖,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件网棍,死亡現(xiàn)場(chǎng)離奇詭異黔龟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)滥玷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門氏身,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人惑畴,你說(shuō)我怎么就攤上這事蛋欣。” “怎么了如贷?”我有些...
    開(kāi)封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵陷虎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我杠袱,道長(zhǎng)尚猿,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任楣富,我火速辦了婚禮谊路,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘菩彬。我一直安慰自己缠劝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布骗灶。 她就那樣靜靜地躺著惨恭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耙旦。 梳的紋絲不亂的頭發(fā)上脱羡,一...
    開(kāi)封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音免都,去河邊找鬼锉罐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绕娘,可吹牛的內(nèi)容都是我干的脓规。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼险领,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼侨舆!你這毒婦竟也來(lái)了秒紧?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挨下,失蹤者是張志新(化名)和其女友劉穎熔恢,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體臭笆,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叙淌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了愁铺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹰霍。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖帜讲,靈堂內(nèi)的尸體忽然破棺而出衅谷,到底是詐尸還是另有隱情,我是刑警寧澤似将,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布获黔,位于F島的核電站,受9級(jí)特大地震影響在验,放射性物質(zhì)發(fā)生泄漏玷氏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一腋舌、第九天 我趴在偏房一處隱蔽的房頂上張望盏触。 院中可真熱鬧,春花似錦块饺、人聲如沸赞辩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辨嗽。三九已至,卻和暖如春淮腾,著一層夾襖步出監(jiān)牢的瞬間糟需,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工谷朝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洲押,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓圆凰,卻偏偏與公主長(zhǎng)得像杈帐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子送朱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容