基于 vue2 的响应式基础组件(滚动条),移动端和桌面端都支持
本文章是个人开源项目 vue2do,文档地址是: https://zen0822.github.io/#/component/scroller
scroller.js
/**
* scroller 组件 滚动条
*
* @prop height - 滚动区域的高度(auto | { Number }px | 100% }),
* auto:根据滚动内容的高度
* { Number }:自定义像素高度
* 100%:根据父元素的高度
* @prop width - 滚动区域的宽度(auto | {Number}px | 100%),同上
* @prop autoHide - 自动隐藏滚动条
*
* @event scrollY - 滚动事件
* return isBottom - 滚动条是否到低
* isTop - 滚动条是否到顶
* top - 滚动条到滚动区域的顶部的当前距离
* offset - 滚动条离滚动区域的顶部的距离
* @event scrollX - 滚动事件
* return isRight - 滚动条是否到结束的地方
* isLeft - 滚动条是否到开始的地方
* left - 滚动条到滚动区域的最左边的当前距离
* offset - 滚动条离滚动区域的顶部的距离
* @event yBarChange - y-bar 滚动条改变
* return isBottom - 滚动条是否到低
* isTop - 滚动条是否到顶
* top - 滚动条到滚动区域的顶部的当前距离
* offset - 滚动条离滚动区域的顶部的距离
* @event xBarChange - x-bar 滚动条改变
* return isRight - 滚动条是否到结束的地方
* isLeft - 滚动条是否到开始的地方
* left - 滚动条到滚动区域的最左边的当前距离
* offset - 滚动条离滚动区域的顶部的距离
* @event scrollerChange - 滚动区域的高度/宽度变化
*/
import './Scroller.scss'
import baseMixin from '../../mixin/base'
import apiMixin from './Scroller.api'
import render from './Scroller.render.js'
import {
offset as propOffset
} from '../../util/dom/prop'
import MotionFade from '../MotionFade/MotionFade'
// 滚动一次的滚动区域走的像素大小
const SCROLL_PIXEL = 10
export default {
name: 'Scroller',
mixins: [baseMixin, apiMixin],
render,
components: {
'motion-fade': MotionFade
},
props: {
height: {
type: [Number, String],
default: 'auto',
validator(val) {
if (typeof val === 'number') {
return true
} else if (val === 'auto' || val === '100%') {
return true
} else {
return false
}
}
},
width: {
type: [Number, String],
default: 'auto',
validator(val) {
if (typeof val === 'number') {
return true
} else if (val === 'auto' || val === '100%') {
return true
} else {
return false
}
}
},
autoHide: {
type: Boolean,
default: false
}
},
data() {
this.compName = 'scroller' // 组件名字
this.interValInitScroller = '' // 初始化滚动条定时器
return {
yData: { // y-scroller detail
barAndScrollerOffset: 0, // 滚动条和滚动区域的偏移值
barLength: 0, // 滚动条的高度
barTop: 0, // bar 的高度
boxBarRate: 0, // 滚动内容 / 滚动条区域
boxAndScrollerOffset: 0, // 滚动内容和滚动区域的偏移值
isMousedown: false, // 滚动条的 mousedown 事件
oldBarTop: 0, // 记录上一次滚动条的高度
scrollBarPixel: 0, // 滚动一次的滚动条走的像素大小
scrollerContainBox: false // 滚动条的高度是否大于滚动区域
},
xData: { // x-scroller detail
barLength: 0,
barLeft: 0,
barAndScrollerOffset: 0,
boxBarRate: 0,
boxAndScrollerOffset: 0,
isMousedown: false,
oldBarLeft: 0,
scrollBarPixel: 0,
scrollerContainBox: false
},
boxTop: 0, // box 离最顶端的偏移值
boxLeft: 0, // box 离最开始的偏移值
boxHeight: 0, // 滚动内容的高度
boxWidth: 0, // 滚动内容的宽度
boxStyleHeight: 0, // 滚动内容的样式高度
boxStyleWidth: 0, // 滚动内容的样式宽度
scrollerHeight: 0, // 滚动区域的高度
scrollerWidth: 0, // 滚动区域的宽度
parentHeight: 0, // 滚动区域的父元素的高度
parentWidth: 0, // 滚动区域的父元素的宽度
showBar: false, // 滚动条自动隐藏的状态
isTouchStart: false, // 滚动区域的 touchend 事件
scrolling: false, // 记录连续滚动的标注
moving: false, // 记录是否还在触摸移动中
hasScrollerGrandpa: false, // 是否有 scroller 组件的祖先
touchStart: { // 记录开始触摸滚动区域的坐标
x: 0,
y: 0
},
pointStart: { // 记录开始点击滚动条的坐标
x: 0,
y: 0
}
}
},
computed: {
boxStyle() {
return {
top: this.boxTop + 'px',
left: this.boxLeft + 'px'
}
},
scrollerStyle() {
return {
height: this.scrollerHeight + 'px',
width: this.scrollerWidth + 'px'
}
},
xComputed() { // x 方向的计算属性
return {
barDisplay: !this.xData.scrollerContainBox && (!this.autoHide || this.showBar),
isLeft: this.xData.barLeft === 0,
isRight: this.xData.barLeft === this.xData.barAndScrollerOffset,
barStyle: {
'width': this.xData.barLength + 'px',
'left': this.xData.barLeft + 'px'
}
}
},
yComputed() { // y 方向的计算属性
return