写在前面
最近在做移动端方面运用到了饿了么的vue
前端组件库,因为不想单纯用组件而使用它,故想深入了解一下实现原理。后续将会继续研究一下其他的组件实现原理,有兴趣的可以关注下。
代码在这里:戳我
1. 说明
父容器overflow:hidden;
,子页面transform:translateX(-100%);width:100%;
2. 核心解析
2.1 页面初始化
由于所有页面都在手机屏幕左侧一个屏幕宽度的位置,因此最开始的情况是页面中看不到任何一个子页面,所以第一步应该设置应该显示的子页面,默认情况下defaultIndex:0
function reInitPages() {
// 得出页面是否能够被滑动
// 1. 子页面只有一个
// 2. 用户手动设置不能滑动 noDragWhenSingle = true
noDrag = children.length === 1 && noDragWhenSingle;
var aPages = [];
var intDefaultIndex = Math.floor(defaultIndex);
var defaultIndex = (intDefaultIndex >= 0 && intDefaultIndex < children.length)
? intDefaultIndex : 0;
// 得到当前被激活的子页面索引
index = defaultIndex;
children.forEach(function(child, index) {
aPages.push(child);
// 所有页面移除激活class
child.classList.remove('is-active');
if (index === defaultIndex) {
// 给激活的子页面加上激活class
child.classList.add('is-active');
}
});
pages = aPages;
}
2.2 容器滑动开始(onTouchStart)
在低版本的android
手机上,设置event.preventDefault()
会起到一定的性能提升作用,使得滑动起来不是那么卡。
前置工作:
- 如果用户设置了
prevent:true
, 滑动时阻止默认行为 - 如果用户设置了
stopPropagation:true
, 滑动时阻止事件向上传播 - 如果动画尚未结束,阻止滑动
- 设置
dragging:true
,滑动开始 - 设置用户滚动为
false
滑动开始:
使用一个全局对象记录信息,这些信息包括:
dragState = {
startTime // 开始时间
startLeft // 开始的X坐标
startTop // 开始的Y坐标(相对于整个页面viewport pageY)
startTopAbsolute // 绝对Y坐标(相对于文档顶部 clientY)
pageWidth // 一个页面宽度
pageHeight // 一个页面的高度
prevPage // 上一个页面
d