The original intention of writing plug-ins

1. Seamless rolling effect is often required for projects. MsClass was used as an old plug-in when WRITING JQ, which is relatively easy to use.

2. I turned to Vue. I didn’t find a good seamless scrolling plugin in Vue-Awesome, except for swiper, which was too heavy, so I built my own wheel.

3. In this share, when writing this plug-in pit, also review, if there are flaws in the code welcome to point out.

Source referencevue-seamless-scroll

1. Simple implementation of scrolling up and down base version (original version)

html

1. Solt provides a default slot to place HTML passed in by the parent component

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

javascript

1. AnimationFrame API compatibility processing

2. ArrayEqual checks whether the array is equal to listen for changes in data to achieve seamless scrolling of updates

<script> require('comutils/animationFrame') //requestAnimationFrame api const arrayEqual = require('comutils/arrayEqual') export default { data () { return { yPos: 0, reqFrame: null } }, props: { data: {// data Data Type: Array, default: []}, classOption: {// Parameters type: Object, default: {}}}, computed: Transform: 'translate(0,${this.ypos}px)'}}, defaultOption () {return {step: 1, // limitMoveNum: 5, // start seamless scrolling hoverStop: true, // start hover control direction: 1 //1 up 0 down}}, options () {return object.assign ({}, this.defaultoption, this.classoption)}, MoveSwitch () {/ / judgment to the initial value and the length of the data to the rolling to control whether scroll to return this. Data. The length < this. Options. LimitMoveNum}}, the methods: { enter () { if (! this.options.hoverStop || this.moveSwitch) return cancelAnimationFrame(this.reqFrame) }, leave () { if (! this.options.hoverStop || this.moveSwitch) return this._move() }, _move () {/ / scroll enclosing 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') If (this.options. Direction! == 1) { setTimeout(() => { this.yPos = this.$refs.wrapper.offsetHeight / 2 * -1 }, 20) } this._move() } } }, Mounted () {this._initMove()}, watch: {// Select * from db. // Select * from db. arrayEqual(newData, oldData.concat(oldData))) { cancelAnimationFrame(this.reqFrame) this._initMove() } } } } </script>Copy the code

1.1 Optimization 1: Added whether to enable real-time data monitoring refresh on The openWatch

Note the changes to myclass.vue during this commit

1.2 Optimization 2: Added singleHeight waitTime parameter to control whether to scroll in one step

The commit record

1.3 Optimization 3: Added support for mobile touch event scroll lists

The commit record

1.4 Optimization 4: Removed emit callbacks (simplified initialization)

<my-class :data="listData" :class-option="classOption" @copy-data="listData = listData.concat(listData)"<my-class :data= <my-class :data="listData" :class-option="classOption" class="warp">
Copy the code
$emit('copyData') timer = setTimeout(() => {//20ms delay ensures that the innerHtml is retrieved  = 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>Copy the code

The commit record

1.5 bug1: Resolve the animationFrame error bug in Internet Explorer 9

The cause of this problem was investigated for a long time. Finally, it was found that the return was not added and the timer ID was not obtained

1.6 Optimization 5: Add left and right seamless scrolling

You can view commit as follows

1.7 Vue.use() provides install global registration

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
Copy the code

1.8 Bug Solved the single step scrolling failure bug caused by frequent fast operation of touchMove and some code optimization

//1. Encapsulate the unanimate method for multiple calls

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

//2. Frequent fast operation of touchMove causes scrolling disorder bug

 _move() {this._cancle() {this._cancle()}Copy the code

//3. Unanimate before the end of the life cycle

 beforeDestroy () {
      this._cancle()
}
Copy the code

//4. Fix the bug of not sending parameter warnings

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

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

Margin-top: ‘hidden’; margin-top: ‘hidden’;

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

//6. New hover stop function

Previously, this._move() had a built-in delay because of the single step. By default, the single step limited the hover to stop the seamless scrolling. Later, this._move() was implemented with a switch.

commit

TKS

If you’re interested in implementing a similar seamless scroll with native JS, leave a comment, and I can also write seamless Scroll at some point

Vue-seamless – Scroll if you find a bug or something that’s not working, just star it.