【问题标题】:How can I use vnode or binding directive to call a component method in VUE 3?如何在 VUE 3 中使用 vnode 或绑定指令调用组件方法?
【发布时间】:2022-10-06 19:48:48
【问题描述】:

我创建了一个指令,我需要使该指令调用一个存在于具有该指令的组件内的函数。

// Component with directive, this component has the method \'setDisabled()\'
<v-button v-can:edit.disable=\"[something]\" @click=\"add\" />


// Directive created
const can = {
    mounted: async (el, binding, vnode) => {
        let hasAccess = validateAccess()
        if (!hasAccess) {
            // should call v-button setDisabled() in here
        }
    },
}

在 VUE 2 中,这可以通过使用 vnode.context 来实现,但在 VUE 3 中,我似乎只能使用 binding.instance 从父组件访问方法。

那么,有没有办法在组件挂载之后使用el、binding或者vnode来调用方法呢?到目前为止,只看到了 vnode 中的道具,没有方法或反应数据。

  • \"来自父组件的方法\" - 不正确。 binding.instance 是当前实例,正如预期的那样。如果您对此有疑问,请考虑解决它。它非常特定于组件,但您通常会问。是 Vuetify 吗?那你可以先验证一下是否真的有这样的方法
  • \'v-button\' 是一个自定义组件。是的,\'binding.instance\' 正在返回在其模板中具有 v-button 的组件的实例。我正在尝试从具有指令的 \'v-button\' 访问方法
  • 该指令是为 DOM 操作目的而设计的。如果你想调用组件的方法,为什么不传递一个 prop 并基于该 prop 调用组件内部的方法呢?引用该组件的另一种方法是在其父级中使用ref。当您不想操作 DOM 时,根本不需要使用指令
  • @Duannx 这个想法是有一个指令,当该方法存在时,该指令可以在组件内部调用该方法。由于该指令是在挂载的钩子上触发的,因此所有方法都可以使用了。使用道具会强制重新渲染组件,这似乎是不必要的。我尝试使用 REF,但我需要设置 ref 并将其传递到指令中以实现此目的。拥有访问组件方法的指令不需要所有这些。
  • 如果您的组件状态依赖于一个道具,那么重新渲染是必要的。这是 Vue 处理响应式数据的方式。我想说的重点是在指令中调用组件方法是一种意想不到的方式。它看起来很干净,但可能会导致一些副作用并且难以维护。我建议不要使用它

标签: vue.js vuejs3 vue-directives


【解决方案1】:

Vue3 的黑客解决方案

约束

  1. Vue 文档阐明

    Official Docs: Script Setup 使用 &lt;script setup&gt; 的组件默认关闭 - 即通过模板引用或 $parent 链检索的组件的公共实例不会暴露内部声明的任何绑定。

    Official Docs: Custom Directives 一般来说,不建议在组件上使用自定义指令。

    1. 传递给指令钩子的binding.instance 参数表示

      • 具有使用 v 指令的元素/组件的父组件
      • 不是定义 v 指令的组件。
    2. 传递给指令钩子的vnode 参数表示

      • Native DOM Element 使用 v 指令的元素
      • Custom component with single root使用v指令的组件的根元素
      • Custom component with multiple roots 使用 v 指令的组件的第一个根元素

    然而

    1. 您可以访问自定义组件实例使用 vnode
    2. 你可以访问底层方法来自 vnode 的自定义组件使用
      • 公开vnode.el.__vueParentComponent.exposed
      • 提供vnode.el.__vueParentComponent.provides

      解决方案:

      1. 使用defineExpose公开组件方法
        const setDisabled = () => { /* Your precious method */};
        defineExpose({
          setDisabled
        });
        
        1. 使用 vnode 访问公开的方法
        const vCan = {
          mounted: async (el, binding, vnode)=> {
            vnode.el.__vueParentComponent.exposed.setDisabled()
          },
        };
        
        1. 还要确保指令定义对象是使用 camelCase 定义的,并且具有 v 前缀,例如 vCan

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 2019-08-05
    • 1970-01-01
    • 2023-02-23
    • 2017-11-16
    • 1970-01-01
    • 2017-12-19
    • 2021-10-20
    • 2021-01-31
    相关资源
    最近更新 更多