vuejs actualiza los datos principales del componente secundario


Estoy empezando a jugar con vuejs (2.0). Construí una página simple con un componente en ella. La página tiene una instancia de Vue con datos. En esa página me registré y agregué el componente a html. El componente tiene un input[type=text]. Quiero que ese valor se refleje en el padre (instancia principal de Vue).

¿Cómo actualizo correctamente los datos principales del componente? Pasar un prop enlazado desde el padre no es bueno y lanza algunas advertencias a la consola. Tienen algo en su doc, pero no es trabajo.

Author: coffee-grinder, 2016-12-01

4 answers

El enlace bidireccional ha sido obsoleto en Vue 2.0 en favor del uso de una arquitectura más basada en eventos. En general, un niño no debe mutar sus accesorios. Más bien, debería $emit y dejar que el padre responda a esos eventos.

En su caso específico, podría usar un componente personalizado con v-model. Esta es una sintaxis especial que permite algo cercano al enlace bidireccional, pero en realidad es una abreviatura de la arquitectura basada en eventos descrita anteriormente. Usted puede leer sobre aquí -> https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events.

Aquí hay un ejemplo simple:

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value'],
  methods: {
    updateValue: function (value) {
      this.$emit('input', value);
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentValue: 'hello'
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentValue}}</p>
  <child v-model="parentValue"></child>
</div>

<template id="child">
   <input type="text" v-bind:value="value" v-on:input="updateValue($event.target.value)">
</template>

Los documentos indican que

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

Es equivalente a

<custom-input v-model="something"></custom-input>

Es por eso que la prop en el hijo necesita ser named value, y por qué el hijo necesita emit emitir un evento llamado input.

 92
Author: asemahle,
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-04-06 00:37:00

De la documentación :

En SDV.js, la relación del componente padre-hijo se puede resumir como props abajo, eventos arriba. El padre pasa datos al hijo a través de accesorios, y el hijo envía mensajes al padre a través de eventos. Veamos cómo funcionan a continuación.

introduzca la descripción de la imagen aquí

Cómo pasar props

El siguiente es el código para pasar props a un elemento hijo:

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

Cómo emitir evento

HTML:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

JS:

Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
 69
Author: Saurabh,
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-31 23:34:29

También es posible pasar props como Objeto o Matriz. En este caso los datos serán bidireccionales:

(Esto se observa al final del tema: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow )

Vue.component('child', {
  template: '#child',
  props: {post: Object},
  methods: {
    updateValue: function () {
      this.$emit('changed');
    }
  }
});

new Vue({
  el: '#app',
  data: {
    post: {msg: 'hello'},
    changed: false
  },
  methods: {
    saveChanges() {
        this.changed = true;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{post.msg}}</p>
  <p v-if="changed == true">Parent msg: Data been changed - received signal from child!</p>
  <child :post="post" v-on:changed="saveChanges"></child>
</div>

<template id="child">
   <input type="text" v-model="post.msg" v-on:input="updateValue()">
</template>
 0
Author: Perlovka,
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-23 23:50:50

En el componente hijo: this.$emit.('eventname', this.variable)

En el componente padre:

<component @eventname="updateparent"></component>

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}
 0
Author: Sarvar Nishonboyev,
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-09-09 10:15:50