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.mzph.cn/news/249025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP常用的自定义函数

PHP常用的自定义函数 目录 php常用自定义函数类下载php 设置字符编码为utf-8路径格式化(替换双斜线为单斜线)转码打印输出api返回信息字符串截取 方法一:方法二:数组 字符串 对象 json格式的字符串互转强制类型转换php序列化serialize与返回序列化unserialeze创建日志文件获取i…

春第十周作业

作业: 这个作业属于那个课程C语言程序设计II这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/software-engineering-class2-2018/homework/3162我在这个课程的目标是阅读并学习这个作业在那个具体方面帮助我实现目标知道了我们以后工作所需的是雇主所需的参…

第六次作业(C语言)

心得体会 该题主要涉及知识点有:1、函数的定义;2、函数的调用(即prime函数的调用);3、素数的判断;4、大小排序。 看到题时我首先想到了嵌套循环,可是仔细一看题目要求的是用prime函数的调用&…

ProtocolHandler继承体系

转载于:https://www.cnblogs.com/GooPolaris/p/10815072.html

高频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

实验 4 [bx]和 loop 的使用

实验结论 实验1:综合使用 loop,[bx],编写完整汇编程序,实现向内存 b800:07b8 开始的连续 16 个字单元重复填充字数据 0403H。 1.源代码及实验结果 运行结果:屏幕中央出现一排红色的心❤。 2.将源代码程序中字数据 0403H→修改为 0…

linux开发工具之gcc

首先gcc编译链接的一个实例如下所示: 接下来看一下gcc的常见选项: gcc的使用示例: 转载于:https://www.cnblogs.com/wsw-seu/p/10826124.html

音频基本概念

音频基本概念 声音的本质 音调:频率 音量:振幅 音色:与材质有关,谐波(不规则的正玄波) 屏幕快照 2018-12-04 下午1.53.40.png采样-量化-编码 采样大小: 一个采样用多少bit存放,目前常…

How to use external classes and PHP files in Laravel Controller?

By: Povilas KoropLaravel is an MVC framework with its own folder structure, but sometimes we want to use something external which doesn’t follow the same structure. Let’s review two different scenarios – when we have external class and when it’s just a…

Vue 从入门到进阶之路(十四)

之前的文章我们对 vue 的基础用法已经有了很直观的认识&#xff0c;本章我们来看一下 vue 中的生命周期函数。 上图为 Vue官方为我们提供的完整的生命周期函数的流程图&#xff0c;下面的案例我们只是走了部分情况流程&#xff0c;但所有的生命周期函数都涉及到了。 1 <!DOC…

css 清除浮动float 嗒嘀嗒滴 ----20181120

手动给父元素添加高度通过clear清除内部和外部浮动给父元素添加overfloat属性并结合zoom:1使用给父元素添加浮动        常用方法&#xff1a; ①给兄弟元素添加clear属性&#xff1a;添加一个class为clear&#xff1a;both&#xff0c; ②添加伪类&#xff1a;.clearf…

微软最爽命令行工具发布!

最近微软发布了命令行工具Windows Terminal&#xff0c;简直要让我们爽翻天 长期以来&#xff0c;Linux和Mac下的命令行工具自成一派&#xff0c;Windows却是另一套命令系统。这就比较恶心了&#xff0c;这也是很多开发者不选择Windows系统的原因。 但是现在完全不一样了&#…

vue项目中 axios请求拦截器与取消pending请求功能 - 年少、 - 博客园

在开发vue项目中&#xff0c;请求是不可缺少的&#xff0c;在发送请求时常常需要统一处理一些请求头参数等设置与响应事件&#xff0c;这时利用请求拦截器再好不过。 这里以axios请求为例 实现了设置统一请求头添加token, 其中token在登录时被存入了localStorage中。 同时拦…

gitbook 入门教程之解决windows热加载失败问题

破镜如何贴花黄 gitbook 在 Windows 系统无法热加载,总是报错! gitbook 是一款文档编写利器,可以方便地 markdown 输出成美观优雅的 html ,gitbook serve 启动服务器后,原来相貌平平的 markdown 丑小鸭摇身一变就成了倾国倾城的 html 绝色佳人. 如果源文件发生更改,Windows 却无…

NodeJS入门04-Express路由和中间件 - 小之 - 博客园

nodeJS入门04-Express路由和中间件 Express框架是后台的Node框架&#xff0c;在后台的受欢迎的程度&#xff0c;和jQuery一样&#xff0c;就是企业的事实上的标准。 路由 路由是指如何定义应用的端点&#xff08;URIs&#xff09;以及如何响应客户端的请求。 路由是由一个 …

jmeter(四十五)常用Beanshell脚本

整理了一批jmeter常用的beanshell脚本供大家参考&#xff01; 时间戳 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; try{ Date date new Date(); //获取当前时间 SimpleDateFormat sf new SimpleDateFormat("yyyy-MM-dd HH:mm…

nodejs开发 过程中express路由与中间件的理解 - pyj063 - 博客园

nodejs开发 过程中express路由与中间件的理解 nodejs开发 express路由与中间件 路由 通常HTTP URL的格式是这样的&#xff1a; http://host[:port][path] http表示协议。 host表示主机。 port为端口&#xff0c;可选字段&#xff0c;不提供时默认为80。 path指定请求资源的…

(五)Unity插件生成

1&#xff09;新建空的AndroidStudio工程&#xff0c;但是新建过程时最小SDK版本要与unity一致&#xff0c;如下图所示&#xff0c;本次操作均为api16 2&#xff09;创建Library&#xff0c;如下图所示&#xff0c;新建module&#xff0c;然后选择Android Library。 新建模块为…