El patrón Vue es props
hacia abajo y hacia events
arriba. Suena simple, pero es fácil de olvidar al escribir un componente personalizado.
A partir de Vue 2.2.0, puede usar v-model (con propiedades calculadas ). He descubierto que esta combinación crea una interfaz simple, limpia y consistente entre componentes:
- Todo lo que se
props
pasa a su componente permanece reactivo (es decir, no está clonado ni requiere una watch
función para actualizar una copia local cuando se detectan cambios).
- Los cambios se emiten automáticamente a los padres.
- Se puede usar con múltiples niveles de componentes.
Una propiedad calculada permite que el definidor y el captador se definan por separado. Esto permite que el Task
componente se reescriba de la siguiente manera:
Vue.component('Task', {
template: '#task-template',
props: ['list'],
model: {
prop: 'list',
event: 'listchange'
},
computed: {
listLocal: {
get: function() {
return this.list
},
set: function(value) {
this.$emit('listchange', value)
}
}
}
})
La propiedad del modelo define qué prop
está asociado v-model
y qué evento se emitirá en los cambios. Luego puede llamar a este componente desde el padre de la siguiente manera:
<Task v-model="parentList"></Task>
La listLocal
propiedad calculada proporciona una interfaz getter y setter simple dentro del componente (piense que es una variable privada). Dentro de #task-template
usted puede renderizar listLocal
y permanecerá reactivo (es decir, si parentList
cambia, actualizará el Task
componente). También puede mutar listLocal
llamando al configurador (por ejemplo, this.listLocal = newList
) y emitirá el cambio al padre.
Lo bueno de este patrón es que puede pasar listLocal
a un componente secundario de Task
(usar v-model
), y los cambios del componente secundario se propagarán al componente de nivel superior.
Por ejemplo, supongamos que tenemos un EditTask
componente separado para realizar algún tipo de modificación en los datos de la tarea. Al usar el mismo v-model
patrón de propiedades calculadas podemos pasar listLocal
al componente (usando v-model
):
<script type="text/x-template" id="task-template">
<div>
<EditTask v-model="listLocal"></EditTask>
</div>
</script>
Si EditTask
emite un cambio llamará apropiadamente set()
en listLocal
y por lo tanto propagar el evento para el nivel superior. Del mismo modo, el EditTask
componente también podría llamar a otros componentes secundarios (como elementos de formulario) usando v-model
.