你們好啊,我是大家的攻城獅,我是 Ken,人賤賤愛的前端攻城獅,我要告訴你個嚴重的問題,這幾天心情低落,代碼擼不動啊,結果今天一到公司,打開禪道,你們可能不知道什麼是 禪道
就是專門給程序猿提各類 bug 的地方,一早來了三個 bug,頓時一萬個草泥馬從腦門飄過:前端
最後我仍是慫了,咱們來看看究竟是什麼 bug?一看挖槽,原來是兼容性問題,你知道嗎?作前端最懼怕的是什麼呢?就是尼瑪的兼容,尤爲是有一個頑固的瀏覽器,IE,這個千刀萬剮的傢伙,禍害了多少代的程序猿,哈哈,幸虧的是咱們只須要兼容移動端,pc 端的網站須要兼容 ipad 端。vue
接下來看看是什麼問題?原來是在 pc 端右鍵菜單不能出現了,我一看原來是沒有兼容移動端的事件,由於在 pc 端咱們只須要使用 @contextmenu
這個事件就能夠實現右鍵菜單的出現了,node
固然在此以前咱們須要實現一個菜單組件,咱們這個菜單可能須要兼容二級菜單,因此須要實現二級菜單:express
<template>
<!-- 右鍵菜單 -->
<ul class="menu" v-show="show">
<li
:key="index"
@click="clickOuterEvent(clickMenu.fnName, clickMenus.text)"
class="menu-item icon-right-arrow"
v-for="(clickMenu,index) in clickMenus"
>
<i class="menu-item-bg"></i>
{{clickMenu.text}}
<span class="right-arrow" v-show="clickMenu.secondaryMenu"></span>
<ul class="secondary-menu">
<li
:key="index"
@click.stop="clickEvent(item.fnName, item.text)"
class="menu-item"
v-for="(item,index) in clickMenu.secondaryMenu"
>
<i class="menu-item-bg"></i>
{{item.text}}
</li>
</ul>
</li>
</ul>
</template>
這其中有一個邏輯當右鍵時,右鍵菜單纔會出現,因此須要一個控制右鍵菜單 menuShow
,固然咱們也須要知道菜單名稱是什麼,就須要一個數組來控制 clickMenus
:數組
<script>
export default {
name: 'fyMenu',
props: {
menuShow: {
type: Boolean,
default: false,
},
clickMenus: {
type: Array,
default: () => {
return []
},
},
// 鼠標右鍵菜單
contextmenu: {
type: Object,
default: function _default() {
return { height: 0, width: -10 }
},
},
},
data() {
return {
show: this.menuShow,
}
},
methods: {
clickOuterEvent(name, text) {
this.$emit('update:menu-show', false)
this.$emit('clickOuterEvent', name, text)
},
clickEvent(name, text) {
this.$emit('update:menu-show', false)
this.$emit('clickEvent', name, text)
},
getShow() {
this.show = false
},
documentListen() {
document.addEventListener('click', this.getShow, false)
}
},
watch: {
menuShow(val) {
this.show = val
},
},
mounted() {
this.documentListen()
},
beforeDestroy() {
document.removeEventListener('click', this.getShow, false)
}
}
</script>
在外面的組件咱們應該這樣使用:瀏覽器
<fy-menu
:clickMenus="clickMenus"
:menu-show="showMenu"
@clickOuterEvent="clickEvent"
ref="menu"
></fy-menu>
export default {
data() {
return {
clickMenus: [
{
fnName: 'modifyGroup',
text: '編輯',
},
{
fnName: 'combineGroup',
text: this.ufd.text['text.plan.combine.group'],
},
{
fnName: 'delete',
text: this.ufd.text['text.del'],
},
],
showMenu: false, // 展現菜單標誌
}
},
methods: {
clickEvent(name){}
}
}
接下來咱們須要瞭解下移動端事件,由於移動端不像 pc 端同樣有鼠標事件,移動端只有觸摸事件:ide
今天咱們處理 bug 的使用最簡單的一種方式,就是使用 @touchstart
,@touchend
:函數
// 實現移動端長按出現右鍵菜單
start(e, group, nodeIndex, dayIndex, dayPriceSort, groupIndex) {
clearTimeout(this.loop) //再次清空定時器,防止重複註冊定時器
let that = this
this.loop = setTimeout(() => {
that.ipadMenucontext(e, group, nodeIndex, dayIndex, dayPriceSort, groupIndex)
}, 1000)
},
end(e) {
e.preventDefault()
clearTimeout(this.loop) //清空定時器,防止重複註冊定時器
},
咱們能夠看到使用經過延遲函數裏執行咱們右鍵時須要處理的動做,在咱們手指開始觸摸時,須要先使用 clearTimeout
先清除上一次的定時器,再去執行咱們想要執行的動做,再觸摸結束以後,咱們須要清除定時器oop
因此這樣處理完成以後,咱們能夠在 ipad 端看到當咱們手指長按 iPad 屏幕的時候,右鍵菜單就會出現了。網站
以上就是移動端長按實現右鍵菜單。
接下來就是總結
在vue中長按事件並無封裝,在使用的時候須要咱們本身取寫一個方法獲取長按事件。
方法一:使用@touchstart,@touchend
start () {
clearTimeout(this.loop); //再次清空定時器,防止重複註冊定時器
this.loop = setTimeout(() => {
console.log("長按了");
}, 1000);
},
end () {
clearTimeout(this.loop); //清空定時器,防止重複註冊定時器
},
備註:使用的時候注意若是是圖片,建議把圖片設置爲背景,直接使用圖片,在長按時會觸發瀏覽器對圖片的保存、分享等。
方法二:
export default {
install(Vue, options = {
time: 2000,
}) {
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)
}
// 定義變量
let pressTimer = null
// 定義函數處理程序
// 建立計時器( 1秒後執行函數 )
let start = (e) => {
if (e.type === 'click' && e.button !== 0) {
return
}
if (pressTimer === null) {
pressTimer = setTimeout(() => {
// 執行函數
handler()
}, options.time)
}
}
// 取消計時器
let cancel = (e) => {
// 檢查計時器是否有值
if (pressTimer !== null) {
clearTimeout(pressTimer)
pressTimer = null
}
}
// 運行函數
const handler = (e) => {
// 執行傳遞給指令的方法
binding.value(e)
}
// 添加事件監聽器
el.addEventListener('mousedown', start)
el.addEventListener('touchstart', start)
// 取消計時器
el.addEventListener('click', cancel)
el.addEventListener('mouseout', cancel)
el.addEventListener('touchend', cancel)
el.addEventListener('touchcancel', cancel)
},
})
},
}
人生代碼 發起了一個讀者討論有時候問題歡迎你們加入討論啊,給我一些建議啊,否則我都聽不到粉絲的聲音