Guia
Essenciais
- Instalação
- Introdução
- A Instância Vue
- Sintaxe de Templates
- Dados Computados e Observadores
- Interligações de Classe e Estilo
- Renderização Condicional
- Renderização de Listas
- Manipulação de Eventos
- Interligações em Formulários
- Básico sobre Componentes
Componentes em Detalhes
- Registro de Componentes
- Propriedades
- Eventos Personalizados
- Slots
- Dinâmicos & Assíncronos
- Lidando com Casos Extremos
Transições & Animações
- Transições de Visibilidade e Listas
- Transições de Estado
Reuso & Composição
- Mixins
- Diretivas Personalizadas
- Funções de Renderização & JSX
- Plugins
- Filtros
Ferramentas
- Componentes Single-File
- Testes Unitários
- Testing
- Suporte ao TypeScript
- Publicando em Produção
Escalonando
- Roteamento
- Gerenciamento de Estado
- Renderizando no Lado do Servidor
- Segurança
Internamente
- Reatividade em Profundidade
Migração
- Migração do Vue 1.x
- Migração do Vue Router 0.7.x
- Migração do Vuex 0.6.x para 1.0
Diversos
- Comparação com Outros Frameworks
- Junte-se à Comunidade Vue.js!
- Conheça a Equipe
Você está navegando a documentação da v2.x e anterior. Para a v3.x, clique aqui.
Básico sobre Componentes
Exemplo Base
Aqui está um exemplo de um componente Vue:
// Definindo novo componente chamado button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">Você clicou em mim {{ count }} vezes.</button>'
})
Componentes são instâncias reutilizáveis do Vue com um nome: Nesse caso, <button-counter>
. Podemos usar esses componentes como um elemento personalizado dentro da instância Vue raiz criada com new Vue
:
<div id="components-demo">
<button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })
Como componentes são instância Vue reutilizáveis, eles aceitam as mesmas opções que new Vue
, como data
, computed
, watch
, methods
e gatilhos de ciclo de vida. As únicas exceções são as poucas opções específicas de raiz, como el
.
Reutilizando Componentes
Componentes podem ser reutilizados quantas vezes você quiser:
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
Perceba que ao clicar nos botões, cada um mantêm seu próprio e único count
. Isso acontece porque cada vez que você usa um componente, uma nova instância dele é criada.
Use data
como uma Função
Quando definimos o componente <button-counter>
, você talvez percebeu que a opção data
não recebeu um objeto, como abaixo:
data: {
count: 0
}
Em vez disso, a opção data
de um componente precisa ser uma função, para que cada instância possa manter uma cópia independente do object data retornado:
data: function () {
return {
count: 0
}
}
Se Vue não tivesse essa regra, clicar em um botão afetaria a data de todas outras instâncias, como abaixo:
Organizando Componentes
É comum que um aplicativo seja organizado em uma árvore de componentes aninhados:
Por exemplo, você pode ter componentes para o cabeçalho, barra lateral e área de conteúdo, cada um normalmente contendo outros componentes para navegação, como links, postagens de blog, etc.
Para usar esses componentes em templates, eles devem ser registrados para que Vue saiba deles. Há dois tipos de registro de componentes, sendo eles: global e local. Até agora, nós só registramos componentes de maneira global, usando Vue.component
:
Vue.component('my-component-name', {
// ... options ...
})
Componentes registrados globalmente podem ser usados no template de qualquer instância Vue raiz (new Vue
) criada posteriormente – e até mesmo dentro de todos subcomponentes dessa árvore de componentes da instância Vue.
Isso é tudo que você precisa saber sobre registro por hora, mas assim que você terminar de ler essa página e se sentir confortável com o conteúdo, recomendamos retornar mais tarde para ler o guia completo em Component Registration.
Passando Dados aos Filhos com Props
Anteriormente falamos sobre criar componentes para postagens de blog. O problema é que, o componente não será útil a não ser que você possa passar dados para ele, como título e conteúdo da postagem específica que desejamos mostrar. É aí que props entra.
Props são atributos personalizáveis que você pode registrar em um componente. Quando um valor é passado para um atributo prop, ele torna-se uma propriedade daquela instância de componente. Para passar um título ao nosso componente de postagem de blog, podemos incluir na lista de props que esse componente aceita, usando a opção props
:
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
Um componente pode ter quantos props você quiser, e por padrão, qualquer valor pode ser passado para qualquer prop. No template acima, você verá que nós podemos acessar esse valor dentro da instância do componente, da mesma forma como data
.
Assim que um prop é registrado, você pode passar dados para ele como um atributo personalizado, dessa forma:
<blog-post title="Minha jornada com Vue"></blog-post>
<blog-post title="Postagens com Vue"></blog-post>
<blog-post title="Porque Vue é tão divertido"></blog-post>
Todavia, tipicamente você vai querer ter um array de posts em data
:
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'Minha jornada com Vue' },
{ id: 2, title: 'Postagens com Vue' },
{ id: 3, title: 'Porque Vue é tão divertido' }
]
}
})
Quando quisermos renderizar um componente para cada:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
No exemplo acima, você verá que podemos usar v-bind
para dinamicamente passar props. Isso é especialmente útil quando você não sabe, de antemão, exatamente que tipo de conteúdo irá renderizar, como ao obter postagens de uma API.
Isso é tudo que você precisa saber de props por hora, mas assim que você terminar de ler essa página e se sentir confortável com o conteúdo, recomendamos retornar mais tarde para ler o guia completo em Props.
Um Elemento Raiz Único
Quando construindo um componente <blog-post>
, seu template eventualmente conterá mais que apenas o título:
<h3>{{ title }}</h3>
No mínimo, você vai querer incluir o conteúdo da postagem:
<h3>{{ title }}</h3>
<div v-html="content"></div>
No entando, se você tentar isso no seu template, Vue mostrará um erro, explicando que todo componente deve ter um único elemento raiz. Você pode corrigir esse problema por envolver todo o template em um elemento pai, como abaixo:
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
À medida que nosso componente cresce, é provável que nós iremos mostrar mais que apenas o título e o conteúdo da postagem, como também a data de publicação, comentários e mais. Definir um prop para cada pedaço de informação pode se tornar bem irritante:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"
v-bind:publishedAt="post.publishedAt"
v-bind:comments="post.comments"
></blog-post>
Então agora é uma boa hora para reestruturar o componente <blog-post>
para aceitar um único prop 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>
`
})
O exemplo acima (e alguns outros futuramente) usa Template strings para fazer templates de mais de uma linha mais legíveis. No entanto, isso não é suportado pelo Internet Explorer (IE), se você precisa de suporte para IE e não está usando uma ferramenta como Babel ou TypeScript, você ainda pode fazer da forma pré-ES6.
Agora, toda vez que uma nova propriedade é adicionado ao objeto post
, ela será automaticamente acessível dentro do componente <blog-post>
.
Escutando Eventos de Componentes Filho
À medida que desenvolvemos nosso componente <blog-post>
, alguns recursos podem precisar comunicar de volta para o componente pai. Por exemplo, talvez decidamos incluir uma funcionalidade de acessibilidade que aumenta o tamanho da fonte das nossas postagens, enquanto deixa o resto da página no tamanho padrão:
No componente pai, nós podemos suportar essa funcionalidade por adicionar a propriedade postFontSize
para data:
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})
Que pode ser usada no template para controlar o tamanho de todas postagens:
<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>
Agora vamos adicionar um botão para aumentar o tamanho do texto logo à direita de cada postagem:
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>
Aumentar fonte
</button>
<div v-html="post.content"></div>
</div>
`
})
O problema é que, esse botão não faz nada:
<button>
Aumentar fonte
</button>
Quando clicamos no botão, precisamos comunicar o componente pai que ele deve aumentar o tamanho da fonte de todas postagens. Felizmente, instâncias Vue provêm um evento para resolver esse problema. O pai pode escolher escutar qualquer evento na instância do componente filho com v-on
, assim como faríamos com um evento DOM nativo:
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
Então o componente filho pode emitir um evento em si mesmo chamando o método $emit
, passando o nome do evento:
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
Graças ao escutador v-on:enlarge-text="postFontSize += 0.1"
, o pai receberá o evento e atualizará o valor postFontSize
.
Emitindo um Valor com um Evento
Às vezes é útil emitir um valor específico com um evento. Por exemplo, nós talvez queiramos que o componente <blog-post>
seja responsável de quando em quanto aumentar a fonte. Nesses casos, podemos usar o 2° parâmetro do método $emit
para prover esse valor:
<button v-on:click="$emit('enlarge-text', 0.1)">
Aumentar fonte
</button>
Quando ouvirmos por esse evento no componente pai, podemos acessar o valor emitido com $event
:
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>
Ou, se o manipulador de eventos é um método:
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>
Então o valor será passado como o primeiro parâmetro desse método:
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
Usando v-model
em Componentes
Eventos personalizados podem também ser usados para criar inputs personalizados que funcionam com v-model
. Lembre-se que:
<input v-model="searchText">
tem a mesma funcionalidade que:
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
No entanto, quando usado em um componente, v-model
fará isso:
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
Para isso realmente funcionar, o <input>
dentro do componente precisa:
- Vincular o atributo
value
com o propvalue
- No
input
, emitir seu próprio eventoinput
personalizado com o novo valor
Aqui isso em ação:
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
Agora v-model
deve funcionar perfeitamente com esse componente:
<custom-input v-model="searchText"></custom-input>
Isso é tudo que você precisa saber sobre eventos personalizados de componentes por hora, mas assim que você terminar de ler essa página e se sentir confortável com o conteúdo, recomendamos retornar mais tarde para ler o guia completo em Custom Events.
Distribuição de Conteúdo com Slots
Assim como em elementos HTML, muitas vezes é útil ser capaz de passar conteúdo para um componente, dessa forma:
<alert-box>
Algo ruim aconteceu.
</alert-box>
Que renderizaria algo assim:
Felizmente, isso é facilmente realizado com um elemento personalizado <slot>
:
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Erro!</strong>
<slot></slot>
</div>
`
})
Como você vê acima, nós só adicionamos o slot para aonde queremos que o conteúdo vá – e é isso!
Isso é tudo que você precisa saber sobre slots por hora, mas assim que você terminar de ler essa página e se sentir confortável com o conteúdo, recomendamos retornar mais tarde para ler o guia completo em Slots.
Componentes Dinâmicos
Às vezes, é útil alternar dinamicamente entre componentes, como em uma interface de abas:
O exemplo acima é possível por causa do elemento <component>
com o atributo especial is
:
<!-- Componente atualiza quando currentTabComponent muda -->
<component v-bind:is="currentTabComponent"></component>
No exemplo acima, currentTabComponent
pode conter:
- o nome do componente registrado, ou
- o objeto de opções de um componente
Veja esse exemplo para experimentar com todo o código, ou essa versão para um exemplo ligando ao objeto de opções de um componente em vez de seu nome registrado.
Tenha em mente que esse atributo pode ser utilizado com elementos HTML comuns, porém, eles serão tratados como componentes, o que significa que todos os atributos serão vinculados como atributos do DOM. Para algumas propriedades, como value
, funcionarem da maneira esperada, você terá que vincula-las usando o modificador .prop
.
Isso é tudo que você precisa saber sobre componentes dinâmicos por hora mas, assim que você terminar de ler essa página e se sentir confortável com o conteúdo, recomendamos retornar mais tarde para ler o guia completo sobre componentes Dinâmicos & Assíncronos.
Ressalvas na Análise do Template DOM
Alguns elementos HTML, como <ul>
, <ol>
, <table>
e <select>
têm restrições do que pode aparecer dentro deles, e alguns elementos como <li>
, <tr>
, e <option>
podem aparecer apenas dentro de certos elementos.
Isso nos leva a problemas quando usamos componentes com element que tem tais restrições. Por exemplo:
<table>
<blog-post-row></blog-post-row>
</table>
O componente <blog-post-row>
será renderizado antes do elemento <table>
por ser um conteúdo inválido, causando erros na renderização. Felizmente, o atributo especial is
oferece uma solução alternativa:
<table>
<tr is="blog-post-row"></tr>
</table>
Deve ser notado que essa limitação não se aplica se você está usando string templates de uma das seguintes fontes:
- Template Strings (Ex:
template: '...'
) - Componentes Single-File (
.vue
) <script type="text/x-template">
Isso é tudo que você precisa saber sobre componentes dinâmicos por hora – na verdade, esse é o fim da seção Essenciais do Vue. Parabéns! Ainda há mais a ser aprendido, mas antes, recomendamos que tire um tempo para brincar com o Vue você mesmo e criar alguma coisa divertida.
Assim que você se sentir confortável com o conteúdo que vimos, recomendamos retornar mais tarde para ler o guia completo de componentes Dinâmicos & Assíncronos, como também as outras páginas na seção Componentes em Detalhes da barra lateral.