mutation action similar, except that the mutation is submitted Action, rather than directly change the status, and can contain any action in the asynchronous operation, the parameters of each mutation is an object 1, may contain the following six properties:
commit; current namespace corresponding to the commit
dispatch; namespace corresponding to the current dispatch
State; namespace corresponding to the current State
getters; current namespace corresponding getters
rootState; root module State
getters root module; rootGetters
Similar to the mutation, created Vuex.Store () can be created through the actions of each action when instances warehouse
Neither should we call an action, but is called by store.dispatch, dispatch can take two parameters, as follows:
type; the corresponding action name
payload; incoming parameters
There is also a dispatch written is passed to an object, the object can take a type argument, type the name of the specified action, the entire object is passed as an argument to the action. Note: action can contain a asynchronous operation
E.g:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="https://unpkg.com/[email protected]/dist/vuex.js"></script> </head> <body> <div id="app"> <p>{{no}}</p> <button @click="test">测试</button> </div> <script> const store = new Vuex.Store({ state:{no:100}, mutations:{ increment(state,payload){state.no+=payload.no;} }, actions:{ increment({commit},info){ return new Promise(function(Resolve, Reject) { // Action in the object returns a Promise the setTimeout ( function () { the commit ( ' INCREMENT ' , info) Resolve ( ' OK ' ) }, 500 ) }) } } }) var App = new new Vue ( { EL: " #app " , Store, computed: { NO () { return this.$store.state.no} }, methods:{ test(){ this.$store.dispatch('increment',{no:100}) } } }) </script> </body> </html>
We do not return a promise object action can also be held, internal vuex calls Promise.resolve automatically return value to a target Promise
Source code analysis
writer by: Desert QQ: 22969969
Creating Vuex.Store () performs installModule () to install root module initialization, and mutation related as follows:
function installModule (Store, rootState, path, module, Hot) { // install modules / * slightly * / module.forEachAction ( function (Action, Key) { // Action objects traverse module module, if found, then the implementation of this anonymous function parameter 1: each action value key: the key corresponding to the name var of the type = action.root key: namespace + key;? // corresponding namespaces key + var Handler = action.handler || action; // get the corresponding function registerAction (Store, of the type, Handler, local); // call registerAction registered Action }); / * slightly * / }
registerAction is used to register action as follows:
function the RegisterAction (Store, type, handler, local) { // Register action function store: Store Example type: name action handler comprise namespace: function local: contextual objects var entry = store._actions [type] || ( store._actions [type] = []); // if _actions store object corresponding to the type is empty, the array is initialized to an empty entry.push ( function wrappedActionHandler (payload, CB) { // to store._actions push into an anonymous function var RES = handler.call (Store, { // this function dispatch: local.dispatch, the commit: local.commit, getters: local.getters, State: local.state, rootGetters: store.getters, rootState: store.state }, payload, CB); // execution handler function context for Store, parameters of the object is 1, 2 is parameter data payload, the return value is stored in res IF ) {(isPromise (res!) / / If not a res Promise res = Promise.resolve (res); // it is converted into an object Promise } IF (store._devtoolHook) { return res. the catch ( function (ERR) { store._devtoolHook.emit ( 'vuex : error ' , ERR); the throw ERR }) } else { return res } }); }
From here we can see that each action corresponding parameter 1 is the handler function is performed here, the incoming object, the return value if not Promise object, call Promise.resolve () to convert it to an object Promise
We like to call this $ store.dispatch ( 'increment', {no: 100}). Action a trigger, the first trigger dispatch function Store redefined, it will function Store the current context object prototype continue Store the dispatch function, as follows:
= Store.prototype.dispatch function dispatch (_type, _payload) { // distribute an action asynchronous operation var the this $. 1 = the this ; // Check-style Object dispatch var REF = unifyObjectStyle (_type, _payload); // specification following parameters, returns an object, and the commit call is the same as here var type = ref.type; var payload = ref.payload; var Action = {type: type, payload: payload}; var entry = the this ._actions [type]; / / try to obtain type type of Action IF (!entry) { //如果不存在则报错并返回 { console.error(("[vuex] unknown action type: " + type)); } return } try { this._actionSubscribers .filter(function (sub) { return sub.before; }) .forEach(function (sub) { return sub.before(action, this$1.state); }); } catch (e) { { console.warn("[vuex] error in before action subscribers: "); console.error(e); } } var result = entry.length > 1 ? Promise.all(entry.map(function (handler) { return handler(payload); })) : entry[0](payload); //执行该action,如果大于1则用Promise.all() return result.then(function (res) { try { this$1._actionSubscribers .filter(function (sub) { return sub.after; }) .forEach(function (sub) { return sub.after(action, this$1.state); }); } catch (e) { { console.warn("[vuex] error in after action subscribers: "); console.error(e); } } return res }) };
The last return was a res, Promise is the object, thus achieving the asynchronous operation.