简体   繁体   English

如何从 Vue.js 功能组件发出事件?

[英]How to emit an event from Vue.js Functional component?

As the title of the question, this context is not available in the functional component.作为问题的标题, this上下文在功能组件中不可用。 So if I have to emit an event, how can I do that?所以如果我必须发出一个事件,我该怎么做呢?

For example in below code snippet:例如在下面的代码片段中:

<template functional>
    <div>
        <some-child @change="$emit('change')"></some-child>
    </div>
</template>

My functional component doesn't have this context and hence $emit is not available.我的功能组件没有this上下文,因此$emit不可用。 How can I bubble-up this event?我怎样才能冒泡这个活​​动?

Child Component子组件

<template functional>
  <button @click="listeners['custom-event']('message from child')">
    Button from child
  </button>
</template>

Parent Component父组件

<template>
  <div>
    <child-component @custom-event="call_a_method" />
  </div>
</template>

See it in action on codesandbox在代码沙箱上查看它的实际操作

Do you want to emit the event from the vue instance?你想从 vue 实例中发出事件吗?

export default {
  functional: true,
  render(createElement, { listeners }) {
    return createElement(
      "button",
      {
        on: {
          click: event => {
            const emit_event = listeners.event_from_child;
            emit_event("Hello World!Is this the message we excpected? :/");
          }
        }
      },
      "Pass event to parent"
    );
  }
};

See it also a sandbox example here另请参阅此处的沙盒示例

This is explained in the docs Passing Attributes and Events to Child Elements/Components :这在将属性和事件传递给子元素/组件的文档中进行了解释:

If you are using template-based functional components, you will also have to manually add attributes and listeners.如果您使用基于模板的功能组件,您还必须手动添加属性和侦听器。 Since we have access to the individual context contents, we can use data.attrs to pass along any HTML attributes and listeners (the alias for data.on ) to pass along any event listeners.由于我们可以访问各个上下文内容,因此我们可以使用data.attrs传递任何 HTML 属性和listeners器( data.on的别名)来传递任何事件侦听器。

At the most basic level, you can delegate all listeners like this:在最基本的层面上,您可以像这样委派所有侦听器:

<some-child v-on="listeners"></some-child>

If you only want to bind the change listener, you can do:如果您只想绑定change侦听器,您可以执行以下操作:

<some-child @change="listeners.change"></some-child>

but this will fail if listeners.change is undefined/null (not provided to the functional component).但是如果listeners.change是 undefined/null (未提供给功能组件),这将失败。

If you need to handle the situation where there is no change listener, then you can do this:如果您需要处理没有change侦听器的情况,那么您可以这样做:

<some-child @change="listeners.change && listeners.change($event)"></some-child>

otherwise you would have to settle by writing the render function by hand, since I don't think it is possible to conditionally assign the change listener to <some-child> in the template of a functional component.否则您将不得不通过手动编写渲染函数来解决,因为我认为不可能有条件地将change侦听器分配给功能组件模板中的<some-child> (Or maybe you can? I'm not sure.) (或者也许你可以?我不确定。)

If you want to pass event listener conditionally you can do it inside functional component template like this:如果您想有条件地传递事件侦听器,您可以在功能组件模板中执行此操作,如下所示:

v-on="listeners.change ? { change: listeners.change } : null"

The issue of conditionally attaching listeners is discussed here这里讨论了有条件地附加侦听器的问题

a component with jsx:带有 jsx 的组件:

export default {
  name: "MyText",
  functional: true,// functional component
  props: {
    value: {
      type: [String, Number],
      default: ""
    }
  },
  render(h, context) {
    const { props } = context;

    // with jsx

    // return (
    //   <button
    //     onClick={() => {
    //       console.log(context.listeners);
    //       context.listeners.input(Math.random().toString(36));
    //       context.listeners["my-change"](Math.random().toString(36));
    //       context.data.on.change(Math.random().toString(36));
    //     }}
    //   >
    //     {props.value}
    //   </button>
    // );

    // or use h function
    return h(
      "h1",
      {
        on: {
         // emit some event when click h1
          click: () => {
            // has value prop has has input event auto
            // event name come  what event u listen in parent component
            console.log(context.listeners);
            context.listeners.input(Math.random().toString(36));
            context.listeners["my-change"](Math.random().toString(36));
            context.data.on.change(Math.random().toString(36));
          }
        }
      },
      props.value
    );
  }
};

conext.listeners is just an alias for context.data.on . conext.listeners只是context.data.on的别名。 in parent componet, you should listen my-change and change , or has error.在父组件中,您应该听my-changechange ,否则有错误。

event name inside component comes what event u listen in parent component组件内的事件名称来自您在父组件中侦听的事件

<MyText
  v-model="value"
  @change="change"
  @my-change="myChange"
  @u-change="uChange"
/>

vue 2.6.11 works well. vue 2.6.11 运行良好。

see the codesandbox online 在线查看代码框

Parent:家长:

<Child @onFunction="handleFunction">

and this is the child component:这是子组件:

Child孩子

<template functional>
    <div>
        <some-child @change="execute"></some-child>
    </div>
</template>

methods:
  execute(){
   @emit("onFunction")
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM