首页 文章

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

提问于
浏览
0

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

所以一个页面有10个可以内联编辑的字段,

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

它们中的每一个都有一个名为"editing"的数据字段,在用户点击它时设置为 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

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

    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 .

  • 3

    你确定要一辆活动 Bus 吗?这给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;
        }
      } 
    })
    

相关问题