将“检测外部点击”自定义指令从 Vue 2 迁移到 Vue 3

Posted

技术标签:

【中文标题】将“检测外部点击”自定义指令从 Vue 2 迁移到 Vue 3【英文标题】:Migrating "detect click outside" custom directive from Vue 2 to Vue 3 【发布时间】:2020-12-31 07:44:49 【问题描述】:

基于这个问题Detect click outside element 和这个答案https://***.com/a/42389266,我正在尝试将指令从Vue 2 迁移到Vue 3。似乎binding.expressionvnode.context 不存在更多。我怎样才能让它发挥作用?

app.directive('click-outside', 
    beforeMount (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);
    ,
    unmounted (el) 
        document.body.removeEventListener('click', el.clickOutsideEvent);
    
);

【问题讨论】:

我不知道您的具体用例,但是很多时候人们想要在事件之外使用点击,他们没有考虑到可访问性,因为只有键盘的用户可能需要相同的功能才能发生当外部发生模糊事件或“焦点”时。如果您不想重新发明***并且可以添加另一个库,这是我过去使用的一个很棒的库,用于实现外部点击和外部模糊。 npmjs.com/package/vue-outside-events @maxshuty 感谢您的建议,但显示的库适用于 vue 2 【参考方案1】:

您可以像这样使用binding.value

const  createApp  = Vue;

const highlightEl = (color ) => (event, el) => 
  if (el) 
    el.style.background = color;
   else 
    event.target.style.background = color;
  

const clearHighlightEl = (event, el) => 
  if (el) 
    el.style.background = '';
   else 
    event.target.style.background = '';
  


const app = Vue.createApp(
  setup() 
    return 
      highlightEl,
      clearHighlightEl
    
  
)

app.directive('click-outside', 
  beforeMount(el, binding, vnode) 
    el.clickOutsideEvent = function(event) 
      if (!(el === event.target || el.contains(event.target))) 
        binding.value(event, el);
      
    ;
    document.body.addEventListener('click', el.clickOutsideEvent);
  ,
  unmounted(el) 
    document.body.removeEventListener('click', el.clickOutsideEvent);
  
);

app.mount('#app')
<script src="https://unpkg.com/vue@3.0.0-rc.11/dist/vue.global.prod.js"></script>

<div id="app">
  <h1 v-click-outside="highlightEl('yellow')" @click="clearHighlightEl">Element 1</h1>
  <p v-click-outside="highlightEl('#FFCC77')" @click="clearHighlightEl">Element 2</p>
</div>

【讨论】:

【参考方案2】:

在上下文之外,在 vue3 中有一个更简单的方法与组合。

Link to Vueuse ClickOutside

<template>
  <div ref="target">
    Hello world
  </div>
  <div>
    Outside element
  </div>
</template>

<script>
import  ref  from 'vue'
import  onClickOutside  from '@vueuse/core'

export default 
  setup() 
    const target = ref(null)

    onClickOutside(target, (event) => console.log(event))

    return  target 
  

</script>

【讨论】:

这是真正的 vue3 解决方案 @MojtabaHn 我确认了

以上是关于将“检测外部点击”自定义指令从 Vue 2 迁移到 Vue 3的主要内容,如果未能解决你的问题,请参考以下文章

vue3.2 setup 之局部自定义指令

vue3.2 setup 之局部自定义指令

10天从入门到精通Vue-vue的过滤器自定义指令Vue实例的生命周期

Vue 模板:如何自动将自定义属性添加到具有 v-on:click 指令的元素

vue3自定义指令详解

vue.js自定义指令入门