You are browsing Nuxt 2 docs. Go to Nuxt 3 docs, or learn more about Nuxt 2 Long Term Support.

Translated page Contents of this page might be outdated.

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.


Este diretório não pode ser renomeado sem configuração adicional.

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:

  1. Importará a Vuex
  2. 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):

store/index.js
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:

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:

pages/todos.vue
<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:

store/getters.js
export default {
  getCounter(state) {
    return state.counter
  }
}

E as mutações (mutations) correspondentes podem estar no ficheiro store/mutations.js:

store/mutations.js
export default {
  increment(state) {
    state.counter++
  }
}

E as ações (actions) correspondentes podem estar no ficheiro store/actions.js:

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:

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:

store/index.js
actions: {
  nuxtServerInit ({ commit }, { req }) {
    if (req.session.user) {
      commit('user', req.session.user)
    }
  }
}
Só o módulo principal (em 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.

As ações assíncronas de nuxtServerInit devem retornar uma promessa (Promise) ou utilizar async e await para permitir o servidor da Nuxt esperar por estas.
store/index.js
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