Vue Composition API:是否有更好的方法在可消耗文件中调用 `emit`?

Vue Composition API: Is there a better way in calling `emit` inside consumable file?

在分离的逻辑文件中访问 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 是一种不好的做法?

您可能已经找到了解决方案,但如果您尝试类似的方法(如最初提出的问题),则有一个名为 getCurrentInstance that has an emitter (the Vue 2 plugin for Composition API has one too 的选项。

import { getCurrentInstance } from 'vue';

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

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

  return { foo };
}

但请记住,这仅适用于具有 SetupContext.

的调用 functions/components

编辑

以上解决方案适用于 Vue 3,但适用于早期版本的 Vue + Composition API plugin, there is but a slight difference: As with the rest of the Instance Properties, you'll have to prefix it with $ to become $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 的组合 API,但是,他们确实导出了这个 ComponentInternalInstance 接口。

P.S。最好坚持 old-school 将实例分配给变量并执行 context.$emitvm.$emit 的方式,而不必为所有内容明确指定上下文。我最初提出这个想法时没有意识到这些实例属性可能是供内部使用的,下一个组合的情况并非如此API。