vue無縫滾動的插件開發填坑分享

寫插件的初衷

1.項目經常需要無縫滾動效果,當時寫jq的時候用用msClass這個老插件,相對不上很好用。

2.后來轉向vue在vue-awesome沒有找到好的無縫滾動插件,除了配置swiper可以實現但是相對來說太重了,于是自己造了個輪子。

3.在這分享下,當時寫這個插件的坑,自己也復習下,如果代碼上有瑕疵歡迎指出。

源碼參考 vue-seamless-scroll

1.簡單的實現上下滾動基本版(最初版)

html

1.solt提供默認插槽位來放置父組件傳入的html

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

1.animationFrame 動畫api兼容處理

2.arrayEqual 判斷數組是否相等 來監聽data的變化來實現更新無縫滾動


<script>require('comutils/animationFrame')  //requestAnimationFrame apiconst arrayEqual = require('comutils/arrayEqual')export default {data () {return {yPos: 0,reqFrame: null}},props: {data: { // data 數據type: Array,default: []},classOption: { //參數type: Object,default: {}}},computed: {pos () {// 給父元素的stylereturn {transform: `translate(0,${this.yPos}px)`}},defaultOption () {return {step: 1, //步長limitMoveNum: 5, //啟動無縫滾動最小數據數hoverStop: true, //是否啟用鼠標hover控制direction: 1 //1 往上 0 往下}},options () {// 合并參數return Object.assign({}, this.defaultOption, this.classOption)},moveSwitch () {//判斷傳入的初始滾動值和data的length來控制是否滾動return this.data.length < this.options.limitMoveNum}},methods: {enter () {if (!this.options.hoverStop || this.moveSwitch) returncancelAnimationFrame(this.reqFrame)},leave () {if (!this.options.hoverStop || this.moveSwitch) returnthis._move()},_move () {//滾動this.reqFrame = requestAnimationFrame(() => {let h = this.$refs.wrapper.offsetHeight / 2let direction = this.options.directionif (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復制一份 emit到父元素  后期版本這里已經優化if (this.options.direction !== 1) {setTimeout(() => {this.yPos = this.$refs.wrapper.offsetHeight / 2 * -1}, 20)}this._move()}}},mounted () {this._initMove()},watch: {//監聽data的變化data (newData, oldData) {if (!arrayEqual(newData, oldData.concat(oldData))) {cancelAnimationFrame(this.reqFrame)this._initMove()}}}}
</script>

1.1 優化1: 新增配置openWatch 是否開啟data監控實時刷新

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

1.2 優化2: 新增配置singleHeight waitTime參數 控制是否單步滾動

commit記錄

1.3 優化3:添加對移動端touch事件滾動列表支持

commit記錄

1.4 優化4: 去掉了emit回調(簡化初始化)


//原本組件調用
<my-class :data="listData" :class-option="classOption" @copy-data="listData = listData.concat(listData)">
//簡化后組件調用
<my-class :data="listData" :class-option="classOption" class="warp">

用js的來復制一份innerHtml來代替之前的做法簡化使用
//this.$emit('copyData')timer = setTimeout(() => { //20ms延遲 作用保證能取到最新的htmlthis.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報錯的bug

這個問題的原因查了比較久最后發現是當時沒有加return沒有取到定時器id

1504257-20181113142133648-879443480.png

1.6 優化5:添加左右無縫滾動

類似上下可以查看commit

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


import vueMyCLass from './components/myClass.vue'let myScrollconst 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頻繁快速操作導致單步滾動失效bug 和部分代碼優化

//1.封裝多次調用的取消動畫方法


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

//2.touchMove頻繁快速操作導致滾動錯亂bug

_move () {this._cancle() //進入move立即先清除動畫 防止頻繁touchMove導致多動畫同時進行}    

//3.生命周期結束前取消動畫

beforeDestroy () {this._cancle()
}

//4.修復不傳參數報警告的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如果沒有overflow等限制會導致我里面計算高度和實際有些許差距導致最后效果到臨界位置有輕微抖動
//默認加上了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.新增單步滾動也能hover停止的功能

之前因為單步滾動內置了延遲執行this._move()默認單步限制了鼠標懸停停止無縫滾動,后來通過給this._move()加上開關達到效果。

commit

TKS

如果對原生js實現類似的無縫滾動有興趣可以留言,我抽空也可以寫下seamless-scroll

vue-seamless-scroll發現bug或者有什么不足望指點,感覺不錯點個star吧。

原文地址:https://segmentfault.com/a/1190000013010808

轉載于:https://www.cnblogs.com/lalalagq/p/9951954.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249025.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249025.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring 注解 @Resource和@Autowired

Resource和Autowired兩者都是做bean的注入使用。 其實Resource并不是Spring的注解,他的包是javax.annotation.Resource 需要導入。但是Spring支持該注解的注入。 共同點:兩者都可以寫在字段和setter方法上。兩者如果都寫在字段上,就不需要寫…

洛谷 P1091 合唱隊型

很容易想到維護一個最長上升子序列和一個最長下降子序列。然后枚舉一個點k,取所有以k結尾的最長上升子序列和以k開頭的最長下降子序列的長度的和中最大的,表示留下的人數。再用總人數減去這個,等于出隊人數 另外類似的一道題:最長…

PHP常用的自定義函數

PHP常用的自定義函數 目錄 php常用自定義函數類下載php 設置字符編碼為utf-8路徑格式化(替換雙斜線為單斜線)轉碼打印輸出api返回信息字符串截取 方法一:方法二:數組 字符串 對象 json格式的字符串互轉強制類型轉換php序列化serialize與返回序列化unserialeze創建日志文件獲取i…

Spring注解@Component、@Repository、@Service、@Controller區別

很長時間沒做web項目都把以前學的那點框架知識忘光了,今天把以前做的一個項目翻出來看一下發現用Component標記一個組件,而網上有的用Service標記組件,我暈就查了一下資料: Spring 2.5 中除了提供 Component 注釋外,還…

春第十周作業

作業: 這個作業屬于那個課程C語言程序設計II這個作業要求在哪里https://edu.cnblogs.com/campus/zswxy/software-engineering-class2-2018/homework/3162我在這個課程的目標是閱讀并學習這個作業在那個具體方面幫助我實現目標知道了我們以后工作所需的是雇主所需的參…

在原生js中的事件監聽方法

一、傳統事件綁定方法我們在學習的時候,最初接觸的事件綁定方式大多是傳統事件綁定方法。傳統事件綁定方法事例如下: window.οnlοadfunction(){alert("頁面已加載"); } document.getElementById("btn").οnclickfunction(){alert(…

MySql修改數據庫編碼為UTF8

mysql 創建 數據庫時指定編碼很重要,很多開發者都使用了默認編碼,亂碼問題可是防不勝防。制定數據庫的編碼可以很大程度上避免倒入導出帶來的亂碼問題。 網頁數據一般采用UTF8編碼,而數據庫默認為latin 。我們可以通過修改數據庫默認編碼方式…

第六次作業(C語言)

心得體會 該題主要涉及知識點有:1、函數的定義;2、函數的調用(即prime函數的調用);3、素數的判斷;4、大小排序。 看到題時我首先想到了嵌套循環,可是仔細一看題目要求的是用prime函數的調用&…

Javascript系列——對象元素的數組去重實現

概要 這是一篇記錄文,記錄數組操作對象去重的實現。 需求 有這樣一個數組 [{_id: 123,name: 張三 },{_id: 124,name: 李四 },{_id: 123,name: 張三 }] 實際上我們只需要 [{_id: 123,name: 張三 },{_id: 124,name: 李四 }] 去重 簡單數組的去重 Array.from(new Set([…

關于__getattribute__

先看一個案例 class Tree(object):def __init__(self,name):self.namenameself.cateplantdef __getattribute__(self, item):if item大樹:print(log 大樹)return 我愛大樹else:return object.__getattribute__(self,item)aaTree(rrrr) print(aa.name) print(aa.cate) 運行結果…

通過Navicat for MySQL遠程連接的時候報錯mysql 1130的解決方法

來源:互聯網 作者:佚名 時間:10-16 18:41:20 【大 中 小】 錯誤代碼是1130,ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this MySQL server 是無法給遠程連接的用戶權限問題 Navicat for mysql 1130錯誤 用…

Java Language Changes for Java SE 9

Java9引入了module模塊的概念,是類與接口和數據資源的一種封裝,并可以聲明與其他模塊的依賴關系。這里總結一下Java9帶來的新特性。更簡練的try-with-resources語句final Resource resource1 new Resource("resource1");//a final resourceRe…

ProtocolHandler繼承體系

轉載于:https://www.cnblogs.com/GooPolaris/p/10815072.html

mysql數據庫存儲過程及調用方法

mysql數據庫存儲過程及調用方法 mysql5.0以后就支持存儲過程了,目前mysql的6.0Alpha版也已經推出。6.0不僅支持大型數據庫如oracle等的絕大部分功 能,如存儲過程、視圖、觸發器、job等等,而且修正了這些功能所存在的bug,其中6.0.1…

紅蜻蜓

日本人なら一度は耳にしたことのある曲でしょう。忘れかけている里山の風景が目に浮かびます。このあたりは昔養蠶が盛んで、何処へ行っても桑畑があったものでしたが、最近はとんと見かけません。小さい頃、よく桑の実をつんで食べたものでした。(このあたりでは&q…

elastic學習筆記

要點 不同工具之間版本匹配很重要由點及面,先實踐起來再學細節的原理和使用 技術棧 laravel5.5框架scout組件elasticsearch6.3.0搜索引擎輔助 elasticsearch-head 查看集群數據可視化 中文分詞插件Ik介紹 laravel是一款現代化的php框架es是搜索引擎es-head是管理查看…

mysql 存儲過程中limit

mysql 存儲過程中limit 1、mysql的高版本(5.5),存儲過程中的limit可以使用變量,如下:select * from student limit iStart,iNum; 2、mysql的低版本(5.1),存儲過程中的limit不能使用…

高頻ES6

var promise new Promise((resolve, reject)> {if (操作成功) {resolve (value)}else{reject(error)} }) promise.than(function (value) {/*成功*/}, function(value) {/*失敗*/}) Promise是異步編程的一種解決方案, 比傳統的解決方案--回調函數和事件更加強大.由社區最早…

NodeJS+Express+MongoDB - 張果 - 博客園

目錄 一、MongoDB 1.1、安裝MongoDB 1.1.1、配置運行環境1.1.2、運行MongoDB1.2、數據庫操作 1.2.1、創建數據庫與查看數據庫1.2.2、刪除數據庫1.2.3、插入數據1.2.4、查詢數據1.2.5、修改1.2.6、刪除二、NodeJS訪問MongoDB 2.1、安裝MongoDB訪問驅動2.2、添加數據2.3、修改數…

一個好用的瀏覽器暗色瀏覽插件 Dark Reader

轉載于:https://www.cnblogs.com/tyong/p/9973363.html