Anwendungsstruktur
Tatsächlich unterliegt Vuex keinen Einschränkungen hinsichtlich der Organisation Ihrer Codestruktur. Im Gegenteil, es erzwingt eine Reihe übergeordneter Prinzipien:
1. Ebene Der Status wird im Store zentralisiert.
2. Die einzige Möglichkeit, den Status zu ändern, besteht darin, Mutationen einzureichen, was eine synchrone Transaktion ist.
3. Asynchrone Logik sollte in Aktion gekapselt sein.
Solange Sie diese Regeln befolgen, liegt es an Ihnen, wie Sie Ihr Projekt strukturieren. Wenn Ihre Store-Datei sehr groß ist, teilen Sie sie einfach in Aktions-, Mutations- und Getter-Dateien auf.
Für etwas komplexere Anwendungen müssen wir möglicherweise Module verwenden. Das Folgende ist eine einfache Projektstruktur:
├── index.html
├── main.js
├── api
│ └── ... # API hier starten Anfrage
├── Komponenten
│ ├── App.vue
│ └── ...
└── Store
├── index.js
├── Actions.js ├── Actions.js ├── Mutationen.js # Wurzelmutationen
└── Module
├── Cart.js # Cart-Modul └── Produkte .js # Produktmodul
Weitere Informationen finden Sie unter Beispiel für einen Einkaufswagen.
Module
Aufgrund der Verwendung eines einzelnen Statusbaums ist der gesamte Status der Anwendung in einem großen Objekt enthalten. Da jedoch der Umfang unserer Anwendung weiter zunahm, wurde dieser Store sehr aufgebläht.
Um dieses Problem zu lösen, ermöglicht uns Vuex, den Store in Module zu unterteilen. Jedes Modul enthält seinen eigenen Status, seine eigene Mutation, seine eigene Aktion und seinen eigenen Getter, sogar verschachtelte Module. So ist es organisiert:
const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA's state store.state.b // -> moduleB's state
Modul lokaler Status
Der erste Parameter, den die Mutations- und Getter-Methoden des Moduls empfangen, ist der lokale Status des Moduls.
const moduleA = { state: { count: 0 }, mutations: { increment: (state) { // state 是模块本地的状态。 state.count++ } }, getters: { doubleCount (state) { return state.count * 2 } } }
In ähnlicher Weise macht context.state in den Aktionen des Moduls den lokalen Status und context.rootState den Root-Status verfügbar.
const moduleA = { // ... actions: { incrementIfOdd ({ state, commit }) { if (state.count % 2 === 1) { commit('increment') } } } }
In den Gettern des Moduls wird der Root-Status auch als dritter Parameter offengelegt.
const moduleA = { // ... getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } }
Namespace
Bitte beachten Sie, dass die Aktionen, Mutationen und Getter innerhalb des Moduls weiterhin im globalen Namespace registriert sind – diesem This ermöglicht es mehreren Modulen, auf denselben Mutations-/Aktionstyp zu reagieren. Sie können dem Modulnamen ein Präfix oder Suffix hinzufügen, um den Namespace festzulegen und Namenskonflikte zu vermeiden. Wenn Ihr Vuex-Modul wiederverwendbar ist und die Ausführungsumgebung unbekannt ist, sollten Sie dies tun. Entfernung, wir möchten ein Todos-Modul erstellen:
// types.js // 定义 getter、 action 和 mutation 的常量名称 // 并且在模块名称上加上 `todos` 前缀 export const DONE_COUNT = 'todos/DONE_COUNT' export const FETCH_ALL = 'todos/FETCH_ALL' export const TOGGLE_DONE = 'todos/TOGGLE_DONE' // modules/todos.js import * as types from '../types' // 用带前缀的名称来定义 getters, actions and mutations const todosModule = { state: { todos: [] }, getters: { [types.DONE_COUNT] (state) { // ... } }, actions: { [types.FETCH_ALL] (context, payload) { // ... } }, mutations: { [types.TOGGLE_DONE] (state, payload) { // ... } } }
Dynamisches Modul registrieren
Sie können zum Erstellen die Methode store.registerModule verwenden Im Store registrieren. Dann ein Modul registrieren:
store.registerModule('myModule', { // ... })
Der Wert „store.state.myModule“ des Moduls wird als Status des Moduls angezeigt.
Andere Vue-Plug-Ins können ein Modul an den Anwendungsspeicher anhängen und dann die Statusverwaltungsfunktion von Vuex durch dynamische Registrierung nutzen. Beispielsweise integriert die Bibliothek vuex-router-sync vue-router und vuex, indem sie den Routing-Status der Anwendung in einem dynamisch registrierten Modul verwaltet.
Sie können auch store.unregisterModule(moduleName) verwenden, um dynamisch registrierte Module zu entfernen. Sie können diese Methode jedoch nicht zum Entfernen statischer Module verwenden (d. h. Module, die beim Erstellen des Speichers deklariert wurden).
Plugins
Der Store von Vuex erhält die Plugins-Option, die Hooks für jede Mutation verfügbar macht. Ein Vuex-Plugin ist eine einfache Methode, die sotre als einzigen Parameter akzeptiert:
const myPlugin = store => { // 当 store 在被初始化完成时被调用 store.subscribe((mutation, state) => { // mutation 之后被调用 // mutation 的格式为 {type, payload}。 }) }
und es dann wie folgt verwendet:
const store = new Vuex.Store({ // ... plugins: [myPlugin] })
Mutationen innerhalb von Plugins übermitteln
Plugins können den Status nicht direkt ändern – genau wie Ihre Komponenten können sie nur durch Mutationen ausgelöst werden.
Durch die Übermittlung von Mutationen kann das Plug-in verwendet werden, um die Datenquelle mit dem Store zu synchronisieren. Zum Beispiel, um die Websocket-Datenquelle mit dem Store zu synchronisieren (dies ist nur ein Beispiel zur Veranschaulichung der Verwendung, in der Praxis werden der Methode createPlugin weitere Optionen angehängt, um komplexe Aufgaben abzuschließen).
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] })
Status-Snapshot generieren
Manchmal möchte das Plug-in den Status „ Snapshot“ und Statusänderungen vor und nach der Änderung. Um diese Funktionen zu implementieren, ist eine tiefe Kopie des Statusobjekts erforderlich:
const myPluginWithSnapshot = store => { let prevState = _.cloneDeep(store.state) store.subscribe((mutation, state) => { let nextState = _.cloneDeep(state) // 对比 prevState 和 nextState... // 保存状态,用于下一次 mutation prevState = nextState }) }
** Plug-Ins, die Status-Snapshots generieren, können nur sein Wird während der Entwicklungsphase mit Webpack oder Browserify verwendet, lassen Sie das Build-Tool für uns erledigen:
const store = new Vuex.Store({ // ... plugins: process.env.NODE_ENV !== 'production' ? [myPluginWithSnapshot] : [] })
Das Plug-in ist standardmäßig aktiviert . Für die Auslieferung an die Produktion müssen Sie DefinePlugin von Webpack oder Envify von Browserify verwenden, um „process.env.NODE_ENV !== 'produktion'“ in „false“ zu konvertieren.
Integriertes Logger-Plug-in
如果你正在使用 vue-devtools,你可能不需要。
Vuex 带来一个日志插件用于一般的调试:
import createLogger from 'vuex/dist/logger' const store = new Vuex.Store({ plugins: [createLogger()] })
createLogger 方法有几个配置项:
const logger = createLogger({ collapsed: false, // 自动展开记录 mutation transformer (state) { // 在记录之前前进行转换 // 例如,只返回指定的子树 return state.subTree }, mutationTransformer (mutation) { // mutation 格式 { type, payload } // 我们可以按照想要的方式进行格式化 return mutation.type } })
日志插件还可以直接通过