从Vue中的自定义事件获取事件源?

sor*_*ist 5 javascript vue.js

我正在构建一个由未指定数量的子组件组成的 Vue 组件。只有一个子组件始终可见,并且只有当当前可见的子组件发出事件时,用户才能在子组件之间进行切换is-valid

我想保持这种解耦,这样孩子们就不知道他们的父母,只能通过发出事件进行通信。这也意味着子组件不知道他们在父组件中的位置。

因此,父组件必须以某种方式跟踪事件来自哪个子组件。如果事件来自右侧子级(当前可见的),则会激活一些按钮,允许用户转到下一个或上一个子级。

到目前为止,这是我的代码:

超文本标记语言

<div id="app">
    <template id="m-child">
        <div>
            <button v-on:click="setstate(true)">Valid</button>
            <button v-on:click="setstate(false)">Invalid</button>
        </div>
    </template>

    <template id="m-parent">
        <div>
            <m-child v-on:newstate="newchildstate"></m-child>
            <m-child v-on:newstate="newchildstate"></m-child>
            <m-child v-on:newstate="newchildstate"></m-child>
        </div>
    </template>

    <m-parent></m-parent>
</div>
Run Code Online (Sandbox Code Playgroud)

JS

Vue.component('m-child', {
    template: '#m-child',
    data: function() {
        return {};
    },
    methods: {
        setstate: function (valid) {
            this.$emit('newstate', valid);
        }
    }
});

Vue.component('m-parent', {
    template: '#m-parent',
    methods: {
        newchildstate: function (valid) {
            console.log('valid:' + valid + ', but where from?');
        }
    }
});

new Vue({
    el: '#app'
});
Run Code Online (Sandbox Code Playgroud)

当然,我可以在子事件绑定上硬编码索引:

        <m-child v-on:newstate="newchildstate(0, $event)"></m-child>
        <m-child v-on:newstate="newchildstate(1, $event)"></m-child>
        <m-child v-on:newstate="newchildstate(2, $event)"></m-child>
Run Code Online (Sandbox Code Playgroud)

但这会使整个设置的模块化程度降低很多,我只想能够在 DOM 中插入一些子元素并使其立即工作。

我查看了 Vue 事件的 API,似乎没有办法从事件对象获取源。

cra*_*g_h 2

这取决于您想要收到的内容,我个人的偏好是传入 aprop来设置唯一的 id 并将其传回$emit

<m-child v-on:newstate="newchildstate" :id="1"></m-child>
<m-child v-on:newstate="newchildstate" :id="2"></m-child>
<m-child v-on:newstate="newchildstate" :id="3"></m-child>
Run Code Online (Sandbox Code Playgroud)

然后,在您的子组件中,您可以创建emit一个具有状态和 id 的对象id

孩子:

this.$emit('newstate', {id: this.id, state: valid});
Run Code Online (Sandbox Code Playgroud)

家长:

newchildstate: function (valid) {
  console.log('valid:' + valid.state + ', from' + valid.id);
}
Run Code Online (Sandbox Code Playgroud)

我意识到这看起来与您的硬编码示例没有太大不同,但在某些时候您parent会想要处理,因此您可以使用初始状态event设置一个数组,然后使用:datav-for

data: {
  children: [true, false, false] // setup states
}
Run Code Online (Sandbox Code Playgroud)

然后你会这样做:

<div v-for="(state, index) in states">
  <m-child v-on:newstate="newchildstate" :id="index"></m-child>
</div>
Run Code Online (Sandbox Code Playgroud)

在你的视图模型中:

  methods: {
    newchildstate: function(valid) {
      this.$set(this.states, valid.id, valid.state);
    }
  }
Run Code Online (Sandbox Code Playgroud)

这是一个 JSFiddle,它通过 prop 动态启动数组并设置子组件: https: //jsfiddle.net/2y9727e2/