Plugins
Les stores Vuex prennent une option plugins
qui expose des hooks pour chaque mutation. Un plugin Vuex est simplement une fonction qui reçoit un store comme unique argument :
const myPlugin = store => {
// appelé quand le store est initialisé
store.subscribe((mutation, state) => {
// appelé après chaque mutation.
// Les mutations arrivent au format `{ type, payload }`.
})
}
Et peut être utilisé ainsi :
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
Acter des mutations dans des plugins
Les plugins ne sont pas autorisés à muter directement l'état. Tout comme vos composants, ils peuvent simplement déclencher des changements en actant des mutations.
En actant des mutations, un plugin peut être utilisé pour synchroniser la source de données avec le store. Par exemple, pour synchroniser la source de données d'une websocket vers le store (c'est juste un exemple artificiel, en réalité la fonction createPlugin
peut prendre des options additionnelles pour des tâches plus complexes) :
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 = new Vuex.Store({
state,
mutations,
plugins: [plugin]
})
Prendre des instantanés de l'état
Parfois un plugin peut vouloir recevoir des « instantanés » de l'état, et également comparer l'état post mutation avec l'état prémutation. Pour faire ceci, vous aurez besoin d'effectuer une copie complète de l'état :
const myPluginWithSnapshot = store => {
let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {
let nextState = _.cloneDeep(state)
// comparer `prevState` et `nextState`...
// sauver l'état pour la prochaine mutation
prevState = nextState
})
}
Les plugins qui peuvent prendre des instantanés ne devraient être utilisés que pendant le développement. Lorsqu'on utilise webpack ou Browserify, on peut laisser nos outils de développement (« devtools ») s'occuper de ça pour nous :
const store = new Vuex.Store({
// ...
plugins: process.env.NODE_ENV !== 'production'
? [myPluginWithSnapshot]
: []
})
Le plugin sera utilisé par défaut. Pour la production, vous aurez besoin de DefinePlugin pour webpack ou de envify pour Browserify pour convertir la valeur de process.env.NODE_ENV !== 'production'
à false
pour le build final.
Plugin de logs intégré
Si vous utilisez vue-devtools vous n'avez probablement pas besoin de ça.
Vuex fournit un plugin de logs à des fins de débogage :
import createLogger from 'vuex/dist/logger'
const store = new Vuex.Store({
plugins: [createLogger()]
})
La fonction createLogger
prend quelques options :
const logger = createLogger({
collapsed: false, // auto-expand logged mutations
filter (mutation, stateBefore, stateAfter) {
// retourne `true` si une mutation devrait être logguée
// `mutation` est un `{ type, payload }`
return mutation.type !== "aBlocklistedMutation"
},
transformer (state) {
// transforme l'état avant de le logguer.
// retourne par exemple seulement un sous-arbre spécifique
return state.subTree
},
mutationTransformer (mutation) {
// les mutations sont logguées au format `{ type, payload }`
// nous pouvons les formater comme nous le souhaitons.
return mutation.type
},
logger: console, // implementation de l'API `console`, par défaut `console`
})
Le fichier de logs peut aussi être inclus directement via une balise script
, et exposera la fonction createVuexLogger
globalement.
Notez que le plugin de logs peut prendre des instantanés de l'état, ne l'utilisez donc que durant le développement.