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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42632711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:18:37  来源:igfitidea点击:

How to call function on child component on parent events

javascriptvue.jsevent-handlingvuejs2

提问by jbodily

Context

语境

In Vue 2.0 the documentation and othersclearly indicate that communication from parent to child happens via props.

在 Vue 2.0 中,文档和其他文件清楚地表明父子之间的通信是通过 props 发生的。

Question

How does a parent tell its child an event has happened via props?

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

Should I just watch a prop called event? That doesn't feel right, nor do alternatives ($emit/$onis for child to parent, and a hub model is for distant elements).

我应该只看一个叫做事件的道具吗?这感觉不对,替代方案也不对($emit/$on用于孩子到父母,而集线器模型用于遥远的元素)。

Example

例子

I have a parent container and it needs to tell its child container that it's okay to engage certain actions on an API. I need to be able to trigger functions.

我有一个父容器,它需要告诉它的子容器可以在 API 上进行某些操作。我需要能够触发功能。

回答by joerick

Give the child component a refand use $refsto call a method on the child component directly.

给子组件一个ref,用来$refs直接调用子组件上的一个方法。

html:

html:

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

javascript:

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);
    }
  }
})

For more info, see Vue documentation on refs.

有关更多信息,请参阅refs 上的 Vue 文档

回答by Roy J

What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watchthat prop. When the child takes action, it notifies the parent via an emit, and the parent might then change the state again.

您所描述的是父级中的状态更改。您通过道具将其传递给孩子。正如你所建议的,你会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>

If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.

如果你真的想将事件传递给孩子,你可以通过创建一个总线(它只是一个 Vue 实例)并将它作为 prop 传递给孩子来实现

回答by drinor

You can use $emitand $on. Using @RoyJ code:

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

html:

html:

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

javascript:

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);
    }
  }
})

Running example: https://jsfiddle.net/rjurado/m2spy60r/1/

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

回答by nilobarp

A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.

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

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/[email protected]/dist/vue.js"></script>

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

The parent keeps track of the child handler functions and calls whenever necessary.

父进程跟踪子处理程序函数并在必要时调用。

回答by brightknight08

If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.

如果你有时间,可以使用 Vuex store 来直接观察变量(又名状态)或触发(又名调度)一个动作。

回答by Jason Stewart

Did not like the event-bus approachusing $onbindings in the child during create. Why? Subsequent createcalls (I'm using vue-router) bind the message handler more than once--leading to multiple responses per message.

不喜欢的事件总线方式使用$on绑定在期间孩子create。为什么?后续create调用(我正在使用vue-router)不止一次绑定消息处理程序——导致每条消息有多个响应。

The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a littlebetter. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.

通过道具下来从父到子,并把财产观察者在孩子的正统解决方案工作一点更好。唯一的问题是孩子只能对价值转变采取行动。多次传递相同的消息需要某种簿记来强制转换,以便孩子可以接受更改。

I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.

我发现如果我将消息包装在一个数组中,它总是会触发子观察者——即使值保持不变。

Parent:

家长:

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

Child:

孩子:

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

HTML:

HTML:

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

回答by Mukundhan

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

下面的例子是自我解释的。其中 refs 和 events 可用于从父和子调用函数。

// 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>

回答by user10097040

I think we should to have a consideration about the necessity of parent to use the child's methods.In fact,parents needn't to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough

我觉得我们应该考虑一下parent使用child方法的必要性。其实父母不需要关心child的方法,而是可以把child组件当作FSA(finite state machine)来对待。Parents组件控制子组件的状态。所以解决状态变化或只使用计算功能就足够了

回答by Ardian Zack

you can use key to reload child component using key

您可以使用 key 使用 key 重新加载子组件

<component :is="child1" :filter="filter" :key="componentKey"></component>

If you want to reload component with new filter, if button click filter the child component

如果要使用新过滤器重新加载组件,如果按钮单击过滤子组件

reloadData() {            
   this.filter = ['filter1','filter2']
   this.componentKey += 1;  
},

and use the filter to trigger the function

并使用过滤器触发功能