當(dāng)我們?cè)谑褂肰ue框架開發(fā)網(wǎng)頁時(shí),經(jīng)常會(huì)碰到需要處理點(diǎn)擊外部事件的情況。例如,當(dāng)我們打開一個(gè)下拉菜單或者模態(tài)框時(shí),我們希望在點(diǎn)擊菜單或模態(tài)框以外的地方時(shí)自動(dòng)關(guān)閉它們。那么,如何在Vue中實(shí)現(xiàn)這樣的功能呢?
created: function () {
document.addEventListener('click', this.onClickOutside);
},
beforeDestroy: function () {
document.removeEventListener('click', this.onClickOutside);
},
methods: {
onClickOutside: function (event) {
if (!this.$el.contains(event.target)) {
this.visible = false;
}
}
}
在代碼中,我們首先在Vue實(shí)例的created鉤子函數(shù)中添加一個(gè)監(jiān)聽document的click事件的事件處理函數(shù)onClickOutside,用于處理點(diǎn)擊事件。當(dāng)組件被銷毀時(shí),我們需要在beforeDestroy鉤子函數(shù)中移除該事件處理函數(shù),避免造成內(nèi)存泄漏。
在onClickOutside函數(shù)中,我們通過對(duì)比event.target與Vue組件內(nèi)元素的關(guān)系來判斷是否點(diǎn)擊了組件外部。如果點(diǎn)擊了外部,則需要將組件的visible屬性設(shè)為false,以此來關(guān)閉菜單或模態(tài)框等組件。而在這些組件內(nèi)部,我們需要通過v-if、v-show等指令來根據(jù)visible屬性的值控制組件的顯示與隱藏。
除了通過添加document的click事件來實(shí)現(xiàn)點(diǎn)擊外部事件的監(jiān)聽,Vue也提供了另外一種更方便的方式。我們可以使用Vue官方提供的一個(gè)插件v-click-outside(https://github.com/ndelvalle/v-click-outside),它提供了一個(gè)自定義指令v-click-outside,用于在Vue組件中監(jiān)聽點(diǎn)擊事件并根據(jù)事件目標(biāo)判斷是否點(diǎn)擊了組件外部。使用該插件,我們?cè)赩ue組件中添加v-click-outside指令即可實(shí)現(xiàn)點(diǎn)擊外部關(guān)閉組件的功能。
import vClickOutside from 'v-click-outside';
Vue.use(vClickOutside);
export default {
directives: {
'click-outside': {
bind: function (el, binding, vnode) {
el.clickOutsideEvent = function (event) {
if (!(el == event.target || el.contains(event.target))) {
vnode.context[binding.expression](event);
}
};
document.body.addEventListener('click', el.clickOutsideEvent);
},
unbind: function (el) {
document.body.removeEventListener('click', el.clickOutsideEvent);
}
}
}
}
在該插件中,我們先通過Vue.use(vClickOutside)使用插件。然后,在Vue組件中定義v-click-outside指令,并將其綁定到實(shí)際的DOM元素上。在指令綁定時(shí),我們添加一個(gè)自定義事件clickOutsideEvent來處理點(diǎn)擊事件,并將其添加到document.body上。在指令解綁時(shí),我們需要移除該事件。具體的判斷邏輯與上述方法相同。
需要注意的是,以上兩種方法均需要考慮到多個(gè)組件同時(shí)存在的情況。如果同時(shí)存在多個(gè)需要關(guān)閉的組件,我們需要為每個(gè)組件單獨(dú)綁定事件,避免影響其他組件的正常運(yùn)行。