|
1 | 1 | /*!
|
2 |
| - * Vuex v0.8.2 |
| 2 | + * Vuex v1.0.0-rc |
3 | 3 | * (c) 2016 Evan You
|
4 | 4 | * Released under the MIT License.
|
5 | 5 | */
|
|
64 | 64 | // allow multiple mutation objects to contain duplicate
|
65 | 65 | // handlers for the same mutation type
|
66 | 66 | if (Array.isArray(existing)) {
|
67 |
| - existing.push(obj[key]); |
| 67 | + prev[key] = existing.concat(obj[key]); |
68 | 68 | } else {
|
69 |
| - prev[key] = [prev[key], obj[key]]; |
| 69 | + prev[key] = [existing].concat(obj[key]); |
70 | 70 | }
|
71 | 71 | } else {
|
72 | 72 | prev[key] = obj[key];
|
|
77 | 77 | }
|
78 | 78 |
|
79 | 79 | /**
|
80 |
| - * Deep clone an object. Faster than JSON.parse(JSON.stringify()). |
| 80 | + * Check whether the given value is Object or not |
81 | 81 | *
|
82 | 82 | * @param {*} obj
|
83 |
| - * @return {*} |
| 83 | + * @return {Boolean} |
84 | 84 | */
|
85 | 85 |
|
86 |
| - function deepClone(obj) { |
87 |
| - if (Array.isArray(obj)) { |
88 |
| - return obj.map(deepClone); |
89 |
| - } else if (obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') { |
90 |
| - var cloned = {}; |
91 |
| - var keys = Object.keys(obj); |
92 |
| - for (var i = 0, l = keys.length; i < l; i++) { |
93 |
| - var key = keys[i]; |
94 |
| - cloned[key] = deepClone(obj[key]); |
95 |
| - } |
96 |
| - return cloned; |
97 |
| - } else { |
98 |
| - return obj; |
99 |
| - } |
| 86 | + function isObject(obj) { |
| 87 | + return obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; |
| 88 | + } |
| 89 | + |
| 90 | + /** |
| 91 | + * Get state sub tree by given keys. |
| 92 | + * |
| 93 | + * @param {Object} state |
| 94 | + * @param {Array<String>} nestedKeys |
| 95 | + * @return {Object} |
| 96 | + */ |
| 97 | + function getNestedState(state, nestedKeys) { |
| 98 | + return nestedKeys.reduce(function (state, key) { |
| 99 | + return state[key]; |
| 100 | + }, state); |
100 | 101 | }
|
101 | 102 |
|
102 | 103 | /**
|
|
125 | 126 |
|
126 | 127 | var hook = typeof window !== 'undefined' && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
127 | 128 |
|
128 |
| - var devtoolMiddleware = { |
129 |
| - onInit: function onInit(state, store) { |
130 |
| - if (!hook) return; |
131 |
| - hook.emit('vuex:init', store); |
132 |
| - hook.on('vuex:travel-to-state', function (targetState) { |
133 |
| - store._dispatching = true; |
134 |
| - store._vm.state = targetState; |
135 |
| - store._dispatching = false; |
136 |
| - }); |
137 |
| - }, |
138 |
| - onMutation: function onMutation(mutation, state) { |
139 |
| - if (!hook) return; |
| 129 | + function devtoolPlugin(store) { |
| 130 | + if (!hook) return; |
| 131 | + |
| 132 | + hook.emit('vuex:init', store); |
| 133 | + |
| 134 | + hook.on('vuex:travel-to-state', function (targetState) { |
| 135 | + store.replaceState(targetState); |
| 136 | + }); |
| 137 | + |
| 138 | + store.on('mutation', function (mutation, state) { |
140 | 139 | hook.emit('vuex:mutation', mutation, state);
|
141 |
| - } |
142 |
| - }; |
| 140 | + }); |
| 141 | + } |
143 | 142 |
|
144 | 143 | function override (Vue) {
|
145 | 144 | var version = Number(Vue.version.split('.')[0]);
|
|
317 | 316 | * - {Object} state
|
318 | 317 | * - {Object} actions
|
319 | 318 | * - {Object} mutations
|
320 |
| - * - {Array} middlewares |
| 319 | + * - {Array} plugins |
321 | 320 | * - {Boolean} strict
|
322 | 321 | */
|
323 | 322 |
|
|
332 | 331 | var mutations = _ref$mutations === undefined ? {} : _ref$mutations;
|
333 | 332 | var _ref$modules = _ref.modules;
|
334 | 333 | var modules = _ref$modules === undefined ? {} : _ref$modules;
|
335 |
| - var _ref$middlewares = _ref.middlewares; |
336 |
| - var middlewares = _ref$middlewares === undefined ? [] : _ref$middlewares; |
| 334 | + var _ref$plugins = _ref.plugins; |
| 335 | + var plugins = _ref$plugins === undefined ? [] : _ref$plugins; |
337 | 336 | var _ref$strict = _ref.strict;
|
338 | 337 | var strict = _ref$strict === undefined ? false : _ref$strict;
|
339 | 338 | classCallCheck(this, Store);
|
|
342 | 341 | this._dispatching = false;
|
343 | 342 | this._rootMutations = this._mutations = mutations;
|
344 | 343 | this._modules = modules;
|
| 344 | + this._events = Object.create(null); |
345 | 345 | // bind dispatch to self
|
346 | 346 | var dispatch = this.dispatch;
|
347 | 347 | this.dispatch = function () {
|
|
367 | 367 | Vue.config.silent = silent;
|
368 | 368 | this._setupModuleState(state, modules);
|
369 | 369 | this._setupModuleMutations(modules);
|
370 |
| - this._setupMiddlewares(middlewares, state); |
371 | 370 | // add extra warnings in strict mode
|
372 | 371 | if (strict) {
|
373 | 372 | this._setupMutationCheck();
|
374 | 373 | }
|
| 374 | + // apply plugins |
| 375 | + devtoolPlugin(this); |
| 376 | + plugins.forEach(function (plugin) { |
| 377 | + return plugin(_this); |
| 378 | + }); |
375 | 379 | }
|
376 | 380 |
|
377 | 381 | /**
|
|
382 | 386 | */
|
383 | 387 |
|
384 | 388 | createClass(Store, [{
|
385 |
| - key: 'dispatch', |
| 389 | + key: 'replaceState', |
386 | 390 |
|
387 | 391 |
|
| 392 | + /** |
| 393 | + * Replace root state. |
| 394 | + * |
| 395 | + * @param {Object} state |
| 396 | + */ |
| 397 | + |
| 398 | + value: function replaceState(state) { |
| 399 | + this._dispatching = true; |
| 400 | + this._vm.state = state; |
| 401 | + this._dispatching = false; |
| 402 | + } |
| 403 | + |
388 | 404 | /**
|
389 | 405 | * Dispatch an action.
|
390 | 406 | *
|
391 | 407 | * @param {String} type
|
392 | 408 | */
|
393 | 409 |
|
| 410 | + }, { |
| 411 | + key: 'dispatch', |
394 | 412 | value: function dispatch(type) {
|
395 | 413 | for (var _len2 = arguments.length, payload = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
396 | 414 | payload[_key2 - 1] = arguments[_key2];
|
397 | 415 | }
|
398 | 416 |
|
399 | 417 | var silent = false;
|
| 418 | + var isObjectStyleDispatch = false; |
400 | 419 | // compatibility for object actions, e.g. FSA
|
401 | 420 | if ((typeof type === 'undefined' ? 'undefined' : _typeof(type)) === 'object' && type.type && arguments.length === 1) {
|
402 |
| - payload = [type.payload]; |
| 421 | + isObjectStyleDispatch = true; |
| 422 | + payload = type; |
403 | 423 | if (type.silent) silent = true;
|
404 | 424 | type = type.type;
|
405 | 425 | }
|
406 |
| - var mutation = this._mutations[type]; |
| 426 | + var handler = this._mutations[type]; |
407 | 427 | var state = this.state;
|
408 |
| - if (mutation) { |
| 428 | + if (handler) { |
409 | 429 | this._dispatching = true;
|
410 | 430 | // apply the mutation
|
411 |
| - if (Array.isArray(mutation)) { |
412 |
| - mutation.forEach(function (m) { |
413 |
| - return m.apply(undefined, [state].concat(toConsumableArray(payload))); |
| 431 | + if (Array.isArray(handler)) { |
| 432 | + handler.forEach(function (h) { |
| 433 | + isObjectStyleDispatch ? h(state, payload) : h.apply(undefined, [state].concat(toConsumableArray(payload))); |
414 | 434 | });
|
415 | 435 | } else {
|
416 |
| - mutation.apply(undefined, [state].concat(toConsumableArray(payload))); |
| 436 | + isObjectStyleDispatch ? handler(state, payload) : handler.apply(undefined, [state].concat(toConsumableArray(payload))); |
417 | 437 | }
|
418 | 438 | this._dispatching = false;
|
419 |
| - if (!silent) this._applyMiddlewares(type, payload); |
| 439 | + if (!silent) { |
| 440 | + var mutation = isObjectStyleDispatch ? payload : { type: type, payload: payload }; |
| 441 | + this.emit('mutation', mutation, state); |
| 442 | + } |
420 | 443 | } else {
|
421 | 444 | console.warn('[vuex] Unknown mutation: ' + type);
|
422 | 445 | }
|
|
476 | 499 | }, {
|
477 | 500 | key: '_setupModuleState',
|
478 | 501 | value: function _setupModuleState(state, modules) {
|
| 502 | + var _this3 = this; |
| 503 | + |
| 504 | + if (!isObject(modules)) return; |
| 505 | + |
479 | 506 | Object.keys(modules).forEach(function (key) {
|
480 |
| - Vue.set(state, key, modules[key].state || {}); |
| 507 | + var module = modules[key]; |
| 508 | + |
| 509 | + // set this module's state |
| 510 | + Vue.set(state, key, module.state || {}); |
| 511 | + |
| 512 | + // retrieve nested modules |
| 513 | + _this3._setupModuleState(state[key], module.modules); |
481 | 514 | });
|
482 | 515 | }
|
483 | 516 |
|
|
492 | 525 | key: '_setupModuleMutations',
|
493 | 526 | value: function _setupModuleMutations(updatedModules) {
|
494 | 527 | var modules = this._modules;
|
495 |
| - var allMutations = [this._rootMutations]; |
496 | 528 | Object.keys(updatedModules).forEach(function (key) {
|
497 | 529 | modules[key] = updatedModules[key];
|
498 | 530 | });
|
499 |
| - Object.keys(modules).forEach(function (key) { |
| 531 | + var updatedMutations = this._createModuleMutations(modules, []); |
| 532 | + this._mutations = mergeObjects([this._rootMutations].concat(toConsumableArray(updatedMutations))); |
| 533 | + } |
| 534 | + |
| 535 | + /** |
| 536 | + * Helper method for _setupModuleMutations. |
| 537 | + * The method retrieve nested sub modules and |
| 538 | + * bind each mutations to its sub tree recursively. |
| 539 | + * |
| 540 | + * @param {Object} modules |
| 541 | + * @param {Array<String>} nestedKeys |
| 542 | + * @return {Array<Object>} |
| 543 | + */ |
| 544 | + |
| 545 | + }, { |
| 546 | + key: '_createModuleMutations', |
| 547 | + value: function _createModuleMutations(modules, nestedKeys) { |
| 548 | + var _this4 = this; |
| 549 | + |
| 550 | + if (!isObject(modules)) return []; |
| 551 | + |
| 552 | + return Object.keys(modules).map(function (key) { |
500 | 553 | var module = modules[key];
|
501 |
| - if (!module || !module.mutations) return; |
| 554 | + var newNestedKeys = nestedKeys.concat(key); |
| 555 | + |
| 556 | + // retrieve nested modules |
| 557 | + var nestedMutations = _this4._createModuleMutations(module.modules, newNestedKeys); |
| 558 | + |
| 559 | + if (!module || !module.mutations) { |
| 560 | + return mergeObjects(nestedMutations); |
| 561 | + } |
| 562 | + |
502 | 563 | // bind mutations to sub state tree
|
503 | 564 | var mutations = {};
|
504 | 565 | Object.keys(module.mutations).forEach(function (name) {
|
|
508 | 569 | args[_key3 - 1] = arguments[_key3];
|
509 | 570 | }
|
510 | 571 |
|
511 |
| - original.apply(undefined, [state[key]].concat(args)); |
| 572 | + original.apply(undefined, [getNestedState(state, newNestedKeys)].concat(args)); |
512 | 573 | };
|
513 | 574 | });
|
514 |
| - allMutations.push(mutations); |
| 575 | + |
| 576 | + // merge mutations of this module and nested modules |
| 577 | + return mergeObjects([mutations].concat(toConsumableArray(nestedMutations))); |
515 | 578 | });
|
516 |
| - this._mutations = mergeObjects(allMutations); |
517 | 579 | }
|
518 | 580 |
|
519 | 581 | /**
|
|
528 | 590 | }, {
|
529 | 591 | key: '_setupMutationCheck',
|
530 | 592 | value: function _setupMutationCheck() {
|
531 |
| - var _this3 = this; |
| 593 | + var _this5 = this; |
532 | 594 |
|
533 | 595 | var Watcher = getWatcher(this._vm);
|
534 | 596 | /* eslint-disable no-new */
|
535 | 597 | new Watcher(this._vm, 'state', function () {
|
536 |
| - if (!_this3._dispatching) { |
| 598 | + if (!_this5._dispatching) { |
537 | 599 | throw new Error('[vuex] Do not mutate vuex store state outside mutation handlers.');
|
538 | 600 | }
|
539 | 601 | }, { deep: true, sync: true });
|
540 | 602 | /* eslint-enable no-new */
|
541 | 603 | }
|
542 |
| - |
543 |
| - /** |
544 |
| - * Setup the middlewares. The devtools middleware is always |
545 |
| - * included, since it does nothing if no devtool is detected. |
546 |
| - * |
547 |
| - * A middleware can demand the state it receives to be |
548 |
| - * "snapshots", i.e. deep clones of the actual state tree. |
549 |
| - * |
550 |
| - * @param {Array} middlewares |
551 |
| - * @param {Object} state |
552 |
| - */ |
553 |
| - |
554 |
| - }, { |
555 |
| - key: '_setupMiddlewares', |
556 |
| - value: function _setupMiddlewares(middlewares, state) { |
557 |
| - var _this4 = this; |
558 |
| - |
559 |
| - this._middlewares = [devtoolMiddleware].concat(middlewares); |
560 |
| - this._needSnapshots = middlewares.some(function (m) { |
561 |
| - return m.snapshot; |
562 |
| - }); |
563 |
| - if (this._needSnapshots) { |
564 |
| - console.log('[vuex] One or more of your middlewares are taking state snapshots ' + 'for each mutation. Make sure to use them only during development.'); |
565 |
| - } |
566 |
| - var initialSnapshot = this._prevSnapshot = this._needSnapshots ? deepClone(state) : null; |
567 |
| - // call init hooks |
568 |
| - this._middlewares.forEach(function (m) { |
569 |
| - if (m.onInit) { |
570 |
| - m.onInit(m.snapshot ? initialSnapshot : state, _this4); |
571 |
| - } |
572 |
| - }); |
573 |
| - } |
574 |
| - |
575 |
| - /** |
576 |
| - * Apply the middlewares on a given mutation. |
577 |
| - * |
578 |
| - * @param {String} type |
579 |
| - * @param {Array} payload |
580 |
| - */ |
581 |
| - |
582 |
| - }, { |
583 |
| - key: '_applyMiddlewares', |
584 |
| - value: function _applyMiddlewares(type, payload) { |
585 |
| - var _this5 = this; |
586 |
| - |
587 |
| - var state = this.state; |
588 |
| - var prevSnapshot = this._prevSnapshot; |
589 |
| - var snapshot = void 0, |
590 |
| - clonedPayload = void 0; |
591 |
| - if (this._needSnapshots) { |
592 |
| - snapshot = this._prevSnapshot = deepClone(state); |
593 |
| - clonedPayload = deepClone(payload); |
594 |
| - } |
595 |
| - this._middlewares.forEach(function (m) { |
596 |
| - if (m.onMutation) { |
597 |
| - if (m.snapshot) { |
598 |
| - m.onMutation({ type: type, payload: clonedPayload }, snapshot, prevSnapshot, _this5); |
599 |
| - } else { |
600 |
| - m.onMutation({ type: type, payload: payload }, state, _this5); |
601 |
| - } |
602 |
| - } |
603 |
| - }); |
604 |
| - } |
605 | 604 | }, {
|
606 | 605 | key: 'state',
|
607 | 606 | get: function get() {
|
608 | 607 | return this._vm.state;
|
609 | 608 | },
|
610 | 609 | set: function set(v) {
|
611 |
| - throw new Error('[vuex] Vuex root state is read only.'); |
| 610 | + throw new Error('[vuex] Use store.replaceState() to explicit replace store state.'); |
612 | 611 | }
|
613 | 612 | }]);
|
614 | 613 | return Store;
|
|
619 | 618 | console.warn('[vuex] already installed. Vue.use(Vuex) should be called only once.');
|
620 | 619 | return;
|
621 | 620 | }
|
622 |
| - Vue = _Vue; |
| 621 | + Vue = _Vue |
| 622 | + // reuse Vue's event system |
| 623 | + ;['on', 'off', 'once', 'emit'].forEach(function (e) { |
| 624 | + Store.prototype[e] = Store.prototype['$' + e] = Vue.prototype['$' + e]; |
| 625 | + }); |
623 | 626 | override(Vue);
|
624 | 627 | }
|
625 | 628 |
|
|
0 commit comments