diff --git a/.npmrc b/.npmrc deleted file mode 100644 index e7afe10..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -registry=https://registry.npm.taobao.org \ No newline at end of file diff --git a/demo/store/mpstore.esm.js b/demo/store/mpstore.esm.js index 998be4c..faae009 100644 --- a/demo/store/mpstore.esm.js +++ b/demo/store/mpstore.esm.js @@ -1,5 +1,5 @@ /*! - * Mpstore.js v0.1.13 + * Mpstore.js v0.1.14 * (c) 2019-2019 Imtaotao * Released under the MIT License. */ @@ -538,8 +538,11 @@ function updateComponents(store, callback) { return; } + var simulateDeps = depComponents.slice(); + var len = simulateDeps.length; + var renderedCallback = function renderedCallback() { - if (++total === depComponents.length) { + if (++total === len) { if (!callback._called) { callback._called = true; callback(); @@ -547,15 +550,15 @@ function updateComponents(store, callback) { } }; - for (var i = 0; i < depComponents.length; i++) { - var _depComponents$i = depComponents[i], - isPage = _depComponents$i.isPage, - component = _depComponents$i.component, - didUpdate = _depComponents$i.didUpdate, - willUpdate = _depComponents$i.willUpdate, - createState = _depComponents$i.createState; + for (var i = 0; i < len; i++) { + var _simulateDeps$i = simulateDeps[i], + isPage = _simulateDeps$i.isPage, + component = _simulateDeps$i.component, + didUpdate = _simulateDeps$i.didUpdate, + willUpdate = _simulateDeps$i.willUpdate, + createState = _simulateDeps$i.createState; - if (component.data[GLOBALWORD]) { + if (component._$loaded && component.data[GLOBALWORD]) { var newPartialState = createState(); if (typeof willUpdate === 'function') { @@ -849,7 +852,7 @@ function () { this.depComponents = []; this.GLOBALWORD = 'global'; this.isDispatching = false; - this.version = '0.1.13'; + this.version = '0.1.14'; this.state = Object.freeze(createModule({})); this.middleware = new Middleware(this); } @@ -1080,14 +1083,20 @@ function () { } }; + function onLoad() { + addDep(this); + this.store = store; + this._$loaded = true; + } + + function onUnload() { + this._$loaded = false; + remove(store.depComponents, this); + } + if (isPage) { - config.onLoad = createWraper(config.onLoad, function () { - addDep(this); - this.store = store; - }); - config.onUnload = createWraper(config.onUnload, null, function () { - remove(store.depComponents, this); - }); + config.onLoad = createWraper(config.onLoad, onLoad, null); + config.onUnload = createWraper(config.onUnload, null, onUnload); } else { config.lifetimes = config.lifetimes || {}; @@ -1099,13 +1108,8 @@ function () { return config[name] = config.lifetimes[name] = fn; }; - set('attached', createWraper(get('attached'), function () { - addDep(this); - this.store = store; - })); - set('detached', createWraper(get('detached'), null, function () { - remove(store.depComponents, this); - })); + set('attached', createWraper(get('attached'), onLoad, null)); + set('detached', createWraper(get('detached'), null, onUnload)); } } }]); @@ -1113,7 +1117,7 @@ function () { return Store; }(); -var version = '0.1.13'; +var version = '0.1.14'; var nativePage = Page; var nativeComponent = Component; diff --git a/dist/mpstore.common.js b/dist/mpstore.common.js index 8984a85..5b8438b 100644 --- a/dist/mpstore.common.js +++ b/dist/mpstore.common.js @@ -1,5 +1,5 @@ /*! - * Mpstore.js v0.1.13 + * Mpstore.js v0.1.14 * (c) 2019-2019 Imtaotao * Released under the MIT License. */ @@ -542,8 +542,11 @@ function updateComponents(store, callback) { return; } + var simulateDeps = depComponents.slice(); + var len = simulateDeps.length; + var renderedCallback = function renderedCallback() { - if (++total === depComponents.length) { + if (++total === len) { if (!callback._called) { callback._called = true; callback(); @@ -551,15 +554,15 @@ function updateComponents(store, callback) { } }; - for (var i = 0; i < depComponents.length; i++) { - var _depComponents$i = depComponents[i], - isPage = _depComponents$i.isPage, - component = _depComponents$i.component, - didUpdate = _depComponents$i.didUpdate, - willUpdate = _depComponents$i.willUpdate, - createState = _depComponents$i.createState; + for (var i = 0; i < len; i++) { + var _simulateDeps$i = simulateDeps[i], + isPage = _simulateDeps$i.isPage, + component = _simulateDeps$i.component, + didUpdate = _simulateDeps$i.didUpdate, + willUpdate = _simulateDeps$i.willUpdate, + createState = _simulateDeps$i.createState; - if (component.data[GLOBALWORD]) { + if (component._$loaded && component.data[GLOBALWORD]) { var newPartialState = createState(); if (typeof willUpdate === 'function') { @@ -853,7 +856,7 @@ function () { this.depComponents = []; this.GLOBALWORD = 'global'; this.isDispatching = false; - this.version = '0.1.13'; + this.version = '0.1.14'; this.state = Object.freeze(createModule({})); this.middleware = new Middleware(this); } @@ -1084,14 +1087,20 @@ function () { } }; + function onLoad() { + addDep(this); + this.store = store; + this._$loaded = true; + } + + function onUnload() { + this._$loaded = false; + remove(store.depComponents, this); + } + if (isPage) { - config.onLoad = createWraper(config.onLoad, function () { - addDep(this); - this.store = store; - }); - config.onUnload = createWraper(config.onUnload, null, function () { - remove(store.depComponents, this); - }); + config.onLoad = createWraper(config.onLoad, onLoad, null); + config.onUnload = createWraper(config.onUnload, null, onUnload); } else { config.lifetimes = config.lifetimes || {}; @@ -1103,13 +1112,8 @@ function () { return config[name] = config.lifetimes[name] = fn; }; - set('attached', createWraper(get('attached'), function () { - addDep(this); - this.store = store; - })); - set('detached', createWraper(get('detached'), null, function () { - remove(store.depComponents, this); - })); + set('attached', createWraper(get('attached'), onLoad, null)); + set('detached', createWraper(get('detached'), null, onUnload)); } } }]); @@ -1117,7 +1121,7 @@ function () { return Store; }(); -var version = '0.1.13'; +var version = '0.1.14'; var nativePage = Page; var nativeComponent = Component; diff --git a/dist/mpstore.es6m.js b/dist/mpstore.es6m.js index b99d1c3..16a67ba 100644 --- a/dist/mpstore.es6m.js +++ b/dist/mpstore.es6m.js @@ -1,5 +1,5 @@ /*! - * Mpstore.js v0.1.13 + * Mpstore.js v0.1.14 * (c) 2019-2019 Imtaotao * Released under the MIT License. */ @@ -399,23 +399,25 @@ function updateComponents (store, callback) { callback(); return } + const simulateDeps = depComponents.slice(); + const len = simulateDeps.length; const renderedCallback = () => { - if (++total === depComponents.length) { + if (++total === len) { if (!callback._called) { callback._called = true; callback(); } } }; - for (let i = 0; i < depComponents.length; i++) { + for (let i = 0; i < len; i++) { const { isPage, component, didUpdate, willUpdate, createState, - } = depComponents[i]; - if (component.data[GLOBALWORD]) { + } = simulateDeps[i]; + if (component._$loaded && component.data[GLOBALWORD]) { const newPartialState = createState(); if (typeof willUpdate === 'function') { if (willUpdate.call(store, component, newPartialState) === false) { @@ -669,7 +671,7 @@ class Store { this.depComponents = []; this.GLOBALWORD = 'global'; this.isDispatching = false; - this.version = '0.1.13'; + this.version = '0.1.14'; this.state = Object.freeze(createModule({})); this.middleware = new Middleware(this); } @@ -873,44 +875,29 @@ class Store { } } }; + function onLoad () { + addDep(this); + this.store = store; + this._$loaded = true; + } + function onUnload () { + this._$loaded = false; + remove(store.depComponents, this); + } if (isPage) { - config.onLoad = createWraper( - config.onLoad, - function () { - addDep(this); - this.store = store; - }, - ); - config.onUnload = createWraper( - config.onUnload, - null, - function () { - remove(store.depComponents, this); - }, - ); + config.onLoad = createWraper(config.onLoad, onLoad, null); + config.onUnload = createWraper(config.onUnload, null, onUnload); } else { config.lifetimes = config.lifetimes || {}; const get = name => config[name] || config.lifetimes[name]; const set = (name, fn) => config[name] = config.lifetimes[name] = fn; - set('attached', createWraper( - get('attached'), - function () { - addDep(this); - this.store = store; - }, - )); - set('detached', createWraper( - get('detached'), - null, - function () { - remove(store.depComponents, this); - }, - )); + set('attached', createWraper(get('attached'), onLoad, null)); + set('detached', createWraper(get('detached'), null, onUnload)); } } } -const version = '0.1.13'; +const version = '0.1.14'; const nativePage = Page; const nativeComponent = Component; function expandConfig (config, expandMethods, isPage) { diff --git a/dist/mpstore.esm.js b/dist/mpstore.esm.js index 998be4c..faae009 100644 --- a/dist/mpstore.esm.js +++ b/dist/mpstore.esm.js @@ -1,5 +1,5 @@ /*! - * Mpstore.js v0.1.13 + * Mpstore.js v0.1.14 * (c) 2019-2019 Imtaotao * Released under the MIT License. */ @@ -538,8 +538,11 @@ function updateComponents(store, callback) { return; } + var simulateDeps = depComponents.slice(); + var len = simulateDeps.length; + var renderedCallback = function renderedCallback() { - if (++total === depComponents.length) { + if (++total === len) { if (!callback._called) { callback._called = true; callback(); @@ -547,15 +550,15 @@ function updateComponents(store, callback) { } }; - for (var i = 0; i < depComponents.length; i++) { - var _depComponents$i = depComponents[i], - isPage = _depComponents$i.isPage, - component = _depComponents$i.component, - didUpdate = _depComponents$i.didUpdate, - willUpdate = _depComponents$i.willUpdate, - createState = _depComponents$i.createState; + for (var i = 0; i < len; i++) { + var _simulateDeps$i = simulateDeps[i], + isPage = _simulateDeps$i.isPage, + component = _simulateDeps$i.component, + didUpdate = _simulateDeps$i.didUpdate, + willUpdate = _simulateDeps$i.willUpdate, + createState = _simulateDeps$i.createState; - if (component.data[GLOBALWORD]) { + if (component._$loaded && component.data[GLOBALWORD]) { var newPartialState = createState(); if (typeof willUpdate === 'function') { @@ -849,7 +852,7 @@ function () { this.depComponents = []; this.GLOBALWORD = 'global'; this.isDispatching = false; - this.version = '0.1.13'; + this.version = '0.1.14'; this.state = Object.freeze(createModule({})); this.middleware = new Middleware(this); } @@ -1080,14 +1083,20 @@ function () { } }; + function onLoad() { + addDep(this); + this.store = store; + this._$loaded = true; + } + + function onUnload() { + this._$loaded = false; + remove(store.depComponents, this); + } + if (isPage) { - config.onLoad = createWraper(config.onLoad, function () { - addDep(this); - this.store = store; - }); - config.onUnload = createWraper(config.onUnload, null, function () { - remove(store.depComponents, this); - }); + config.onLoad = createWraper(config.onLoad, onLoad, null); + config.onUnload = createWraper(config.onUnload, null, onUnload); } else { config.lifetimes = config.lifetimes || {}; @@ -1099,13 +1108,8 @@ function () { return config[name] = config.lifetimes[name] = fn; }; - set('attached', createWraper(get('attached'), function () { - addDep(this); - this.store = store; - })); - set('detached', createWraper(get('detached'), null, function () { - remove(store.depComponents, this); - })); + set('attached', createWraper(get('attached'), onLoad, null)); + set('detached', createWraper(get('detached'), null, onUnload)); } } }]); @@ -1113,7 +1117,7 @@ function () { return Store; }(); -var version = '0.1.13'; +var version = '0.1.14'; var nativePage = Page; var nativeComponent = Component; diff --git a/dist/mpstore.min.js b/dist/mpstore.min.js index e7767d5..9903a25 100644 --- a/dist/mpstore.min.js +++ b/dist/mpstore.min.js @@ -1,6 +1 @@ -/*! - * Mpstore.js v0.1.13 - * (c) 2019-2019 Imtaotao - * Released under the MIT License. - */ -"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n-1&&e.splice(n,1)}function callHook(e,t,n){if(e&&"function"==typeof e[t])return e[t].apply(e,n)}function isEmptyObject(e){for(var t in e)return!1;return!0}function mapObject(e,t){var n={};for(var a in e)e.hasOwnProperty(a)&&(n[a]=t(e[a]));return n}function createWraper(e,t,n){return function(){for(var a,r=arguments.length,o=new Array(r),i=0;i1&&void 0!==arguments[1]?arguments[1]:new WeakMap;if(null==e||isPrimitive(e)||"function"==typeof e||e instanceof Date)return e;if(t.has(e))return t.get(e);var n="function"!=typeof e.constructor?Object.create(null):new e.constructor;for(var a in t.set(e,n),e)n[a]=clone(e[a],t);return n}function mixin(e){var t=Object.create(null);if("function"==typeof e){e((function(e,n){assert("string"==typeof e,"The mixed method name must a string."),assert("function"==typeof n,"The mixed method is not a function."),assert(!(e in t),'The "'.concat(e,'" is exist,')),t[e]=n}))}return t}Object.defineProperty(exports,"__esModule",{value:!0});var MODULE_FLAG=Symbol("module");function isModule(e){return isPlainObject(e)&&!0===e[MODULE_FLAG]}function addModuleFlag(e){return e[MODULE_FLAG]=!0,e}function createModule(e){return assert(isPlainObject(e),"The base module object must be an plain object"),isModule(e)?e:(addModuleFlag(e),e)}function getModule(e,t){if(!t)return e;for(var n=e,a=t.split("."),r=0,o=a.length;re.length)for(r=t.length;--r>=e.length;){var i="".concat(n,"[").concat(r,"]");a.push(new Patch(ADD,i,t[r],e[r]))}}else a.push(new Patch(REPLACE,n,t,e))}function walkObject(e,t,n,a){for(var r in e){var o="".concat(n,".").concat(r);r in t?e[r]!==t[r]&&diffValues(e[r],t[r],o,a):a.push(new Patch(REMOVE,o,null,e[r]))}for(var i in t)if(!(i in e)){var s="".concat(n,".").concat(i);a.push(new Patch(ADD,s,t[i],null))}}function diff(e,t,n){var a=[];return walkObject(e,t,n,a),a}var REG=/[^\[\].]+(?=[\[\].])/g;function separatePath(e,t){var n=t.match(REG);if(n&&n.shift()&&n.length>0){for(var a=-1,r=null,o=e,i=null;a++0){if(!1===callHook(a,"willUpdate",[u,p,y,l])){i();continue}applyPatchs(u,y,i),"function"==typeof f&&f.call(e,u,p,y),callHook(a,"didUpdate",[u,p,l]),u.timeTravel&&u.timeTravel.push(y)}else i()}else i()}else t()}var TimeTravel=function(){function e(t,n,a){_classCallCheck(this,e),this.history=[],this.limit=a,this.component=t,this.GLOBALWORD=n,this.length=this.history.length,this.current=this.history.length,this.finallyState=t.data[n]}return _createClass(e,[{key:"push",value:function(e){var t=this.limit,n=this.history,a=this.GLOBALWORD,r=this.history.length,o=this.component.data;if(t>0){var i=r-t;i>=0&&this.history.splice(0,i+1),this.history.push(e),this.length=n.length,this.current=n.length,this.finallyState=clone(o[a])}}},{key:"go",value:function(e){var t=this.current,n=this.history,a=this.component,r=this.GLOBALWORD,o=this.finallyState;if(assert(r in a.data,"You can't use [timeTravel] because it only works for [global state]"),this.limit>0&&0!==e){var i=e+t,s=Math.abs(e);if(i<0||i>n.length)return void warning("Index [".concat(i,"] is not within the allowed range."),!0);for(var c=0,l=clone(a.data[r]);c++0&&applyPatchs(a,f),this.current+=e}}},{key:"forward",value:function(){this.go(1)}},{key:"back",value:function(){this.go(-1)}},{key:"toStart",value:function(){this.go(-this.current)}},{key:"toEnd",value:function(){this.go(this.history.length-this.current)}}]),e}(),COMMONACTION=function(){};function match(e,t){return e.action===COMMONACTION||(Array.isArray(e.action)?e.action.indexOf(t)>-1:t===e.action)}function handleLayer(e,t,n,a,r,o){try{t.call(n,a,r,e),o()}catch(t){var i=n.hooks;o(),i&&"function"==typeof i.middlewareError?i.middlewareError(e,a,t):warning("".concat(t,"\n\n --- from middleware [").concat(e.toString(),"] action."))}}var Middleware=function(){function e(t){_classCallCheck(this,e),this.stack=[],this.store=t,this.isProcessing=!1}return _createClass(e,[{key:"use",value:function(e,t){assert(!this.isProcessing,"can't allow add new middleware in the middleware processing."),this.stack.push({fn:t,action:e})}},{key:"remove",value:function(e,t){var n=this.stack.findIndex((function(n){return n.fn===t&&n.action===e}));n>-1&&this.stack.splice(n,1)}},{key:"process",value:function(e,t,n){var a=this;this.isProcessing=!0;var r=function(){a.isProcessing=!1};if(this.stack.length>0){var o=0;!function t(i){var s=a.stack[o];for(o++;s&&!match(s,e);)s=a.stack[o++];s?handleLayer(e,s.fn,a.store,i,t,r):n(i,r)}(t)}else n(t,r)}}]),e}(),storeId=0;function assertReducer(e,t){var n=t.setter,a=t.partialState,r=e.toString();return assert(!("partialState"in t&&!isPlainObject(a)),"The [partialState] must be an object."+"\n\n --- from [".concat(r,"] action.")),"function"!=typeof n&&(t.setter=function(){warning("Can't changed [".concat(r,"] action value. Have you defined a setter?")+"\n\n --- from [".concat(r,"] action."))}),t}function filterReducer(e,t,n){var a=t.toString(),r=n.namespace,o=n.partialState;if("namespace"in n)assert("string"==typeof r,"The module namespace must be a string."+"\n\n --- from [".concat(a,"] action.")),n.partialState=createModuleByNamespace(r,o,e,a,(function(e,t){return"The [".concat(e,"] already exists in [").concat(t,"] module, ")+"Please don't repeat defined. \n\n --- from [".concat(a,"] action.")}));else for(var i in o)assert(!e.hasOwnProperty(i),"The [".concat(i,"] already exists in global state, ")+"Please don't repeat defined. \n\n --- from [".concat(a,"] action."));return n}var Store=function(){function e(t){_classCallCheck(this,e),this.hooks=t,this.reducers=[],this.id=++storeId,this.depComponents=[],this.GLOBALWORD="global",this.isDispatching=!1,this.version="0.1.13",this.state=Object.freeze(createModule({})),this.middleware=new Middleware(this)}return _createClass(e,[{key:"add",value:function(e,t){var n=_typeof(e);assert("string"===n||"symbol"===n,"The action must be a Symbol or String, but now is [".concat(n,"].")),assert(!this.reducers.find((function(t){return t.action===e})),"Can't repeat defined [".concat(e.toString(),"] action.")),assertReducer(e,t),filterReducer(this.state,e,t),t.action=e,this.reducers.push(t);var a=t.partialState;a&&!isEmptyObject(a)&&(this.state=mergeState(this.state,a))}},{key:"dispatch",value:function(e,t,n){var a=this,r=this.reducers,o=this.isDispatching,i=e.toString();assert(!o,'It is not allowed to call "dispatch" during dispatch execution.'+"\n\n --- from [".concat(i,"] action.")),this.middleware.process(e,t,(function(t,o){a.isDispatching=!0;try{var s,c=r.find((function(t){return t.action===e}));assert(c,"The [".concat(i,"] action does not exist. ")+"Maybe you have not defined.");var l=c.namespace,u="string"==typeof l;if(u){var f=a.getModule(l,"\n\n --- from [".concat(i,"] action."));s=c.setter(f,t,a.state)}else s=c.setter(a.state,t);assert(isPlainObject(s),"setter function should be return a plain object."),isEmptyObject(s)||(u?(s=createModuleByNamespace(l,s,a.state,i),a.state=mergeState(a.state,s)):a.state=deepFreeze(mergeModule(a.state,s)))}finally{a.isDispatching=!1,o()}updateComponents(a,(function(){"function"==typeof n&&n(t)}))}))}},{key:"use",value:function(e,t){var n=this;return"function"==typeof e&&e!==COMMONACTION&&(t=e,e=COMMONACTION),this.middleware.use(e,t),function(){return n.middleware.remove(e,t)}}},{key:"setNamespace",value:function(e){assert(e&&"string"==typeof e,"The [namespace] must be a string"),this.GLOBALWORD=e}},{key:"getModule",value:function(e,t){if(assert("string"==typeof e,"the namespace mast be a string"),!e)return this.state;var n=getModule(this.state,e);return t&&null===n&&warning("The [".concat(e,"] module is not exist.").concat(t||"")),n}},{key:"addModule",value:function(e,t){var n=this;if(assert("string"==typeof e,"the namespace mast be a string"),isPlainObject(t)){var a=Object.keys(t),r=Object.getOwnPropertySymbols(t);if(a.length+r.length>0){for(var o=0,i=function(a){var r=t[a];r.namespace=e,n.add(a,r)};o0&&applyPatchs(e,r,o)}};if(t)e.onLoad=createWraper(e.onLoad,(function(){b(this),this.store=r})),e.onUnload=createWraper(e.onUnload,null,(function(){remove(r.depComponents,this)}));else{e.lifetimes=e.lifetimes||{};var O=function(t){return e[t]||e.lifetimes[t]},w=function(t,n){return e[t]=e.lifetimes[t]=n};w("attached",createWraper(O("attached"),(function(){b(this),this.store=r}))),w("detached",createWraper(O("detached"),null,(function(){remove(r.depComponents,this)})))}}}]),e}(),version="0.1.13",nativePage=Page,nativeComponent=Component;function expandConfig(e,t,n){isEmptyObject(t)||(n?mixinMethods(e,t):(e.methods=e.methods||{},mixinMethods(e.methods,t)))}function index(e,t){var n=new Store(t),a=mixin(e);return Page=createWraper(nativePage,(function(e){callHook(t,"createBefore",[e,!0]),expandConfig(e,a,!0),n.rewirteConfigAndAddDep(e,!0)})),Component=createWraper(nativeComponent,(function(e){callHook(t,"createBefore",[e,!1]),expandConfig(e,a,!1),n.rewirteConfigAndAddDep(e,!1)})),n}exports.clone=clone,exports.createModule=createModule,exports.default=index,exports.diff=diff,exports.isModule=isModule,exports.restore=restore,exports.version=version; +"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n-1&&e.splice(n,1)}function callHook(e,t,n){if(e&&"function"==typeof e[t])return e[t].apply(e,n)}function isEmptyObject(e){for(var t in e)return!1;return!0}function mapObject(e,t){var n={};for(var a in e)e.hasOwnProperty(a)&&(n[a]=t(e[a]));return n}function createWraper(e,t,n){return function(){for(var a,r=arguments.length,o=new Array(r),i=0;i1&&void 0!==arguments[1]?arguments[1]:new WeakMap;if(null==e||isPrimitive(e)||"function"==typeof e||e instanceof Date)return e;if(t.has(e))return t.get(e);var n="function"!=typeof e.constructor?Object.create(null):new e.constructor;for(var a in t.set(e,n),e)n[a]=clone(e[a],t);return n}function mixin(e){var t=Object.create(null);if("function"==typeof e){e((function(e,n){assert("string"==typeof e,"The mixed method name must a string."),assert("function"==typeof n,"The mixed method is not a function."),assert(!(e in t),'The "'.concat(e,'" is exist,')),t[e]=n}))}return t}Object.defineProperty(exports,"__esModule",{value:!0});var MODULE_FLAG=Symbol("module");function isModule(e){return isPlainObject(e)&&!0===e[MODULE_FLAG]}function addModuleFlag(e){return e[MODULE_FLAG]=!0,e}function createModule(e){return assert(isPlainObject(e),"The base module object must be an plain object"),isModule(e)?e:(addModuleFlag(e),e)}function getModule(e,t){if(!t)return e;for(var n=e,a=t.split("."),r=0,o=a.length;re.length)for(r=t.length;--r>=e.length;){var i="".concat(n,"[").concat(r,"]");a.push(new Patch(ADD,i,t[r],e[r]))}}else a.push(new Patch(REPLACE,n,t,e))}function walkObject(e,t,n,a){for(var r in e){var o="".concat(n,".").concat(r);r in t?e[r]!==t[r]&&diffValues(e[r],t[r],o,a):a.push(new Patch(REMOVE,o,null,e[r]))}for(var i in t)if(!(i in e)){var s="".concat(n,".").concat(i);a.push(new Patch(ADD,s,t[i],null))}}function diff(e,t,n){var a=[];return walkObject(e,t,n,a),a}var REG=/[^\[\].]+(?=[\[\].])/g;function separatePath(e,t){var n=t.match(REG);if(n&&n.shift()&&n.length>0){for(var a=-1,r=null,o=e,i=null;a++0){if(!1===callHook(a,"willUpdate",[d,m,v,f])){c();continue}applyPatchs(d,v,c),"function"==typeof h&&h.call(e,d,m,v),callHook(a,"didUpdate",[d,m,f]),d.timeTravel&&d.timeTravel.push(v)}else c()}else c()}else t()}var TimeTravel=function(){function e(t,n,a){_classCallCheck(this,e),this.history=[],this.limit=a,this.component=t,this.GLOBALWORD=n,this.length=this.history.length,this.current=this.history.length,this.finallyState=t.data[n]}return _createClass(e,[{key:"push",value:function(e){var t=this.limit,n=this.history,a=this.GLOBALWORD,r=this.history.length,o=this.component.data;if(t>0){var i=r-t;i>=0&&this.history.splice(0,i+1),this.history.push(e),this.length=n.length,this.current=n.length,this.finallyState=clone(o[a])}}},{key:"go",value:function(e){var t=this.current,n=this.history,a=this.component,r=this.GLOBALWORD,o=this.finallyState;if(assert(r in a.data,"You can't use [timeTravel] because it only works for [global state]"),this.limit>0&&0!==e){var i=e+t,s=Math.abs(e);if(i<0||i>n.length)return void warning("Index [".concat(i,"] is not within the allowed range."),!0);for(var c=0,l=clone(a.data[r]);c++0&&applyPatchs(a,f),this.current+=e}}},{key:"forward",value:function(){this.go(1)}},{key:"back",value:function(){this.go(-1)}},{key:"toStart",value:function(){this.go(-this.current)}},{key:"toEnd",value:function(){this.go(this.history.length-this.current)}}]),e}(),COMMONACTION=function(){};function match(e,t){return e.action===COMMONACTION||(Array.isArray(e.action)?e.action.indexOf(t)>-1:t===e.action)}function handleLayer(e,t,n,a,r,o){try{t.call(n,a,r,e),o()}catch(t){var i=n.hooks;o(),i&&"function"==typeof i.middlewareError?i.middlewareError(e,a,t):warning("".concat(t,"\n\n --- from middleware [").concat(e.toString(),"] action."))}}var Middleware=function(){function e(t){_classCallCheck(this,e),this.stack=[],this.store=t,this.isProcessing=!1}return _createClass(e,[{key:"use",value:function(e,t){assert(!this.isProcessing,"can't allow add new middleware in the middleware processing."),this.stack.push({fn:t,action:e})}},{key:"remove",value:function(e,t){var n=this.stack.findIndex((function(n){return n.fn===t&&n.action===e}));n>-1&&this.stack.splice(n,1)}},{key:"process",value:function(e,t,n){var a=this;this.isProcessing=!0;var r=function(){a.isProcessing=!1};if(this.stack.length>0){var o=0;!function t(i){var s=a.stack[o];for(o++;s&&!match(s,e);)s=a.stack[o++];s?handleLayer(e,s.fn,a.store,i,t,r):n(i,r)}(t)}else n(t,r)}}]),e}(),storeId=0;function assertReducer(e,t){var n=t.setter,a=t.partialState,r=e.toString();return assert(!("partialState"in t&&!isPlainObject(a)),"The [partialState] must be an object."+"\n\n --- from [".concat(r,"] action.")),"function"!=typeof n&&(t.setter=function(){warning("Can't changed [".concat(r,"] action value. Have you defined a setter?")+"\n\n --- from [".concat(r,"] action."))}),t}function filterReducer(e,t,n){var a=t.toString(),r=n.namespace,o=n.partialState;if("namespace"in n)assert("string"==typeof r,"The module namespace must be a string."+"\n\n --- from [".concat(a,"] action.")),n.partialState=createModuleByNamespace(r,o,e,a,(function(e,t){return"The [".concat(e,"] already exists in [").concat(t,"] module, ")+"Please don't repeat defined. \n\n --- from [".concat(a,"] action.")}));else for(var i in o)assert(!e.hasOwnProperty(i),"The [".concat(i,"] already exists in global state, ")+"Please don't repeat defined. \n\n --- from [".concat(a,"] action."));return n}var Store=function(){function e(t){_classCallCheck(this,e),this.hooks=t,this.reducers=[],this.id=++storeId,this.depComponents=[],this.GLOBALWORD="global",this.isDispatching=!1,this.version="0.1.14",this.state=Object.freeze(createModule({})),this.middleware=new Middleware(this)}return _createClass(e,[{key:"add",value:function(e,t){var n=_typeof(e);assert("string"===n||"symbol"===n,"The action must be a Symbol or String, but now is [".concat(n,"].")),assert(!this.reducers.find((function(t){return t.action===e})),"Can't repeat defined [".concat(e.toString(),"] action.")),assertReducer(e,t),filterReducer(this.state,e,t),t.action=e,this.reducers.push(t);var a=t.partialState;a&&!isEmptyObject(a)&&(this.state=mergeState(this.state,a))}},{key:"dispatch",value:function(e,t,n){var a=this,r=this.reducers,o=this.isDispatching,i=e.toString();assert(!o,'It is not allowed to call "dispatch" during dispatch execution.'+"\n\n --- from [".concat(i,"] action.")),this.middleware.process(e,t,(function(t,o){a.isDispatching=!0;try{var s,c=r.find((function(t){return t.action===e}));assert(c,"The [".concat(i,"] action does not exist. ")+"Maybe you have not defined.");var l=c.namespace,u="string"==typeof l;if(u){var f=a.getModule(l,"\n\n --- from [".concat(i,"] action."));s=c.setter(f,t,a.state)}else s=c.setter(a.state,t);assert(isPlainObject(s),"setter function should be return a plain object."),isEmptyObject(s)||(u?(s=createModuleByNamespace(l,s,a.state,i),a.state=mergeState(a.state,s)):a.state=deepFreeze(mergeModule(a.state,s)))}finally{a.isDispatching=!1,o()}updateComponents(a,(function(){"function"==typeof n&&n(t)}))}))}},{key:"use",value:function(e,t){var n=this;return"function"==typeof e&&e!==COMMONACTION&&(t=e,e=COMMONACTION),this.middleware.use(e,t),function(){return n.middleware.remove(e,t)}}},{key:"setNamespace",value:function(e){assert(e&&"string"==typeof e,"The [namespace] must be a string"),this.GLOBALWORD=e}},{key:"getModule",value:function(e,t){if(assert("string"==typeof e,"the namespace mast be a string"),!e)return this.state;var n=getModule(this.state,e);return t&&null===n&&warning("The [".concat(e,"] module is not exist.").concat(t||"")),n}},{key:"addModule",value:function(e,t){var n=this;if(assert("string"==typeof e,"the namespace mast be a string"),isPlainObject(t)){var a=Object.keys(t),r=Object.getOwnPropertySymbols(t);if(a.length+r.length>0){for(var o=0,i=function(a){var r=t[a];r.namespace=e,n.add(a,r)};o0&&applyPatchs(e,r,o)}};function O(){b(this),this.store=r,this._$loaded=!0}function w(){this._$loaded=!1,remove(r.depComponents,this)}if(t)e.onLoad=createWraper(e.onLoad,O,null),e.onUnload=createWraper(e.onUnload,null,w);else{e.lifetimes=e.lifetimes||{};var M=function(t){return e[t]||e.lifetimes[t]},P=function(t,n){return e[t]=e.lifetimes[t]=n};P("attached",createWraper(M("attached"),O,null)),P("detached",createWraper(M("detached"),null,w))}}}]),e}(),version="0.1.14",nativePage=Page,nativeComponent=Component;function expandConfig(e,t,n){isEmptyObject(t)||(n?mixinMethods(e,t):(e.methods=e.methods||{},mixinMethods(e.methods,t)))}function index(e,t){var n=new Store(t),a=mixin(e);return Page=createWraper(nativePage,(function(e){callHook(t,"createBefore",[e,!0]),expandConfig(e,a,!0),n.rewirteConfigAndAddDep(e,!0)})),Component=createWraper(nativeComponent,(function(e){callHook(t,"createBefore",[e,!1]),expandConfig(e,a,!1),n.rewirteConfigAndAddDep(e,!1)})),n}exports.clone=clone,exports.createModule=createModule,exports.default=index,exports.diff=diff,exports.isModule=isModule,exports.restore=restore,exports.version=version; diff --git a/package.json b/package.json index d141694..807ced9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rustle/mp-store", - "version": "0.1.13", + "version": "0.1.14", "description": "A lightweight wechat miniprogram state management library", "main": "dist/mpstore.common.js", "module": "dist/mpstore.esm.js", diff --git a/src/store.js b/src/store.js index bfdaf7c..c4594ca 100644 --- a/src/store.js +++ b/src/store.js @@ -363,45 +363,29 @@ export class Store { } } + function onLoad () { + addDep(this) + // rigister store to component within + this.store = store + this._$loaded = true + } + + function onUnload () { + this._$loaded = false + // clear cache + remove(store.depComponents, this) + } + if (isPage) { - config.onLoad = createWraper( - config.onLoad, - function () { - addDep(this) - // rigister store to component within - this.store = store - }, - ) - - config.onUnload = createWraper( - config.onUnload, - null, - function () { - // clear cache - remove(store.depComponents, this) - }, - ) + config.onLoad = createWraper(config.onLoad, onLoad, null) + config.onUnload = createWraper(config.onUnload, null, onUnload) } else { // Component config.lifetimes = config.lifetimes || {} const get = name => config[name] || config.lifetimes[name] const set = (name, fn) => config[name] = config.lifetimes[name] = fn - - set('attached', createWraper( - get('attached'), - function () { - addDep(this) - this.store = store - }, - )) - - set('detached', createWraper( - get('detached'), - null, - function () { - remove(store.depComponents, this) - }, - )) + set('attached', createWraper(get('attached'), onLoad, null)) + set('detached', createWraper(get('detached'), null, onUnload)) } } } \ No newline at end of file diff --git a/src/update.js b/src/update.js index eac262e..90e6975 100644 --- a/src/update.js +++ b/src/update.js @@ -24,28 +24,32 @@ export function updateComponents (store, callback) { callback() return } + + // the component maybe aleard unload, so, need copy + const simulateDeps = depComponents.slice() + const len = simulateDeps.length // call `callback`, when all component views are rendered const renderedCallback = () => { - if (++total === depComponents.length) { + if (++total === len) { if (!callback._called) { callback._called = true callback() } } } - - // the component maybe aleard unload, so, can't use `len` - for (let i = 0; i < depComponents.length; i++) { + + for (let i = 0; i < len; i++) { const { isPage, component, didUpdate, willUpdate, createState, - } = depComponents[i] + } = simulateDeps[i] - if (component.data[GLOBALWORD]) { + // no update required if uninstalled + if (component._$loaded && component.data[GLOBALWORD]) { const newPartialState = createState() // the `willUpdate` function will optimize component diff --git a/test/README.md b/test/README.md index 2dcffbf..51cb240 100644 --- a/test/README.md +++ b/test/README.md @@ -147,4 +147,7 @@ + [x] createModule 将会添加一个 symbol 值作为标识符 + [x] createModule 必须传入一个 plainObject + [x] isModule 检查时,必须是一个 plainObject -+ [x] isModule 将检查 symbol 标识符 \ No newline at end of file ++ [x] isModule 将检查 symbol 标识符 + +### update ++ [x] 更新的时候如果有组件卸载的话,是否所有的依赖的组件都能正常更新 \ No newline at end of file diff --git a/test/script/update.spec.js b/test/script/update.spec.js new file mode 100644 index 0000000..1aedbb5 --- /dev/null +++ b/test/script/update.spec.js @@ -0,0 +1,73 @@ +import { isError } from '../utils' +import createStore from '../../src/index' + +describe('Update', () => { + it('uninstalling components during update', done => { + let i = 0 + const store = createStore() + const ccm = cfg => { + cfg.template = '
{{ global.name }}
' + const id = simulate.load(Component(cfg)) + const cm = simulate.render(id) + cm.instance._cfg = cfg + cm.attach(document.createElement('parent-wrapper')) + return cm + } + store.add('action', { + partialState: { + name: 'chen', + }, + setter: (state, payload) => ({name: payload}), + }) + const cmOne = ccm({ + storeConfig: { + useState: () => ({ + name: state => state.name, + }), + }, + }) + const cmTwo = ccm({ + storeConfig: { + useState: () => ({ + name: state => state.name, + }), + }, + attached() { + i++ + expect(this._$loaded).toBeTrue() + // unload component + const setData = this.setData + this.setData = (data, callback) => { + i++ + setData.call(this, data, callback) + this._cfg.detached.call(this) + expect(this._$loaded).toBeFalse() + } + }, + }) + const cmThree = ccm({ + storeConfig: { + useState: () => ({ + name: state => state.name, + }), + }, + }) + expect(store.depComponents.length).toBe(3) + expect(cmOne.dom.textContent).toBe('chen') + expect(cmTwo.dom.textContent).toBe('chen') + expect(cmThree.dom.textContent).toBe('chen') + store.dispatch('action', 'tao', payload => { + expect(i).toBe(2) + expect(payload).toBe('tao') + expect(store.depComponents.length).toBe(2) + expect(cmOne.dom.textContent).toBe('tao') + expect(cmTwo.dom.textContent).toBe('tao') + expect(cmThree.dom.textContent).toBe('tao') + done() + }) + expect(store.depComponents.length).toBe(2) + expect(cmOne.dom.textContent).toBe('tao') + expect(cmTwo.dom.textContent).toBe('tao') + expect(cmThree.dom.textContent).toBe('tao') + }) +}) \ No newline at end of file