Vue.js para principiantes lección 8: componentes

Hoy, en la octava lección del curso Vue, tendrá su primera exposición a los componentes. Los componentes son bloques de código reutilizables que pueden incluir tanto la apariencia de partes de la aplicación como la implementación de las capacidades del proyecto. Ayudan a los programadores a crear una base de código modular que es fácil de mantener. Vue.js principiantes lección 1: instancia VueVue.js para principiantes, lección 2: atributos de enlaceVue.js principiantes lección 3: renderizado condicionalVue.js principiantes lección 4: listas de renderizaciónVue .js para principiantes, lección 5: manejo de eventosVue.js para principiantes, lección 6: clases y estilos vinculantes



















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.htmlencuentra 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.jsse 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 elpara organizar su enlace al elemento DOM. En el caso de un componente, se utiliza una propiedad templateque 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 dataahora 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 dataahora es una función que devuelve un objeto con datos, se garantiza que cada componente recibirá su propio conjunto de datos. Si la entidad datano 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 producten 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, agreguemosindex.htmlun par de componentes másal códigoproduct. De hecho, así es como se organiza la reutilización de componentes. El códigoindex.htmlse 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 componenteproduct, por lo que el códigoindex.htmlse 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 productes 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 productgenere premiuminformació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 premiuminstancia 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, propsse 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 premiumes Booleany lo que este parámetro es necesario ajustando requireda 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 premiumen 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 productsabe 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 premiumcomponente. 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" llamadopremium. Vinculamos este atributo personalizado usando la construcción de dos puntos a una propiedadpremiumalmacenada en nuestros datos de instancia de Vue.



Ahora la instancia raíz de Vue puede pasar alpremiumcomponente secundarioproduct. Dado que el atributo está vinculado a una propiedadpremiumde los datos de la instancia de Vue, el valor actualpremiumsiempre se pasará al componenteproduct.



La figura anterior, a saber, la inscripciónUser 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 Productahora tiene un parámetro de entrada premiumque 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 sepremiumestablece en un valortrue, el usuario tiene derecho a envío gratuito. Creemos una nueva propiedad calculadashippingy usemos el parámetro en ellapremium:



shipping() {
  if (this.premium) {
    return "Free";
  } else {
    return 2.99
  }
}


Si se this.premiumalmacena en un parámetro true, la propiedad calculada shippingvolverá 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 queShipping: Free aparece en la página debido al hecho de que al componente se le transmite un parámetro de entradapremiumestablecido 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-detailsque deba usar un parámetro de entrada detailsy 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






All Articles