# Gerenciamento de Estado
# Implementação Oficial Estilo Flux
Grandes aplicações podem frequentemente crescer em complexidade, devido à múltiplas partes do estado da aplicação espalhadas em vários componentes e em interações entre eles. Para resolver esse problema, Vue oferece o Vuex (opens new window), nossa própria biblioteca de gerenciamento de estado inspirada na arquitetura Elm. Ele é também integrado ao vue-devtools (opens new window), permitindo uma navegação pelo histórico de mudanças de estado (opens new window) (time travel debugging) sem qualquer configuração inicial.
# Informação para Desenvolvedores React
Se você vem do React, deve estar se perguntando como o Vuex se compara ao Redux (opens new window), a implementação Flux mais popular do ecossistema. O Redux é agnóstico quanto à camada view, de forma que ele pode ser usado facilmente com Vue através de ligações simples (opens new window). O Vuex é diferente por saber que está em uma aplicação Vue. Isso permite uma melhor integração com Vue ao fornecer uma API mais intuitiva e uma melhor experiência de desenvolvimento.
# Gerenciamento de Estado Simples do Zero
Frequentemente as pessoas esquecem que a fonte de verdade de aplicações Vue são os objetos reativos data
- uma instância Vue apenas direciona acesso à eles. Portanto, se você possui uma parte do estado que deveria ser compartilhado entre instâncias múltiplas, você pode usar um método reactive
para tornar um objeto reativo.
const { createApp, reactive } = Vue
const sourceOfTruth = reactive({
message: 'Olá'
})
const appA = createApp({
data() {
return sourceOfTruth
}
}).mount('#app-a')
const appB = createApp({
data() {
return sourceOfTruth
}
}).mount('#app-b')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app-a">App A: {{ message }}</div>
<div id="app-b">App B: {{ message }}</div>
2
3
Agora, sempre que sourceOfTruth
mudar, tanto appA
e appB
irão atualizar suas views automaticamente. Possuímos uma única fonte de verdade agora, porém a depuração vira um pesadelo. Qualquer dado pode ser modificado em qualquer parte de nossa aplicação a qualquer momento, sem deixar rastro algum.
const appB = createApp({
data() {
return sourceOfTruth
},
mounted() {
sourceOfTruth.message = 'Adeus' // ambas aplicações irão renderizar "Adeus"
}
}).mount('#app-b')
2
3
4
5
6
7
8
Para ajudar a resolver esse problema, podemos adotar o padrão store:
const store = {
debug: true,
state: reactive({
message: 'Olá!'
}),
setMessageAction(newValue) {
if (this.debug) {
console.log('setMessageAction disparado com', newValue)
}
this.state.message = newValue
},
clearMessageAction() {
if (this.debug) {
console.log('clearMessageAction disparado')
}
this.state.message = ''
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Perceba que todas as ações que modificam o estado da store são colocadas dentro da própria store. Esse tipo de gerenciamento de estado centralizado facilita a compreensão de que tipo de mutações podem acontecer e como elas são disparadas. Agora, temos um log de mudanças para quando algo der errado.
Além disso, cada instância/componente pode ainda possuir e gerenciar seu estado privado:
<div id="app-a">{{sharedState.message}}</div>
<div id="app-b">{{sharedState.message}}</div>
2
3
const appA = createApp({
data() {
return {
privateState: {},
sharedState: store.state
}
},
mounted() {
store.setMessageAction('Adeus!')
}
}).mount('#app-a')
const appB = createApp({
data() {
return {
privateState: {},
sharedState: store.state
}
}
}).mount('#app-b')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Dica
Você jamais deve substituir o objeto state
original - os componentes e a store precisam compartilhar a referência para o mesmo objeto, de forma que as mutações sejam acompanhadas.
Ao desenvolvermos uma convenção em que componentes não devem modificar diretamente o estado pertencente à store, mas sim disparar eventos que comuniquem a store à realizar ações, nós chegamos na arquitetura Flux (opens new window). A vantagem dessa convenção é que podemos registrar todas as mudanças de estado e implementar auxiliares avançados de depuração, tais como logs de mutação, snapshots e repetição de histórico (history re-rolls) / navegação de histórico (time travel).
O que nos leva totalmente de volta ao Vuex (opens new window), então se você leu até aqui, provavelmente é hora de testá-lo!