一个vue3指令,兼容pc与移动端的拖动tab切换,鼠标拖动与触摸拖动触控监听
<View class="app-tabs-container" :class="{ appear: state.showTabsTrans }" v-tabs-pointer-event:[state.hasMove]="handleProductChange">
<router-view v-slot="{ Component }">
<KeepAlive>
<component :is="Component" :key="route.fullPath"></component>
</KeepAlive>
</router-view>
</View>
import vTabsPointerEvent from '@/directives/vTabsPointerEvent';
vTabsPointerEvent.ts
const vPointerEvent = {
mounted(el: HTMLElement, binding: any) {
const childNum = el.children.length;
el.style.width = 'max-content';
const childWidth = Math.floor(el.clientWidth / childNum);
const emitIndex = binding.value || (() => {});
/** 未限制最左右侧页面尽头的不可滑动,需添加页面位置标志监听 */
const discoverTabsType = localStorage.getItem('discoverTabsType') || 'appIndex';
let startX = 0;
/** 限制出现上下滑动时禁止切面切换事件 */
let startY = 0;
let hasMove = false;
el.addEventListener('pointerdown', event => {
event.preventDefault();
startX = event.pageX;
startY = event.pageY;
el.style.transition = '';
});
el.addEventListener('pointermove', event => {
if (event.pointerType === 'mouse' && event.buttons === 0) return event.stopPropagation(); // 鼠标滑过忽略
const nowOffsetX = event.pageX - startX;
/** 限制最左右侧页面尽头的不可滑动 */
if ((discoverTabsType === 'appIndex' && nowOffsetX > 0) || (discoverTabsType === 'appSort' && nowOffsetX < 0)) {
hasMove = false;
event.stopPropagation();
return;
}
const nowOffsetY = event.pageY - startY;
if (Math.abs(nowOffsetX) > 10) hasMove = true;
if (Math.abs(nowOffsetY) > 20) hasMove = false;
});
el.addEventListener('pointerup', event => {
emitIndex(hasMove);
if (!hasMove) return event.stopPropagation();
hasMove = false;
});
/** 兼容鼠标拖动的滚动事件 */
el.addEventListener('mouseleave', event => {
if (event.pointerType === 'mouse' && event.buttons === 0) return; // 鼠标滑过忽略
if (!hasMove) return event.stopPropagation();
emitIndex(hasMove);
hasMove = false;
});
el.addEventListener('touchmove', event => {
/** 页面可上下滑动 */
if (hasMove) event.preventDefault();
});
el.addEventListener('click', event => {
/** 监听会在 @click 事件触发后才触发,无法拦截 @click 事件 */
event.preventDefault();
/** 滑动有偏移的话就阻止点击事件的捕获 */
if (Math.abs(startX - event.clientX) > 5) event.stopPropagation();
});
}
};
export default vPointerEvent;