Vue.js para iniciantes lição 8: componentes

Hoje, na oitava aula do curso Vue, você terá sua primeira exposição aos componentes. Os componentes são blocos de código reutilizáveis ​​que podem incluir a aparência de partes do aplicativo e a implementação de recursos do projeto. Eles ajudam os programadores a criar uma base de código modular fácil de manter. Vue.js para iniciantes lição 1: instância VueVue.js para iniciantes, lição 2: atributos de vinculaçãoVue.js para iniciantes lição 3: renderização condicionalVue.js para iniciantes lição 4: exibição de listasVue .js para iniciantes, lição 5: manipulação de eventosVue.js para iniciantes, lição 6: classes e estilos de ligação



















Vue.js para iniciantes lição 7: propriedades calculadas

Vue.js para iniciantes lição 8: componentes



O propósito da lição



O objetivo principal desta lição é criar nosso primeiro componente e explorar os mecanismos de transmissão de dados aos componentes.



Código inicial



Aqui está o código do arquivo index.htmlencontrado na tag com a <body>qual começaremos:



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


Aqui está o 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;
    }
  }
})


Tarefa



Não precisamos que todos os dados, métodos e propriedades calculadas no aplicativo Vue estejam localizados na instância raiz do Vue. Com o tempo, isso levará a um código que será muito difícil de manter. Em vez disso, gostaríamos de dividir o código em partes modulares que sejam mais fáceis de trabalhar e que tornem o desenvolvimento mais flexível.



A solução do problema



Vamos começar pegando o código existente e movendo-o para um novo componente.



É assim que o main.jscomponente é registrado no arquivo :



Vue.component('product', {})


O primeiro argumento é o nome do componente de nossa escolha. O segundo é um objeto de opções semelhante ao que usamos para instanciar o Vue em tutoriais anteriores.



Na instância Vue, usamos uma propriedade elpara organizar sua vinculação ao elemento DOM. No caso de um componente, é utilizada uma propriedade templateque define o código HTML do componente.



Vamos descrever o modelo de componente em um objeto com opções:



Vue.component('product', {
  template: `
    <div class="product">
… //    HTML-,        product
    </div>
  `
})


Existem várias maneiras de criar modelos no Vue. Agora estamos usando um literal de modelo, o conteúdo do qual está entre crases.



Se descobrir que o código do modelo não será colocado em um único elemento raiz, como um elemento <div>com uma classe product, isso resultará na seguinte mensagem de erro:



Component template should contain exactly one root element


Em outras palavras, um template de componente só pode retornar um elemento.



Por exemplo, o seguinte modelo é bem formado porque é representado por apenas um elemento:



Vue.component('product', {
  template: `<h1>I'm a single element!</h1>`
})


Mas se o modelo contiver vários irmãos, não funcionará. Aqui está um exemplo de um padrão ruim:



Vue.component('product', {
  template: `
    <h1>I'm a single element!</h1>
    <h2>Not anymore</h2>
    `
})


Como resultado, se um template incluir muitos elementos, por exemplo, um conjunto de elementos incluídos em nossa <div>classe product, esses elementos deverão ser colocados em um elemento de contêiner externo. Como resultado, o modelo terá apenas um elemento raiz.



Agora que o modelo contém o código HTML que costumava estar no arquivo index.html, podemos adicionar dados, métodos e propriedades computadas ao componente que estava anteriormente na instância raiz do Vue:



Vue.component('product', {
  template: `
  <div class="product">
…
  </div>
  `,
  data() {
    return {
      //   
    }
  },
    methods: {
      //   
    },
    computed: {
      //    
    }
})


Como você pode ver, a estrutura desse componente é quase completamente igual à estrutura da instância Vue com a qual trabalhamos anteriormente. Você notou que dataagora isso não é uma propriedade, mas um método de um objeto com opções? Porque isto é assim?



A questão é que os componentes geralmente são criados com planos para reutilizá-los. Se tivermos muitos componentes product, precisamos garantir que cada um deles tenha suas próprias instâncias de entidade data. Como dataagora é uma função que retorna um objeto com dados, cada componente receberá seu próprio conjunto de dados. Se a entidade datanão fosse uma função, então cada componenteproduct, onde quer que tais componentes fossem usados, conteria os mesmos dados. Isso vai contra a ideia de componentes reutilizáveis.



Agora que movemos o código relacionado ao produto para um componente nativo product, o código para descrever a instância raiz do Vue se parece com este:



var app = new Vue({
  el: '#app'
})


Agora só precisamos colocar o componente productno código do arquivo index.html. Isso parecerá assim:



<div id="app">
  <product></product>
</div>


Se você recarregar a página do aplicativo agora, ela retornará ao formato anterior.





Página do aplicativo



Se você agora olhar para as ferramentas de desenvolvedor do Vue, notará que há uma entidade raiz e um componente de produto.





Analisando o aplicativo com as ferramentas de desenvolvedor Vue



Agora, apenas para demonstrar a capacidade de reutilização dos componentes, vamos adicionarindex.htmlmais alguns componentesao códigoproduct. Na verdade, é assim que a reutilização de componentes é organizada. O códigoindex.htmlserá semelhante a este:



<div id="app">
  <product></product>
  <product></product>
  <product></product>
</div>


E a página exibirá três cópias do cartão do produto.





Vários cartões de produtos exibidos em uma página



Observe que, no futuro, trabalharemos com um componenteproduct, então o códigoindex.htmlserá semelhante a este:



<div id="app">
  <product></product>
</div>


Tarefa



Os aplicativos geralmente precisam de componentes para aceitar dados, parâmetros de entrada de entidades pai. Nesse caso, o pai do componente producté a própria instância raiz do Vue.



Deixe a instância raiz do Vue ter uma descrição de alguns dados. Este dado indica se o usuário é titular de conta premium. O código para descrever uma instância Vue pode ser assim:



var app = new Vue({
  el: '#app',
  data: {
    premium: true
  }
})


Vamos decidir se os usuários premium têm direito a frete grátis.



Isso significa que queremos que o componente productproduza premiumdiferentes informações de custo de envio , dependendo do que está escrito na propriedade raiz da instância Vue.



Como posso enviar os dados armazenados na propriedade da premiuminstância raiz do Vue para o filho que é o componente product?



A solução do problema



No Vue, para transferir dados de entidades pai para filhos, uma propriedade de objeto com opções propsdescritas pelos componentes é usada. Este é um objeto que descreve os parâmetros de entrada do componente, cujos valores devem ser definidos com base nos dados recebidos da entidade pai.



Vamos começar descrevendo que tipo de parâmetros de entrada o componente espera receber product. Para fazer isso, adicione a propriedade correspondente ao objeto com as opções usadas ao criá-lo:



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  //    , ,  
})


Observe que isso usa a capacidade integrada do Vue para validar os parâmetros passados ​​para um componente. Ou seja, nós indicam que o tipo de parâmetro de entrada premiumé Booleaneo que este parâmetro é necessário, definindo requireda true.



A seguir, vamos fazer uma alteração no modelo que exibe os parâmetros passados ​​para o objeto. Ao exibir o valor da propriedade premiumna página, teremos certeza de que o mecanismo que estamos investigando está funcionando corretamente.



<p>User is premium: {{ premium }}</p>


Até agora, está tudo bem. O componente productsabe que receberá o parâmetro de tipo necessário para sua operação Boolean. Preparamos um local para exibir os dados relevantes.



Mas ainda não passamos o parâmetro para o premiumcomponente. Você pode fazer isso usando um atributo personalizado que é semelhante à "linha" que leva a um componente através do qual é possível transmitir os parâmetros de entrada e, em particular premium.



Vamos modificar o código em index.html:



<div id="app">
  <product :premium="premium"></product>
</div>


Vamos atualizar a página.





Saída dos dados passados ​​para o componente



Os parâmetros de entrada agora são passados ​​para o componente. Vamos falar exatamente sobre o que acabamos de fazer.



Passamos ao componente um parâmetro de entrada, ou "atributo personalizado" chamadopremium. Ligamos esse atributo personalizado usando a construção de dois pontos a uma propriedadepremiumarmazenada em nossos dados de instância do Vue.



Agora a instância raiz do Vue pode passar para opremiumcomponente filhoproduct. Uma vez que o atributo está vinculado a uma propriedadepremiumdos dados da instância Vue, o valor atualpremiumsempre será passado para o componenteproduct.



A imagem acima, ou seja, a inscriçãoUser is premium: true, prova que tudo foi feito corretamente.



Agora verificamos que o mecanismo de transferência de dados que estamos estudando funciona conforme o esperado. Se você olhar as ferramentas de desenvolvedor do Vue, verá que o componente Productagora tem um parâmetro de entrada premiumque armazena um valor true.





Parâmetro de entrada do componente



Agora que os dados sobre se o usuário tem uma conta premium entram no componente, vamos usar esses dados para exibir as informações de custo de envio na página. Não vamos esquecer que, se o parâmetro forpremiumdefinido com um valortrue, o usuário tem direito a frete grátis. Vamos criar uma nova propriedade computadashippinge usar o parâmetro nelapremium:



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


Se this.premiumarmazenado em um parâmetro true, a propriedade computada shippingretornará Free. Caso contrário, ele retornará 2.99.



Vamos remover o código de saída do valor do parâmetro do modelo do componente premium. Agora o elemento <p>Shipping: {{ shipping }}</p>que estava presente no código com o qual começamos hoje poderá mostrar informações sobre o custo de envio.





Os usuários premium recebem entrega gratuita de



texto queShipping: Freeaparece na página devido ao fato de que o componente é transmitido como um parâmetro de entradapremiumdefinido como um valortrue.



Maravilhoso! Agora, aprendemos como transferir dados de entidades pai para filhos e podemos usar esses dados no componente para gerenciar o custo de envio de mercadorias.



A propósito, é importante notar que você não deve alterar seus parâmetros de entrada em componentes filhos.



Oficina



Crie um novo componente product-detailsque deve usar um parâmetro de entrada detailse ser responsável por renderizar a parte do cartão do produto que foi formado anteriormente usando o seguinte código:



<ul>
  <li v-for="detail in details">{{ detail }}</li>
</ul>


Aqui está um modelo que você pode usar para resolver esse problema.



Aqui está a solução para o problema.



Resultado



Hoje foi sua primeira introdução aos componentes do Vue. Aqui está o que você aprendeu:



  • Os componentes são blocos de código apresentados como elementos personalizados.
  • Os componentes tornam seu aplicativo mais fácil de gerenciar, dividindo-o em partes reutilizáveis. Eles contêm descrições do componente visual e da funcionalidade da parte correspondente do aplicativo.
  • Os dados do componente são representados por um método de um data()objeto com opções.
  • Os parâmetros de entrada ( props) são usados ​​para passar dados de entidades pai para entidades filho .
  • Podemos descrever os requisitos para os parâmetros de entrada que o componente assume.
  • .
  • .
  • Vue .




Você está usando as ferramentas de desenvolvedor do Vue?



Vue.js para iniciantes lição 1: instância Vue

Vue.js para iniciantes, lição 2: atributos de vinculação

Vue.js para iniciantes lição 3: renderização condicional

Vue.js para iniciantes lição 4: exibição de listas

Vue .js para iniciantes lição 5: processamento de eventos

Vue.js para iniciantes lição 6: classes e estilos de ligação

Vue.js para iniciantes lição 7: propriedades calculadas

Vue.js para iniciantes lição 8: componentes






All Articles