We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
实现效果:为了防止滑动穿透,需要在弹框的touchmove事件中添加e.preventDefault()阻止默认的行为,但是如果弹窗的内容太长需要滚动,在需要滚动的内容的父级元素上添加 v-scroll即可
基本思路:利用Vue.directive()中的bind钩子,在钩子中对需要滚动的元素绑定touchstart,touchmove和touchend事件,之后利用e.touches判断滚动方向及距离
需要html元素结构满足要求:
1.绑定v-scroll的元素要给高度。 因为为了让内部滚动。。外层元素一定要有高度
2.绑定v-scroll的内部必须是类名为vscroller的节点 在v-scroll的代码中通过这个类来定位需要滚动的元素
<div v-scroll> <div class="vscroller"> 内容 内容 内容 </div> </div>
v-scroll的实现代码
import Vue from 'vue' Vue.directive('scroll', { bind: function(el, binding) { let needScroll = false, scroller = null, oldY = null, totalDetaY = 0, containerH, scrollerH, pageY, detaY, oldTime = null // 获取需要绑定元素及需要滚动的元素 el.style['overflow'] = 'hidden' // 为了避免内容溢出 scroller = el.querySelector('.vscroller') || null // 为滚动内容添加touch事件的监听器 if (scroller) { scroller.addEventListener('touchstart', function(e) { needScroll = isNeedScroll() }) scroller.addEventListener('touchmove', function(e) { e.preventDefault(); if(needScroll) { computePosition(e) handleScroll() } }) scroller.addEventListener('touchend', function(e) { oldY = null }) } // 内部函数 function isNeedScroll() { containerH = el.getBoundingClientRect().height scrollerH = scroller.getBoundingClientRect().height if (containerH >= scrollerH) return false return true } function computePosition(e) { pageY = e.touches[0].pageY detaY = 0 // 计算移动距离, 更新旧的位置坐标 if (!oldY) oldY = pageY detaY = pageY - oldY oldY = pageY } function handleScroll() { totalDetaY += detaY // 判断是否是滑动边界 if (totalDetaY > 0) totalDetaY = 0 if (containerH - totalDetaY > scrollerH) totalDetaY = containerH - scrollerH translate(scroller, 0, totalDetaY) } function translate(target, x, y) { target.style['transform'] = `translate(${x}px, ${y}px)` } } })
实现细节:
1.如果在bind中直接调用 elemetn.getBoundingClientRect() 方法可能会获取不到位置信息,因为bind钩子执行时元素还没被渲染到页面中。所以选择在touch事件的监听器中调用
isNeedScroll() 方法主要用于判断是否需要滚动,如果内容高度不足够的话,那么不需要滚动。同时,这个方法在touchstart中调用,而不在touchmove中,每次滑动只调用一次,有利于提高性能。
通过css translate方法进行位置的更改,性能更好 (相关知识点:合成层?---需要学习一波)
将逻辑拆分成不同方法,以便后续功能扩展(目前只能竖着滑,应该可以通过v-scroll="'h'|'v'"判断滑动方向)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
实现效果:为了防止滑动穿透,需要在弹框的touchmove事件中添加e.preventDefault()阻止默认的行为,但是如果弹窗的内容太长需要滚动,在需要滚动的内容的父级元素上添加 v-scroll即可
基本思路:利用Vue.directive()中的bind钩子,在钩子中对需要滚动的元素绑定touchstart,touchmove和touchend事件,之后利用e.touches判断滚动方向及距离
需要html元素结构满足要求:
1.绑定v-scroll的元素要给高度。 因为为了让内部滚动。。外层元素一定要有高度
2.绑定v-scroll的内部必须是类名为vscroller的节点 在v-scroll的代码中通过这个类来定位需要滚动的元素
v-scroll的实现代码
实现细节:
1.如果在bind中直接调用 elemetn.getBoundingClientRect() 方法可能会获取不到位置信息,因为bind钩子执行时元素还没被渲染到页面中。所以选择在touch事件的监听器中调用
isNeedScroll() 方法主要用于判断是否需要滚动,如果内容高度不足够的话,那么不需要滚动。同时,这个方法在touchstart中调用,而不在touchmove中,每次滑动只调用一次,有利于提高性能。
通过css translate方法进行位置的更改,性能更好 (相关知识点:合成层?---需要学习一波)
将逻辑拆分成不同方法,以便后续功能扩展(目前只能竖着滑,应该可以通过v-scroll="'h'|'v'"判断滑动方向)
The text was updated successfully, but these errors were encountered: