写插件的初衷

1.项目经常需要无缝滚动效果,当时写jq的时候用用msClass这个老插件,相对不上很好用。

2.后来转向vue在vue-awesome没有找到好的无缝滚动插件,除了配置swiper可以实现但是相对来说太重了,于是自己造了个轮子。

3.在这分享下,当时写这个插件的坑,自己也复习下,如果代码上有瑕疵欢迎指出。

源码参考 vue-seamless-scroll

1.简单的实现上下滚动基本版(最初版)

html

1.solt提供默认插槽位来放置父组件传入的html

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

javascript

1.animationFrame 动画api兼容处理

2.arrayEqual 判断数组是否相等 来监听data的变化来实现更新无缝滚动


&lt;script&gt; require('comutils/animationFrame') //requestAnimationFrame api
const arrayEqual = require('comutils/arrayEqual')
export default {
data () {
return {
yPos: 0,
reqFrame: null
}
},
props: {
data: { // data 数据
type: Array,
default: []
},
classOption: { //参数
type: Object,
default: {}
}
},
computed: {
pos () {
// 给父元素的style
return {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 &lt; 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 () {
//滚动
this.reqFrame = requestAnimationFrame(
() =&gt; {
let h = this.$refs.wrapper.offsetHeight / 2
let direction = this.options.direction
if (direction === 1) {
if (Math.abs(this.yPos) &gt;= h) this.yPos = 0
} else {
if (this.yPos &gt;= 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(() =&gt; {
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()
}
}
}
}
&lt;/script&gt;

1.1 优化1: 新增配置openWatch 是否开启data监控实时刷新

有兴趣可以看本次commit记录 myClass.vue的更改

1.2 优化2: 新增配置singleHeight waitTime参数 控制是否单步滚动

commit记录

1.3 优化3:添加对移动端touch事件滚动列表支持

commit记录

1.4 优化4: 去掉了emit回调(简化初始化)


//原本组件调用
&lt;my-class :data="listData" :class-option="classOption" @copy-data="listData = listData.concat(listData)"&gt;
//简化后组件调用
&lt;my-class :data="listData" :class-option="classOption" class="warp"&gt;

用js的来复制一份innerHtml来代替之前的做法简化使用
//this.$emit('copyData') timer = setTimeout(() =&gt; { //20ms延迟 作用保证能取到最新的html
this.copyHtml = this.$refs.slotList.innerHTML
}, 20)
// template
&lt;template&gt;
&lt;div @mouseenter="enter" @mouseleave="leave" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"&gt;
&lt;div ref="wrap" :style="pos"&gt;
&lt;div ref="slotList" :style="float"&gt;
&lt;slot&gt;&lt;/slot&gt;
&lt;/div&gt;
&lt;div v-html="copyHtml" :style="float"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;

commit记录

1.5 bug1: 解决ie9下animationFrame报错的bug

这个问题的原因查了比较久最后发现是当时没有加return没有取到定时器id

![](https://img2018.cnblogs.com/blog/1504257/201811/1504257-20181113142133648-879443480.png)

1.6 优化5:添加左右无缝滚动

类似上下可以查看commit

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


import vueMyCLass from './components/myClass.vue' let myScroll const defaultComponentName = 'vue-seamless-scroll' // expose component to global scope
if (typeof window !== 'undefined' &amp;&amp; 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: () =&gt; {
return []
}
},
classOption: {
type: Object,
default: () =&gt; {
return {}
}
}
}

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

部分人喜欢用margin-top如果没有overflow等限制会导致我里面计算高度和实际有些许差距导致最后效果到临界位置有轻微抖动
//默认加上了overflow: 'hidden'


computed: {
float () {
return this.options.direction &gt; 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

vue无缝滚动的插件开发填坑分享的更多相关文章

  1. vue 无缝滚动文字

    前言 用vue做无缝滚动,字体弹幕 就上代码吧 <head> <meta charset="UTF-8"> <style> div, ul, l ...

  2. 基于vue的无缝滚动组件

    vue-seamless-scroll A simple, Seamless scrolling for Vue.js 在awesome上一直没有发现vue的无缝滚动组件,在工作之余写了个组件,分享出 ...

  3. vue+node.js+webpack开发微信公众号功能填坑——v -for循环

    页面整体框架实现,实现小功能,循环出数据,整体代码是上一篇 vue+node.js+webpack开发微信公众号功能填坑--组件按需引入 修改部门代码 app.vue <yd-flexbox&g ...

  4. 使用vue开发微信公众号下SPA站点的填坑之旅

    原文发表于本人博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅.作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^ ...

  5. Vue填坑(1)----通过vue-cli,认识vue-router

    开始 首先,确保之前已经安装过 npm 和 nodejs(为了避免版本的问题,最好使用较新的版本). 全局安装 vue-cli : npm install -g vue-cli 新建文件夹 my-pr ...

  6. jQuery 间歇式无缝滚动特效分享(三张图片平行滚动)

    最近项目中门户首页需要做出图片间歇式无缝滚动特效,但是在网上找资料都是不太理想,不过可以指导.最后自己写了一个demo实现了这个特效,分享出来. 1.jquery.cxscroll.js /*! * ...

  7. Vue的 $parent,并不能准确找到上一层的控件,所以如果需要,需要填坑这个 bug,递归寻找下上级

    Vue的 $parent,并不能准确找到上一层的控件,所以如果需要,需要填坑这个 bug,递归寻找下上级 // Find components upward function findComponen ...

  8. vue插件 vue-seamless-scroll 无缝滚动插件ES6使用总结

    最近因为需求需要写一个项目信息无缝向上滚动组件,在网上搜了一下,看到大家的一致好评就果断的使用了vue-seamless-scroll组件.下面就简单的介绍它的使用,具体详细的使用推荐大家去看下开发者 ...

  9. Vue 消息无缝滚动

    vue实现消息向上无缝滚动效果 <ul class="new-list" :class="{anim:animate}" @mouseenter=&quo ...

随机推荐

  1. [luogu P2590 ZJOI2008] 树的统计 (树链剖分)

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...

  2. EasyUI闪屏,EasyUI页面加载提示:原理+代码+效果图

    使用EasyUI时,有个经常遇到的问题,页面还没有渲染完成的时候,就展现了. 刚刚开始很混乱,等加载完成后,就好了. 参考这篇文章http://blog.csdn.net/zheng0518/arti ...

  3. jQuery(Dom节点操作)

  4. HDU3236 Gift Hunting

    /* HDU3236 Gift Hunting http://acm.hdu.edu.cn/showproblem.php?pid=3236 dp 滚动数组 * * */ #include <c ...

  5. 操作服务器及MySQL数据库可以使其远程链接

    转自原文操作服务器及MySQL数据库可以使其远程链接 一般情况分三个地方准备,MySQL数据库,防火墙,还有你的服务器主机的准备 操作系统为centos6.5.其他系统大致差不多. 1:在服务器中安装 ...

  6. poi判断一行是隐藏的getZeroHeight()

    poi判断一行是隐藏的 getZeroHeight() boolean isZeroHeight = row.getZeroHeight(); if(isZeroHeight){ // 如果为隐藏行就 ...

  7. C# 中使用 Obsolete 标志 代码过期

    今天对项目做了一次更新,创建了一个新的类来替换原来的工作. 可是又不想删掉.一旦删掉在SVN上就不存在了.决定还是用 Obsolete来标志代码过期吧. MSDN上关于Obsolete 标签的介绍 h ...

  8. html5的postmessage实现js前端跨域訪问及调用解决方式

    关于跨域訪问.使用JSONP的方法.我前面已经demo过了.详细见http://supercharles888.blog.51cto.com/609344/856886,HTML5提供了一个很强大的A ...

  9. windows、linux劫持技术

    windows系统以下能够利用detours劫持 realse  模式劫持,调试的程序不能够 函数劫持能够实现的效果. 函数的劫持原理 我们怎样实现-detours detours是微软亚洲研究院出品 ...

  10. win10 bcdedit加入vhdx启动

    第一步,先用hyper-v.imagex或者其他vhd安装器.将win10 系统安装到一个vhd文件里(vhdx更好.动态扩展等诸多优良特性).比方d:\win10tp.vhdx 第二步,运行例如以下 ...