Plugins
Os stores do Vuex aceitam a opção plugins que expõe gatilhos (ou hooks) para cada mutação. Um plugin Vuex é simplesmente uma função que recebe um store como seu único argumento:
const myPlugin = (store) => {
// chamado quando o store é inicializado
store.subscribe((mutation, state) => {
// chamada após cada mutação.
// A mutação vem no formato de `{ type, payload }`.
})
}
E pode ser usada assim:
const store = createStore({
// ...
plugins: [myPlugin]
})
Confirmando (ou fazendo commit de) Mutações Dentro de Plugins
Plugins não tem permissão para alterar o estado diretamente - similar aos seus componentes, eles podem apenas acionar mudanças confirmando (ou fazendo o commit de) mutações.
Por confirmar (ou fazer commit de) mutações, um plugin pode ser usado para sincronizar uma fonte de dados ao store. Por exemplo, para sincronizar uma fonte de dados websocket ao store (isso é só um exemplo inventado, na realidade a função createPlugin pode receber parâmetros adicionais para tarefas mais complexas):
export default function createWebSocketPlugin (socket) {
return (store) => {
socket.on('data', data => {
store.commit('receiveData', data)
})
store.subscribe(mutation => {
if (mutation.type === 'UPDATE_DATA') {
socket.emit('update', mutation.payload)
}
})
}
}
const plugin = createWebSocketPlugin(socket)
const store = createStore({
state,
mutations,
plugins: [plugin]
})
Capturando os Momentos do Estado
Às vezes, um plugin pode querer receber "momentos" do estado, e também comparar o estado pós-mutação com o estado de pré-mutação. Para conseguir isso, você precisará realizar uma cópia-profunda do objeto de estado:
const myPluginWithSnapshot = (store) => {
let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {
let nextState = _.cloneDeep(state)
// compara `prevState` e `nextState`...
// salva o estado para a próxima mutação
prevState = nextState
})
}
Plugins que capturam momentos do estado devem ser usados apenas durante o desenvolvimento. Quando usamos webpack ou Browserify, podemos construir nossas próprias ferramentas de distribuição (ou nossos próprios builds) que lidam com isso para nós:
const store = createStore({
// ...
plugins: process.env.NODE_ENV !== 'production'
? [myPluginWithSnapshot]
: []
})
O plugin vai ser usado por padrão. Para produção, você vai precisar do DefinePlugin para webpack ou envify para Browserify para converter o valor do process.
para false
na distribuição (ou build) final.
Plugin de Log Integrado
Vuex vem com um plugin de log para casos comuns de depuração:
import { createLogger } from 'vuex'
const store = createStore({
plugins: [createLogger()]
})
A função createLogger
tem algumas opções:
const logger = createLogger({
collapsed: false, // expande automaticamente mutações registradas no log
filter (mutation, stateBefore, stateAfter) {
// retorna `true` se uma mutação deve ser registrada no log
// `mutation` é um `{ type, payload }`
return mutation.type !== "aBlocklistedMutation"
},
actionFilter (action, state) {
// o mesmo que `filter`, mas para ações
// `action` é um `{ type, payload }`
return action.type !== "aBlocklistedAction"
},
transformer (state) {
// transforma o estado antes de regitrá-lo no log.
// por exemplo, retorna apenas uma sub-árvore específica
return state.subTree
},
mutationTransformer (mutation) {
// mutações são registradas no log no formato de `{ type, payload }`
// mas podemos formatá-las como quisermos.
return mutation.type
},
actionTransformer (action) {
// O mesmo que mutationTransformer mas para ações
return action.type
},
logActions: true, // Log de Ações
logMutations: true, // Log de mutações
logger: console, // implementação da API `console`, valor padrão `console`
})
O arquivo de log também pode ser incluído diretamente via tag <script>
, e vai expor a função createVuexLogger
globalmente.
Perceba que o plugin de log captura momentos do estado, então use-o apenas durante o desenvolvimento.