如何在除vuejs中的当前组件之外的所有兄弟组件中触发事件?

时间:2017-07-10 09:32:29

标签: vue.js vuejs2

我有一个可重用的组件,可以对数据进行内联编辑。

因此页面有10个可以内联编辑的字段,

<editfield :value="field" v-for="field in fieldslist"></editfield>

每个人都有一个名为&#34;编辑&#34;的数据字段。用户点击时设置为truefalse。每次将字段设置为编辑时,都会使用事件总线发出事件editing-another-field

edit(){
    this.editing = true;
    EventBus.$emit('editing-another-field');
}

我在创建组件时添加了事件监听器

created(){
    EventBus.$on('editing-another-field', ()=>{ this.editing = false;});
} 

我面临的问题是它即使在正在编辑的电流组件中也会触发事件。

如何在除当前组件之外的所有其他同级组件中提及editing的更新值。

2 个答案:

答案 0 :(得分:3)

为什么不将当前组件作为事件参数传递,并使用它来检查事件是源自此组件还是来自另一个组件。

edit() {
  this.editing = true;
  EventBus.$emit('editing-another-field', this);
}

created() {
  EventBus.$on('editing-another-field', source => {
    if (source !== this) {
      this.editing = false;
    }
  });
}

或者您可以这样做(在销毁组件时取消注册事件侦听器以避免内存泄漏非常重要):

edit() {
  EventBus.$emit('editing-field', this);
}

created() {
  this.editingFieldHandler = vm => {
    this.editing = vm === this;
  };

  EventBus.$on('editing-field', this.editingFieldHandler);
}

destroyed() {
  EventBus.$off('editing-field', this.editingFieldHandler);
}

否则,您可以先发出事件,然后将this.editing设置为true。

答案 1 :(得分:0)

你确定要一辆活动巴士吗?这给JQuery留下了不好的回忆;-)我认为将自己限制在父母和孩子的树上会更加清晰。思考MVVM,formLockedBy是一个完全有效且明智的属性,可以存储在父母身上并传递给孩子们。

下面的解决方案running here显示了一个包含两个字段的表单。这些字段都是modal-component的实例。父管理formLockedBy属性。子字段查看此属性以了解禁用自身。当用户开始键入字段时,该字段会发出editing个事件并设置formLockedBy。同样,当字段发出savecancel事件时,父级会清除formLockedBy,其他输入会恢复生命。

注意优点......

  • 只有父母会侦听事件。
  • formLockedBy中存储的标识符只是字段的字符串名称。这比传递和存储对Vue组件的引用更安全。如果您不喜欢这样,可以考虑adding a safe id到对象proto。
  • 没有惊喜。父实例将响应的完整事件列表在实例化子项的标记中声明。孩子在props中指定父母需要的一切。

<强> HTML

<div id="example">
  <modal-input name='First Name' 
    :form-locked-by='this.formLockedBy' 
    v-on:save='formLockedBy = null'
    v-on:cancel='formLockedBy = null'
    v-on:editing='fieldActive'
  ></modal-input>
  <modal-input name='Address' 
    :form-locked-by='this.formLockedBy' 
    v-on:save='formLockedBy = null'
    v-on:cancel='formLockedBy = null'
    v-on:editing='fieldActive'
  ></modal-input>
</div>

<强> JS

Vue.component('modal-input', {
  template: `<div>
    {{name}} :
    <input :name='name' type="text" v-on:keydown="active" :disabled="formLockedBy && formLockedBy != name"/>
    <span v-if="editing && formLockedBy == name">
      <input type="button" value="Save" v-on:click="$emit('save');editing=false;"></input>
      <input type="button" value="Cancel" v-on:click="$emit('cancel');editing=false;"></input>
    </span>
  </div>`,
  data : function(){
    return {editing:false};
  },
  props: ['name','formLockedBy'],
  methods : { 
    active : function(event){
      if(!this.editing){
        this.editing = true;
        this.$emit('editing',{field:this.name})      
      }
      return true;
    }
  }
});
// create a root instance
new Vue({
  el: '#example',
  data: {
    formLockedBy : null
  },
  methods : {
    fieldActive : function(args){
      this.formLockedBy = args.field;
    }
  } 
})