with vuejs vue page example event custom change javascript vue.js vue-component

javascript - vuejs - vue js custom event



vuejs actualiza datos primarios del componente secundario (7)

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 una input[type=text] . Quiero que ese valor se refleje en el padre (instancia principal de Vue).

¿Cómo actualizo correctamente los datos primarios del componente? Pasar un accesorio encuadernado del padre no es bueno y arroja algunas advertencias a la consola. Tienen algo en su documento pero no funciona.


De la documentation :

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

Cómo pasar accesorios

El siguiente es el código para pasar accesorios 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 } } })


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

En su caso específico, puede 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. Puede leer sobre esto 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 afirman 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 el accesorio en el niño necesita ser nombrado valor, y por qué el niño necesita $ emitir un evento llamado input .


En componente hijo:

<component @eventname="updateparent"></component> methods: { updateparent(variable) { this.parentvariable = variable } }

En el componente principal:

this.$emit(''update:title'', newTitle)


Estoy de acuerdo con la emisión de eventos y las respuestas del modelo v para los anteriores. Sin embargo, pensé en publicar lo que encontré sobre componentes con múltiples elementos de formulario que desean emitir a sus padres, ya que este parece ser uno de los primeros artículos devueltos por Google.

Sé que la pregunta especifica una sola entrada, pero esta parecía la coincidencia más cercana y podría ahorrarle a la gente algo de tiempo con componentes vue similares. Además, nadie ha mencionado aún el modificador .sync .

Hasta donde sé, la solución v-model solo es adecuada para una entrada que regresa a su padre. Me tomé un poco de tiempo buscándolo, pero la documentación de Vue (2.3.0) muestra cómo sincronizar múltiples accesorios enviados en el componente de regreso al padre (a través de la emisión, por supuesto).

Se llama apropiadamente el modificador .sync .

Esto es lo documentation dice la documentation :

En algunos casos, es posible que necesitemos un "enlace bidireccional" para un accesorio. Desafortunadamente, el enlace bidireccional verdadero puede crear problemas de mantenimiento, porque los componentes secundarios pueden mutar al padre sin que la fuente de esa mutación sea obvia tanto en el padre como en el niño.

Por eso, en su lugar, recomendamos emitir eventos en el patrón de update:myPropName . Por ejemplo, en un componente hipotético con un title propiedad, podríamos comunicar la intención de asignar un nuevo valor con:

<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" ></text-document>

Luego, el padre puede escuchar ese evento y actualizar una propiedad de datos local, si así lo desea. Por ejemplo:

<text-document v-bind:title.sync="doc.title"></text-document>

Para mayor comodidad, ofrecemos una abreviatura de este patrón con el modificador .sync:

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

También puede sincronizar múltiples a la vez enviando a través de un objeto. Mira la documentation


La forma más simple es usar this.$emit

Padre vue

<template> <div> <button @click="replyDaddy">Reply Daddy</button> </div> </template> <script> export default { name: "Child", methods: { replyDaddy() { this.$emit("listenerChild", "I''m here my Daddy!"); } } }; </script>

Child.vue

<template> <div> <button @click="replyDaddy">Reply Daddy</button> </div> </template> <script> export default { name: "Child", methods: { replyDaddy() { this.$emit("listenerChild", "I''m here my Daddy!"); } } }; </script>

Mi ejemplo completo: https://codesandbox.io/s/update-parent-property-ufj4b


También es posible pasar accesorios como Object o Array. En este caso, los datos se vincularán en dos sentidos:

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

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

<template> <div> <h1>{{ message }}</h1> <child v-on:listenerChild="listenerChild"/> </div> </template> <script> import Child from "./Child"; export default { name: "Father", data() { return { message: "Where are you, my Child?" }; }, components: { Child }, methods: { listenerChild(reply) { this.message = reply; } } }; </script>


Componente hijo

Use this.$emit(''event_name'') para enviar un evento al componente padre.

Componente principal

Para escuchar ese evento en el componente padre, hacemos v-on:event_name y se v-on:event_name un método (por ex. handleChange ) que queremos ejecutar en ese evento

Hecho :)