Cómo llamar a la función en el componente secundario en los eventos principales


Contexto

En la Vue 2.0 la documentación y otros indican claramente que la comunicación de padres a hijos ocurre 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 simplemente ver un accesorio llamado evento? Eso no se siente bien, ni tampoco las alternativas ($emit/$on es para hijo a padre, y un modelo hub es para elementos distantes).

Ejemplo

Tengo un contenedor padre y necesita dile a su contenedor hijo que está bien realizar ciertas acciones en una API. Necesito poder activar funciones.

Author: Emile Bergeron, 2017-03-06

6 answers

Dé al componente secundario un ref y use $refs para llamar directamente a un método en el componente secundario.

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);
    }
  }
})
 59
Author: joerick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 14:25:00

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 usted sugirió, usted watch que prop. Cuando el hijo toma acción, notifica al padre a través de un 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 hijo, puede hacerlo creando un bus (que es solo una instancia de Vue) y pasándolo al hijo como prop .

 35
Author: Roy J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-19 15:14:49

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

 18
Author: drinor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-06 20:28:57

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

 4
Author: brightknight08,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-25 14:23:57

A

No le gustó el enfoque de bus de eventos usando enlaces $on en el hijo durante create. ¿Por qué? Las llamadas posteriores create (estoy usando vue-router) enlazan el manejador de mensajes más de una vez leading lo que lleva a múltiples respuestas por mensaje.

La solución ortodoxa de pasar apoyos de padre a hijo y poner un vigilante de propiedades en el hijo 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 múltiple times necesita algún tipo de contabilidad para forzar una transición para que el niño pueda recoger el cambio.

He encontrado que si envuelvo el mensaje en una matriz, siempre activará el vigilante hijo even incluso si el valor sigue siendo el mismo.

Padre:

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

Hijo:

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

HTML:

<parent>
   <child v-bind="{ 'msgChild': msgChild }"></child>
</parent>
 1
Author: Jason Stewart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-05 06:34:50

Creo que deberíamos tener una consideración sobre la necesidad de que los padres usen el methods.In de hecho, los padres no necesitan preocuparse por el método del hijo, pero pueden tratar el componente hijo como una FSA(máquina de estados finitos).Componente de padres para controlar el estado del niño component.So la solución para ver el cambio de estado o simplemente usar la función compute es suficiente

 0
Author: user10097040,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-26 13:57:56