介绍
用于提供下拉刷新的交互操作。
分析
UML组件类图建模
注意:忽略了部分的属性和方法
布局
组件布局源代码:
render() { return ( <div class="pull-refresh"> <div ref="track" class="pull-refresh__track"> <div class="pull-refresh__head"> {this.genStatus()} </div> {this.slots()} </div> </div> ); },
提示区域
.van-pull-refresh { &__head { // 下面只摘抄关键的 position: absolute; left: 0; width: 100%; transform: translateY(-100%); } }
逻辑实现
1.添加手势处理 TouchMixin
为滚动容器绑定手势事件,并计算相关的手势方向和滑动距离
export const TouchMixin = { data() { return { direction: '' }; }, methods: { touchStart(event) { this.resetTouchStatus(); this.startX = event.touches[0].clientX; this.startY = event.touches[0].clientY; }, touchMove(event) { const touch = event.touches[0]; this.deltaX = touch.clientX - this.startX; this.deltaY = touch.clientY - this.startY; this.offsetX = Math.abs(this.deltaX); this.offsetY = Math.abs(this.deltaY); this.direction = this.direction || getDirection(this.offsetX, this.offsetY); }, resetTouchStatus() { this.direction = ''; this.deltaX = 0; this.deltaY = 0; this.offsetX = 0; this.offsetY = 0; }, // avoid Vue 2.6 event bubble issues by manually binding events // https://github.com/youzan/vant/issues/3015 bindTouchEvent(el) { const { onTouchStart, onTouchMove, onTouchEnd } = this; on(el, 'touchstart', onTouchStart); on(el, 'touchmove', onTouchMove); if (onTouchEnd) { on(el, 'touchend', onTouchEnd); on(el, 'touchcancel', onTouchEnd); } }, }, };
2.组件内实现手势的事件处理逻辑
/* * 只有核心逻辑 */ methods: { onTouchStart (event) { }, // 1. 调用touchMixin的手势计算 // 2. 阻止事件默认行为和冒泡 // 3. 对滑动的距离进行优化处理 // 4. 根据距离,设置组件的状态 onTouchMove (event) { this.touchMove(event); if (this.ceiling && this.deltaY >= 0 && this.direction === 'vertical') { preventDefault(event); this.setStatus(this.ease(this.deltaY)); } }, onTouchEnd (event) { this.$emit('refresh'); } }