import { _, isArray, each, isKey, isPlainObject, extend, isFunction, Widget, Providers } from "@/core"; import { Fix } from "./fix"; function initWatch(vm, watch) { vm._watchers || (vm._watchers = []); for (const key in watch) { const handler = watch[key]; if (isArray(handler)) { for (let i = 0; i < handler.length; i++) { vm._watchers.push(createWatcher(vm, key, handler[i])); } } else { vm._watchers.push(createWatcher(vm, key, handler)); } } each(vm.$watchDelayCallbacks, (i, watchDelayCallback) => { let innerWatch = watchDelayCallback[0]; const innerHandler = watchDelayCallback[1]; if (isKey(innerWatch)) { const key = innerWatch; innerWatch = {}; innerWatch[key] = innerHandler; } for (const key in innerWatch) { const handler = innerWatch[key]; if (isArray(handler)) { for (let i = 0; i < handler.length; i++) { vm._watchers.push(createWatcher(vm, key, handler[i])); } } else { vm._watchers.push(createWatcher(vm, key, handler)); } } }); } function createWatcher(vm, keyOrFn, cb, options) { if (isPlainObject(cb)) { options = cb; cb = cb.handler; } options = options || {}; return Fix.watch( vm.model, keyOrFn, _.bind(cb, vm), extend(options, { store: vm.store }) ); } let target = null; const targetStack = []; function pushTarget(_target) { if (target) targetStack.push(target); Fix.Model.target = target = _target; } function popTarget() { Fix.Model.target = target = targetStack.pop(); } export const Model = Fix.Model; const oldWatch = Fix.watch; Fix.watch = function (model, expOrFn, cb, options) { if (isPlainObject(cb)) { options = cb; cb = cb.handler; } if (typeof cb === "string") { cb = model[cb]; } return oldWatch.call( this, model, expOrFn, function () { options && options.store && pushTarget(options.store); let res; try { res = cb.apply(this, arguments); } catch (e) { console.error(e); } options && options.store && popTarget(); return res; }, options ); }; Widget.findStore = function findStore(widget) { if (target != null) { return target; } widget = widget || Widget.context; let p = widget; while (p) { if (p instanceof Fix.Model || p.store || p.__cacheStore) { break; } p = p._parent || (p.options && p.options.element) || p._context; } if (p) { if (p instanceof Fix.Model) { return (widget.__cacheStore = p); } widget.__cacheStore = p.store || p.__cacheStore; return p.__cacheStore || p.store; } }; function createStore() { let needPop = false; const workerMode = Providers.getProvider("bi.provider.system").getWorkerMode(); if (workerMode && this._worker) { return; } if (this.store) { pushTarget(this.store); return true; } if (this._store || this.options._store) { const store = Widget.findStore( this.options.context || this._parent || this.options.element || this._context ); if (store) { pushTarget(store); needPop = true; } this.store = (this._store || this.options._store).call(this); this.store && (this.store._widget = this); needPop && popTarget(); needPop = false; pushTarget(this.store); if (this.store instanceof Fix.Model) { this.model = this.store.model; } else { this.model = this.store; } needPop = true; } return needPop; } const _init = Widget.prototype._init; Widget.prototype._init = function () { const needPop = createStore.call(this); try { _init.apply(this, arguments); } catch (e) { console.error(e); } needPop && popTarget(); }; const __initWatch = Widget.prototype.__initWatch; Widget.prototype.__initWatch = function () { __initWatch.apply(this, arguments); const workerMode = Providers.getProvider("bi.provider.system").getWorkerMode(); if (workerMode && this._worker) { return; } if (this._store) { initWatch(this, this.watch); } }; const unMount = Widget.prototype.__destroy; Widget.prototype.__destroy = function () { try { unMount.apply(this, arguments); } catch (e) { console.error(e); } this.store && isFunction(this.store.destroy) && this.store.destroy(); each(this._watchers, (i, unwatches) => { unwatches = isArray(unwatches) ? unwatches : [unwatches]; each(unwatches, (j, unwatch) => { unwatch(); }); }); this._watchers && (this._watchers = []); if (this.store) { this.store._parent && (this.store._parent = null); this.store._widget && (this.store._widget = null); this.store = null; } delete this.__cacheStore; }; _.each(["_render", "__afterRender", "_mount", "__afterMount"], (name) => { const old = Widget.prototype[name]; old && (Widget.prototype[name] = function () { this.store && pushTarget(this.store); let res; try { res = old.apply(this, arguments); } catch (e) { console.error(e); } this.store && popTarget(); return res; }); });