From 659ddd7483f3ce33f5a40724042053d004ff55fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=E5=B1=8F=E5=B1=B1=E6=9C=80=E9=80=9F=E4=B8=8B?= =?UTF-8?q?=E5=B1=B1=E4=BC=A0=E8=AF=B4?= Date: Thu, 23 Nov 2023 17:51:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A0JIRA=20=E6=9B=B4=E6=96=B0subs=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fineui/src/fix/fix.js | 146 ++++++++++++++++----------------- 1 file changed, 71 insertions(+), 75 deletions(-) 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"); -};