# Introdução
NOTA
Conhece o Vue 2 e só quer ver o que há de novo no Vue 3? Confira o Guia de Migração!
# O que é Vue.js?
Vue (pronuncia-se /vjuː/, como view, em inglês) é um framework progressivo para a construção de interfaces de usuário. Ao contrário de outros frameworks monolíticos, Vue foi projetado desde sua concepção para ser adotável incrementalmente. A biblioteca principal é focada exclusivamente na camada visual (view layer), sendo fácil adotar e integrar com outras bibliotecas ou projetos existentes. Por outro lado, Vue também é perfeitamente capaz de dar poder a sofisticadas Single-Page Applications quando usado em conjunto com ferramentas modernas e bibliotecas de apoio (opens new window).
Se você gostaria de saber mais sobre Vue antes de mergulhar nele, nós criamos um vídeo (em inglês) passeando pelos princípios básicos e um exemplo de projeto.
# Primeiros Passos
DICA
O guia oficial supõe um nível intermediário em HTML, CSS e JavaScript. Se você é totalmente novo no mundo do frontend, mergulhar diretamente em um framework pode não ser a melhor ideia para começar - compreenda primeiro o básico e depois volte! Experiência anterior com outros frameworks ajuda, mas não é obrigatória.
A forma mais simples de testar o Vue é usando o exemplo de Olá Mundo (opens new window). Sinta-se à vontade para abrí-lo em outra aba e acompanhar conosco durante os próximos exemplos básicos.
A página Instalação deste guia oferece mais opções para instalar o Vue. Nota: nós não recomendamos que iniciantes comecem com o vue-cli
, especialmente se você não está familiarizado com ferramentas de build baseadas em Node.js.
# Renderização Declarativa
No núcleo do Vue está um sistema que nos permite declarativamente renderizar dados no DOM (Document Object Model) usando uma sintaxe de template simples:
<div id="counter">
Contador: {{ counter }}
</div>
2
3
const Counter = {
data() {
return {
counter: 0
}
}
}
Vue.createApp(Counter).mount('#counter')
2
3
4
5
6
7
8
9
Acabamos de criar nosso primeiro aplicativo Vue! Isso parece muito similar a renderizar uma template string, mas o Vue fez bastante trabalho interno. Os dados e o DOM estão agora interligados e tudo se tornou reativo. Como podemos ter certeza? Dê uma olhada no exemplo a seguir, onde a propriedade counter
incrementa a cada segundo, e você verá como o DOM renderizado muda:
const Counter = {
data() {
return {
counter: 0
}
},
mounted() {
setInterval(() => {
this.counter++
}, 1000)
}
}
2
3
4
5
6
7
8
9
10
11
12
Contador: 0
Além de simples interpolação de texto, podemos interligar atributos de elementos:
<div id="bind-attribute">
<span v-bind:title="message">
Pare o mouse sobre mim e veja a dica interligada dinamicamente!
</span>
</div>
2
3
4
5
const AttributeBinding = {
data() {
return {
message: 'Você carregou esta página em ' + new Date().toLocaleString()
}
}
}
Vue.createApp(AttributeBinding).mount('#bind-attribute')
2
3
4
5
6
7
8
9
Veja o exemplo Interligação dinâmica de atributos por vuejs-br (@vuejs-br) no CodePen.
Aqui nos deparamos com algo novo. O atributo v-bind
que você está vendo é chamado de diretiva. Diretivas são prefixadas com v-
para indicar que são atributos especiais providos pelo Vue, e como você deve ter percebido, aplicam comportamento especial de reatividade ao DOM renderizado. Neste caso, basicamente estamos dizendo: "mantenha o atributo title
do elemento sempre atualizado em relação à propriedade message
da instância atualmente ativa".
# Tratando Interação do Usuário
Para permitir aos usuários interagir com o aplicativo, podemos usar a diretiva v-on
para anexar escutas a eventos (event listeners) que invocam métodos em nossas instâncias:
<div id="event-handling">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">Inverter Mensagem</button>
</div>
2
3
4
const EventHandling = {
data() {
return {
message: 'Olá Vue.js!'
}
},
methods: {
reverseMessage() {
this.message = this.message
.split('')
.reverse()
.join('')
}
}
}
Vue.createApp(EventHandling).mount('#event-handling')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Veja o exemplo Escutas em eventos por vuejs-br (@vuejs-br) no CodePen.
Observe que neste método atualizamos o estado da aplicação sem tocar no DOM - todas as manipulações são tratadas pelo Vue e o código que você escreve é focado na lógica de manipulação de dados.
Vue também provê a diretiva v-model
, que torna a interligação de mão dupla (two-way binding) entre a caixa de texto e o estado da aplicação uma moleza:
<div id="two-way-binding">
<p>{{ message }}</p>
<input v-model="message" />
</div>
2
3
4
const TwoWayBinding = {
data() {
return {
message: 'Olá Vue.js!'
}
}
}
Vue.createApp(TwoWayBinding).mount('#two-way-binding')
2
3
4
5
6
7
8
9
Veja o exemplo Interligação de mão dupla por vuejs-br (@vuejs-br) no CodePen.
# Condicionais e Repetições
Também é fácil alternar a presença de um elemento:
<div id="conditional-rendering">
<span v-if="seen">Agora você me viu</span>
</div>
2
3
const ConditionalRendering = {
data() {
return {
seen: true
}
}
}
Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
2
3
4
5
6
7
8
9
Este exemplo demonstra que nós podemos interligar dados não apenas ao texto e aos atributos, mas também à estrutura do DOM. Mais do que isso, Vue também provê um poderoso sistema de transições que pode automaticamente aplicar efeitos de transição quando elementos são inseridos/atualizados/removidos pelo Vue.
Você pode alterar seen
de true
para false
no exemplo abaixo para ver em ação:
Veja o exemplo Renderização condicional por vuejs-br (@vuejs-br) no CodePen.
Existem mais algumas diretivas, cada uma com sua própria funcionalidade. Por exemplo, a diretiva v-for
pode ser usada para exibir uma lista de itens usando dados de um Array:
<div id="list-rendering">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
2
3
4
5
6
7
const ListRendering = {
data() {
return {
todos: [
{ text: 'Aprender JavaScript' },
{ text: 'Aprender Vue' },
{ text: 'Criar algo incrível' }
]
}
}
}
Vue.createApp(ListRendering).mount('#list-rendering')
2
3
4
5
6
7
8
9
10
11
12
13
Veja o exemplo Renderização de listas por vuejs-br (@vuejs-br) no CodePen.
# Composição com Componentes
O sistema de componentes também é outro importante conceito no Vue, por ser uma abstração que proporciona a construção de aplicações de larga escala compostas por pequenos componentes, auto-contidos e frequentemente reutilizáveis. Se nós pensarmos sobre isso, quase qualquer tipo de interface de uma aplicação pode ser abstraída em uma árvore de componentes:
No Vue, um componente é essencialmente uma instância com opções pré-definidas. Registrar um componente no Vue é trivial: criamos um objeto para o componente assim como fizemos com o objeto app
e o utilizamos na opção components
de seu elemento pai:
const TodoItem = {
template: `<li>Isto é uma tarefa</li>`
}
// Cria uma aplicação Vue
const app = Vue.createApp({
components: {
TodoItem // Registra um novo componente
},
... // Outras propriedades para o componente
})
// Monta a aplicação Vue
app.mount(...)
2
3
4
5
6
7
8
9
10
11
12
13
14
Agora você pode compor com ele no template de outro componente:
<ol>
<!-- Cria uma instância do componente todo-item -->
<todo-item></todo-item>
</ol>
2
3
4
Mas isto renderizaria o mesmo texto toda vez que um item fosse utilizado, o que não é lá muito interessante. Devemos poder passar os dados do escopo superior (parent) para os componentes filhos. Vamos modificar o componente para fazê-lo aceitar uma prop:
const TodoItem = {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
}
2
3
4
Agora podemos passar o dado todo
em cada repetição de componente usando v-bind
:
<div id="todo-list-app">
<ol>
<!--
Agora provemos cada todo-item com o objeto todo que ele
representa, de forma que seu conteúdo possa ser dinâmico.
Também precisamos prover cada componente com uma "chave",
a qual será explicada posteriormente.
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const TodoItem = {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
}
const TodoList = {
data() {
return {
groceryList: [
{ id: 0, text: 'Vegetais' },
{ id: 1, text: 'Queijo' },
{ id: 2, text: 'Qualquer outra coisa que humanos podem comer' }
]
}
},
components: {
TodoItem
}
}
const app = Vue.createApp(TodoList)
app.mount('#todo-list-app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Veja o exemplo Introdução a componentes por vuejs-br (@vuejs-br) no CodePen.
Este é um exemplo fictício, mas conseguimos separar nossa aplicação em duas pequenas unidades, sendo que o componente filho está razoavelmente bem desacoplado do componente pai graças à funcionalidade de props
. Podemos agora melhorar nosso componente <todo-item>
com template e lógica mais complexos, sem afetar o restante.
Em uma aplicação grande, é essencial dividir todo o aplicativo em componentes para tornar o desenvolvimento gerenciável. Falaremos mais sobre componentes futuramente neste guia, mas aqui está um exemplo (imaginário) da aparência que o template de um aplicativo poderia ter com o uso de componentes:
<div id="app">
<app-nav></app-nav>
<app-view>
<app-sidebar></app-sidebar>
<app-content></app-content>
</app-view>
</div>
2
3
4
5
6
7
# Relação com Elementos Customizados
Você pode ter notado que componentes Vue são similares aos Elementos Customizados, parte da Especificação de Web Components (opens new window). Na verdade, partes do design de componentes do Vue (por exemplo, a API de slot
) foram influenciados pela especificação antes de serem implementados nativamente nos navegadores.
A principal diferença é que o modelo de componentes do Vue é projetado como parte de um framework coerente, que fornece muitos recursos adicionais necessários para a construção de aplicativos não triviais, por exemplo, templates reativos e gerenciamento de estado - ambos os quais a especificação não cobre.
O Vue também oferece um ótimo suporte para consumir e criar elementos personalizados. Para obter mais detalhes, verifique a seção Vue e Web Components.
# Pronto para Mais?
Nós introduzimos brevemente os recursos mais básicos do núcleo do Vue - o resto deste guia se aprofundará neles e em outros recursos avançados em um nível muito maior de detalhes, portanto certifique-se de ler tudo!