|
@@ -1,5 +1,5 @@
|
|
|
/*!
|
|
|
- * Vuex v1.0.0-rc
|
|
|
+ * Vuex v2.0.0-rc.1
|
|
|
* (c) 2016 Evan You
|
|
|
* Released under the MIT License.
|
|
|
*/
|
|
@@ -9,121 +9,6 @@
|
|
|
(global.Vuex = factory());
|
|
|
}(this, function () { 'use strict';
|
|
|
|
|
|
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
|
|
|
- return typeof obj;
|
|
|
- } : function (obj) {
|
|
|
- return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
|
- };
|
|
|
-
|
|
|
- var classCallCheck = function (instance, Constructor) {
|
|
|
- if (!(instance instanceof Constructor)) {
|
|
|
- throw new TypeError("Cannot call a class as a function");
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- var createClass = function () {
|
|
|
- function defineProperties(target, props) {
|
|
|
- for (var i = 0; i < props.length; i++) {
|
|
|
- var descriptor = props[i];
|
|
|
- descriptor.enumerable = descriptor.enumerable || false;
|
|
|
- descriptor.configurable = true;
|
|
|
- if ("value" in descriptor) descriptor.writable = true;
|
|
|
- Object.defineProperty(target, descriptor.key, descriptor);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return function (Constructor, protoProps, staticProps) {
|
|
|
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
|
- if (staticProps) defineProperties(Constructor, staticProps);
|
|
|
- return Constructor;
|
|
|
- };
|
|
|
- }();
|
|
|
-
|
|
|
- var toConsumableArray = function (arr) {
|
|
|
- if (Array.isArray(arr)) {
|
|
|
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
|
|
|
-
|
|
|
- return arr2;
|
|
|
- } else {
|
|
|
- return Array.from(arr);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * Merge an array of objects into one.
|
|
|
- *
|
|
|
- * @param {Array<Object>} arr
|
|
|
- * @return {Object}
|
|
|
- */
|
|
|
-
|
|
|
- function mergeObjects(arr) {
|
|
|
- return arr.reduce(function (prev, obj) {
|
|
|
- Object.keys(obj).forEach(function (key) {
|
|
|
- var existing = prev[key];
|
|
|
- if (existing) {
|
|
|
- // allow multiple mutation objects to contain duplicate
|
|
|
- // handlers for the same mutation type
|
|
|
- if (Array.isArray(existing)) {
|
|
|
- prev[key] = existing.concat(obj[key]);
|
|
|
- } else {
|
|
|
- prev[key] = [existing].concat(obj[key]);
|
|
|
- }
|
|
|
- } else {
|
|
|
- prev[key] = obj[key];
|
|
|
- }
|
|
|
- });
|
|
|
- return prev;
|
|
|
- }, {});
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Check whether the given value is Object or not
|
|
|
- *
|
|
|
- * @param {*} obj
|
|
|
- * @return {Boolean}
|
|
|
- */
|
|
|
-
|
|
|
- function isObject(obj) {
|
|
|
- return obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object';
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Get state sub tree by given keys.
|
|
|
- *
|
|
|
- * @param {Object} state
|
|
|
- * @param {Array<String>} nestedKeys
|
|
|
- * @return {Object}
|
|
|
- */
|
|
|
- function getNestedState(state, nestedKeys) {
|
|
|
- return nestedKeys.reduce(function (state, key) {
|
|
|
- return state[key];
|
|
|
- }, state);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Hacks to get access to Vue internals.
|
|
|
- * Maybe we should expose these...
|
|
|
- */
|
|
|
-
|
|
|
- var Watcher = void 0;
|
|
|
- function getWatcher(vm) {
|
|
|
- if (!Watcher) {
|
|
|
- var noop = function noop() {};
|
|
|
- var unwatch = vm.$watch(noop, noop);
|
|
|
- Watcher = vm._watchers[0].constructor;
|
|
|
- unwatch();
|
|
|
- }
|
|
|
- return Watcher;
|
|
|
- }
|
|
|
-
|
|
|
- var Dep = void 0;
|
|
|
- function getDep(vm) {
|
|
|
- if (!Dep) {
|
|
|
- Dep = vm._data.__ob__.dep.constructor;
|
|
|
- }
|
|
|
- return Dep;
|
|
|
- }
|
|
|
-
|
|
|
var hook = typeof window !== 'undefined' && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
|
|
|
|
|
function devtoolPlugin(store) {
|
|
@@ -135,12 +20,12 @@
|
|
|
store.replaceState(targetState);
|
|
|
});
|
|
|
|
|
|
- store.on('mutation', function (mutation, state) {
|
|
|
+ store.subscribe(function (mutation, state) {
|
|
|
hook.emit('vuex:mutation', mutation, state);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function override (Vue) {
|
|
|
+ function applyMixin (Vue) {
|
|
|
var version = Number(Vue.version.split('.')[0]);
|
|
|
|
|
|
if (version >= 2) {
|
|
@@ -166,440 +51,332 @@
|
|
|
|
|
|
function vuexInit() {
|
|
|
var options = this.$options;
|
|
|
- var store = options.store;
|
|
|
- var vuex = options.vuex;
|
|
|
// store injection
|
|
|
-
|
|
|
- if (store) {
|
|
|
- this.$store = store;
|
|
|
+ if (options.store) {
|
|
|
+ this.$store = options.store;
|
|
|
} else if (options.parent && options.parent.$store) {
|
|
|
this.$store = options.parent.$store;
|
|
|
}
|
|
|
- // vuex option handling
|
|
|
- if (vuex) {
|
|
|
- if (!this.$store) {
|
|
|
- console.warn('[vuex] store not injected. make sure to ' + 'provide the store option in your root component.');
|
|
|
- }
|
|
|
- var state = vuex.state;
|
|
|
- var actions = vuex.actions;
|
|
|
- var getters = vuex.getters;
|
|
|
- // handle deprecated state option
|
|
|
-
|
|
|
- if (state && !getters) {
|
|
|
- console.warn('[vuex] vuex.state option will been deprecated in 1.0. ' + 'Use vuex.getters instead.');
|
|
|
- getters = state;
|
|
|
- }
|
|
|
- // getters
|
|
|
- if (getters) {
|
|
|
- options.computed = options.computed || {};
|
|
|
- for (var key in getters) {
|
|
|
- defineVuexGetter(this, key, getters[key]);
|
|
|
- }
|
|
|
- }
|
|
|
- // actions
|
|
|
- if (actions) {
|
|
|
- options.methods = options.methods || {};
|
|
|
- for (var _key in actions) {
|
|
|
- options.methods[_key] = makeBoundAction(this.$store, actions[_key], _key);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Setter for all getter properties.
|
|
|
- */
|
|
|
-
|
|
|
- function setter() {
|
|
|
- throw new Error('vuex getter properties are read-only.');
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * Define a Vuex getter on an instance.
|
|
|
- *
|
|
|
- * @param {Vue} vm
|
|
|
- * @param {String} key
|
|
|
- * @param {Function} getter
|
|
|
- */
|
|
|
+ function mapGetters(getters) {
|
|
|
+ var res = {};
|
|
|
+ normalizeMap(getters).forEach(function (_ref) {
|
|
|
+ var key = _ref.key;
|
|
|
+ var val = _ref.val;
|
|
|
|
|
|
- function defineVuexGetter(vm, key, getter) {
|
|
|
- if (typeof getter !== 'function') {
|
|
|
- console.warn('[vuex] Getter bound to key \'vuex.getters.' + key + '\' is not a function.');
|
|
|
- } else {
|
|
|
- Object.defineProperty(vm, key, {
|
|
|
- enumerable: true,
|
|
|
- configurable: true,
|
|
|
- get: makeComputedGetter(vm.$store, getter),
|
|
|
- set: setter
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
+ res[key] = function mappedGetter() {
|
|
|
+ if (!(val in this.$store.getters)) {
|
|
|
+ console.error("[vuex] unknown getter: " + val);
|
|
|
+ }
|
|
|
+ return this.$store.getters[val];
|
|
|
+ };
|
|
|
+ });
|
|
|
+ return res;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * Make a computed getter, using the same caching mechanism of computed
|
|
|
- * properties. In addition, it is cached on the raw getter function using
|
|
|
- * the store's unique cache id. This makes the same getter shared
|
|
|
- * across all components use the same underlying watcher, and makes
|
|
|
- * the getter evaluated only once during every flush.
|
|
|
- *
|
|
|
- * @param {Store} store
|
|
|
- * @param {Function} getter
|
|
|
- */
|
|
|
+ function mapActions(actions) {
|
|
|
+ var res = {};
|
|
|
+ normalizeMap(actions).forEach(function (_ref2) {
|
|
|
+ var key = _ref2.key;
|
|
|
+ var val = _ref2.val;
|
|
|
|
|
|
- function makeComputedGetter(store, getter) {
|
|
|
- var id = store._getterCacheId;
|
|
|
+ res[key] = function mappedAction() {
|
|
|
+ var _$store;
|
|
|
|
|
|
- // cached
|
|
|
- if (getter[id]) {
|
|
|
- return getter[id];
|
|
|
- }
|
|
|
- var vm = store._vm;
|
|
|
- var Watcher = getWatcher(vm);
|
|
|
- var Dep = getDep(vm);
|
|
|
- var watcher = new Watcher(vm, function (vm) {
|
|
|
- return getter(vm.state);
|
|
|
- }, null, { lazy: true });
|
|
|
- var computedGetter = function computedGetter() {
|
|
|
- if (watcher.dirty) {
|
|
|
- watcher.evaluate();
|
|
|
- }
|
|
|
- if (Dep.target) {
|
|
|
- watcher.depend();
|
|
|
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
|
+ args[_key] = arguments[_key];
|
|
|
}
|
|
|
- return watcher.value;
|
|
|
+
|
|
|
+ return (_$store = this.$store).dispatch.apply(_$store, [val].concat(args));
|
|
|
};
|
|
|
- getter[id] = computedGetter;
|
|
|
- return computedGetter;
|
|
|
- }
|
|
|
+ });
|
|
|
+ return res;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * Make a bound-to-store version of a raw action function.
|
|
|
- *
|
|
|
- * @param {Store} store
|
|
|
- * @param {Function} action
|
|
|
- * @param {String} key
|
|
|
- */
|
|
|
+ function normalizeMap(map) {
|
|
|
+ return Array.isArray(map) ? map.map(function (key) {
|
|
|
+ return { key: key, val: key };
|
|
|
+ }) : Object.keys(map).map(function (key) {
|
|
|
+ return { key: key, val: map[key] };
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- function makeBoundAction(store, action, key) {
|
|
|
- if (typeof action !== 'function') {
|
|
|
- console.warn('[vuex] Action bound to key \'vuex.actions.' + key + '\' is not a function.');
|
|
|
- }
|
|
|
- return function vuexBoundAction() {
|
|
|
- for (var _len = arguments.length, args = Array(_len), _key2 = 0; _key2 < _len; _key2++) {
|
|
|
- args[_key2] = arguments[_key2];
|
|
|
- }
|
|
|
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
|
|
|
+ return typeof obj;
|
|
|
+ } : function (obj) {
|
|
|
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
|
+ };
|
|
|
|
|
|
- return action.call.apply(action, [this, store].concat(args));
|
|
|
- };
|
|
|
+ var classCallCheck = function (instance, Constructor) {
|
|
|
+ if (!(instance instanceof Constructor)) {
|
|
|
+ throw new TypeError("Cannot call a class as a function");
|
|
|
}
|
|
|
+ };
|
|
|
|
|
|
- // option merging
|
|
|
- var merge = Vue.config.optionMergeStrategies.computed;
|
|
|
- Vue.config.optionMergeStrategies.vuex = function (toVal, fromVal) {
|
|
|
- if (!toVal) return fromVal;
|
|
|
- if (!fromVal) return toVal;
|
|
|
- return {
|
|
|
- getters: merge(toVal.getters, fromVal.getters),
|
|
|
- state: merge(toVal.state, fromVal.state),
|
|
|
- actions: merge(toVal.actions, fromVal.actions)
|
|
|
- };
|
|
|
+ var createClass = function () {
|
|
|
+ function defineProperties(target, props) {
|
|
|
+ for (var i = 0; i < props.length; i++) {
|
|
|
+ var descriptor = props[i];
|
|
|
+ descriptor.enumerable = descriptor.enumerable || false;
|
|
|
+ descriptor.configurable = true;
|
|
|
+ if ("value" in descriptor) descriptor.writable = true;
|
|
|
+ Object.defineProperty(target, descriptor.key, descriptor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return function (Constructor, protoProps, staticProps) {
|
|
|
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
|
+ if (staticProps) defineProperties(Constructor, staticProps);
|
|
|
+ return Constructor;
|
|
|
};
|
|
|
- }
|
|
|
+ }();
|
|
|
|
|
|
- var Vue = void 0;
|
|
|
- var uid = 0;
|
|
|
+ var Vue = void 0; // bind on install
|
|
|
|
|
|
var Store = function () {
|
|
|
-
|
|
|
- /**
|
|
|
- * @param {Object} options
|
|
|
- * - {Object} state
|
|
|
- * - {Object} actions
|
|
|
- * - {Object} mutations
|
|
|
- * - {Array} plugins
|
|
|
- * - {Boolean} strict
|
|
|
- */
|
|
|
-
|
|
|
function Store() {
|
|
|
var _this = this;
|
|
|
|
|
|
- var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
|
|
-
|
|
|
- var _ref$state = _ref.state;
|
|
|
- var state = _ref$state === undefined ? {} : _ref$state;
|
|
|
- var _ref$mutations = _ref.mutations;
|
|
|
- var mutations = _ref$mutations === undefined ? {} : _ref$mutations;
|
|
|
- var _ref$modules = _ref.modules;
|
|
|
- var modules = _ref$modules === undefined ? {} : _ref$modules;
|
|
|
- var _ref$plugins = _ref.plugins;
|
|
|
- var plugins = _ref$plugins === undefined ? [] : _ref$plugins;
|
|
|
- var _ref$strict = _ref.strict;
|
|
|
- var strict = _ref$strict === undefined ? false : _ref$strict;
|
|
|
+ var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
|
|
classCallCheck(this, Store);
|
|
|
|
|
|
- this._getterCacheId = 'vuex_store_' + uid++;
|
|
|
- this._dispatching = false;
|
|
|
- this._rootMutations = this._mutations = mutations;
|
|
|
- this._modules = modules;
|
|
|
- this._events = Object.create(null);
|
|
|
- // bind dispatch to self
|
|
|
- var dispatch = this.dispatch;
|
|
|
- this.dispatch = function () {
|
|
|
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
|
- args[_key] = arguments[_key];
|
|
|
- }
|
|
|
-
|
|
|
- dispatch.apply(_this, args);
|
|
|
- };
|
|
|
- // use a Vue instance to store the state tree
|
|
|
- // suppress warnings just in case the user has added
|
|
|
- // some funky global mixins
|
|
|
if (!Vue) {
|
|
|
throw new Error('[vuex] must call Vue.use(Vuex) before creating a store instance.');
|
|
|
}
|
|
|
- var silent = Vue.config.silent;
|
|
|
- Vue.config.silent = true;
|
|
|
- this._vm = new Vue({
|
|
|
- data: {
|
|
|
- state: state
|
|
|
- }
|
|
|
- });
|
|
|
- Vue.config.silent = silent;
|
|
|
- this._setupModuleState(state, modules);
|
|
|
- this._setupModuleMutations(modules);
|
|
|
- // add extra warnings in strict mode
|
|
|
- if (strict) {
|
|
|
- this._setupMutationCheck();
|
|
|
+
|
|
|
+ if (typeof Promise === 'undefined') {
|
|
|
+ throw new Error('[vuex] vuex requires a Promise polyfill in this browser.');
|
|
|
}
|
|
|
+
|
|
|
+ var _options$state = options.state;
|
|
|
+ var state = _options$state === undefined ? {} : _options$state;
|
|
|
+ var _options$modules = options.modules;
|
|
|
+ var modules = _options$modules === undefined ? {} : _options$modules;
|
|
|
+ var _options$plugins = options.plugins;
|
|
|
+ var plugins = _options$plugins === undefined ? [] : _options$plugins;
|
|
|
+ var _options$strict = options.strict;
|
|
|
+ var strict = _options$strict === undefined ? false : _options$strict;
|
|
|
+
|
|
|
+ // store internal state
|
|
|
+
|
|
|
+ this._options = options;
|
|
|
+ this._committing = false;
|
|
|
+ this._actions = Object.create(null);
|
|
|
+ this._mutations = Object.create(null);
|
|
|
+ this._subscribers = [];
|
|
|
+
|
|
|
+ // bind commit and dispatch to self
|
|
|
+ var store = this;
|
|
|
+ var dispatch = this.dispatch;
|
|
|
+ var commit = this.commit;
|
|
|
+
|
|
|
+ this.dispatch = function boundDispatch(type, payload) {
|
|
|
+ return dispatch.call(store, type, payload);
|
|
|
+ };
|
|
|
+ this.commit = function boundCommit(type, payload) {
|
|
|
+ return commit.call(store, type, payload);
|
|
|
+ };
|
|
|
+
|
|
|
+ // init state and getters
|
|
|
+ var getters = extractModuleGetters(options.getters, modules);
|
|
|
+ initStoreState(this, state, getters);
|
|
|
+
|
|
|
+ // apply root module
|
|
|
+ this.module([], options);
|
|
|
+
|
|
|
+ // strict mode
|
|
|
+ if (strict) enableStrictMode(this);
|
|
|
+
|
|
|
// apply plugins
|
|
|
- devtoolPlugin(this);
|
|
|
- plugins.forEach(function (plugin) {
|
|
|
+ plugins.concat(devtoolPlugin).forEach(function (plugin) {
|
|
|
return plugin(_this);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Getter for the entire state tree.
|
|
|
- * Read only.
|
|
|
- *
|
|
|
- * @return {Object}
|
|
|
- */
|
|
|
-
|
|
|
createClass(Store, [{
|
|
|
key: 'replaceState',
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Replace root state.
|
|
|
- *
|
|
|
- * @param {Object} state
|
|
|
- */
|
|
|
-
|
|
|
value: function replaceState(state) {
|
|
|
- this._dispatching = true;
|
|
|
+ this._committing = true;
|
|
|
this._vm.state = state;
|
|
|
- this._dispatching = false;
|
|
|
+ this._committing = false;
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Dispatch an action.
|
|
|
- *
|
|
|
- * @param {String} type
|
|
|
- */
|
|
|
-
|
|
|
}, {
|
|
|
- key: 'dispatch',
|
|
|
- value: function dispatch(type) {
|
|
|
- for (var _len2 = arguments.length, payload = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
|
- payload[_key2 - 1] = arguments[_key2];
|
|
|
- }
|
|
|
+ key: 'module',
|
|
|
+ value: function module(path, _module, hot) {
|
|
|
+ var _this2 = this;
|
|
|
|
|
|
- var silent = false;
|
|
|
- var isObjectStyleDispatch = false;
|
|
|
- // compatibility for object actions, e.g. FSA
|
|
|
- if ((typeof type === 'undefined' ? 'undefined' : _typeof(type)) === 'object' && type.type && arguments.length === 1) {
|
|
|
- isObjectStyleDispatch = true;
|
|
|
- payload = type;
|
|
|
- if (type.silent) silent = true;
|
|
|
- type = type.type;
|
|
|
- }
|
|
|
- var handler = this._mutations[type];
|
|
|
- var state = this.state;
|
|
|
- if (handler) {
|
|
|
- this._dispatching = true;
|
|
|
- // apply the mutation
|
|
|
- if (Array.isArray(handler)) {
|
|
|
- handler.forEach(function (h) {
|
|
|
- isObjectStyleDispatch ? h(state, payload) : h.apply(undefined, [state].concat(toConsumableArray(payload)));
|
|
|
- });
|
|
|
- } else {
|
|
|
- isObjectStyleDispatch ? handler(state, payload) : handler.apply(undefined, [state].concat(toConsumableArray(payload)));
|
|
|
- }
|
|
|
- this._dispatching = false;
|
|
|
- if (!silent) {
|
|
|
- var mutation = isObjectStyleDispatch ? payload : { type: type, payload: payload };
|
|
|
- this.emit('mutation', mutation, state);
|
|
|
- }
|
|
|
- } else {
|
|
|
- console.warn('[vuex] Unknown mutation: ' + type);
|
|
|
+ if (typeof path === 'string') path = [path];
|
|
|
+ if (!Array.isArray(path)) {
|
|
|
+ throw new Error('[vuex] module path must be a string or an Array.');
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
- * Watch state changes on the store.
|
|
|
- * Same API as Vue's $watch, except when watching a function,
|
|
|
- * the function gets the state as the first argument.
|
|
|
- *
|
|
|
- * @param {Function} fn
|
|
|
- * @param {Function} cb
|
|
|
- * @param {Object} [options]
|
|
|
- */
|
|
|
+ var isRoot = !path.length;
|
|
|
+ var state = _module.state;
|
|
|
+ var actions = _module.actions;
|
|
|
+ var mutations = _module.mutations;
|
|
|
+ var modules = _module.modules;
|
|
|
|
|
|
- }, {
|
|
|
- key: 'watch',
|
|
|
- value: function watch(fn, cb, options) {
|
|
|
- var _this2 = this;
|
|
|
+ // set state
|
|
|
|
|
|
- if (typeof fn !== 'function') {
|
|
|
- console.error('Vuex store.watch only accepts function.');
|
|
|
- return;
|
|
|
+ if (!isRoot && !hot) {
|
|
|
+ var parentState = getNestedState(this.state, path.slice(0, -1));
|
|
|
+ if (!parentState) debugger;
|
|
|
+ var moduleName = path[path.length - 1];
|
|
|
+ Vue.set(parentState, moduleName, state || {});
|
|
|
}
|
|
|
- return this._vm.$watch(function () {
|
|
|
- return fn(_this2.state);
|
|
|
- }, cb, options);
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
- * Hot update mutations & modules.
|
|
|
- *
|
|
|
- * @param {Object} options
|
|
|
- * - {Object} [mutations]
|
|
|
- * - {Object} [modules]
|
|
|
- */
|
|
|
-
|
|
|
- }, {
|
|
|
- key: 'hotUpdate',
|
|
|
- value: function hotUpdate() {
|
|
|
- var _ref2 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
|
|
+ if (mutations) {
|
|
|
+ Object.keys(mutations).forEach(function (key) {
|
|
|
+ _this2.mutation(key, mutations[key], path);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- var mutations = _ref2.mutations;
|
|
|
- var modules = _ref2.modules;
|
|
|
+ if (actions) {
|
|
|
+ Object.keys(actions).forEach(function (key) {
|
|
|
+ _this2.action(key, actions[key], path);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- this._rootMutations = this._mutations = mutations || this._rootMutations;
|
|
|
- this._setupModuleMutations(modules || this._modules);
|
|
|
+ if (modules) {
|
|
|
+ Object.keys(modules).forEach(function (key) {
|
|
|
+ _this2.module(path.concat(key), modules[key], hot);
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Attach sub state tree of each module to the root tree.
|
|
|
- *
|
|
|
- * @param {Object} state
|
|
|
- * @param {Object} modules
|
|
|
- */
|
|
|
-
|
|
|
}, {
|
|
|
- key: '_setupModuleState',
|
|
|
- value: function _setupModuleState(state, modules) {
|
|
|
- var _this3 = this;
|
|
|
-
|
|
|
- if (!isObject(modules)) return;
|
|
|
-
|
|
|
- Object.keys(modules).forEach(function (key) {
|
|
|
- var module = modules[key];
|
|
|
-
|
|
|
- // set this module's state
|
|
|
- Vue.set(state, key, module.state || {});
|
|
|
-
|
|
|
- // retrieve nested modules
|
|
|
- _this3._setupModuleState(state[key], module.modules);
|
|
|
+ key: 'mutation',
|
|
|
+ value: function mutation(type, handler) {
|
|
|
+ var path = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
|
|
|
+
|
|
|
+ var entry = this._mutations[type] || (this._mutations[type] = []);
|
|
|
+ var store = this;
|
|
|
+ entry.push(function wrappedMutationHandler(payload) {
|
|
|
+ handler(getNestedState(store.state, path), payload);
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Bind mutations for each module to its sub tree and
|
|
|
- * merge them all into one final mutations map.
|
|
|
- *
|
|
|
- * @param {Object} updatedModules
|
|
|
- */
|
|
|
-
|
|
|
}, {
|
|
|
- key: '_setupModuleMutations',
|
|
|
- value: function _setupModuleMutations(updatedModules) {
|
|
|
- var modules = this._modules;
|
|
|
- Object.keys(updatedModules).forEach(function (key) {
|
|
|
- modules[key] = updatedModules[key];
|
|
|
+ key: 'action',
|
|
|
+ value: function action(type, handler) {
|
|
|
+ var path = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
|
|
|
+
|
|
|
+ var entry = this._actions[type] || (this._actions[type] = []);
|
|
|
+ var store = this;
|
|
|
+ var dispatch = this.dispatch;
|
|
|
+ var commit = this.commit;
|
|
|
+
|
|
|
+ entry.push(function wrappedActionHandler(payload, cb) {
|
|
|
+ var res = handler({
|
|
|
+ dispatch: dispatch,
|
|
|
+ commit: commit,
|
|
|
+ state: getNestedState(store.state, path)
|
|
|
+ }, payload, cb);
|
|
|
+ if (!isPromise(res)) {
|
|
|
+ res = Promise.resolve(res);
|
|
|
+ }
|
|
|
+ return res.catch(function (err) {
|
|
|
+ console.error('[vuex] error in Promise returned from action "' + type + '":');
|
|
|
+ console.error(err);
|
|
|
+ });
|
|
|
});
|
|
|
- var updatedMutations = this._createModuleMutations(modules, []);
|
|
|
- this._mutations = mergeObjects([this._rootMutations].concat(toConsumableArray(updatedMutations)));
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Helper method for _setupModuleMutations.
|
|
|
- * The method retrieve nested sub modules and
|
|
|
- * bind each mutations to its sub tree recursively.
|
|
|
- *
|
|
|
- * @param {Object} modules
|
|
|
- * @param {Array<String>} nestedKeys
|
|
|
- * @return {Array<Object>}
|
|
|
- */
|
|
|
-
|
|
|
}, {
|
|
|
- key: '_createModuleMutations',
|
|
|
- value: function _createModuleMutations(modules, nestedKeys) {
|
|
|
- var _this4 = this;
|
|
|
-
|
|
|
- if (!isObject(modules)) return [];
|
|
|
-
|
|
|
- return Object.keys(modules).map(function (key) {
|
|
|
- var module = modules[key];
|
|
|
- var newNestedKeys = nestedKeys.concat(key);
|
|
|
-
|
|
|
- // retrieve nested modules
|
|
|
- var nestedMutations = _this4._createModuleMutations(module.modules, newNestedKeys);
|
|
|
-
|
|
|
- if (!module || !module.mutations) {
|
|
|
- return mergeObjects(nestedMutations);
|
|
|
- }
|
|
|
-
|
|
|
- // bind mutations to sub state tree
|
|
|
- var mutations = {};
|
|
|
- Object.keys(module.mutations).forEach(function (name) {
|
|
|
- var original = module.mutations[name];
|
|
|
- mutations[name] = function (state) {
|
|
|
- for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
|
- args[_key3 - 1] = arguments[_key3];
|
|
|
- }
|
|
|
-
|
|
|
- original.apply(undefined, [getNestedState(state, newNestedKeys)].concat(args));
|
|
|
- };
|
|
|
- });
|
|
|
+ key: 'commit',
|
|
|
+ value: function commit(type, payload) {
|
|
|
+ var _this3 = this;
|
|
|
|
|
|
- // merge mutations of this module and nested modules
|
|
|
- return mergeObjects([mutations].concat(toConsumableArray(nestedMutations)));
|
|
|
+ // check object-style commit
|
|
|
+ var mutation = void 0;
|
|
|
+ if (isObject(type) && type.type) {
|
|
|
+ payload = mutation = type;
|
|
|
+ type = type.type;
|
|
|
+ } else {
|
|
|
+ mutation = { type: type, payload: payload };
|
|
|
+ }
|
|
|
+ var entry = this._mutations[type];
|
|
|
+ if (!entry) {
|
|
|
+ console.error('[vuex] unknown mutation type: ' + type);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this._committing = true;
|
|
|
+ entry.forEach(function commitIterator(handler) {
|
|
|
+ handler(payload);
|
|
|
});
|
|
|
+ this._committing = false;
|
|
|
+ if (!payload || !payload.silent) {
|
|
|
+ this._subscribers.forEach(function (sub) {
|
|
|
+ return sub(mutation, _this3.state);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ key: 'dispatch',
|
|
|
+ value: function dispatch(type, payload) {
|
|
|
+ var entry = this._actions[type];
|
|
|
+ if (!entry) {
|
|
|
+ debugger;
|
|
|
+ console.error('[vuex] unknown action type: ' + type);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ return entry.length > 1 ? Promise.all(entry.map(function (handler) {
|
|
|
+ return handler(payload);
|
|
|
+ })) : entry[0](payload);
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Setup mutation check: if the vuex instance's state is mutated
|
|
|
- * outside of a mutation handler, we throw en error. This effectively
|
|
|
- * enforces all mutations to the state to be trackable and hot-reloadble.
|
|
|
- * However, this comes at a run time cost since we are doing a deep
|
|
|
- * watch on the entire state tree, so it is only enalbed with the
|
|
|
- * strict option is set to true.
|
|
|
- */
|
|
|
-
|
|
|
}, {
|
|
|
- key: '_setupMutationCheck',
|
|
|
- value: function _setupMutationCheck() {
|
|
|
- var _this5 = this;
|
|
|
-
|
|
|
- var Watcher = getWatcher(this._vm);
|
|
|
- /* eslint-disable no-new */
|
|
|
- new Watcher(this._vm, 'state', function () {
|
|
|
- if (!_this5._dispatching) {
|
|
|
- throw new Error('[vuex] Do not mutate vuex store state outside mutation handlers.');
|
|
|
+ key: 'subscribe',
|
|
|
+ value: function subscribe(fn) {
|
|
|
+ var subs = this._subscribers;
|
|
|
+ if (subs.indexOf(fn) < 0) {
|
|
|
+ subs.push(fn);
|
|
|
+ }
|
|
|
+ return function () {
|
|
|
+ var i = subs.indexOf(fn);
|
|
|
+ if (i > -1) {
|
|
|
+ subs.splice(i, 1);
|
|
|
}
|
|
|
- }, { deep: true, sync: true });
|
|
|
- /* eslint-enable no-new */
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ key: 'hotUpdate',
|
|
|
+ value: function hotUpdate(newOptions) {
|
|
|
+ var _this4 = this;
|
|
|
+
|
|
|
+ this._actions = Object.create(null);
|
|
|
+ this._mutations = Object.create(null);
|
|
|
+ var options = this._options;
|
|
|
+ if (newOptions.actions) {
|
|
|
+ options.actions = newOptions.actions;
|
|
|
+ }
|
|
|
+ if (newOptions.mutations) {
|
|
|
+ options.mutations = newOptions.mutations;
|
|
|
+ }
|
|
|
+ if (newOptions.modules) {
|
|
|
+ for (var key in newOptions.modules) {
|
|
|
+ options.modules[key] = newOptions.modules[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.module([], options, true);
|
|
|
+
|
|
|
+ // update getters
|
|
|
+ var getters = extractModuleGetters(newOptions.getters, newOptions.modules);
|
|
|
+ if (Object.keys(getters).length) {
|
|
|
+ (function () {
|
|
|
+ var oldVm = _this4._vm;
|
|
|
+ initStoreState(_this4, _this4.state, getters);
|
|
|
+ if (_this4.strict) {
|
|
|
+ enableStrictMode(_this4);
|
|
|
+ }
|
|
|
+ // dispatch changes in all subscribed watchers
|
|
|
+ // to force getter re-evaluation.
|
|
|
+ _this4._committing = true;
|
|
|
+ oldVm.state = null;
|
|
|
+ _this4._committing = false;
|
|
|
+ Vue.nextTick(function () {
|
|
|
+ return oldVm.$destroy();
|
|
|
+ });
|
|
|
+ })();
|
|
|
+ }
|
|
|
}
|
|
|
}, {
|
|
|
key: 'state',
|
|
@@ -613,17 +390,90 @@
|
|
|
return Store;
|
|
|
}();
|
|
|
|
|
|
+ function initStoreState(store, state, getters) {
|
|
|
+ // bind getters
|
|
|
+ store.getters = {};
|
|
|
+ var computed = {};
|
|
|
+ Object.keys(getters).forEach(function (key) {
|
|
|
+ var fn = getters[key];
|
|
|
+ // use computed to leverage its lazy-caching mechanism
|
|
|
+ computed[key] = function () {
|
|
|
+ return fn(store._vm.state);
|
|
|
+ };
|
|
|
+ Object.defineProperty(store.getters, key, {
|
|
|
+ get: function get() {
|
|
|
+ return store._vm[key];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // use a Vue instance to store the state tree
|
|
|
+ // suppress warnings just in case the user has added
|
|
|
+ // some funky global mixins
|
|
|
+ var silent = Vue.config.silent;
|
|
|
+ Vue.config.silent = true;
|
|
|
+ store._vm = new Vue({
|
|
|
+ data: { state: state },
|
|
|
+ computed: computed
|
|
|
+ });
|
|
|
+ Vue.config.silent = silent;
|
|
|
+ }
|
|
|
+
|
|
|
+ function extractModuleGetters() {
|
|
|
+ var getters = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
|
|
+ var modules = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
|
|
+ var path = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
|
|
|
+
|
|
|
+ if (!modules) return getters;
|
|
|
+ Object.keys(modules).forEach(function (key) {
|
|
|
+ var module = modules[key];
|
|
|
+ var modulePath = path.concat(key);
|
|
|
+ if (module.getters) {
|
|
|
+ Object.keys(module.getters).forEach(function (getterKey) {
|
|
|
+ var rawGetter = module.getters[getterKey];
|
|
|
+ if (getters[getterKey]) {
|
|
|
+ console.error('[vuex] duplicate getter key: ' + getterKey);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ getters[getterKey] = function wrappedGetter(state) {
|
|
|
+ return rawGetter(getNestedState(state, modulePath));
|
|
|
+ };
|
|
|
+ });
|
|
|
+ }
|
|
|
+ extractModuleGetters(getters, module.modules, modulePath);
|
|
|
+ });
|
|
|
+ return getters;
|
|
|
+ }
|
|
|
+
|
|
|
+ function enableStrictMode(store) {
|
|
|
+ store._vm.$watch('state', function () {
|
|
|
+ if (!store._committing) {
|
|
|
+ throw new Error('[vuex] Do not mutate vuex store state outside mutation handlers.');
|
|
|
+ }
|
|
|
+ }, { deep: true, sync: true });
|
|
|
+ }
|
|
|
+
|
|
|
+ function isObject(obj) {
|
|
|
+ return obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object';
|
|
|
+ }
|
|
|
+
|
|
|
+ function isPromise(val) {
|
|
|
+ return val && typeof val.then === 'function';
|
|
|
+ }
|
|
|
+
|
|
|
+ function getNestedState(state, path) {
|
|
|
+ return path.reduce(function (state, key) {
|
|
|
+ return state[key];
|
|
|
+ }, state);
|
|
|
+ }
|
|
|
+
|
|
|
function install(_Vue) {
|
|
|
if (Vue) {
|
|
|
- console.warn('[vuex] already installed. Vue.use(Vuex) should be called only once.');
|
|
|
+ console.error('[vuex] already installed. Vue.use(Vuex) should be called only once.');
|
|
|
return;
|
|
|
}
|
|
|
- Vue = _Vue
|
|
|
- // reuse Vue's event system
|
|
|
- ;['on', 'off', 'once', 'emit'].forEach(function (e) {
|
|
|
- Store.prototype[e] = Store.prototype['$' + e] = Vue.prototype['$' + e];
|
|
|
- });
|
|
|
- override(Vue);
|
|
|
+ Vue = _Vue;
|
|
|
+ applyMixin(Vue);
|
|
|
}
|
|
|
|
|
|
// auto install in dist mode
|
|
@@ -633,7 +483,9 @@
|
|
|
|
|
|
var index = {
|
|
|
Store: Store,
|
|
|
- install: install
|
|
|
+ install: install,
|
|
|
+ mapGetters: mapGetters,
|
|
|
+ mapActions: mapActions
|
|
|
};
|
|
|
|
|
|
return index;
|