javascript vue.js event-handling vuejs2

javascript - Cómo llamar a la función en el componente secundario en eventos primarios



vue.js event-handling (9)

Creo que deberíamos tener en cuenta la necesidad de que los padres usen los métodos del niño. De hecho, los padres no deben preocuparse por el método del niño, sino que pueden tratar el componente infantil como una FSA (máquina de estados finitos). para controlar el estado del componente secundario. Por lo tanto, la solución para observar el cambio de estado o simplemente usar la función de cálculo es suficiente

Contexto

En Vue 2.0, la documentación y others indican claramente que la comunicación de padres a hijos se realiza a través de accesorios.

Pregunta

¿Cómo le dice un padre a su hijo que un evento ha sucedido a través de accesorios?

¿Debo ver un accesorio llamado evento? Eso no se siente bien, ni tampoco las alternativas ( $emit / $on es para hijos a padres, y un modelo de concentrador es para elementos distantes).

Ejemplo

Tengo un contenedor principal y necesita decirle a su contenedor secundario que está bien involucrar ciertas acciones en una API. Necesito poder activar funciones.


Dele al componente hijo una ref y use $refs para llamar directamente a un método en el componente hijo.

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

Para obtener más información, consulte la documentación de Vue en las referencias .


Lo que está describiendo es un cambio de estado en el padre. Se lo pasas al niño a través de un accesorio. Como sugeriste, watch ese accesorio. Cuando el niño toma medidas, notifica al padre a través de una emit , y el padre puede cambiar el estado nuevamente.

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>

Si realmente desea pasar eventos a un niño, puede hacerlo creando un autobús (que es solo una instancia de Vue) y pasándolo al niño como accesorio .


No me gustó el vuejs.org/v2/guide/… usando $on enlaces en el niño durante la create . ¿Por qué? Las llamadas de create posteriores (estoy usando vue-router ) enlazan el controlador de mensajes más de una vez, lo que genera múltiples respuestas por mensaje.

La solución ortodoxa de pasar los accesorios de padres a hijos y poner un vigilante en el niño funcionó un poco mejor. El único problema es que el niño solo puede actuar en una transición de valor. Pasar el mismo mensaje varias veces necesita algún tipo de contabilidad para forzar una transición para que el niño pueda recoger el cambio.

Descubrí que si envuelvo el mensaje en una matriz, siempre activará el observador secundario, incluso si el valor sigue siendo el mismo.

Padre:

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

Niño:

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

HTML:

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


Podría usar un mixin para establecer un atributo de datos compartidos. Cámbielo en el padre, mírelo en el hijo:

// mixin export default { data() { return { clicked: false } } } // parent export default { mixins: [myMixin], methods: { btnClick() { this.clicked = true } } } // child export default { mixins: [myMixin], watch: { clicked(val) { if(val) { // yay } } } }


Puede usar $emit y $on . Usando el código @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); } } })

Ejemplo de ejecución: https://jsfiddle.net/rjurado/m2spy60r/1/


Si tiene tiempo, use la tienda Vuex para ver variables (también conocido como estado) o desencadenar (también conocido como despachar) una acción directamente.


Una forma simple de desacoplar los métodos de llamada en los componentes secundarios es emitir un controlador desde el elemento secundario y luego invocarlo desde el elemento primario.

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>

El padre realiza un seguimiento de las funciones y llamadas del controlador secundario siempre que sea necesario.


El siguiente ejemplo es auto explicativo. donde las referencias y los eventos se pueden usar para llamar a la función desde y hacia padre e hijo.

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