【问题标题】:What is the difference between Vue's 'v-on' directive and vue.$on?Vue 的 'v-on' 指令和 vue.$on 有什么区别?
【发布时间】:2020-05-26 15:36:14
【问题描述】:

假设我有两个这样的兄弟组件:

<div id="root2">
    <some-component>First</some-component>
    <some-component>Second</some-component>
</div>

...这些组件的定义如下:

Vue.component('some-component', {
    template: '<button @click="doSomething" @somethingwasdone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    methods: {
        doSomething() {
            Event.$emit('somethingWasDone');
        },

        reactToSomething() {
            this.isDisabled = true;
        }
    },
    data() {
        return {
            isDisabled: false,
        }
    },
    created() {
        Event.$on('somethingWasDone', () => this.reactToSomething());
    }
});

假设我的目标是在按下其中一个按钮时禁用这两个按钮。我特意包含了两个事件监听器,一个是“v-on”指令的形式,一个是在 Vue 实例上定义的 $on 方法的形式。我无法让前者工作,我不确定为什么。

我的猜测是它必须与发出事件的范围有关。但是,即使我单击的组件在使用 v-on 指令时也不会监听它发出的事件。非常感谢任何帮助!

问候,

瑞恩


更新:我在我的代码中发现一个错误,其中 v-for 指令 (@) 正在侦听的事件是“componentclicked”而不是“somethingwasdone”。在修复错误时,我注意到这两种方法实际上都有效。

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:

    每个 Vue 实例(包括根实例)都有 $on 和 $emit 方法,它们允许发送和接收事件。在处理事件时,您必须牢记发出事件的范围。

    在您的示例中,您似乎正在尝试在同一组件中发出和捕获事件。为此,您将需要使用组件实例 $emit 和 $on 方法。通过这种方式,事件在组件中发出并保持在此范围内。本例中使用的语法是 this.$emit() 和 this.$on(), this 定义组件实例。

    Vue.component('some-component', {
        template: '<button @click="doSomething" @somethingWasDone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
        methods: {
            doSomething() {
                this.$emit('somethingWasDone');
            },
    
            reactToSomething() {
                this.isDisabled = true;
            }
        },
        data() {
            return {
                isDisabled: false,
            }
        },
        created() {
            this.$on('somethingWasDone', () => this.reactToSomething());
        }
    });
    

    v-on 是模板中用于从父组件侦听相同事件的语法。

    <div id="root2">
         <some-component v-on:somethingWasDone="doSomething">First</some-component>
        <some-component v-on:somethingWasDone="doSomething">Second</some-component>
    </div>
    

    如果您使用的是根实例 Vue.$on 和 Vue.$emit,那么您就是在全局级别发出/监听事件。

    【讨论】:

    • 感谢您的回复。但是,我的目标是在其中任何一个被按下时更新兄弟组件。针对您对 $on 和 $emit 仍然有限的评论,“this”关键字似乎仅适用于组件实例,而不适用于全局组件。 IE。只有按下的按钮被禁用。使用专用的事件中心,或者 - 如您的示例 - 根实例,我使用 $on 和 $emit 让它工作!
    • 你说得对,要更新兄弟组件,你必须使用全局事件。本地事件仅适用于父子通信。编码愉快!
    【解决方案2】:

    据我了解,当您发出事件时,它们会被发送到父组件。所以你必须在父组件中实现逻辑。

    <div id="root2">
      <some-component
        v-on:somethingWasDone="isDisabled = true"
        :disabled="isDisabled">
       First
      </some-component>
    
      <some-component
        v-on:somethingWasDone="isDisabled = true"
        :isDisabled="isDisabled">
       Second
      </some-component>
    </div>
    
    // ...
    
    data() {
      return {
        isDisabled: false
      }
    }
    

    isDisabled 变量添加到父级,并作为some-component 中的道具。

    Vue.component('some-component', {
        template: '<button @click="doSomething" @componentclicked="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
        props: ["isDisabled"],
        methods: {
            doSomething() {
                Event.$emit('somethingWasDone');
            }
        },
    });
    

    【讨论】:

      猜你喜欢
      • 2019-04-02
      • 2017-10-04
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多