首页 文章

如何在父事件上调用子组件上的函数

提问于
浏览
61

上下文

在Vue 2.0中,文档和others清楚地表明从父母到孩子的沟通是通过道具进行的 .

问题

父母如何告诉孩子通过道具发生的事件?

我应该只看一个名为事件的道具吗?这感觉不对,也没有替代方案( $emit / $on 用于子级到父级,而中心模型用于远程元素) .

示例

我有一个父容器,它需要告诉它的子容器,可以在API上使用某些操作 . I need to be able to trigger functions.

8 回答

  • 0

    给子组件 ref 并使用 $refs 直接调用子组件上的方法 .

    HTML:

    <div id="app">
      <child-component ref="childComponent"></child-component>
      <button @click="click">Click</button>  
    </div>
    

    JavaScript的:

    var ChildComponent = {
      template: '<div>{{value}}</div>',
      data: function () {
        return {
          value: 0
        };
      },
      methods: {
        setValue: function(value) {
            this.value = value;
        }
      }
    }
    
    new Vue({
      el: '#app',
      components: {
        'child-component': ChildComponent
      },
      methods: {
        click: function() {
            this.$refs.childComponent.setValue(2.0);
        }
      }
    })
    
  • 0

    你所描述的是父母的状态变化 . 你通过道具把它传给了孩子 . 正如你的建议,你会 watch 那个道具 . 当孩子采取行动时,它会通过 emit 通知父母,然后父母可能会再次更改状态 .

    var Child = {
      template: '<div>{{counter}}</div>',
      props: ['canI'],
      data: function () {
        return {
          counter: 0
        };
      },
      watch: {
        canI: function () {
          if (this.canI) {
            ++this.counter;
            this.$emit('increment');
          }
        }
      }
    }
    new Vue({
      el: '#app',
      components: {
        'my-component': Child
      },
      data: {
        childState: false
      },
      methods: {
        permitChild: function () {
          this.childState = true;
        },
        lockChild: function () {
          this.childState = false;
        }
      }
    })
    
    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
    <div id="app">
    <my-component :can-I="childState" v-on:increment="lockChild"></my-component>
    <button @click="permitChild">Go</button>
    </div>
    

    如果您确实想要将事件传递给孩子,则可以通过creating a bus (which is just a Vue instance) and passing it to the child as a prop执行此操作 .

  • 20

    您可以使用 $emit$on . 使用@RoyJ代码:

    HTML:

    <div id="app">
      <my-component></my-component>
      <button @click="click">Click</button>  
    </div>
    

    JavaScript的:

    var Child = {
      template: '<div>{{value}}</div>',
      data: function () {
        return {
          value: 0
        };
      },
      methods: {
        setValue: function(value) {
            this.value = value;
        }
      },
      created: function() {
        this.$parent.$on('update', this.setValue);
      }
    }
    
    new Vue({
      el: '#app',
      components: {
        'my-component': Child
      },
      methods: {
        click: function() {
            this.$emit('update', 7);
        }
      }
    })
    

    运行示例:https://jsfiddle.net/rjurado/m2spy60r/1/

  • 1

    如果您有时间,请使用Vuex商店直接观察变量(也称为状态)或触发(也称为调度)操作 .

  • 4

    create 期间,不喜欢event-bus approach在孩子身上使用 $on 绑定 . 为什么?后续的 create 调用(我正在使用 vue-router )多次绑定消息处理程序 - 导致每条消息有多个响应 .

    将道具从父母传给孩子并将物品观察者放在孩子身上的正统解决方案效果更好 . 唯一的问题是孩子只能对 Value 转变采取行动 . 多次传递相同的信息需要某种簿记来强制转换,以便孩子可以接受改变 .

    我发现如果我将消息包装在一个数组中,它将始终触发子监视器 - 即使值保持不变 .

    家长:

    {
       data: function() {
          msgChild: null,
       },
       methods: {
          mMessageDoIt: function() {
             this.msgChild = ['doIt'];
          }
       }   
       ...
    }
    

    儿童:

    {
       props: ['msgChild'],
       watch: {
          'msgChild': function(arMsg) {
             console.log(arMsg[0]);
          }
       }
    }
    

    HTML:

    <parent>
       <child v-bind="{ 'msgChild': msgChild }"></child>
    </parent>
    
  • 72

    The below example is self explainatory. where refs and events can be used to call function from and to parent and child.

    // PARENT
    <template>
      <parent>
        <child
          @onChange="childCallBack"
          ref="childRef"
          :data="moduleData"
        />
        <button @click="callChild">Call Method in child</button>
      </parent>
    </template>
    
    <script>
    export default {
      methods: {
        callChild() {
          this.$refs.childRef.childMethod('Hi from parent');
        },
        childCallBack(message) {
          console.log('message from child', message);
        }
      }
    };
    </script>
    
    // CHILD
    <template>
      <child>
        <button @click="callParent">Call Parent</button>
      </child>
    </template>
    
    <script>
    export default {
      methods: {
        callParent() {
          this.$emit('onChange', 'hi from child');
        },
        childMethod(message) {
          console.log('message from parent', message);
        }
      }
    }
    </script>
    
  • 41

    我认为我们应该考虑父母使用孩子的方法的必要性 . 事实上,父母不需要关心孩子的方法,但可以将孩子组件视为FSA(有限状态机) . 父母组件控制子组件的状态 . 因此,观察状态更改或仅使用计算功能的解决方案就足够了

  • 1

    在子组件上调用方法的简单解耦方法是从子组件中发出处理程序,然后从父组件调用它 .

    var Child = {
      template: '<div>{{value}}</div>',
      data: function () {
        return {
          value: 0
        };
      },
      methods: {
      	setValue(value) {
        	this.value = value;
        }
      },
      created() {
        this.$emit('handler', this.setValue);
      }
    }
    
    new Vue({
      el: '#app',
      components: {
        'my-component': Child
      },
      methods: {
      	setValueHandler(fn) {
        	this.setter = fn
        },
        click() {
        	this.setter(70)
        }
      }
    })
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
    
    <div id="app">
      <my-component @handler="setValueHandler"></my-component>
      <button @click="click">Click</button>  
    </div>
    

    父级会在必要时跟踪子处理程序函数和调用 .

相关问题