Diretório do Armazém de Estado
O diretório store contém os ficheiros do nosso armazém de estado de Vuex. O armazém de estado da Vuex é fornecido com a Nuxt de origem, mas está desativada por predefinição. A criação de um ficheiro index.js neste diretório ativa o armazém de estado.
A utilização de um armazém de estado para gerir o estado é importante para todas as grandes aplicações. É por isto que a Nuxt implementa a Vuex no seu núcleo.
Ativar o Armazém de Estado
O Nuxt irá procurar pelo diretório store. Se ele conter um ficheiro, que não seja um ficheiro oculto ou um ficheiro README.md, então a memória será ativada. Isto significa que o Nuxt irá:
A Nuxt procurará pelo diretório store. Se conter um ficheiro, que não é um ficheiro oculto ou um ficheiro README.md, então o armazém de estado será ativado. Isto significa que a Nuxt:
- Importará a Vuex
-
Adicionará a opção
storeà instância raiz do Vue.
Módulos
Cada ficheiro .js no diretório store é transformado num módulo nominal (sendo index o módulo raiz). O nosso valor state deve ser sempre uma function para evitar estado partilhado indesejado no lado do servidor.
Para começarmos, exportamos o estado (state), como uma função (function) e os recuperadores (getters), mutações (mutations) e ações (actions) como objetos (object):
export const state = () => ({
counter: 0
})
export const getters = {
getCounter(state) {
return state.counter
}
}
export const mutations = {
increment(state) {
state.counter++
}
}
export const actions = {
async fetchCounter({ state }) {
// requisitar
const res = { data: 10 };
state.counter = res.data;
return res.data;
}
}
Então, podemos ter um ficheiro store/todos.js:
export const state = () => ({
list: []
})
export const mutations = {
add(state, text) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}
O armazém de estado será criado como tal:
new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment(state) {
state.counter++
}
},
modules: {
todos: {
namespaced: true,
state: () => ({
list: []
}),
mutations: {
add(state, { text }) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, { todo }) {
todo.done = !todo.done
}
}
}
}
})
E no nosso pages/todos.vue, ao usar o módulo todos:
<template>
<ul>
<li v-for="todo in todos" :key="todo.text">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
</ul>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos () {
return this.$store.state.todos.list
}
},
methods: {
addTodo (e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todos/toggle'
})
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
O método do módulo também funciona para definições de alto nível sem implementar um sub-diretório no diretório do armazém de estado.
Exemplo para o estado (state): criamos um ficheiro store/state.js e adicionamos o seguinte:
export default () => ({
counter: 0
})
E os recuperadores (getters) correspondentes podem estar no ficheiro store/getters.js:
export default {
getCounter(state) {
return state.counter
}
}
E as mutações (mutations) correspondentes podem estar no ficheiro store/mutations.js:
export default {
increment(state) {
state.counter++
}
}
E as ações (actions) correspondentes podem estar no ficheiro store/actions.js:
export default {
async fetchCounter({ state }) {
// requisitar
const res = { data: 10 };
state.counter = res.data;
return res.data;
}
}
Exemplo de estrutura de pasta
Uma estrutura complexa de ficheiros ou pastas de configuração do armazém de estado pode ter o seguinte aspeto:
store/
--| index.js
--| ui.js
--| shop/
----| cart/
------| actions.js
------| getters.js
------| mutations.js
------| state.js
----| products/
------| mutations.js
------| state.js
------| itemsGroup1/
--------| state.js
Extensões no Armazém de Estado
Podemos adicionar extensões adicionais ao armazém de estado, colocando-os no ficheiro store/index.js:
import myPlugin from 'myPlugin'
export const plugins = [myPlugin]
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
Mais informações sobre as extensões: documentação da Vuex .
A Ação nuxtServerInit
Se a ação nuxtServerInit estiver definida no armazém de estado e o modo for universal, a Nuxt a chamará com o contexto (somente do lado do servidor). É útil quando temos alguns dados no servidor que queremos fornecer diretamente ao lado do cliente.
Por exemplo, digamos que temos sessões no lado do servidor e podemos aceder ao utilizador conectado através da req.session.user. Para adicionar o utilizador autenticado ao nosso armazém de estado, atualizamos o nosso store/index.js para o seguinte:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
store/index.js) receberá esta ação. Temos de encadear as ações do nosso módulo a partir daí.O contexto é fornecido a nuxtServerInit como o segundo argumento no método asyncData.
Se o nuxt generate for executado, a nuxtServerInit será executada para cada rota dinâmica gerada.
nuxtServerInit devem retornar uma promessa (Promise) ou utilizar async e await para permitir o servidor da Nuxt esperar por estas.actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
Modo Estrito da Vuex
O modo estrito é ativado por predefinição no modo de desenvolvimento e desativado no modo de produção. Para desativar o modo estrito no desenvolvimento, sigamos o exemplo abaixo em store/index.js:
export const strict = false
Sébastien Chopin
Nazaré da Piedade
Nobu
川音리오
Maciek Palmowski
Nestor Vera
Daniel Roe
Yue Yang
Jeronimas
Alessandro Carrano
Clément Ollivier
Alexander Lichter
N3-rd
Adrien Zaganelli
Mag
Stefan Huber
Olga Bulat
Paiva
Florian Reuschel
Savas Vedova
Steven
Vinícius Alves
Kareem Dabbeet
Valentín Costa
Ryan Skinner
Alex Hirzel
Ajeet Chaulagain
René Eschke
Nico Devs
Muhammad
Naoki Hamada
Tom
Yann Aufray
Anthony Chu
Nuzhat Minhaz
Lucas Portet
Richard Schloss
Bobby
bpy
Antony Konstantinidis
Hibariya
Jose Seabra
Eze
Florian Lefebvre
Lucas Recoaro
Julien SEIXAS