在Vue中实现 兼容PC端下拉操作和移动端下拉操作 的思路
1. html
<template> <div class="ebook-reader"> <div id="read"></div> <div class="ebook-reader-mask" @click="onMaskClick" @touchmove="move" @touchend="moveEnd" @mousedown.left="onMouseEnter" @mousemove.left="onMouseMove" @mouseup.left="onMouseEnd" ></div> <!-- 兼容PC端下拉操作和移动端下拉操作写法: .left事件修饰符表示按下鼠标左键 --> </div> </template>
2. js
export default { mixins: [ebookMixin], /* 使用vue里的mixin机制优化重复代码,方便统一维护 computed: { ...mapGetters([ 'fileName', 'menuVisible' ]) }, */ methods: { /** this.mouseState: * 1 - 鼠标进入 * 2 - 鼠标进入后的移动 * 3 - 鼠标从移动状态松手 * 4 - 鼠标还原 (4表示的是点击事件) */ // 鼠标进入 onMouseEnter(e) { this.mouseState = 1 this.mouseStartTime = e.timeStamp e.preventDefault() e.stopPropagation() }, // 鼠标移动 onMouseMove(e) { if (this.mouseState === 1) { this.mouseState = 2 } else if (this.mouseState === 2) { let offsetY = 0 /** 如果第一次的Y轴偏移量存在,则根据当前的Y轴偏移量计算出下拉的距离,存入vuex中 */ if (this.firstOffsetY) { offsetY = e.clientY - this.firstOffsetY this.setOffsetY(offsetY) } else { /** 如果第一次的Y轴偏移量不存在,则设置第一次的Y轴偏移量 */ this.firstOffsetY = e.clientY // 在鼠标事件中,直接通过e.clientY获取鼠标Y轴的位置 } } e.preventDefault() e.stopPropagation() }, // 鼠标事件结束 onMouseEnd(e) { if (this.mouseState === 2) { /** 当onMouseEnd的时候,如果mouseState为2,说明经历过了onMouseMove事件 */ this.setOffsetY(0) this.firstOffsetY = null this.mouseState = 3 } else { /** 当onMouseEnd的时候,如果mouseState不为2,说明没有经历过了onMouseMove事件,则判定为点击事件 */ this.mouseState = 4 } /** 当从onMouseEnter到onMouseEnd两次的事件小于200ms的时候,也认为是点击事件 */ const time = e.timeStamp - this.mouseStartTime if (time < 200) { this.mouseState = 4 } e.preventDefault() e.stopPropagation() }, // 触摸下拉事件 move(e) { let offsetY = 0 /** 如果第一次的Y轴偏移量存在,则根据当前的Y轴偏移量计算出下拉的距离,存入vuex中 */ if (this.firstOffsetY) { offsetY = e.changedTouches[0].clientY - this.firstOffsetY this.setOffsetY(offsetY) } else { /** 如果第一次的Y轴偏移量不存在,则设置第一次的Y轴偏移量 */ this.firstOffsetY = e.changedTouches[0].clientY // 在移动端touchmove事件中,需要通过e.changedTouches[0].clientY获取触摸的位置 } /** * 增加 e.preventDefault() 解决在做移动端下拉操作的时候,真机测试时会把整个网页都进行下拉,(微信端)可能会出现的 "此网页由xxx提供"的现象 */ e.preventDefault() /** * 下拉操作中也要添加e.stopPropagation()来阻止事件冒泡广播 */ e.stopPropagation() }, // 触摸下拉事件结束后重置第一次Y轴偏移量和重置vuex里的offsetY moveEnd(e) { this.setOffsetY(0) this.firstOffsetY = null }, // mask蒙层点击事件,当点击左边区域切换到上一页,点击右边区域切换到下一页,点击中间部分切换导航和菜单 onMaskClick(e) { /** * 在触发PC端鼠标下拉操作中,由于鼠标抬起一定会触发onMaskClick事件,因此通过mouseState状态来控制是否往下执行 * this.mouseState === 2 || this.mouseState === 3 表示此时是鼠标下拉操作,不是点击事件 * */ if (this.mouseState && (this.mouseState === 2 || this.mouseState === 3)) { return } const offsetX = e.offsetX const width = window.innerWidth if(offsetX > 0 && offsetX < width * 0.3) { this.prevPage() } else if (offsetX > 0 && offsetX > width * 0.7) { this.nextPage() } else { this.toggleTitleAndMenu() } }, }优质内容筛选与推荐>>