export default { install(Vue, options = { time: 1000 }) { Vue.directive('longpress', { bind: function (el, binding, vNode) { // 確保提供的表達式是函數 if (typeof binding.value !== 'function') { // 獲取組件名稱 const compName = vNode.context.name; // 將警告傳遞給控制檯 let warn = `[longpress:] provided expression '${binding.expression}' is not afunction, but has to be `; if (compName) { warn += `Found in component '${compName}' `; } console.warn(warn); } var startX, startY, startTime; // 定義變量 let pressTimer = null; // 定義函數處理程序 // 建立計時器( 1秒後執行函數 ) let start = (e) => { if (e.type === 'click' && e.button !== 0) { return; } e.preventDefault(); // 記錄下觸發的座標和時間 startTime = (new Date()).getTime(); startX = e.targetTouches[0].clientX; startY = e.targetTouches[0].clientY; /** * 注意:此到處理長按震動效果,經測試IOS目前不支持震動 **/ if (pressTimer === null) { pressTimer = setTimeout(() => { navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; if (navigator.vibrate) { // 支持 navigator.vibrate(200); } // 執行函數 handler(); }, options.time); } }; // 取消計時器 let cancel = (e) => { /** * 注意:此到處理與click事件的衝突(小於300ms能夠識別爲點擊事件的範圍 而後判斷觸摸點的移動距離) **/ e.preventDefault(); var now = (new Date()).getTime(); if (now - startTime < 300) { var x = (Math.abs(startX - e.changedTouches[0].clientX) < 30); var y = (Math.abs(startY - e.changedTouches[0].clientY) < 30); if (x && y) { e.changedTouches[0].target.click(); } } // 檢查計時器是否有值 if (pressTimer !== null) { clearTimeout(pressTimer); pressTimer = null; } }; // 運行函數 const handler = (e) => { // 執行傳遞給指令的方法 binding.value(e); }; /** * 注意:禁止瀏覽器長按出菜單 **/ document.oncontextmenu = function (e) { e.preventDefault(); return false; }; // 添加事件監聽器 el.addEventListener('mousedown', start); el.addEventListener('touchstart', start); // 取消計時器 el.addEventListener('mouseout', cancel); el.addEventListener('touchend', cancel); el.addEventListener('touchcancel', cancel); } }); } };
另外一種優雅的實現方法web