0% encontró este documento útil (0 votos)
203 vistas54 páginas

Vue2 Handbook

Este documento describe la sintaxis de plantillas y directivas de Vue.js. Vue utiliza una sintaxis de plantilla basada en HTML que vincula declarativamente el DOM renderizado a los datos subyacentes. Las plantillas se compilan en funciones de renderizado del DOM virtual para actualizaciones eficientes. Las directivas como v-if y v-bind aplican efectos secundarios al DOM de forma reactiva cuando cambian los valores de expresión. Las propiedades computadas permiten lógica más compleja de manera declarativa vinculando datos.

Cargado por

Maximiliano Raul
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
203 vistas54 páginas

Vue2 Handbook

Este documento describe la sintaxis de plantillas y directivas de Vue.js. Vue utiliza una sintaxis de plantilla basada en HTML que vincula declarativamente el DOM renderizado a los datos subyacentes. Las plantillas se compilan en funciones de renderizado del DOM virtual para actualizaciones eficientes. Las directivas como v-if y v-bind aplican efectos secundarios al DOM de forma reactiva cuando cambian los valores de expresión. Las propiedades computadas permiten lógica más compleja de manera declarativa vinculando datos.

Cargado por

Maximiliano Raul
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 54

Vue.

js
Handbook

Cesar Meloni

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Sintaxis de Template
Vue.js utiliza una sintaxis de template basada en HTML que le permite vincular de forma declarativa el DOM
renderizado a los datos de la instancia de Vue subyacente. Todas las templates de Vue.js son HTML válidas que
pueden analizarse mediante navegadores compatibles con especificaciones y analizadores de HTML.

Bajo el capó, Vue compila las templates en funciones de renderizado del DOM virtual. Combinado con el sistema
de reactividad, Vue puede averiguar de manera inteligente el número mínimo de componentes para volver a
renderizar y aplicar la cantidad mínima de manipulacion del DOM cuando el estado de la aplicacion cambia.

Si está familiarizado con los conceptos de DOM virtual y prefiere la potencia bruta de JavaScript, también
puede escribir directamente funciones de procesamiento en lugar de plantillas, con soporte opcional de JSX.

Interpolaciones

Texto

La forma más básica de enlace de datos es la interpolación de texto usando la sintaxis de mustaches (llaves
doble):

<span>Message: {{ msg }}</span>

La etiqueta del mustache se reemplazará con el valor de la propiedad msg en el objeto de datos correspondiente.


También se actualizará cada vez que cambie la propiedad msg del objeto de datos.

También puede realizar interpolaciones únicas que no se actualizan en el cambio de datos usando la directiva v-
once, pero tenga en cuenta que esto también afectará a cualquier otro enlace en el mismo nodo:

<span v-once>Esto nunca cambiara: {{ msg }}</span>

HTML Puro

Los mustaches (llaves doble) interpretan los datos como texto plano, no HTML. Para generar HTML real, deberá
utilizar la directiva v-html:

<p>Using mustaches: {{ rawHtml }}</p>


<p>Using v-html directive: <span v-html="rawHtml"></span></p>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Using mustaches: <span style="color: red">This should be red.</span>

Using v-html directive: This should be red.

El contenido del span se reemplazará con el valor de la propiedad rawHtml, interpretado como HTML simple: se
ignoran los enlaces de datos. Tenga en cuenta que no puede utilizar v-html para componer plantillas parciales,
porque Vue no es un motor de plantillas basado en cadenas. En cambio, se prefieren los componentes como la
unidad fundamental para la reutilización y la composición de la interfaz de usuario.

La ejecución dinámica de HTML arbitrario en su sitio web puede ser muy peligrosa porque puede conducir
fácilmente a vulnerabilidades de XSS. Utilice solo la interpolación HTML en contenido de confianza
y nunca en contenido proporcionado por usuario.

Atributos

Los mustaches (llaves doble) no se pueden utilizar dentro de los atributos HTML. En su lugar, use una directiva v-
bind:

<div v-bind:id="dynamicId"></div>

En el caso de los atributos booleanos, donde su mera existencia implica true, v-bind funciona de manera un


poco diferente. En este ejemplo:

<button v-bind:disabled="isButtonDisabled">Button</button>

Si isButtonDisabled tiene el valor de null, undefined o false, el atributo desabled ni siquiera se


incluirá en el elemento <button> representado.

Usando Expresiones JavaScript

Hasta ahora solo hemos estado vinculando a simples claves de propiedad en nuestras template. Pero Vue.js
realmente admite el poder completo de las expresiones de JavaScript dentro de todos los enlaces de datos:

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>

Estas expresiones se evaluarán como JavaScript en el ámbito de datos de la instancia de Vue del propietario. Una
restricción es que cada enlace solo puede contener una expresión, por lo que lo siguiente NO funcionará:

<!-- esto es una declaración, no una expresión -->


{{ var a = 1 }}
<!-- El control de flujo tampoco funcionará, use expresiones ternarias -->
{{ if (ok) { return message } }}

Las expresiones de template están en un espacio aislado y solo tienen acceso a una lista blanca de
elementos globales como Matemáticas y Fecha. No debe intentar acceder a globales definidos por el
usuario en expresiones de template.

Directivas

Las directivas son atributos especiales con el prefijo v-. Se espera que los valores de atributo de la directiva
sean una única expresión de JavaScript (con la excepción de v-for, que se tratará más adelante). El trabajo de
una directiva es aplicar reactivamente efectos secundarios al DOM cuando cambia el valor de su expresión.
Repasemos el ejemplo que vimos en la introducción:

<p v-if="seen">Now you see me</p>

Aquí, la directiva v-if insertaría/eliminaría el elemento basándose en la veracidad del valor de la


expresión seen.

Argumentos

Algunas directivas pueden tomar un “argumento”, denotado por dos puntos después del nombre de la directiva.
Por ejemplo, la directiva v-bind se usa para actualizar de forma reactiva un atributo HTML:

<a v-bind:href="url"> ... </a>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Aquí href es el argumento, que le dice a la directiva v-bind que vincule el atributo href del elemento al valor de
la expresión url.

Otro ejemplo es la directiva v-on, que escucha los eventos DOM:

<a v-on:click="doSomething"> ... </a>

Aquí el argumento es el nombre del evento a escuchar. Hablaremos sobre el manejo de eventos con más detalle
también.

Modificadores

Los modificadores son sufijos especiales indicados por un punto, que indican que una directiva debe estar
vinculada de alguna manera especial. Por ejemplo, el modificador .prevent le dice a la directiva v-on que
llame a event.preventDefault() en el evento activado:

<form v-on:submit.prevent="onSubmit"> ... </form>

Más adelante veremos otros ejemplos de modificadores, para v-on y para v-model, cuando exploremos esas


características.

Modo abreviado

El prefijo v- sirve como una señal visual para identificar atributos específicos de Vue en sus templates. Esto es útil
cuando está utilizando Vue.js para aplicar un comportamiento dinámico a algún marcado existente, pero puede
sentirse detallado para algunas directivas de uso frecuente. Al mismo tiempo, la necesidad del prefijo v- es
menos importante cuando se está construyendo un SPA donde Vue.js administra cada template. Por lo tanto,
Vue.js proporciona abreviaturas especiales para dos de las directivas más utilizadas, v-bind y v-on:

v-bind Abreviado

<!-- full syntax -->


<a v-bind:href="url"> ... </a>
<!-- abreviado -->

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


<a :href="url"> ... </a>

v-on Abreviado

<!-- full syntax -->


<a v-on:click="doSomething"> ... </a>
<!-- abreviado -->
<a @click="doSomething"> ... </a>

Pueden parecer un poco diferentes del HTML normal, pero : y @ son caracteres válidos para los nombres de
atributos y todos los navegadores compatibles con Vue.js pueden analizarlo correctamente. Además, no aparecen
en el marcado final renderizado. La sintaxis abreviada es totalmente opcional, pero es probable que la aprecie
cuando sepa más sobre su uso más adelante.

Propiedades Computadas y Observadores

Propiedades Computadas

Las expresiones en el template son muy convenientes, pero están diseñadas para operaciones simples. Poner
demasiada lógica en sus templates puede hacerlos grandes, complejos y difíciles de mantener. Por ejemplo:

<div id="example">
{{ message.split('').reverse().join('') }}
</div>

En este punto, el template ya no es simple y declarativo. Debe mirarlo por un segundo antes de darse cuenta de
que muestra message al revés. El problema se agrava cuando desea incluir el mensaje invertido en
su template más de una vez.

Es por eso que para cualquier lógica compleja, deberia usar una propiedad computada.

Ejemplo Básico

<div id="example">
<p>Mensaje original: "{{ message }}"</p>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


<p>Mensaje invertido computado: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hola'
},
computed: {
// un getter computado
reversedMessage: function () {
// `this` apunta a la instancia vm
return this.message.split('').reverse().join('')
}
}
})
Result:

Mensaje original: "Hola"

Mensaje invertido computado: "aloH"

Aquí hemos declarado una propiedad computada reversedMessage. La función que


proporcionemos se utilizará como la función getter para la propiedad vm.reversedMessage:

console.log(vm.reversedMessage) // => 'aloH'


vm.message = 'Adios'
console.log(vm.reversedMessage) // => 'soidA'

Puede abrir la consola y jugar con el ejemplo vm usted mismo. El valor de vm.reversedMessage siempre
depende del valor de vm.message.

Puede enlazar datos a propiedades computadas en el template al igual que una propiedad normal. Vue es
consciente de que vm.reversedMessage depende de vm.message, por lo cual actualizará todos los enlaces
que dependan de vm.reversedMessage cuando vm.message cambie. Y lo mejor de todo es que hemos
creado esta relación de dependencia de manera declarativa: la función computada getter no tiene efectos
secundarios, lo que facilita la prueba y la comprensión.

Caching computado vs Métodos

Es posible que haya notado que podemos lograr el mismo resultado al invocar un método en la expresión:

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


<p>Mensaje Invertido: "{{ reverseMessage() }}"</p>
// en componente
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('')
}
}

En lugar de una propiedad computada, podemos definir la misma función como un método en su lugar. Para el
resultado final, los dos enfoques son exactamente los mismos. Sin embargo, la diferencia es que las propiedades
computadas se almacenan en caché según sus dependencias. Una propiedad computada solo se volverá a
evaluar cuando alguna de sus dependencias haya cambiado. Esto significa que mientras message no haya
cambiado, el acceso múltiple a la propiedad computada de reverseMessage regresará inmediatamente el
resultado previamente calculado sin tener que ejecutar la función de nuevo.

Esto también significa que la siguiente propiedad computada nunca se actualizará, porque Date.now() no es
una dependencia reactiva:

computed: {
now: function () {
return Date.now()
}
}

En comparación, una invocación de método siempre ejecutará la función cada vez que ocurre una re-
renderizacion.

¿Por qué necesitamos caché? Imagina que tenemos una costosa propiedad computada A, que requiere hacer un
bucle a través de una gran matriz y hace muchos cálculos. Entonces podemos tener otras propiedades
computadas que a su vez dependen de A. Sin caché, estaríamos ejecutando el captador de A muchas veces más
de lo necesario. En los casos en que no desee el almacenamiento en caché, utilice un método en su lugar.

Propiedad Computada vs Watched

Vue proporciona una forma más genérica de observar y reaccionar a los cambios de datos en una instancia de
Vue: propiedad watch. Cuando tiene algunos datos que necesitan cambiarse en función de otros datos, es
tentador utilizar watch en exceso, especialmente si proviene de tener experiencia en AngularJS. Sin embargo, a
menudo es una mejor idea usar una propiedad computada en lugar de una imperativa llamada a watch .
Considera este ejemplo:

<div id="demo">{{ fullName }}</div>


var vm = new Vue({
el: '#demo',
data: {

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})

El código anterior es imperativo y repetitivo. Compáralo con una versión de propiedad computada:

var vm = new Vue({


el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})

Mucho mejor, ¿no?

Setter Computado

Las propiedades computadas son, de forma predeterminada solo get, pero también puede proporcionar un set
cuando lo necesite:

// ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...

Ahora, cuando ejecute vm.fullName = 'John Doe', se invocará el definidor


y vm.firstName y vm.lastName se actualizarán en consecuencia.

Watchers

Si bien las propiedades computadas son más apropiadas en la mayoría de los casos, hay ocasiones en que es
necesario un observador personalizado. Es por eso que Vue proporciona una forma más genérica de reaccionar a
los cambios de datos a través de la opción watch. Esto es más útil cuando desea realizar operaciones asíncronas
o costosas en respuesta al cambio de datos.

por ejemplo:

<div id="watch-example">
<p>
Haz una pregunta de sí/no:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<!-- Dado que ya existe un rico ecosistema de bibliotecas ajax -->
<!-- y colecciones de métodos de utilidad de uso general, Vue core -->
<!-- es capaz de permanecer pequeño al no reinventarlos. Esto también -->
<!-- te da la libertad de usar aquello con lo que estás familiarizado. -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'No puedo darte una respuesta hasta que hagas una pregunta!'
},
watch: {
// cada vez que la pregunta cambie, esta función será ejecutada
question: function (newQuestion, oldQuestion) {
this.answer = 'Esperando que deje de escribir...'
this.debouncedGetAnswer()
}
},
created: function () {
// _.debounce es una función proporcionada por lodash para limitar cuan

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


// a menudo se puede ejecutar una operación particularmente costosa.
// En este caso, queremos limitar la frecuencia con la que accedemos a
// yesno.wtf/api, esperando hasta que el usuario haya terminado
// de escribir antes de realizar la solicitud ajax.
// Para aprender más sobre la función _.debounce (y su primo
// _.throttle), visite: https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Las preguntas suelen contener un signo de interrogación. ;-)'
return
}
this.answer = 'Pensando...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = '¡Error! No se pudo alcanzar la API. ' + error
})
}
}
})
</script>

Result:

Haz una pregunta de sí/no: 

No puedo darte una respuesta hasta que hagas una pregunta!!

En este caso, el uso de la opción watch nos permite realizar una operación asíncrona (acceder a una API), limita
la frecuencia con la que realizamos esa operación y establece estados intermedios hasta que obtengamos una
respuesta final. Nada de eso sería posible con una propiedad computada.

Además de la opción watch, también puede usar el imperativo vm.$Watch API.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue
Enlace Clases y Estilos
Una necesidad común de data binding es manipular la lista de clases de un elemento y sus estilos en línea. Como
ambos son atributos, podemos usar v-bind para manejarlos: solo necesitamos crear una cadena de texto con
nuestras expresiones. Sin embargo, concatenar cadenas de texto puede llegar a ser incómodo y propenso a
errores. Por esta razón, Vue proporciona mejoras cuando se utiliza v-bind conclass y style. Además de las
cadenas de texto, las expresiones también pueden evaluar objetos o matrices.

Enlace de clases HTML

Sintaxis de Objeto

Podemos pasar un objeto a v-bind:class para la asignación dinámica de clases:

<div v-bind:class="{ active: isActive }"></div>

La sintaxis de arriba tiene como resultado la clase active según el valor


booleano(https://developer.mozilla.org/en-US/docs/Glossary/Truthy) de la propiedad isActive.

Puede hacer multiple asignación de clases al tener más campos en el objeto. Además, la directiva v-
bind:class también puede ser utilizada con el atributo class. De modo que con la siguiente plantilla:

<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>

Y el siguiente objeto data:

data: {
isActive: true,
hasError: false
}

Se renderizará:

<div class="static active"></div>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Cuando isActive o hasError cambien, la lista de clases se actualizará consecuentemente. Por ejemplo,
si hasError se convierte en true, la lista de clases se convertirá en "static active text-danger".

El objeto no tiene por qué estar en la misma línea:

<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}

Esto renderizará el mismo resultado. También podemos enlazar una propiedad computada que retorna un
objeto. Esto es un patrón común y poderoso:

<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}

Sintaxis de Array

Pasamos un array a v-bind:class para aplicar una lista de clases:

<div v-bind:class="[activeClass, errorClass]"></div>


data: {
activeClass: 'active',
errorClass: 'text-danger'
}

Que renderizará:

<div class="active text-danger"></div>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Si le gustaría activar una clase en la lista de manera condicional, usted puede hacerlo con una expresión ternaria:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>

Esto siempre aplicará errorClass, pero solo aplicará activeClass cuando isActive sea verdadero.

Sin embargo, esto puede ser un poco verborrágico si usted tiene multiple clases condicionales. Por eso también
es posible utilizar la sintaxis de objeto dentro de la sintaxis de colección:

<div v-bind:class="[{ active: isActive }, errorClass]"></div>

Con Componentes

Esta sección asume que usted tiene conocimientos sobre Componentes de Vue. Siéntase libre
de saltársela y volver más tarde.

Cuando usa el atributo class en un componente personalizado, estas clases se agregarán al elemento raíz del
componente. Las clases existentes en este elemento no serán sobreescritas.

Por ejemplo, si declara este componente:

Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})

Y agrega algunas clases al usarlo:

<my-component class="baz boo"></my-component>

El HTML renderizado será:

<p class="foo bar baz boo">Hi</p>

Lo mismo aplica para el enlace de clases:

<my-component v-bind:class="{ active: isActive }"></my-component>

Cuando isActive es verdadero, el HTML renderizado será:

<p class="foo bar active">Hi</p>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Enlace de estilos en línea

Sintaxis de Objeto

La sintaxis de objeto para v-bind:style es muy sencilla - es similar a CSS, excepto que es un objeto
JavaScript. Puede usar tanto camelCase como kebab-case (use comillas con kebab-case) para los nombres de
propiedades CSS:

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>


data: {
activeColor: 'red',
fontSize: 30
}

A menudo es una buena idea enlazar directamente un objeto de estilo para que la plantilla sea más limpia:

<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}

Nuevamente, la sintaxis de objeto es a menudo usada en conjunción con propiedades computadas que retornan
objetos.

Sintaxis de Array

La sintaxis de array v-bind:style permite aplicar múltiples objetos de estilo al mismo elemento:

<div v-bind:style="[baseStyles, overridingStyles]"></div>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Auto-prefijado

Cuando utilice una propiedad CSS que requiera prefijos de proveedores en v-bind:style, como por
ejemplo transform, Vue detectará automaticamente y agregará los prefijos correspondientes a los estilos
aplicados.

Valores múltiples

2.3.0+
Desde la versión 2.3.0+ usted puede proveer un array de valores múltiples (de prefijos) a una propiedad de estilo,
por ejemplo:

<div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

Esto solo renderizará el ultimo valor en el array que el navegador soporte. En este ejemplo, se
renderizará display: flex para los navegadores que soportan la versión sin prefijo de flexbox.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Renderización Condicional

v-if

En los string templates, como por ejemplo, Handlebars, escribiríamos un bloque condicional como este:

<!-- template de Handlebars -->


{{#if ok}}
<h1>Sí</h1>
{{/if}}

En Vue, usamos la directiva v-if para lograr lo mismo:

<h1 v-if="ok">Sí</h1>

También es posible agregar un “bloque else“ con v-else:

<h1 v-if="ok">Sí</h1>
<h1 v-else>No</h1>

Grupos Condicionales con v-if en <template>

Debido a que v-if es una directiva, debe adjuntarse a un solo elemento. Pero, ¿y si queremos cambiar más de
un elemento? En este caso, podemos usar v-if en un elemento<template>, que sirve como un envoltorio
invisible. El resultado final procesado no incluirá el elemento <template>.

<template v-if="ok">
<h1>Título</h1>
<p>Párrafo 1</p>
<p>Párrafo 2</p>
</template>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


v-else

Puede usar la directiva v-else para indicar un “bloque else“ para v-if:

<div v-if="Math.random() > 0.5">


Ahora me ves
</div>
<div v-else>
Ahora no
</div>

Un elemento v-else debe seguir inmediatamente a un elemento v-if o v-else-if, de lo contrario, no será


reconocido.

v-else-if

Nuevo en 2.1.0+
El v-else-if, como su nombre lo indica, sirve como “bloque else if“ para v-if. También puede ser
encadenado varias veces:

<div v-if="type === 'A'">


A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Si no es A, B o C
</div>

Similar a v-else, un elementov-else-if debe seguir inmediatamente a un elemento v-if o v-else-if.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Controlando Elementos Reutilizables con key

Vue intenta representar los elementos de la manera más eficiente posible, a menudo reutilizándolos en lugar de
renderizarlos desde cero. Más allá de ayudar a hacer Vue muy rápido, esto puede tener algunas ventajas útiles.
Por ejemplo, si permite a los usuarios alternar entre varios tipos de inicio de sesión:

<template v-if="loginType === 'username'">


<label>Nombre de Usuario</label>
<input placeholder="Ingrese su nombre de usuario">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Ingrese su email">
</template>

Luego, cambiando el loginType en el código anterior no borrará lo que el usuario ya ha ingresado. Dado que
ambos templates utilizan los mismos elementos, el <input> no se reemplaza, solo su placeholder.

Sin embargo, esto no siempre es deseable, por lo que Vue le ofrece una manera de decir: “Estos dos elementos
están completamente separados, no los reutilice”. Agregue un atributo key con valores únicos:

<template v-if="loginType === 'username'">


<label>Nombre de Usuario</label>
<input placeholder="Ingrese su nombre de usuario" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Ingrese su nombre de usuario" key="email-input">
</template>

Observe que los elementos <label> son todavía reutilizables, porque no tienen atributos key.

v-show

Otra opción para mostrar un elemento condicionalmente es la directiva v-show. La utlización es basicamente la


mismo:

<h1 v-show="ok">Hola!</h1>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


La diferencia es que un elemento con v-show siempre se renderizará y permanecerá en el DOM; v-
show simplemente alterna la propiedad CSS display del elemento.

Observe que el uso de v-show no es compatible con elementos <template>, ni tampoco funciona con v-
else.

v-if vs v-show

v-if es una renderización condicional “real” ya que garantiza que los eventos y componentes secundarios
dentro del bloque condicional sean debidamente destruidos y recreados durante la alternancia.

v-if también es lazy: si la condición es falsa en la representación inicial, no se hará nada. El bloque condicional
no se procesará hasta que la condición se convierta en true por primera vez.

En comparación, v-show es mucho más simple: el elemento siempre se representa independientemente de la


condición inicial, con alternancia basada en CSS.

En general, v-if tiene costos de alternancia más altos, mientras quev-show tiene costos de renderización


iniciales más altos. Por lo tanto, prefiera v-show si necesita cambiar algo muy a menudo, y prefierav-if si es
poco probable que la condición cambie en el tiempo de ejecución.

v-if con v-for

Usando v-if y v-for juntos no es recomendado. Vea la guía de estilo para mayor información.

Cuando es utilizado junto con v-for, este tiene una prioridad más alta que v-if. Consulte la guía de
renderización de listas para obtener más información.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Renderizado de lista

Mapeando una matriz a elementos con v-for

Podemos usar la directiva v-for para representar una lista de elementos basada en una matriz. La directiva v-
for requiere una sintaxis especial en forma de item in items, donde los items son la matriz de datos de
origen y el item es un alias para el elemento de matriz que se está iterando:

<ul id="example-1">
<li v-for="item in items">
{{ item.mensaje }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ mensaje: 'Foo' },
{ mensaje: 'Bar' }
]
}
})
Resultado:

•Foo

•Bar

Dentro de los bloques v-for tenemos acceso completo a las propiedades del ámbito principal. v-for también
admite un segundo argumento opcional para el índice del elemento actual.

<ul id="example-2">
<li v-for="(item, index) in items">
{{ MensajePadre }} - {{ index }} - {{ item.mensaje }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


mensajePadre: 'Padre',
items: [
{ mensaje: 'Foo' },
{ mensaje: 'Bar' }
]
}
})

Resultado:

•Padre - 0 - Foo

•Padre - 1 - Bar

También puede usar of como delimitador en lugar de in, de modo que esté más cerca de la sintaxis de
JavaScript para los iteradores:

<div v-for="item of items"></div>

v-for con un Objeto

También puede usar v-for para iterar a través de las propiedades de un objeto.

<ul id="v-for-object" class="demo">


<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
primerNombre: 'John',
apellido: 'Doe',
edad: 30
}
}
})

Resultado:

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


•John

•Doe

•30

También puede proporcionar un segundo argumento para la clave:

<div v-for="(value, key) in object">


{{ key }}: {{ value }}
</div>

primerNombre: John

apellido: Doe

edad: 30

Y otro para el índice:

<div v-for="(value, key, index) in object">


{{ index }}. {{ key }}: {{ value }}
</div>

0. primerNombre: John

1. apellido: Doe

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


2. edad: 30

Al iterar sobre un objeto, el orden se basa en el orden de enumeración de claves de Object.keys(), que
no se garantiza que sea consistente en todas las implementaciones del motor de JavaScript.

key

Cuando Vue está actualizando una lista de elementos representados con v-for, por defecto utiliza una
estrategia de “parche in situ”. Si el orden de los elementos de datos ha cambiado, en lugar de mover los
elementos DOM para que coincidan con el orden de los elementos, Vue aplicará parches a cada elemento en el
lugar y se asegurará de que refleje lo que se debe representar en ese índice en particular. Esto es similar al
comportamiento de track-by="$index" en Vue 1.x.

Este modo predeterminado es eficiente, pero solo es adecuado cuando la salida de renderizado de su lista no
se basa en el estado del componente secundario o el estado temporal de DOM (por ejemplo, valores de
entrada de formulario).

Para proporcionar a Vue una sugerencia para que pueda rastrear la identidad de cada nodo y, por lo tanto,
reutilizar y reordenar los elementos existentes, debe proporcionar un atributo key único para cada elemento. Un
valor ideal para key sería el ID único de cada elemento. Este atributo especial es un equivalente aproximado
a track-by en 1.x, pero funciona como un atributo, por lo que necesita usar v-bind para enlazarlo con valores
dinámicos (usando el modo abreviado aquí):

<div v-for="item in items" :key="item.id">


<!-- content -->
</div>

Se recomienda proporcionar una key con v-for siempre que sea posible, a menos que el contenido DOM
iterado sea simple, o esté confiando intencionalmente en el comportamiento predeterminado para obtener
ganancias en el rendimiento.

Como Vue es un mecanismo genérico para identificar nodos, la key también tiene otros usos que no están
específicamente vinculados a v-for, como veremos más adelante en la guía.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Deteccion del cambios en Array

Metodos de Mutacion

Vue envuelve los métodos de mutación de una matriz observada para que también activen las actualizaciones de
vista. Los métodos envueltos son:

•push()
•pop()
•shift()
•unshift()
•splice()
•sort()
•reverse()
Puede abrir la consola y probar con la matriz de items de los ejemplos anteriores llamando a sus métodos de
mutación. Por ejemplo: example1.items.push ({mensaje: 'Baz'}).

Mutando un Array

Los métodos de mutación, como sugiere su nombre, mutan la matriz original a la que se llama. En comparación,
también hay métodos no mutantes, p. Ej. filter(), concat() y slice(), que no mutan la matriz original
pero siempre devuelven una nueva matriz. Cuando trabaje con métodos no mutantes, puede reemplazar la
matriz anterior por la nueva:

example1.items = example1.items.filter(function (item) {


return item.mensaje.match(/Foo/)
})

Podría pensar que esto hará que Vue elimine el DOM existente y vuelva a renderizar la lista completa;
afortunadamente, ese no es el caso. Vue implementa algunas heurísticas inteligentes para maximizar la
reutilización de elementos DOM, por lo tanto, reemplazar una matriz con otra matriz que contenga objetos
superpuestos es una operación muy eficiente.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Advertencias

Debido a las limitaciones en JavaScript, Vue no puede detectar los siguientes cambios en una matriz:

1.Cuando configura directamente un elemento con el índice, por ejemplo, vm.items[indexOfItem] =


newValue

2.Cuando modifica la longitud de la matriz, por ejemplo, vm.items.length = newLength


Por ejemplo:

var vm = new Vue({


data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // NO es reactivo
vm.items.length = 2 // NO es reactivo

Para superar la advertencia 1, ambos de los siguientes lograrán lo mismo que vm.items[indexOfItem] =


newValue, pero también activarán actualizaciones de estado en el sistema de reactividad:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

También puede usar el método de instancia vm.$Set, que es un alias para el Vue.set global:

vm.$set(vm.items, indexOfItem, newValue)

Para tratar con la advertencia 2, puede usar splice:

vm.items.splice(newLength)

Advertencias con la Deteccion de Cambios en Objetos

Una vez más, debido a las limitaciones del JavaScript moderno, Vue no puede detectar la adición o eliminación
de propiedades. Por ejemplo:

var vm = new Vue({


data: {
a: 1
}

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


})
// `vm.a` ahora es reactivo
vm.b = 2
// `vm.b` NO es reactivo
/

Vue no permite agregar dinámicamente nuevas propiedades reactivas a nivel de raíz a una instancia ya creada.
Sin embargo, es posible agregar propiedades reactivas a un objeto anidado usando el método Vue.set
(objeto, clave, valor). Por ejemplo, dado:

var vm = new Vue({


data: {
userProfile: {
name: 'Anika'
}
}
})

Podría agregar una nueva propiedad de edad al objeto de userProfile anidado con:

Vue.set(vm.userProfile, 'edad', 27)

También puede usar el método de instancia vm. $Set, que es un alias para el Vue.set global:

vm.$set(vm.userProfile, 'edad', 27)

En ocasiones, es posible que desee asignar varias propiedades nuevas a un objeto existente, por ejemplo,
utilizando Object.assign() o _.extend(). En tales casos, debe crear un objeto nuevo con propiedades de
ambos objetos. Así que en lugar de:

Object.assign(vm.userProfile, {
edad: 27,
favoriteColor: 'Vue Green'
})

Podría agregar nuevas propiedades reactivas con:

vm.userProfile = Object.assign({}, vm.userProfile, {


edad: 27,
favoriteColor: 'Vue Green'
})

Mostrando Resultados Filtrados/Ordenados

A veces, queremos mostrar una versión filtrada u ordenada de una matriz sin mutar o restablecer los datos
originales. En este caso, puede crear una propiedad computada que devuelva la matriz filtrada o ordenada.

Por ejemplo:

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


<li v-for="n in numerosImpares">{{ n }}</li>
data: {
numeros: [ 1, 2, 3, 4, 5 ]
},
computed: {
numerosImpares: function () {
return this.numeros.filter(function (numero) {
return numero % 2 === 0
})
}
}

En situaciones donde las propiedades computadas no son factibles (por ejemplo, dentro de los bucles v-
for anidados), puede usar un método:

<li v-for="n in even(numeros)">{{ n }}</li>


data: {
numeros: [ 1, 2, 3, 4, 5 ]
},
methods: {
even: function (numeros) {
return numeros.filter(function (numero) {
return numero % 2 === 0
})
}
}

v-for con un Rango

v-for también puede tomar un entero. En este caso repetirá la plantilla muchas veces.

<div>
<span v-for="n in 10">{{ n }} </span>
</div>
Resultado:

1 2 3 4 5 6 7 8 9 10

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


v-for en un <template>

De forma similar a la plantilla v-if, también puede usar una etiqueta <template> con v-for para renderizar


un bloque de varios elementos. Por ejemplo:

<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>

v-for con v-if

Tenga en cuenta que no se recomienda usar v-if y v-for juntos. Consulte la guía de estilo para más


detalles.

Cuando existen en el mismo nodo, v-for tiene una prioridad más alta que v-if. Eso significa que el v-if se
ejecutará en cada iteración del bucle por separado. Esto puede ser útil cuando desea representar nodos solo
para algunos elementos, como a continuación:

<li v-for="todo in todos" v-if="!todo.isComplete">


{{ todo }}
</li>

Lo anterior hace que todos los que no estén completos, se renderizen.

Si, por el contrario, su intención es omitir condicionalmente la ejecución del bucle, puede colocar el v-if en un
elemento de envoltura (o <template>). Por ejemplo:

<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No quedan todos !</p>

v-for con un Componente

Esta sección asume el conocimiento de Componentes. Siéntase libre de saltearlo y volver más
tarde.

Puede usar v-for directamente en un componente personalizado, como cualquier elemento normal:

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


<my-component v-for="item in items" :key="item.id"></my-component>
En 2.2.0+, cuando se usa v-for con un componente, ahora se requiere una key.

Sin embargo, esto no pasará automáticamente ningún dato al componente, porque los componentes tienen sus
propios ámbitos aislados. Para pasar los datos iterados al componente, también debemos usar props:

<my-component
v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id"
></my-component>

La razón para no inyectar automáticamente el item en el componente es porque hace que el componente esté
estrechamente acoplado a cómo funciona v-for. Ser explícito acerca de dónde provienen sus datos hace que el
componente sea reutilizable en otras situaciones.

Aquí hay un ejemplo completo de una lista de tareas simple:

<div id="todo-list-example">
<form -on:submit.prevent="addNewTodo">
<label for="new-todo">Agregar tarea</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder=E.g. Feed the cat"
>
<button>Agregar</button>
</form>
<ul>
<li
is="todo-item"
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></li>
</ul></div>
Note el atributo is = "todo-item". Esto es necesario en las plantillas DOM, porque solo un
elemento <li> es válido dentro de un <ul>. Hace lo mismo que <todo-item>, pero funciona alrededor
de un error potencial de análisis del navegador. Ver las advertencias de análisis de plantillas
DOM aprender más.

.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button -on:click="$emit(\'remove\')">Remove</button>\
</li>\

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


',
props: ['title']
})
new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [
{
id: 1,
title: 'Do the dishes'
},
{
id: 2,
title: 'Take out the trash'
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function () {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Manejo de eventos

Escuchar eventos

Podemos usar la directiva v-on para escuchar eventos DOM y ejecutar algunos JavaScript cuando se activan.

Por ejemplo:

<div id="example-1">
<button v-on:click="counter += 1">Add 1</button>
<p>Se ha hecho clic en el botón de arriba {{ counter }} veces.</p>
</div>
var example1 = new Vue({
el: '#example-1',
data: {
counter: 0
}
})

Métodos Manejadores de eventos

Sin embargo, la lógica para muchos controladores de eventos será más compleja, por lo que no es posible
mantener su JavaScript en el valor del atributo v-on. Es por eso que v-on también puede aceptar el nombre de
un método al que te gustaría llamar.

Por ejemplo:

<div id="example-2">
<!-- `saludar` es el nombre de un método definido a continuación -->
<button v-on:click="saludar">Saludar</button>
</div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// definir métodos bajo el objeto `methods`
methods: {
saludar: function (event) {
// `this` dentro de los métodos apunta a la instancia de Vue
alert('Hola ' + this.name + '!')
// `evento` es el evento DOM nativo
if (event) {

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


alert(event.target.tagName)
}
}
}
})
// también puedes invocar métodos en JavaScript.
example2.greet() // => 'Hello Vue.js!'

Métodos Manejadores en línea

En lugar de enlazar directamente con un nombre de método, también podemos usar métodos en una declaración
de JavaScript en línea:

<div id="example-3">
<button v-on:click="di('hola')">Di hola</button>
<button v-on:click="di('que')">Di que</button>
</div>
new Vue({
el: '#example-3',
methods: {
di: function (mensaje) {
alert(mensaje)
}
}
})

A veces también necesitamos acceder al evento DOM original en un controlador de instrucciones en línea. Puedes
pasarlo a un método usando la variable especial $event:

<button v-on:click="Alertar('El Form no se puede enviar aun.', $event)">


Enviar
</button>
// ...
methods: {
Alertar: function (message, event) {
// ahora tenemos acceso al evento nativo.
if (event) event.preventDefault()
alert(message)
}
}

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Modificadores de eventos

Es una necesidad muy común llamar a event.preventDefault() o event.stopPropagation() dentro


de los controladores de eventos. Aunque podemos hacer esto fácilmente dentro de los métodos, sería mejor si los
métodos fueran puramente sobre lógica de datos en lugar de tener que lidiar con los detalles del evento DOM.

Para solucionar este problema, Vue proporciona modificadores de eventos para v-on. Recuerde que los
modificadores son directivas postfijos marcados por un punto.

•.stop
•.prevent
•.capture
•.self
•.once
•.passive
<!-- Se detendrá la propagación del evento click. -->
<a v-on:click.stop="hasEsto"></a>
<!-- El evento de enviar ya no volverá a cargar la página. -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- Los modificadores pueden encadenarse -->
<a v-on:click.stop.prevent="hasEsto"></a>
<!-- solo el modificador -->
<form v-on:submit.prevent></form>
<!-- utilizar el modo de captura al agregar el detector de eventos -->
<!-- es decir, un evento dirigido a un elemento interno se maneja aquí antes de ser maneja
<div v-on:click.capture="hazEsto">...</div>
<!-- solo activa el controlador si event.target es el elemento en sí -->
<!-- es decir, no de un elemento hijo -->
<div v-on:click.self="hazEso">...</div>
El orden es importante cuando se usan modificadores porque el código relevante se genera en el mismo
orden. Por lo tanto, el uso de v-on: click.prevent.self evitará todos los clics mientras que v-on:
click.self.prevent solo evitará clics en el elemento en sí.

Nuevo en 2.1.4+
<!-- El evento de clic se activará como máximo una vez. -->
<a v-on:click.once="hasEsto"></a>
A diferencia de los otros modificadores, que son exclusivos de los eventos DOM nativos, el
modificador .once también se puede usar en eventos personalizados. Si aún no ha leído sobre componentes,
no se preocupe de esto por ahora.

Nuevo in 2.3.0+
Vue también ofrece el modificador .passive, correspondiente a la opción pasiva de addEventListener.

<!-- El comportamiento predeterminado del evento scroll (scrolling) sucederá -->


<!-- inmediatamente, en lugar de esperar a que se complete `onScroll` -->
<!-- en caso de que contenga `event.preventDefault ()` -->
<div v-on:scroll.passive="onScroll">...</div>
El modificador .passive es especialmente útil para mejorar el rendimiento en dispositivos móviles.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


No use .passive y .prevent juntos, ya que .prevent se ignorará y su navegador probablemente le
mostrará una advertencia. Recuerde, .passive comunica al navegador que no desea evitar el
comportamiento predeterminado del evento.

Modificadores de Teclas

Cuando escuchamos eventos de teclado, a menudo necesitamos verificar códigos de teclas comunes. Vue
también permite agregar modificadores clave para v-on cuando se escuchan eventos de teclado:

<!-- solo llame a `vm.submit ()` cuando el `keyCode` es 13 -->


<input v-on:keyup.13="submit">
Recordar todos los keyCodes son un dolor de cabeza, por lo que Vue proporciona alias para las teclas más
utilizadas:

<!-- lo mismo que arriba -->


<input v-on:keyup.enter="submit">
<!-- También funciona como abreviacion. -->
<input @keyup.enter="submit">
Aqui esta la lista completa de alias:

•.enter
•.tab
•.delete (captura ambas teclas “Delete” y “Backspace”)
•.esc
•.space
•.up
•.down
•.left
•.right
También puede definir alias modificadores de tecla personalizados a través del objeto
global config.keyCodes:

// habilita `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112

Modificadores automáticos de teclas

Nuevo in 2.5.0+
También puede usar directamente cualquier nombre de tecla válido expuesto a través
de KeyboardEvent.key como modificadores convirtiéndolos a kebab-case:

<input @keyup.page-down="onPageDown">
En el ejemplo anterior, solo se llamará al controlador si $event.key === 'PageDown'

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Algunas teclas (.esc y todas las teclas de flecha) tienen valores key incoherentes en IE9; se deben preferir
sus alias integrados si necesita compatibilidad con IE9.

Modificador del Teclas del Sistema

Nuevo en 2.1.0+
Puede usar los siguientes modificadores para activar eventos listeners de raton o teclado solo cuando se presiona
la tecla modificadora correspondiente:

•.ctrl
•.alt
•.shift
•.meta
Nota: En los teclados de Macintosh, meta es la tecla de comando (⌘). En los teclados de
Windows, meta es la tecla de Windows (). En los teclados de Sun Microsystems, el meta está
marcado como un diamante sólido (◆). En ciertos teclados, específicamente los teclados y
sucesores de máquinas MIT y Lisp, como el teclado Knight, el teclado space-cadet, el meta está
etiquetado como “META”. En los teclados de Symbolics, el meta está etiquetado como “META”
o “Meta”.
Por ejemplo:

<!-- Alt + C -->


<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
Tenga en cuenta que las teclas modificadoras son diferentes de las teclas normales y cuando se usan con
eventos keyup, deben presionarse cuando se emite el evento. En otras palabras, keyup.ctrl solo se
activará si sueltas una tecla mientras mantienes presionada la tecla Ctrl. No se activará si suelta la
tecla ctrl solo. Si desea tal comportamiento, use el código de tecla para ctrl en su
lugar: keyup.17.

Modificador .exact

Nuevo en 2.5.0+
El modificador .exact permite el control de la combinación exacta de modificadores del sistema necesarios
para desencadenar un evento.

<!-- esto se disparará incluso si se presiona Alt o Shift -->


<button @click.ctrl="onClick">A</button>
<!-- esto solo se activará cuando se presione Ctrl y no se presionen otras teclas -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- esto solo se activará cuando no se presionen modificadores del sistema -->
<button @click.exact="onClick">A</button>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Modificador de Boton del Raton

Nuevo en 2.2.0+
•.left
•.right
•.middle
Estos modificadores restringen el controlador a eventos activados por un botón específico del raton.

Porque Listeners en HTML?

Es posible que le preocupe que todo este enfoque de escucha de eventos viole las viejas buenas reglas sobre la
“separation of concerns” (“separación de preocupaciones”). Tenga la tranquilidad de que todas las funciones y
expresiones del controlador de Vue están estrictamente vinculadas a ViewModel que esta manejando la vista
actual, no causará ninguna dificultad de mantenimiento. De hecho, hay varios beneficios en el uso de v-on:

1.Es más fácil ubicar las implementaciones de la función de controlador dentro de su código JS al ojear la
plantilla HTML.

2.Una vez que no tenga que adjuntar manualmente eventos listeners en JS, su código de ViewModel puede ser de
lógica pura y libre de DOM. Esto hace que sea más fácil de probar.

3.Cuando se destruye un ViewModel, todos los eventos listeners se eliminan automáticamente. No tiene que
preocuparse por limpiarlo usted mismo.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Binding en Formularios

Uso básico

Puede usar la directiva v-model para crear bindings de datos bidireccionales (two-way binding) en


elementos input, textarea y select de un formulario. La directiva busca automáticamente la manera correcta de
actualizar el elemento según el tipo de entrada. Aunque un poco mágico, v-model es esencialmente syntax
sugar para actualización de datos a través de eventos de entradas del usuario, además de mostrar un cuidado
especial para algunos casos de borde.

v-model ignorará el value inicial, los atributos checked o selected que se encuentran en cualquier


elemento de formulario. Siempre tratará los datos de la instancia de Vue como la fuente confiable. Debe
declarar el valor inicial del lado de JavaScript, dentro de la opción data de su componente.

Para los idiomas que requieren un IME (chino, japonés, coreano, etc.), notará que el v-model no se
actualiza durante la composición del IME. Si también desea atender estas actualizaciones, use un
evento input en su lugar.

Input

<input v-model="message" placeholder="edíteme">


<p>El mensaje es: {{ message }}</p>

Textarea

<span>El mensaje multilínea es:</span>


<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="agregar múltiples líneas"></textarea>

La interpolación en textareas no funciona (<textarea>{{text}}</textarea>). En su lugar use v-


model.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Checkbox

Checkbox simples con valor booleano:

<input type="checkbox" id="checkbox" v-model="checked">


<label for="checkbox">{{ checked }}</label>

Múltiples checkboxes vinculados al mismo Array:

<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
new Vue({
el: '#example-3',
data: {
checkedNames: []
}
})

Radio

<input type="radio" id="uno" value="Uno" v-model="picked">


<label for="uno">Uno</label>
<br>
<input type="radio" id="Dos" value="Dos" v-model="picked">
<label for="Dos">Dos</label>
<br>
<span>Eligió: {{ picked }}</span>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Select

Selección de un solo elemento:

<select v-model="selected">
<option disabled value="">Seleccione un elemento</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Seleccionado: {{ selected }}</span>
new Vue({
el: '...',
data: {
selected: ''
}
})

Si el valor inicial de su expresión v-model no coincide con ninguna de las opciones, el


elemento <select> se representará en un estado “unselected”. En iOS, esto hará que el usuario no pueda
seleccionar el primer elemento porque iOS no dispara un evento de cambio en este caso. Por lo tanto, se
recomienda proporcionar una opción deshabilitada con un valor vacío, como se muestra en el ejemplo
anterior.

Selección de múltiples elementos (vinculando a un Array):

<select v-model="selected" multiple>


<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Seleccionados: {{ selected }}</span>

Opciones dinámicas renderizadas con v-for:

<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Seleccionado: {{ selected }}</span>
new Vue({
el: '...',
data: {
selected: 'A',
options: [

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


{ text: 'Uno', value: 'A' },
{ text: 'Dos', value: 'B' },
{ text: 'Tres', value: 'C' }
]
}
})

Vinculando a Valores

Para radio, checkbox y option de select, los valores de vinculación del v-model suelen ser cadenas estáticas (o


booleanos para checkbox):

<!-- `picked` es una cadena "a" cuando está chequeado -->


<input type="radio" v-model="picked" value="a">
<!-- `toggle` es verdadero o falso -->
<input type="checkbox" v-model="toggle">
<!-- `selected` es una cadena "abc" cuando se selecciona la primera opción -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>

Pero a veces es posible que queramos vincular el valor a una propiedad dinámica en la instancia de Vue. Podemos
usar v-bind para lograr eso. Además, el uso de v-bind nos permite vincular el valor de entrada a valores no
cadena.

Checkbox

<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
// cuando está marcado:
vm.toggle === 'yes'
// cuando está desmarcado:
vm.toggle === 'no'

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Los atributos de true-value y de false-value no afectan la entrada del atributo value, ya que los
navegadores no incluyen casillas sin marcar en los envíos de formularios. Para garantizar que uno de los dos
valores se envie en un formulario (por ejemplo, “yes” o “no”), use entradas de radio en su lugar.

Radio

<input type="radio" v-model="pick" v-bind:value="a">


// cuando está marcado:
vm.pick === vm.a

Select

<select v-model="selected">
<!-- objeto literal en línea --> -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
// cuando está seleccionado:
typeof vm.selected // => 'object'
vm.selected.number // => 123

Modificadores

.lazy

De forma predeterminada, v-model sincroniza el input con los datos después de cada evento de


tipo input (con la excepción de la composición IME descrito anteriormente). En lugar de esto, puede agregar el
modificador lazy para realizar la sincronización después del evento change:

<!-- sincronizado después de "change" en lugar de "input" -->


<input v-model.lazy="msg" >

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


.number

Si desea que las entradas del usuario se escriban automáticamente como un número, puede agregar el
modificador number al v-model del elemento:

<input v-model.number="age" type="number">

Esto suele ser útil, porque incluso con type="number", el valor retornado por el elemento HTML siempre es
una cadena de texto. Si el valor no se puede analizar con parseFloat(), se retorna el valor original.

.trim

Si desea que las entradas del usuario se recorten automáticamente, puede agregar el modificador trim al v-
model de su elemento:

<input v-model.trim="msg">

v-model con Componentes

Si aún no está familiarizado con los componentes de Vue, puede omitir esto por ahora.
Los tipos de input nativos de HTML no siempre satisfarán sus necesidades. Afortunadamente, los componentes
de Vue le permiten crear input reutilizables con un comportamiento completamente personalizado. Estos
componentes también funcionan con v-model! Para aprender más, lea acerca de inputs personalizados en la
guía de componentes.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Conceptos Básicos de Componentes

Ejemplo base

Aquí un ejemplo de un componente Vue:

// Definir un nuevo componente llamado button-counter


Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">Me ha pulsado {{ count }} veces.</button>'
})

Los componentes son instancias reutilizables de Vue con un nombre: en este caso, <button-counter>.
Podemos usar este componente como un elemento personalizado dentro de una instancia de Vue raíz creada
con new Vue:

<div id="components-demo">
<button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })

Dado que los componentes son instancias reutilizables de Vue, aceptan las mismas opciones que new Vue,
como data, computed, watch, methods, y hooks de ciclo de vida. Las únicas excepciones son algunas
opciones específicas de la raíz como el.

Reutilizando Componentes

Los componentes se pueden reutilizar tantas veces como se desee:

<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
Tenga en cuenta que al hacer clic en los botones, cada uno mantiene su propio count por separado. Esto se debe
a que cada vez que utiliza un componente, se crea una nueva instancia del mismo.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


data Debe ser una función

Cuando definimos el componente <button-counter>, es posible que haya notado que data no devuelve


directamente un objeto, como este:

data: {
count: 0
}

En lugar de eso, la opción data de un componente debe ser una función, de modo que cada instancia pueda
mantener una copia independiente del objeto de datos devuelto:

data: function () {
return {
count: 0
}
}
Si Vue no tuviera esta regla, hacer clic en un botón afectaría los datos de todas las demás instancias.

Organización de Componentes

Es común que una aplicación se organice en un árbol de componentes anidados:

Por ejemplo, puede tener componentes para un encabezado, una barra lateral y un área de contenido, cada uno
de los cuales generalmente contiene otros componentes para enlaces de navegación, publicaciones de blog, etc.

Para usar estos componentes en templates, deben registrarse para que Vue los conozca. Existen dos tipos de
registro de componentes: global y local. Hasta ahora, solo hemos registrado componentes globalmente,
usando Vue.component:

Vue.component('my-component-name', {

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


// ... opciones ...
})
Los componentes registrados globalmente se pueden usar en el template de cualquier instancia de Vue raíz (new
Vue) creada posteriormente, e incluso dentro de todos los subcomponentes del árbol de componentes de esa
instancia de Vue.

Eso es todo lo que necesita saber sobre el registro por ahora, pero una vez que haya terminado de leer esta página
y se sienta cómodo con su contenido, le recomendamos volver más tarde para leer la guía completa de Registro
de Componentes.

Pasando datos a componentes secundarios con Props

Anteriormente, mencionamos la creación de un componente para publicaciones de blog. El problema es que ese
componente no será útil a menos que puedas pasarle datos, como el título y el contenido de la publicación
específica que queremos mostrar. Ahí es donde entran las props.

Las props son atributos personalizados que usted puede registrar en un componente. Cuando se pasa un valor a
un atributo prop, se convierte en una propiedad en esa instancia de componente. Para pasar un título a nuestro
componente de publicación de blog, podemos incluirlo en la lista de props que este componente acepta, usando
la opción props:

Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})

Un componente puede tener tantas props como se desee, y se puede pasar cualquier valor a cualquier prop de
forma predeterminada. En el template anterior, verá que podemos acceder a este valor en la instancia del
componente, al igual que con data.

Una vez que se registra un prop, puede pasarle datos como un atributo personalizado, de la siguiente manera:

<blog-post title="Mi viaje con Vue"></blog-post>


<blog-post title="Blogging con Vue"></blog-post>
<blog-post title="Por qué Vue es tan divertido?"></blog-post>

En una aplicación típica, sin embargo, es probable que tenga un array de post en data:

new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'Mi viaje con Vue' },
{ id: 2, title: 'Blogging con Vue' },
{ id: 3, title: 'Por qué Vue es tan divertido?' }

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


]
}
})

Entonces querrá renderizar un componente para cada uno:

<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>

Arriba, verá que podemos usar v-bind para pasar propiedades dinámicamente. Esto es especialmente útil


cuando no se conoce el contenido exacto que se va a renderizar con anticipación, como cuando se obtienen
posts de una API.

Esto es todo lo que necesita saber sobre propiedades por ahora, pero una vez que haya terminado de leer esta
página y se sienta cómodo con su contenido, le recomendamos volver más tarde para leer la guía completa
de Propiedades.

Un elemento de una sola raíz

Al crear un componente <blog-post>, su plantilla eventualmente no contendrá más que solo el título:

<h3>{{ title }}</h3>


Como mínimo, querrá incluir el contenido del post:

<h3>{{ title }}</h3>


<div v-html="content"></div>

Sin embargo, si intenta esto en su plantilla, Vue mostrará un error, explicando que cada componente debe tener
un solo elemento raíz. Puede corregir este error envolviendo la plantilla en un elemento principal de la siguiente
manera:

<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>

A medida que nuestro componente crezca, es probable que no solo necesitemos el título y el contenido de una
publicación, sino también la fecha de publicación, los comentarios y más. Definir una propiedad para cada pieza
de información relacionada podría volverse muy molesto:

<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


v-bind:publishedAt="post.publishedAt"
v-bind:comments="post.comments"
></blog-post>

Por lo tanto, este podría ser un buen momento para refactorizar el componente <blog-post> para que acepte
una única propiedad post:

<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
El ejemplo anterior y algunos que veremos más adelante, utilizan Plantillas de cadena de texto de
JavaScript para hacer que las plantillas multilínea sean más legibles. Internet Explorer (IE) no las admite, por
lo tanto, si debe ser compatible con IE y no está transpilando (por ejemplo, con Babel o TypeScript),
usa escapes de nueva línea en su lugar

Ahora, cada vez que se agreguen nuevas propiedadaes al objeto post, estarán automáticamente disponible
dentro de <blog-post>.

Enviando mensajes a componentes padre con eventos

A medida que desarrollamos nuestro componente <blog-post>, es posible que algunas funciones requieran la
comunicación hacia el componente padre. Por ejemplo, podemos decidir incluir una función de accesibilidad
para ampliar el texto de las publicaciones del blog, dejando el resto de la página en su tamaño por defecto:

En el padre, podemos admitir esta función agregando una propiedad postFontSize en data:

new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Esta propiedad puede ser usada en la plantilla para controlar el tamaño de la fuente de todas las publicaciones
del blog:

<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
</div>
</div>

Ahora agreguemos un botón para ampliar el texto justo antes del contenido de cada publicación:

Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>
Agrandar texto
</button>
<div v-html="post.content"></div>
</div>
`
})

El problema es que este botón no hace nada:

<button>
Agrandar texto
</button>

Cuando hacemos clic en el botón, debemos comunicar al componente padre que debe agrandar el texto de todas
las publicaciones. Afortunadamente, las instancias de Vue proporcionan un sistema de eventos personalizados
para resolver este problema. Para emitir un evento a los padres, podemos llamar al método $emit, pasando el
nombre del evento:

<button v-on:click="$emit('enlarge-text')">
Agrandar texto
</button>

Luego, en nuestro blog post, podemos escuchar este evento con v-on, tal como lo haríamos con un evento DOM
nativo:

<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Emitiendo un valor con un Evento

A veces es útil emitir un valor específico con un evento. Por ejemplo, podemos querer que el
componente <blog-post> se encargue de cuánto agrandar el texto. En esos casos, podemos usar el segundo
parámetro de $emit para proporcionar este valor:

<button v-on:click="$emit('enlarge-text', 0.1)">


Agrandar texto
</button>

Luego, cuando escuchamos el evento en el componente padre, podemos acceder al valor del evento emitido
con $event:

<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>

O, si el controlador de eventos es un método:

<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>

Entonces el valor se pasará como el primer parámetro de ese método:

methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}

Usando v-model en Componentes

Los eventos personalizados también se pueden usar para crear inputs personalizados que funcionan con v-
model. Recuerde que:

<input v-model="searchText">

hace lo mismo que:

<input
v-bind:value="searchText"

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


v-on:input="searchText = $event.target.value"
>

Cuando se usa en un componente, v-model en su lugar hace esto:

<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
Para que esto realmente funcione, el <input> dentro del componente debe:

•Enlazar el atributo value a una propiedad value


•En el input, emitir su propio evento input personalizado con el nuevo valor
Aquí está en acción:

Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})

Ahora v-model debería funcionar perfectamente con este componente:

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

Por ahora, eso es todo lo que necesita saber sobre los eventos de componentes personalizados, pero una vez que
haya terminado de leer esta página y se sienta cómodo con su contenido, le recomendamos volver más tarde para
leer la guía completa sobre Eventos Personalizados.

Distribución de contenido con Slots

Al igual que con los elementos HTML, a menudo es útil poder pasar contenido a un componente, como este:

<alert-box>
Algo ha ocurrido mal.
</alert-box>

Lo que podría renderizar algo como:

Error! Algo ha ocurrido mal.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Afortunadamente, esta tarea se hace muy simple con el elemento personalizado <slot> de Vue:

Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
Como verá más arriba, solo agregamos la ranura a la que queremos que el contenido vaya – y eso es todo. Hemos
terminado!

Eso es todo lo que necesita saber acerca de slots por ahora, pero una vez que haya terminado de leer esta página
y se sienta cómodo con su contenido, le recomendamos que regrese más tarde para leer la guía completa
de Slots.

Componentes dinámicos

A veces, es útil cambiar dinámicamente entre componentes, como en una interfaz con pestañas:

Componente de Inicio

Lo anterior es posible gracias al elemento <component> de Vue con el atributo especial is:

<!-- El componente cambia cuando currentTabComponent cambia -->


<component v-bind:is="currentTabComponent"></component>

En el ejemplo anterior, currentTabComponent puede contener:

•el nombre de un componente registrado, o


•un objeto de opciones de un componente

Vea este fiddle para experimentar con el código completo, o esta versión para un ejemplo de enlace o binding al
objeto de opciones de un componente, en lugar de su nombre registrado.

Eso es todo lo que necesita saber sobre los componentes dinámicos por ahora, pero una vez que haya terminado
de leer esta página y se sienta cómodo con su contenido, le recomendamos volver más tarde para leer la guía
completa sobre Componentes Dinámicos y Asíncronos.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue


Casos especiales de análisis de plantillas DOM.

Algunos elementos HTML, como <ul>, <ol>, <table> y <select> tienen restricciones sobre qué elementos


pueden aparecer dentro de ellos, y algunos elementos como <li>, <tr> y <option> solo pueden aparecer
dentro de ciertos otros elementos.

Esto conducirá a problemas cuando se utilizan componentes con elementos que tienen tales restricciones. Por
ejemplo:

<table>
<blog-post-row></blog-post-row>
</table>
El componente personalizado <blog-post-row> se colocará como contenido no válido, lo que provocará
errores en el resultado final. Afortunadamente, el atributo especial is ofrece una solución alternativa:

<table>
<tr is="blog-post-row"></tr>
</table>

Debe tenerse en cuenta que esta limitación no se aplica si está utilizando plantillas de cadenas de texto de
una de las siguientes fuentes:

•Plantillas de cadenas de texto (ej: template: '...')


•Componentes de un solo archivo (.vue)
•<script type="text/x-template">
Eso es todo lo que necesita saber sobre los casos especiales de análisis de plantillas DOM por ahora, y en realidad,
el final de los aspectos esenciales de Vue. ¡Felicidades! Todavía hay más que aprender, pero primero,
recomendamos tomar un descanso para practicar con Vue usted mismo y construir algo divertido.

Una vez que se sienta cómodo con el conocimiento que acaba de digerir, le recomendamos que regrese para leer
la guía completa de Componentes Dinámicos y Asíncronos, así como las otras páginas en la
sección Componentes en Profundidad de la barra lateral.

Departamento de Ciencia y Tecnología – Universidad Nacional del Comahue

También podría gustarte