# Fundamentos da Reatividade

Esta seção usa a sintaxe de componente single-file para exemplos de código

# Declarando Estado Reativo

Para criar um estado reativo a partir de um objeto JavaScript, podemos usar o método reactive:

import { reactive } from 'vue' // estado reativo const state = reactive({ count: 0 }) 
1
2
3
4
5
6

reactive é equivalente à API Vue.observable() do Vue 2.x, renomeado para evitar confusões com os Observables do RxJS. Aqui, o estado retornado é um objeto reativo. A conversão reativa é "profunda" - ela afeta todas as propriedades aninhadas do objeto passado.

O caso de uso essencial para o estado reativo no Vue é que podemos usá-lo durante a renderização. Graças ao rastreamento de dependência, a exibição é atualizada automaticamente quando o estado reativo muda.

Esta é a própria essência do sistema de reatividade do Vue. Quando você retorna um objeto de data() em um componente, ele é tornado reativo internamente pelo reactive(). O template é compilado em uma função de renderização que faz uso dessas propriedades reativas.

Você pode aprender mais sobre reactive na seção Básico da API de Reatividade

# Criação de Valores Reativos Avulsos como refs

Imagine o caso em que temos um valor primitivo avulso (por exemplo, uma string) e queremos torná-la reativa. Claro, poderíamos fazer um objeto com uma única propriedade igual à nossa string e passá-la para reactive. Vue tem um método que fará o mesmo para nós - ele é o ref:

import { ref } from 'vue' const count = ref(0) 
1
2
3

ref retornará um objeto reativo e mutável que serve como uma referência reativa para o valor interno que está mantendo - é daí que vem o seu nome. Este objeto contém uma única propriedade chamada value:

import { ref } from 'vue' const count = ref(0) console.log(count.value) // 0 count.value++ console.log(count.value) // 1 
1
2
3
4
5
6
7

# Ref Desempacotada

Quando um ref é retornado como uma propriedade no contexto de renderização (o objeto retornado de setup()) e acessado no template, ele automaticamente se desempacota rasamente para o valor interno. Apenas o ref aninhado exigirá .value no template:

<template> <div> <span>{{ count }}</span> <button @click="count++">Incrementar contador</button> <button @click="nested.count.value ++">Incrementar contador aninhado</button> </div> </template> <script> import { ref } from 'vue' export default { setup() { const count = ref(0) return { count, nested: { count } } } } </script> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Dica

Se você não quiser acessar a instância do objeto real, pode envolvê-lo em um reactive:

nested: reactive({ count }) 
1
2
3

# Acesso em Objetos Reativos

Quando um ref é acessado ou alterado como uma propriedade de um objeto reativo, ele se desempacota automaticamente para o valor interno para que se comporte como uma propriedade normal:

const count = ref(0) const state = reactive({ count }) console.log(state.count) // 0 state.count = 1 console.log(count.value) // 1 
1
2
3
4
5
6
7
8
9

Se uma nova ref for atribuída à uma propriedade vinculada à uma ref existente, ela substituirá a antiga ref:

const otherCount = ref(2) state.count = otherCount console.log(state.count) // 2 console.log(count.value) // 1 
1
2
3
4
5

O desempacotamento de um ref só acontece quando aninhado dentro de um Object reativo. Não há desempacotamento executado quando o ref é acessado de um Array ou um tipo de coleção nativo como Map (opens new window):

const books = reactive([ref('Guia do Vue 3')]) // precisa usar .value aqui console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // precisa usar .value aqui console.log(map.get('count').value) 
1
2
3
4
5
6
7

# Desestruturar Estado Reativo

Quando queremos usar algumas propriedades do grande objeto reativo, pode ser tentador usar desestruturação do ES6 (opens new window) para obter as propriedades que desejamos:

import { reactive } from 'vue' const book = reactive({ author: 'Equipe Vue', year: '2020', title: 'Guia do Vue 3', description: 'Você está lendo esta documentação agora ;)', price: 'grátis' }) let { author, title } = book 
1
2
3
4
5
6
7
8
9
10
11

Infelizmente, com tal desestruturação, a reatividade para ambas as propriedades seria perdida. Para tal, precisamos converter nosso objeto reativo em um conjunto de refs. Esses refs manterão a conexão reativa com o objeto de origem:

import { reactive, toRefs } from 'vue' const book = reactive({ author: 'Equipe Vue', year: '2020', title: 'Guia do Vue 3', description: 'Você está lendo esta documentação agora ;)', price: 'grátis' }) let { author, title } = toRefs(book) title.value = 'Guia detalhado do Vue 3' // precisamos usar .value porque `title` é uma `ref` agora console.log(book.title) // 'Guia detalhado do Vue 3' 
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Você pode aprender mais sobre refs na seção API de Refs

# Evite Mutar Objetos Reativos com readonly

Às vezes, queremos rastrear as alterações do objeto reativo (ref oureactive), mas também queremos evitar alterá-lo de um determinado local do aplicativo. Por exemplo, quando temos um objeto reativo provido, queremos evitar a sua mutação onde ele é injetado. Para fazer isso, podemos criar um proxy somente leitura (readonly) para o objeto original:

import { reactive, readonly } from 'vue' const original = reactive({ count: 0 }) const copy = readonly(original) // a mutação do original fará com que os observadores confiem na cópia original.count++ // alterar a cópia irá falhar e resultar em um aviso copy.count++ // warning: "Set operation on key 'count' failed: target is readonly." 
1
2
3
4
5
6
7
8
9
10
11