O diretório store
O diretório store
contém seus ficheiros de memória do Vuex. A memória do Vuex vem fora da caixa com o Nuxt mas está desativada por padrão. A criação de um ficheiro index.js dentro deste diretório ativa a memória.
Usar uma memória para gerir o estado é importante para toda grande aplicação. Isto é o porquê do Nuxt implementar o Vuex dentro do seu núcleo.
Ativar a memória
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á:
- Importar o Vuex
-
Adicionar a opção
store
à instância raíz do Vue.
Os módulos
Todo ficheiro .js
dentro do diretório store
é transformado em um módulo com nome reservado (com o index
sendo a raiz do módulo). O seu valor de state
sempre será uma function
para evitar estado partilhado indesejado no lado do servidor.
Para começar, exporte o estado (state) como uma função, e as mutações (mutations) e ações (actions) como objetos.
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
Depois, você pode 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
}
}
A memória será criada tal e qual:
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 dentro do seu 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 a implementação de um sub-diretório dentro do diretório store.
Exemplo para estado (state): você cria um ficheiro store/state.js
e adiciona o seguinte.
export default () => ({
counter: 0
})
E os recuperadores (getters) podem estar no ficheiro store/getter.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 }) {
// fazer requisição
const response = { data: 10 };
state.counter = response.data;
return response.data;
}
}
Exemplo de estrutura de pasta
Uma configuração complexa da estrutura de ficheiro/pasta memória pode parecer com isto:
store/
--| index.js
--| ui.js
--| shop/
----| cart/
------| actions.js
------| getters.js
------| mutations.js
------| state.js
----| products/
------| mutations.js
------| state.js
------| itemsGroup1/
--------| state.js
Os plugins na memória
Você pode adicionar plugins adicionais à memória ao por eles dentro do 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 os plugins na: documentação do Vuex .
A ação nuxtServerInit
Se a ação nuxtServerInit
estiver definida dentro da memória (store) e o modo estiver em universal
, o Nuxt irá chamar ele com o contexto (apenas a partir do lado do servidor). É útil quando nós temos algum dado no servidor que nós queremos dar diretamente para o lado do cliente.
Por exemplo, vamos dizer que temos sessões no lado do servidor e podemos acessar o usuário conectado através do req.session.user
. Para adicionar o usuário autenticado a nossa memória (store), nós 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
) será receber esta ação. Você precisará encadear as ações do módulo a partir de lá.O contexto é dado ao nuxtServerInit
como o segundo argumento dentro do método asyncData
.
Se o nuxt generate
for executado, o nuxtServerInit
será executado para cada rota dinâmica gerada.
nuxtServerInit
assíncronas devem retornar uma promessa (Promise) ou usar o async/await para permitir o servidor do nuxt esperar neles.actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
O modo estrito do Vuex
O modo estrito está ativado por padrão no modo de desenvolvimento e desativado no modo de produção. Para desativar o modo estrito em desenvolvimento, siga o exemplo abaixo dentro do store/index.js
:
export const strict = false