/*! * Vuex v1.0.1 * (c) 2017 Evan You * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (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 && obj !== Symbol.prototype ? "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} 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; }, {}); } /** * Deep copy the given object considering circular structure. * This function caches all nested objects and its copies. * If it detects circular structure, use cached copy to avoid infinite loop. * * @param {*} obj * @param {Array} cache * @return {*} */ /** * 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} 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) { if (!hook) return; hook.emit('vuex:init', store); hook.on('vuex:travel-to-state', function (targetState) { store.replaceState(targetState); }); store.subscribe(function (mutation, state) { hook.emit('vuex:mutation', mutation, state); }); } var override = function (Vue) { var version = Number(Vue.version.split('.')[0]); if (version >= 2) { var usesInit = Vue.config._lifecycleHooks.indexOf('init') > -1; Vue.mixin(usesInit ? { init: vuexInit } : { beforeCreate: vuexInit }); } else { (function () { // override init and inject vuex init procedure // for 1.x backwards compatibility. var _init = Vue.prototype._init; Vue.prototype._init = function () { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; options.init = options.init ? [vuexInit].concat(options.init) : vuexInit; _init.call(this, options); }; })(); } /** * Vuex init hook, injected into each instances init hooks list. */ function vuexInit() { var options = this.$options; var store = options.store, vuex = options.vuex; // store injection if (store) { this.$store = 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, 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 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 }); } } /** * 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 makeComputedGetter(store, getter) { var id = store._getterCacheId; // 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(); } return watcher.value; }; getter[id] = computedGetter; return computedGetter; } /** * Make a bound-to-store version of a raw action function. * * @param {Store} store * @param {Function} action * @param {String} 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]; } return action.call.apply(action, [this, store].concat(args)); }; } // 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 Vue = void 0; var uid = 0; 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] : {}, _ref$state = _ref.state, state = _ref$state === undefined ? {} : _ref$state, _ref$mutations = _ref.mutations, mutations = _ref$mutations === undefined ? {} : _ref$mutations, _ref$modules = _ref.modules, modules = _ref$modules === undefined ? {} : _ref$modules, _ref$plugins = _ref.plugins, plugins = _ref$plugins === undefined ? [] : _ref$plugins, _ref$strict = _ref.strict, strict = _ref$strict === undefined ? false : _ref$strict; classCallCheck(this, Store); this._getterCacheId = 'vuex_store_' + uid++; this._dispatching = false; this._rootMutations = this._mutations = mutations; this._modules = modules; this._subscribers = []; // 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(); } // apply plugins devtoolPlugin(this); plugins.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._vm.state = state; this._dispatching = false; } /** * Dispatch an action. * * @param {String} type */ }, { key: 'dispatch', value: function dispatch(type) { var _this2 = this; for (var _len2 = arguments.length, payload = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { payload[_key2 - 1] = arguments[_key2]; } 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) { (function () { var mutation = isObjectStyleDispatch ? payload : { type: type, payload: payload }; _this2._subscribers.forEach(function (sub) { return sub(mutation, state); }); })(); } } else { console.warn('[vuex] Unknown mutation: ' + type); } } /** * 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] */ }, { key: 'watch', value: function watch(fn, cb, options) { var _this3 = this; if (typeof fn !== 'function') { console.error('Vuex store.watch only accepts function.'); return; } return this._vm.$watch(function () { return fn(_this3.state); }, cb, options); } /** * Subscribe to state changes. Fires after every mutation. */ }, { 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); } }; } /** * 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] : {}, mutations = _ref2.mutations, modules = _ref2.modules; this._rootMutations = this._mutations = mutations || this._rootMutations; this._setupModuleMutations(modules || this._modules); } /** * 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 _this4 = 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 _this4._setupModuleState(state[key], module.modules); }); } /** * 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]; }); 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} nestedKeys * @return {Array} */ }, { key: '_createModuleMutations', value: function _createModuleMutations(modules, nestedKeys) { var _this5 = 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 = _this5._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)); }; }); // merge mutations of this module and nested modules return mergeObjects([mutations].concat(toConsumableArray(nestedMutations))); }); } /** * 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-reloadable. * However, this comes at a run time cost since we are doing a deep * watch on the entire state tree, so it is only enabled if the * strict option is set to true. */ }, { key: '_setupMutationCheck', value: function _setupMutationCheck() { var _this6 = this; var Watcher = getWatcher(this._vm); /* eslint-disable no-new */ new Watcher(this._vm, 'state', function () { if (!_this6._dispatching) { throw new Error('[vuex] Do not mutate vuex store state outside mutation handlers.'); } }, { deep: true, sync: true }); /* eslint-enable no-new */ } }, { key: 'state', get: function get$$1() { return this._vm.state; }, set: function set$$1(v) { throw new Error('[vuex] Use store.replaceState() to explicit replace store state.'); } }]); return Store; }(); function install(_Vue) { if (Vue) { console.warn('[vuex] already installed. Vue.use(Vuex) should be called only once.'); return; } Vue = _Vue; override(Vue); } // auto install in dist mode if (typeof window !== 'undefined' && window.Vue) { install(window.Vue); } var index = { Store: Store, install: install }; return index; })));