Vue.js para principiantes lección 7: propiedades calculadas
→ Vue.js para principiantes lección 8: componentes
El propósito de la lección
El objetivo principal de esta lección es crear nuestro primer componente y explorar los mecanismos para pasar datos a los componentes.
Código inicial
Aquí está el código de archivo que se
index.html
encuentra en la etiqueta con la <body>
que comenzaremos:
<div id="app">
<div class="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ title }}</h1>
<p v-if="inStock">In stock</p>
<p v-else>Out of Stock</p>
<p>Shipping: {{ shipping }}</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div
class="color-box"
v-for="(variant, index) in variants"
:key="variant.variantId"
:style="{ backgroundColor: variant.variantColor }"
@mouseover="updateProduct(index)"
></div>
<button
v-on:click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"
>
Add to cart
</button>
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
</div>
</div>
</div>
Aquí está el código
main.js
:
var app = new Vue({
el: '#app',
data: {
product: 'Socks',
brand: 'Vue Mastery',
selectedVariant: 0,
details: ['80% cotton', '20% polyester', 'Gender-neutral'],
variants: [
{
variantId: 2234,
variantColor: 'green',
variantImage: './assets/vmSocks-green.jpg',
variantQuantity: 10
},
{
variantId: 2235,
variantColor: 'blue',
variantImage: './assets/vmSocks-blue.jpg',
variantQuantity: 0
}
],
cart: 0,
},
methods: {
addToCart() {
this.cart += 1;
},
updateProduct(index) {
this.selectedVariant = index;
console.log(index);
}
},
computed: {
title() {
return this.brand + ' ' + this.product;
},
image() {
return this.variants[this.selectedVariant].variantImage;
},
inStock(){
return this.variants[this.selectedVariant].variantQuantity;
}
}
})
Tarea
No necesitamos que todos los datos, métodos y propiedades calculadas en la aplicación Vue estén ubicados en la instancia raíz de Vue. Con el tiempo, esto dará lugar a un código que será muy difícil de mantener. En cambio, nos gustaría dividir el código en piezas modulares con las que sea más fácil trabajar y que hagan el desarrollo más flexible.
La solucion del problema
Comencemos tomando el código existente y moviéndolo a un nuevo componente.
Así es como
main.js
se registra el componente en el archivo :
Vue.component('product', {})
El primer argumento es el nombre del componente de nuestra elección. El segundo es un objeto de opciones similar al que usamos para instanciar Vue en tutoriales anteriores.
En la instancia de Vue, usamos una propiedad
el
para organizar su enlace al elemento DOM. En el caso de un componente, se utiliza una propiedad template
que define el código HTML del componente.
Describamos la plantilla de componente en un objeto con opciones:
Vue.component('product', {
template: `
<div class="product">
… // HTML-, product
</div>
`
})
Hay varias formas de crear plantillas en Vue. Ahora estamos usando un literal de plantilla, cuyo contenido está entre comillas.
Si resulta que el código de la plantilla no se colocará en un solo elemento raíz, como un elemento
<div>
con una clase product
, esto dará como resultado el siguiente mensaje de error:
Component template should contain exactly one root element
En otras palabras, una plantilla de componente solo puede devolver un elemento.
Por ejemplo, la siguiente plantilla está bien formada porque está representada por un solo elemento:
Vue.component('product', {
template: `<h1>I'm a single element!</h1>`
})
Pero si la plantilla contiene varios hermanos, no funcionará. A continuación, se muestra un ejemplo de un mal patrón:
Vue.component('product', {
template: `
<h1>I'm a single element!</h1>
<h2>Not anymore</h2>
`
})
Como resultado, resulta que si una plantilla debe incluir muchos elementos, por ejemplo, un conjunto de elementos incluidos en nuestra
<div>
clase product
, estos elementos deben colocarse en un elemento contenedor externo. Como resultado, la plantilla solo tendrá un elemento raíz.
Ahora que la plantilla contiene el código HTML que solía estar en el archivo
index.html
, podemos agregar datos, métodos, propiedades calculadas al componente que estaban previamente en la instancia raíz de Vue:
Vue.component('product', {
template: `
<div class="product">
…
</div>
`,
data() {
return {
//
}
},
methods: {
//
},
computed: {
//
}
})
Como puede ver, la estructura de este componente es casi exactamente la misma que la estructura de la instancia de Vue con la que trabajamos anteriormente. ¿Ha notado que
data
ahora esto no es una propiedad, sino un método de un objeto con opciones? ¿Por qué esto es tan?
El punto es que los componentes a menudo se crean con planes para reutilizarlos. Si tenemos muchos componentes
product
, debemos asegurarnos de que cada uno de ellos tenga sus propias instancias de entidad data
. Dado que data
ahora es una función que devuelve un objeto con datos, se garantiza que cada componente recibirá su propio conjunto de datos. Si la entidad data
no fuera una función, entonces cada componenteproduct
, dondequiera que se utilicen dichos componentes, contendría los mismos datos. Esto va en contra de la idea de componentes reutilizables.
Ahora que hemos movido el código relacionado con el producto a un componente nativo
product
, el código para describir la instancia raíz de Vue se ve así:
var app = new Vue({
el: '#app'
})
Ahora solo necesitamos colocar el componente
product
en el código del archivo index.html
. Se verá así:
<div id="app">
<product></product>
</div>
Si vuelve a cargar la página de la aplicación ahora, volverá a su forma anterior.
Página de la aplicación
Si ahora observa las herramientas de desarrollo de Vue, notará que hay una entidad raíz y un componente de producto.
Analizando la aplicación con Vue Developer Tools
Ahora, solo para demostrar la capacidad de reutilización de los componentes, agreguemos
index.html
un par de componentes másal códigoproduct
. De hecho, así es como se organiza la reutilización de componentes. El códigoindex.html
se verá así:
<div id="app">
<product></product>
<product></product>
<product></product>
</div>
Y la página mostrará tres copias de la ficha del producto.
Varias tarjetas de producto mostradas en una página
Tenga en cuenta que en el futuro trabajaremos con un componente
product
, por lo que el códigoindex.html
se verá así:
<div id="app">
<product></product>
</div>
Tarea
Las aplicaciones a menudo necesitan componentes para aceptar datos, parámetros de entrada, de entidades principales. En este caso, el padre del componente
product
es la instancia raíz de Vue.
Deje que la instancia raíz de Vue tenga una descripción de algunos datos. Estos datos indican si el usuario es titular de una cuenta premium. El código para describir una instancia de Vue podría verse así:
var app = new Vue({
el: '#app',
data: {
premium: true
}
})
Decidamos que los usuarios premium tienen derecho a envío gratuito.
Esto significa que queremos que el componente
product
genere premium
información de costos de envío diferente según lo que esté escrito en la propiedad de la instancia raíz de Vue.
¿Cómo puedo enviar los datos almacenados en la propiedad de la
premium
instancia raíz de Vue al niño que es el componente product
?
La solucion del problema
En Vue, para transferir datos de entidades padre a hijos,
props
se utiliza una propiedad de objeto con opciones descritas por los componentes. Este es un objeto que describe los parámetros de entrada del componente, cuyos valores deben establecerse en función de los datos recibidos de la entidad principal.
Comencemos describiendo qué tipo de parámetros de entrada espera recibir el componente
product
. Para hacer esto, agregue la propiedad correspondiente al objeto con las opciones utilizadas al crearlo:
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
// , ,
})
Tenga en cuenta que esto utiliza la capacidad incorporada de Vue para validar los parámetros pasados a un componente. A saber, indicamos lo que el tipo de parámetro de entrada
premium
es Boolean
y lo que este parámetro es necesario ajustando required
a true
.
A continuación, hagamos un cambio en la plantilla que muestra los parámetros pasados al objeto. Al mostrar el valor de la propiedad
premium
en la página, nos aseguraremos de que el mecanismo que estamos investigando funcione correctamente.
<p>User is premium: {{ premium }}</p>
Hasta ahora todo va bien. El componente
product
sabe que recibirá el parámetro de tipo requerido para su funcionamiento Boolean
. Hemos preparado un lugar para mostrar los datos relevantes.
Pero aún no hemos pasado el parámetro al
premium
componente. Puede hacer esto utilizando un atributo personalizado que sea similar a la "línea" que conduce a un componente a través del cual es posible transmitir los parámetros de entrada, y en particular premium
.
Modifiquemos el código en
index.html
:
<div id="app">
<product :premium="premium"></product>
</div>
Actualicemos la página.
Salida de los datos pasados al componente
Los parámetros de entrada ahora se pasan al componente. Hablemos exactamente de lo que acabamos de hacer.
Pasamos al componente un parámetro de entrada, o "atributo personalizado" llamado
premium
. Vinculamos este atributo personalizado usando la construcción de dos puntos a una propiedadpremium
almacenada en nuestros datos de instancia de Vue.
Ahora la instancia raíz de Vue puede pasar al
premium
componente secundarioproduct
. Dado que el atributo está vinculado a una propiedadpremium
de los datos de la instancia de Vue, el valor actualpremium
siempre se pasará al componenteproduct
.
La figura anterior, a saber, la inscripción
User is premium: true
, demuestra que todo se hizo correctamente.
Ahora hemos verificado que el mecanismo de transferencia de datos que estamos estudiando está funcionando como se esperaba. Si observa las herramientas de desarrollo de Vue, resulta que el componente
Product
ahora tiene un parámetro de entrada premium
que almacena un valor true
.
Parámetro de entrada del componente
Ahora que los datos sobre si el usuario tiene una cuenta premium ingresan al componente, usemos estos datos para mostrar la información del costo de envío en la página. No olvidemos que si el parámetro se
premium
establece en un valortrue
, el usuario tiene derecho a envío gratuito. Creemos una nueva propiedad calculadashipping
y usemos el parámetro en ellapremium
:
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
Si se
this.premium
almacena en un parámetro true
, la propiedad calculada shipping
volverá Free
. De lo contrario, volverá 2.99
.
Eliminemos el código de salida del valor del parámetro de la plantilla del componente
premium
. Ahora el elemento <p>Shipping: {{ shipping }}</p>
que estaba presente en el código con el que comenzamos hoy podrá mostrar información sobre el costo de envío.
Los usuarios premium obtienen el
texto de envío gratuito que
Shipping: Free
aparece en la página debido al hecho de que al componente se le transmite un parámetro de entradapremium
establecido en un valortrue
.
¡Maravilloso! Ahora hemos aprendido cómo transferir datos de las entidades principales a las secundarias y pudimos usar estos datos en el componente para administrar el costo de envío de mercancías.
Por cierto, vale la pena señalar que no debe cambiar sus parámetros de entrada en los componentes secundarios.
Taller
Cree un nuevo componente
product-details
que deba usar un parámetro de entrada details
y sea responsable de renderizar la parte de la tarjeta de producto que se formó previamente usando el siguiente código:
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
Aquí hay una plantilla que puede usar para resolver este problema.
Aquí está la solución al problema.
Salir
Hoy fue su primera introducción a los componentes de Vue. Esto es lo que aprendiste:
- Los componentes son bloques de código que se presentan como elementos personalizados.
- Los componentes hacen que su aplicación sea más fácil de administrar al dividirla en partes reutilizables. Contienen descripciones del componente visual y la funcionalidad de la parte correspondiente de la aplicación.
- Los datos de los componentes se representan mediante un método de
data()
objeto con opciones. - Los parámetros de entrada (
props
) se utilizan para pasar datos de entidades principales a entidades secundarias . - Podemos describir los requisitos para los parámetros de entrada que toma el componente.
- .
- .
- Vue .
¿Estás usando herramientas de desarrollo de Vue?
→ Lección 1 para principiantes de Vue.js : instancia Vue
→ Vue.js para principiantes, lección 2: atributos de enlace
→ Lección 3 para principiantes de Vue.js: renderizado condicional
→ Lección 4 para principiantes de Vue.js: renderizado de listas
→ Vue .js para principiantes lección 5: procesamiento de eventos
→ Vue.js principiantes lección 6: clases y estilos vinculantes
→ Vue.js principiantes lección 7: propiedades calculadas
→ Vue.js principiantes lección 8: componentes