diff --git a/packages/fineui/src/fix/fix.js b/packages/fineui/src/fix/fix.js index 1006e02e1..a28f5e4a8 100644 --- a/packages/fineui/src/fix/fix.js +++ b/packages/fineui/src/fix/fix.js @@ -1,5 +1,72 @@ import { _ } from "@/core"; +let uid = 0; + +const pendingCleanupDeps = []; + +const cleanupDeps = () => { + for (let i = 0; i < pendingCleanupDeps.length; i++) { + const dep = pendingCleanupDeps[i]; + dep.subs = dep.subs.filter(s => s); + dep._pending = false; + } + pendingCleanupDeps.length = 0; +}; + + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ +class Dep { + constructor() { + this.id = uid++; + this._pending = false; + this.subs = []; + } + + addSub(sub) { + this.subs.push(sub); + } + + removeSub(sub) { + this.subs[this.subs.indexOf(sub)] = null; + if (!this._pending) { + this._pending = true; + pendingCleanupDeps.push(this); + } + } + + depend() { + if (Dep.target) { + Dep.target.addDep(this); + } + } + + notify(options) { + // stabilize the subscriber list first + const subs = this.subs.filter(s => s); + for (let i = 0, l = subs.length; i < l; i++) { + subs[i].update(options); + } + } +} + +// the current target watcher being evaluated. +// this is globally unique because there could be only one +// watcher being evaluated at any time. +Dep.target = null; +const targetStack = []; + +function pushTarget(_target) { + if (Dep.target) targetStack.push(Dep.target); + Dep.target = _target; +} + +function popTarget() { + Dep.target = targetStack.pop(); +} + function noop(a, b, c) { } @@ -7,6 +74,7 @@ function isNative(Ctor) { return typeof Ctor === "function" && /native code/.test(Ctor.toString()); } + const hasProto = "__proto__" in {}; const _toString = Object.prototype.toString; @@ -152,56 +220,6 @@ const $$skipArray = { $vbsetter: falsy }; -let uid = 0; - -/** - * A dep is an observable that can have multiple - * directives subscribing to it. - */ -class Dep { - constructor() { - this.id = uid++; - this.subs = new Set(); - } - - addSub(sub) { - this.subs.add(sub); - } - - removeSub(sub) { - this.subs.delete(sub); - } - - depend() { - if (Dep.target) { - Dep.target.addDep(this); - } - } - - notify(options) { - // stabilize the subscriber list first - const subs = [...this.subs.values()]; - for (let i = 0, l = subs.length; i < l; i++) { - subs[i].update(options); - } - } -} - -// the current target watcher being evaluated. -// this is globally unique because there could be only one -// watcher being evaluated at any time. -Dep.target = null; -const targetStack = []; - -function pushTarget(_target) { - if (Dep.target) targetStack.push(Dep.target); - Dep.target = _target; -} - -function popTarget() { - Dep.target = targetStack.pop(); -} - //如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8 //标准浏览器使用__defineGetter__, __defineSetter__实现 let canHideProperty = true; @@ -286,6 +304,7 @@ function flushSchedulerQueue() { } resetSchedulerState(); + cleanupDeps(); } @@ -853,7 +872,7 @@ function watch(model, expOrFn, cb, options) { options = options || {}; options.user = true; let exps; - if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9BI._.*]+|[|][|]|[&][&]|[(]|[)]/g)) || (exps.length === 1 && expOrFn.indexOf("*") < 0)) { + if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || (exps.length === 1 && expOrFn.indexOf("*") < 0)) { const watcher = new Watcher(model, expOrFn, cb, options); if (options.immediate) { cb(watcher.value); @@ -1420,32 +1439,9 @@ export const Fix = { freeze, del, Watcher, + cleanupDeps, pushTarget, popTarget, watch, toJSON }; - - -window.testT = function (count = 5000) { - const subsArray = []; - - const subsSet = new Set(); - - for (let i = 0; i < count; i++) { - subsArray.push("" + i); - subsSet.add("" + i); - } - - console.time("array"); - for (let i = count; i >= 0; i--) { - remove(subsArray, "" + 1); - } - console.timeEnd("array"); - - console.time("set"); - for (let i = count; i >= 0; i--) { - subsSet.delete("" + 1); - } - console.timeEnd("set"); -};