基于vue.js 2.x的虚拟滚动条的示例代码
前言记得以前偶然有一次浏览过一个开源的cms项目,发现这个项目的左边的菜单已经超出了windows的宽度,我就好奇为什么没出滚动条呢?然后我仔细一看,发现它左侧有一个小的div,然后我尝试着拖动它,发现竟能和原生的滚动条一样!可以通过查看它的源码,发现了这款滚动条的叫做slimScroll,然后我去它的github仓库 看了下,研究了一下源码,给我的感觉是我也能做出来一样的滚动条!通过vue实现! 设计好, 现在开始我们的设计滚动条的步骤: 设计滚动条dom首先要思考的是: 如果要使你需要滚动的内容滚动的话,首先一点是它的父dom必须为固定长宽,即超出部分要隐藏掉,即加了个样式: overflow: hidden,所以,我们给所要滚动的内容加个包装,使它的长宽和父dom相等,然后有一个样式叫: overflow: hidden,这个包装的元素就叫 scrollPanel 其次:我们知道,我们要做到与原生滚动条一样强大!就必须设计水平滚动条和垂直滚动条,滚动条和scrollPanel属于兄弟节点之间的关系,因为滚动条的存在不能使原本的样式排版错误,并且支持top、left来控制其位置,所以滚动条的position必须是absolute,好了,我们叫水平滚动条为:hBar,垂直滚动条为:vBar 最后:我们设计了scrollPanel、vBar、hBar,我们需要一个父div来把他们包装起来,然后加个样式:position: relative 实践设计组件结构首先,我们的插件一共是4个组件,其中3个是子组件,1个是父组件,分别是: vueScroll (父组件)、 scrollPanel (包裹需要滚动内容的子组件)、 vBar (垂直滚动条)、 hBar (水平滚动条) 其次,让我们设计一下各组件所分管的功能。这里的组件分为控制层组件和展示组件(熟悉react的同学应该有所了解),展示层组件只完成展示的功能: vBar 、 hBar 、 scrollPanel,控制层组件有点类似于cpu,可以控制子组件的各个状态,比如宽、高、颜色、透明度、位置等等。控制层组件就是: vueScroll 。 具体实现hBar/vBarhBar/vBar 这两个分别为水平滚动条和垂直滚动条,所实现的功能大体是一样的,所以旧放在一起说了,这里以 vBar 为例。 props 接收父组件传过来的属性,具体为: 2 事件,主要是当鼠标移动的时候,显示滚动条。 其中 state 表示状态,是在运行时可发生改变的,而 ops 则是配置参数,是用户传过来的。 scrollPanel包裹滚动内容的组件,样式需设置为: overflow: hidden 。 1、样式 2、事件 vuescroll控制组件。控制子组件显示的状态,添加各种监听事件等。 1、取得子组件的dom元素,用来取得dom的实时信息。 2、显示滚动条 显示滚动条,包括显示水平滚动条和显示垂直滚动条,这里以显示垂直滚动条为例: 3、获取滚动条的高度 因为dom元素的高度不是固定的,所以你要实时地获取dom真实的高度,滚动条的高度计算公式如下: 即: 滚动条的高度:scrollPanel的高度 == scrollPanel的高度:dom元素高度 4、resizeVBarTop,为了防止误差,并且可以求出滚动条距离父元素的高度。 5、监听滚轮滚动的事件。 0 ? 1 : -1,1);
e.stopPropagation();
}
// ...
6、监听滚动条拖拽事件 0 ? 1 : -1,Math.abs(_delta / vm.vScrollBar.innerDeltaY));
y = _y;
}
function t(e) {
var deltaY = {
deltaY: vm.vScrollBar.ops.deltaY
};
if(!vm.getVBarHeight(deltaY)) {
return;
}
vm.mousedown = true;
y = e.pageY; // 记录初始的Y的位置
vm.showVBar();
document.addEventListener('mousemove',move);
document.addEventListener('mouseup',function(e) {
vm.mousedown = false;
vm.hideVBar();
document.removeEventListener('mousemove',move);
});
}
this.listeners.push({
dom: vm.vScrollBar.el,event: t,type: "mousedown"
});
vm.vScrollBar.el.addEventListener('mousedown',t); // 把事件放到数组里面,等销毁之前移除掉注册的时间。
}
7、适配移动端,监听 touch 事件。原理跟拖拽事件差不多,无非就是多了个判断,来判断当前方向是x还是y。 Math.abs(_deltaY)) {
_delta = _deltaX;
vm.scrollHBar(_delta > 0 ? -1 : 1,Math.abs(_delta / vm.hScrollBar.innerDeltaX));
} else if(Math.abs(_deltaX) < Math.abs(_deltaY)){
_delta = _deltaY;
vm.scrollVBar(_delta > 0 ? -1 : 1,Math.abs(_delta / vm.vScrollBar.innerDeltaY));
}
x = _x;
y = _y;
}
}
function t(e) {
var deltaY = {
deltaY: vm.vScrollBar.ops.deltaY
};
var deltaX = {
deltaX: vm.hScrollBar.ops.deltaX
};
if(!vm.getHBarWidth(deltaX) && !vm.getVBarHeight(deltaY)) {
return;
}
if(e.touches.length) {
e.stopPropagation();
var touch = e.touches[0];
vm.mousedown = true;
x = touch.pageX;
y = touch.pageY;
vm.showBar();
pannel.addEventListener('touchmove',move);
pannel.addEventListener('touchend',function(e) {
vm.mousedown = false;
vm.hideBar();
pannel.removeEventListener('touchmove',move);
});
}
}
pannel.addEventListener('touchstart',t);
this.listeners.push({
dom: pannel,type: "touchstart"
});
}
8、滚动内容 滚动内容的原理无非就是改变 scrollPanel 的 scrollTop/scrollLeft 来达到控制内容上下左右移动的目的。 0 scroll to down <0 scroll to up
}, 9、销毁注册的事件。 刚才我们已经把注册事件放到listeners数组里面了,我们可以在beforedestroy钩子里将他们进行销毁。 运行截图 PC端运行截图如下图所示: 注册监听事件以后如下图所示: 在手机上运行截图: 可以看出,跟原生滚动条表现效果一致。 结语&感悟以上就基本把我设计的滚动条设计完了,首先很感激掘金给了我这么一个分享平台,然后感谢slimScroll的作者给了我这么一个思路。做完这个插件, 我对dom元素的scrollWidth、scrollHeigh、scrollTop、scrollLeft的了解更多了,最后,附上github项目地址 以上部分就是这个组件的核心源码了。希望对大家的学习有所帮助,也希望大家多多支持编程之家。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |