mini-stores
Version:
小程序多状态管理 - 解决跨页面跨组件间通信,简洁小巧高性能,支持微信、支付宝、钉钉、百度、字节、QQ等小程序
269 lines (268 loc) • 9.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Store = void 0;
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var TYPE_ARRAY = '[object Array]';
var TYPE_OBJECT = '[object Object]';
var TYPE_FUNCTION = '[object Function]';
function getType(obj) {
return Object.prototype.toString.call(obj);
}
function deepCopy(data) {
var type = getType(data);
if (type === TYPE_OBJECT) {
var obj = {};
Object.keys(data).forEach(function (key) {
return obj[key] = deepCopy(data[key]);
});
return obj;
}
if (type === TYPE_ARRAY) {
return data.map(deepCopy);
}
return data;
}
function getNowPage() {
var pages = getCurrentPages();
return pages[pages.length - 1];
}
function setState(vm, data) {
vm._new_data = vm._new_data || {};
Object.assign(vm._new_data, data);
return new Promise(function (resolve) {
Promise.resolve().then(function () {
if (vm._new_data) {
var diffState = getDiffState(vm._new_data, vm.data);
vm._new_data = null;
vm.setData(diffState, resolve);
} else {
resolve();
}
});
});
}
function getDiffState(state, preState) {
var newState = {};
stateDiff(deepCopy(state), preState, '', newState);
return newState;
}
function addDiffState(newState, key, val) {
if (key !== '') newState[key] = val;
}
function stateDiff(state, preState, path, newState) {
if (state === preState) return;
var stateType = getType(state);
var preStateType = getType(preState);
if (stateType === TYPE_OBJECT) {
var stateKeys = Object.keys(state);
var preStateKeys = Object.keys(preState || {});
var stateLen = stateKeys.length;
var preStateLen = preStateKeys.length;
if (path !== '') {
if (preStateType !== TYPE_OBJECT || stateLen < preStateLen || stateLen === 0 || preStateLen === 0) {
addDiffState(newState, path, state);
return;
}
preStateKeys.forEach(function (key) {
if (state[key] === undefined) {
state[key] = null;
if (!stateKeys.includes(key)) {
stateKeys.push(key);
}
}
});
}
stateKeys.forEach(function (key) {
var subPath = path === '' ? key : "".concat(path, ".").concat(key);
stateDiff(state[key], preState[key], subPath, newState);
});
return;
}
if (stateType === TYPE_ARRAY) {
if (preStateType !== TYPE_ARRAY || state.length < preState.length || state.length === 0 || preState.length === 0) {
addDiffState(newState, path, state);
return;
}
preState.forEach(function (_, index) {
if (state[index] === undefined) state[index] = null;
});
state.forEach(function (item, index) {
stateDiff(item, preState[index], "".concat(path, "[").concat(index, "]"), newState);
});
return;
}
addDiffState(newState, path, state);
}
function getVmRoute(vm) {
return vm.route;
}
function initRoute(vm) {
return vm.route || vm.__route__;
}
function getValueByPaths(data, paths) {
var value = data;
paths.forEach(function (key) {
var _value;
value = (_value = value) === null || _value === void 0 ? void 0 : _value[key];
});
return value;
}
var Store = exports.Store = /*#__PURE__*/function () {
function Store() {
var _this = this;
_classCallCheck(this, Store);
_defineProperty(this, "__vms", []);
_defineProperty(this, "__delayTimer", null);
_defineProperty(this, "__updateTimer", null);
_defineProperty(this, "__watchTimer", null);
_defineProperty(this, "__watchMap", {});
_defineProperty(this, "data", {});
_defineProperty(this, "watch", {
on: function on(key, callback, vm) {
if (!key || typeof callback !== 'function') {
console.warn("\u8BF7\u4F20\u5165\u6B63\u786E\u53C2\u6570\uFF0C\u5982store.watch.on('key', () => {})");
return;
}
key = String(key);
if (!_this.__watchMap[key]) {
var paths = String(key).split('.').filter(function (f) {
return !!f;
});
if (!paths.length) return;
_this.__watchMap[key] = {
paths: paths,
value: getValueByPaths(_this.data, paths),
callbacks: []
};
}
_this.__watchMap[key].callbacks.push({
vm: vm,
callback: callback
});
},
off: function off(key, callback) {
key = String(key);
if (!_this.__watchMap[key]) return;
_this.__watchMap[key].callbacks = _this.__watchMap[key].callbacks.filter(function (f) {
return f.callback !== callback;
});
}
});
_defineProperty(this, "__proxyCache", new WeakMap());
_defineProperty(this, "__createProxy", function (obj) {
if (_this.__proxyCache.has(obj)) {
return _this.__proxyCache.get(obj);
}
var proxy = new Proxy(obj, {
get: function get(target, propKey, receiver) {
var value = Reflect.get(target, propKey, receiver);
var type = getType(value);
if (type === TYPE_FUNCTION) {
return value.call(_this.data);
}
if (type === TYPE_OBJECT) {
return _this.__createProxy(value);
}
return value;
},
set: function set(target, propKey, value, receiver) {
clearTimeout(_this.__updateTimer);
_this.__updateTimer = setTimeout(function () {
return _this.__update();
});
return Reflect.set(target, propKey, value, receiver);
}
});
_this.__proxyCache.set(obj, proxy);
return proxy;
});
setTimeout(function () {
_this.data = _this.__createProxy(_this.data);
}, 0);
}
return _createClass(Store, [{
key: "bind",
value: function bind(vm, key) {
if (!key) {
console.error("\u8BF7\u8BBE\u7F6Estore\u5728\u5F53\u524D\u7EC4\u4EF6\u5B9E\u4F8Bdata\u4E2D\u7684key\uFF0C\u5982store.bind(this, '$store')");
return;
}
vm.data = vm.data || {};
vm.data[key] = null;
setState(vm, _defineProperty({}, key, this.data));
if (!this.__vms.some(function (f) {
return f.vm === vm && f.key === key;
})) {
this.__vms.push({
vm: vm,
key: key
});
var rootVm = vm.$page || vm.pageinstance || getNowPage() || {};
vm.route = initRoute(vm) || initRoute(rootVm);
}
}
}, {
key: "unbind",
value: function unbind(vm) {
var _this2 = this;
this.__vms = this.__vms.filter(function (f) {
return f.vm !== vm;
});
Object.keys(this.__watchMap).forEach(function (key) {
_this2.__watchMap[key].callbacks = _this2.__watchMap[key].callbacks.filter(function (f) {
return f.vm !== vm;
});
});
}
}, {
key: "__update",
value: function __update() {
var _this3 = this;
var nowVm = getNowPage();
var nowVmRoute = getVmRoute(nowVm);
var delayVms = [];
this.__vms.forEach(function (f) {
var vmRoute = getVmRoute(f.vm);
if (nowVmRoute === vmRoute) {
setState(f.vm, _defineProperty({}, f.key, _this3.data));
} else {
delayVms.push(f);
}
});
clearTimeout(this.__watchTimer);
this.__watchTimer = setTimeout(function () {
Object.keys(_this3.__watchMap).forEach(function (key) {
var item = _this3.__watchMap[key];
var value = getValueByPaths(_this3.data, item.paths);
var oldValue = item.value;
if (oldValue !== value) {
item.value = value;
item.callbacks.forEach(function (f) {
return f.callback(value, oldValue);
});
}
});
}, 0);
if (!delayVms.length) return;
clearTimeout(this.__delayTimer);
this.__delayTimer = setTimeout(function () {
delayVms.forEach(function (f) {
return setState(f.vm, _defineProperty({}, f.key, _this3.data));
});
}, 360);
}
}, {
key: "update",
value: function update() {
this.__update();
}
}]);
}();