【问题标题】:Vue Composition API: Is there a better way in calling `emit` inside consumable file?Vue Composition API:有没有更好的方法在消耗文件中调用`emit`?
【发布时间】:2021-02-21 10:57:50
【问题描述】:

在分离的逻辑文件中访问emit的正确方法(或更好的方法)是什么?

这是我目前所做的工作:

foo.js

export default (emit) => {
    const foo = () => { emit('bar') };
    return { foo };
}

然后在消费组件上:

import { defineComponent } from '@vue/composition-api';
import foo from './foo';

export default defineComponent({
  setup(props, { emit }) {
    const { foo } = foo(emit);
    return { foo };
  }
});

但我想知道是否有更合适的方法来做到这一点?或者在消耗品文件中调用emit 是一种不好的做法?

【问题讨论】:

  • 这与问题无关,但defineComponent 现在随vue 一起提供,因此您可能应该从中导入。除非你使用的是早期版本的 Vue。
  • @YomS。谢谢,但是是的,我知道。目前在 NuxtJS/Vue 2 上执行此操作,这就是我使用单独的 vue/composition-api 包的原因。
  • 啊,我明白了。你想用这个实现什么?我的意思是,如果你打算做一些偶数集线器,你可能想看看 this migration guide 使用外部发射器。
  • 哦,我明白了,看起来不错。我认为这将有助于解决问题以清理它...谢谢!
  • 您好,您找到解决几分钟前删除的上一个问题的方法了吗?我的意思是question

标签: javascript typescript vue.js vuejs3 vue-composition-api


【解决方案1】:

您可能已经找到了解决方案,但如果您尝试类似的方式(如最初提出的问题),有一个名为 getCurrentInstance 的选项,它有一个发射器(Composition API 的 Vue 2 插件has one too)。

import { getCurrentInstance } from 'vue';

export default () => {
  const { emit } = getCurrentInstance();

  const foo = () => {
    emit('bar');
  };

  return { foo };
}

但请记住,这仅适用于调用具有SetupContext 的函数/组件。

编辑

上述解决方案适用于 Vue 3,但对于早期版本的 Vue + Composition API plugin,有一点不同:与 Instance Properties 的其余部分一样,您必须在其前面加上 @ 987654331@ 变为$emit。 (下面的示例现在假设 Typescript 作为目标语言,如评论中所述)。

import { getCurrentInstance } from '@vue/composition-api';

export default () => {
  // Ugly workaround, since the plugin did not have the `ComponentInstance` type exported. 
  // You could use `any` here, but that would defeat the purpose of having type-safety, won't it?
  // And we're marking it as `NonNullable` as the consuming components 
  // will most likely be (unless desired otherwise).
  const { $emit, ...context } = getCurrentInstance() as NonNullable<ReturnType<typeof getCurrentInstance>>;

  const foo = () => {
    $emit.call(context, 'bar');
  };

  return { foo };
}

然而,对于 Vue 3 的 Composition API,他们确实导出了这个 ComponentInternalInstance 接口。

附:最好坚持将实例分配给变量的老式方法并执行context.$emitvm.$emit,而不必为所有内容显式指定上下文。我最初提出这个想法时没有意识到这些 Instance Properties 可能是供内部使用的,而下一个 Composition API 并非完全如此。

【讨论】:

  • 谢谢!,试过了,但这对我的情况完全不起作用。我不确定这是否完全适用于 Vue3,但由于我使用的是 @vue/composition-api - 它必须是 $emit 而不是 emit。还有一个bonus 像我一样使用 TS,你可能会遇到一个错误:Property '$emit' does not exist on type 'CombinedVueInstance 那是因为它只会在运行时填充。所以你必须把它保存在某个地方,比如:const vm = (getCurrentInstance as any)();,然后调用它:vm.$emit('bar');
  • 也许请用我提到的问题更新答案,澄清什么适用于 V3 和什么适用于 V2/composition-api,这样当我将其标记为已解决时,其他人不会感到困惑。
  • @rmondesilva 嘿,你说得对,必须为插件加上 $ 前缀。我编辑了我的答案来解释这一点。
猜你喜欢
  • 2022-08-13
  • 2022-01-19
  • 2020-05-06
  • 1970-01-01
  • 1970-01-01
  • 2020-11-28
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多