Why Vuex
When developing a single-page application using vue.js, we often encounter data or state that is shared between components, or data that needs to be passed through the props layer. On a smaller scale, we use common parent-child component communication methods such as props and events, or use the event bus to communicate between any two components. But as applications become more complex, problems begin to arise, and such communication methods can lead to extremely chaotic data flows.
At this point, we need to use our state management tool Vuex. Vuex is a library designed specifically for vue. js framework and for state management of vue. js applications. It draws lessons from the basic idea of Flux and Redux to extract the state to the global and form a Store. Because Vuex uses new Vue internally to make the data in Store “responsive”, Vuex is a library that utilizes the internal mechanism of Vue. It is highly compatible with Vue and easier and more efficient to use with Vue. The disadvantage is that it cannot be used with other frameworks such as React.
This section will briefly introduce the core internal mechanics of Vuex.
The installation
Vue.js provides a vue. use method to install the plug-in, which internally calls the install method provided by the plug-in.
Vue.use(Vuex);
Copy the code
So our plug-in needs to provide an install method to install it.
let Vue;
export default install (_Vue) {
Vue.mixin({ beforeCreate: vuexInit });
Vue = _Vue;
}
Copy the code
We use vuue. Mixin to confuse the vuexInit method into the beforeCreate hook and store the Vue object with Vue. So what does vuexInit actually do?
We know that when using Vuex, we need to pass store into the Vue instance.
/* New Vue({el: '#app', store}); /* New Vue({el: '#app', store});Copy the code
However, we can access the store in every VM, which requires vuexInit.
function vuexInit () { const options = this.$options; if (options.store) { this.$store = options.store; } else { this.$store = options.parent.$store; }}Copy the code
Because the vuexInit method was previously confused with the vue. mixin method into the beforeCreate hook, the vuexInit method is called for each VM instance.
If it is the root node ($options indicates the root node), assign options.store directly to this.$store. Otherwise, it is not the root node and is obtained from the parent node’s $store.
With this step, we can now access the store instance in any VM through this.$store
Store
Reactivity of data
First we need to “reactalize” state in the Store constructor.
constructor () {
this._vm = new Vue({
data: {
$$state: this.state
}
})
}
Copy the code
Those familiar with “reactive” will know that after this step, state collects the required dependencies in the Dep and updates the corresponding views as they are modified. Let’s look at a little example.
let globalData = {
d: 'hello world'
};
new Vue({
data () {
return {
$$state: {
globalData
}
}
}
});
/* modify */
setTimeout(() => {
globalData.d = 'hi~';
}, 1000);
Vue.prototype.globalData = globalData;
Copy the code
In any template
<div>{{globalData.d}}</div>
Copy the code
The above code has a globalData globally, which is passed into the data of a Vue object, and is then displayed in any Vue template. Since globalData is already in Vue’s Prototype, this. Prototype is accessed directly in the template {{globalData.d}}. At this point, setTimeout modifies globalData.d after 1s, and we notice that globalData.d in the template has changed. In fact, the above part is Vuex relies on Vue core to achieve the “responsivity” of data.
Having covered the core of Vuex’s “responsivity” of data through Vue, let’s move on to the two Store apis.
commit
The first is the COMMIT method, which we know is used to trigger mutation.
commit (type, payload, _options) {
const entry = this._mutations[type];
entry.forEach(function commitIterator (handler) {
handler(payload);
});
}
Copy the code
Remove the corresponding mutations from _mutations, and loop through each mutation.
dispatch
In the same way that dispatch is used to trigger actions, it can contain asynchronous states.
dispatch (type, payload) {
const entry = this._actions[type];
return entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload);
}
Copy the code
Again, take all the corresponding actions in _actions and execute them, or wrap them with promise.all if there are more than one.
The last
At the heart of understanding Vuex is understanding how it is integrated with Vue itself, and how Vue’s responsive mechanisms can be leveraged to make the core Store “responsive.”
Vuex itself code is not much and elegant design, very worth reading, want to read the source code of students see Vuex source code.
Note: This section refers to the Working Principle of Vuex State Management.