@whitesev/utils 2.9.13 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.amd.js +167 -54
- package/dist/index.amd.js.map +1 -1
- package/dist/index.amd.min.js +1 -1
- package/dist/index.amd.min.js.map +1 -1
- package/dist/index.cjs.js +167 -54
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.cjs.min.js +1 -1
- package/dist/index.cjs.min.js.map +1 -1
- package/dist/index.esm.js +167 -54
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.iife.js +167 -54
- package/dist/index.iife.js.map +1 -1
- package/dist/index.iife.min.js +1 -1
- package/dist/index.iife.min.js.map +1 -1
- package/dist/index.system.js +167 -54
- package/dist/index.system.js.map +1 -1
- package/dist/index.system.min.js +1 -1
- package/dist/index.system.min.js.map +1 -1
- package/dist/index.umd.js +167 -54
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types/src/Utils.d.ts +34 -5
- package/dist/types/src/Vue.d.ts +24 -1
- package/package.json +1 -1
- package/src/Utils.ts +103 -31
- package/src/Vue.ts +92 -21
|
@@ -1519,14 +1519,39 @@ declare class Utils {
|
|
|
1519
1519
|
/**
|
|
1520
1520
|
* 自定义的动态响应对象
|
|
1521
1521
|
* @example
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1522
|
+
* const vue = new Utils.Vue();
|
|
1523
|
+
* const reactive = vue.reactive({
|
|
1524
|
+
* name: "",
|
|
1525
|
+
* });
|
|
1526
|
+
* vue.watch(()=>reactive.name, (newValue, oldValue)=>{
|
|
1527
|
+
* console.log("newValue ==> " + newValue);
|
|
1528
|
+
* console.log("oldValue ==> " + oldValue);
|
|
1529
|
+
* })
|
|
1530
|
+
* reactive.name = "测试";
|
|
1531
|
+
* > newValue ==> 测试
|
|
1532
|
+
* > oldValue ==>
|
|
1533
|
+
* reactive.name = "null";
|
|
1534
|
+
* > newValue ==> null
|
|
1535
|
+
* > oldValue ==> 测试
|
|
1536
|
+
* reactive.name = "null";
|
|
1537
|
+
* @example
|
|
1538
|
+
* const vue = new Utils.Vue();
|
|
1539
|
+
* const reactive = vue.reactive({
|
|
1540
|
+
* name: "",
|
|
1541
|
+
* });
|
|
1542
|
+
* vue.watch(()=>reactive.name, (newValue, oldValue)=>{
|
|
1525
1543
|
* console.log("newValue ==> " + newValue);
|
|
1526
1544
|
* console.log("oldValue ==> " + oldValue);
|
|
1545
|
+
* },{
|
|
1546
|
+
* triggerMethod: "set",
|
|
1527
1547
|
* })
|
|
1528
|
-
*
|
|
1529
|
-
* >
|
|
1548
|
+
* reactive.name = "测试";
|
|
1549
|
+
* > newValue ==> 测试
|
|
1550
|
+
* > oldValue ==>
|
|
1551
|
+
* reactive.name = "测试";
|
|
1552
|
+
* > newValue ==> 测试
|
|
1553
|
+
* > oldValue ==> 测试
|
|
1554
|
+
*
|
|
1530
1555
|
*/
|
|
1531
1556
|
Vue: typeof Vue;
|
|
1532
1557
|
ModuleRaid: typeof ModuleRaid;
|
|
@@ -1590,6 +1615,10 @@ declare class Utils {
|
|
|
1590
1615
|
}) => Promise<any> : (...args: {
|
|
1591
1616
|
[K in keyof P]: any;
|
|
1592
1617
|
}) => any;
|
|
1618
|
+
/**
|
|
1619
|
+
* 判断页面中是否存在`worker-src`的CSP规则
|
|
1620
|
+
*/
|
|
1621
|
+
hasWorkerCSP(): Promise<boolean>;
|
|
1593
1622
|
}
|
|
1594
1623
|
declare const utils: Utils;
|
|
1595
1624
|
export { utils as Utils };
|
package/dist/types/src/Vue.d.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
type ObjectWatchOptionItem = {
|
|
2
|
+
/**
|
|
3
|
+
* 是否立即执行
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
immediate?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* 是否仅触发一次
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
once?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* 值改变触发监听器的条件
|
|
14
|
+
* @default "not-same"
|
|
15
|
+
* @desc
|
|
16
|
+
* + `not-same`: 值改变时触发
|
|
17
|
+
* + `set`: 值被设置时触发
|
|
18
|
+
*/
|
|
19
|
+
triggerMethod: "not-same" | "set";
|
|
20
|
+
};
|
|
1
21
|
declare class RefImpl {
|
|
2
22
|
_value: any;
|
|
3
23
|
_isRef: boolean;
|
|
@@ -28,8 +48,11 @@ export declare class Vue {
|
|
|
28
48
|
* 观察被reactive的对象值改变
|
|
29
49
|
* @param source 被观察的对象,这里采用函数返回对象
|
|
30
50
|
* @param changeCallBack 值改变的回调
|
|
51
|
+
* @param options 配置项
|
|
31
52
|
*/
|
|
32
|
-
watch<T>(source: () => T, changeCallBack: (newValue: T | undefined, oldValue: T | undefined) => void):
|
|
53
|
+
watch<T>(source: () => T, changeCallBack: (newValue: T | undefined, oldValue: T | undefined) => void, options?: ObjectWatchOptionItem): {
|
|
54
|
+
unwatch: () => void;
|
|
55
|
+
} | undefined;
|
|
33
56
|
toReactive(value: any): any;
|
|
34
57
|
ref(value: any): RefImpl;
|
|
35
58
|
toRef(object: any, key: any): ObjectRefImpl;
|
package/package.json
CHANGED
package/src/Utils.ts
CHANGED
|
@@ -234,8 +234,8 @@ class Utils {
|
|
|
234
234
|
let timer: any = null as any;
|
|
235
235
|
const that = this;
|
|
236
236
|
return function (...args: A) {
|
|
237
|
-
|
|
238
|
-
timer =
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
timer = setTimeout(function () {
|
|
239
239
|
fn.apply(that, args);
|
|
240
240
|
}, delay);
|
|
241
241
|
};
|
|
@@ -263,7 +263,6 @@ class Utils {
|
|
|
263
263
|
**/
|
|
264
264
|
downloadBase64(base64Data: string, fileName: string, isIFrame?: boolean): void;
|
|
265
265
|
downloadBase64(base64Data: string, fileName: string, isIFrame = false) {
|
|
266
|
-
const that = this;
|
|
267
266
|
if (typeof base64Data !== "string") {
|
|
268
267
|
throw new Error("Utils.downloadBase64 参数 base64Data 必须为 string 类型");
|
|
269
268
|
}
|
|
@@ -276,7 +275,7 @@ class Utils {
|
|
|
276
275
|
$iframe.style.display = "none";
|
|
277
276
|
$iframe.src = base64Data;
|
|
278
277
|
(this.windowApi.document.body || this.windowApi.document.documentElement).appendChild($iframe);
|
|
279
|
-
|
|
278
|
+
setTimeout(() => {
|
|
280
279
|
$iframe!.contentWindow!.document.execCommand("SaveAs", true, fileName);
|
|
281
280
|
(this.windowApi.document.body || this.windowApi.document.documentElement).removeChild($iframe);
|
|
282
281
|
}, 100);
|
|
@@ -2841,7 +2840,6 @@ class Utils {
|
|
|
2841
2840
|
**/
|
|
2842
2841
|
setTimeout(callback: (() => void) | string, delayTime?: number): Promise<any>;
|
|
2843
2842
|
setTimeout(callback: (() => void) | string, delayTime: number = 0): Promise<any> {
|
|
2844
|
-
const that = this;
|
|
2845
2843
|
if (typeof callback !== "function" && typeof callback !== "string") {
|
|
2846
2844
|
throw new TypeError("Utils.setTimeout 参数 callback 必须为 function|string 类型");
|
|
2847
2845
|
}
|
|
@@ -2849,8 +2847,8 @@ class Utils {
|
|
|
2849
2847
|
throw new TypeError("Utils.setTimeout 参数 delayTime 必须为 number 类型");
|
|
2850
2848
|
}
|
|
2851
2849
|
return new Promise((resolve) => {
|
|
2852
|
-
|
|
2853
|
-
resolve(
|
|
2850
|
+
setTimeout(() => {
|
|
2851
|
+
resolve(this.tryCatch().run(callback));
|
|
2854
2852
|
}, delayTime);
|
|
2855
2853
|
});
|
|
2856
2854
|
}
|
|
@@ -2862,12 +2860,11 @@ class Utils {
|
|
|
2862
2860
|
**/
|
|
2863
2861
|
sleep(delayTime?: number): Promise<void>;
|
|
2864
2862
|
sleep(delayTime: number = 0): Promise<void> {
|
|
2865
|
-
const that = this;
|
|
2866
2863
|
if (typeof delayTime !== "number") {
|
|
2867
2864
|
throw new Error("Utils.sleep 参数 delayTime 必须为 number 类型");
|
|
2868
2865
|
}
|
|
2869
2866
|
return new Promise((resolve) => {
|
|
2870
|
-
|
|
2867
|
+
setTimeout(() => {
|
|
2871
2868
|
resolve(void 0);
|
|
2872
2869
|
}, delayTime);
|
|
2873
2870
|
});
|
|
@@ -3397,13 +3394,12 @@ class Utils {
|
|
|
3397
3394
|
intervalTimer: number = 250,
|
|
3398
3395
|
maxTime: number = -1
|
|
3399
3396
|
): Promise<T> {
|
|
3400
|
-
const that = this;
|
|
3401
3397
|
if (checkFn == null) {
|
|
3402
3398
|
throw new TypeError("checkObj 不能为空对象 ");
|
|
3403
3399
|
}
|
|
3404
3400
|
let isResolve = false;
|
|
3405
3401
|
return new Promise((resolve, reject) => {
|
|
3406
|
-
const interval =
|
|
3402
|
+
const interval = setInterval(() => {
|
|
3407
3403
|
let inst = checkFn;
|
|
3408
3404
|
if (typeof checkFn === "function") {
|
|
3409
3405
|
inst = checkFn();
|
|
@@ -3416,14 +3412,14 @@ class Utils {
|
|
|
3416
3412
|
}
|
|
3417
3413
|
if ((typeof propertyName === "function" && propertyName(inst)) || Reflect.has(inst, propertyName as string)) {
|
|
3418
3414
|
isResolve = true;
|
|
3419
|
-
|
|
3415
|
+
clearInterval(interval);
|
|
3420
3416
|
resolve((inst as any)[propertyName as string]);
|
|
3421
3417
|
}
|
|
3422
3418
|
}, intervalTimer);
|
|
3423
3419
|
if (maxTime !== -1) {
|
|
3424
|
-
|
|
3420
|
+
setTimeout(() => {
|
|
3425
3421
|
if (!isResolve) {
|
|
3426
|
-
|
|
3422
|
+
clearInterval(interval);
|
|
3427
3423
|
reject();
|
|
3428
3424
|
}
|
|
3429
3425
|
}, maxTime);
|
|
@@ -3733,14 +3729,39 @@ class Utils {
|
|
|
3733
3729
|
/**
|
|
3734
3730
|
* 自定义的动态响应对象
|
|
3735
3731
|
* @example
|
|
3736
|
-
*
|
|
3737
|
-
*
|
|
3738
|
-
*
|
|
3732
|
+
* const vue = new Utils.Vue();
|
|
3733
|
+
* const reactive = vue.reactive({
|
|
3734
|
+
* name: "",
|
|
3735
|
+
* });
|
|
3736
|
+
* vue.watch(()=>reactive.name, (newValue, oldValue)=>{
|
|
3737
|
+
* console.log("newValue ==> " + newValue);
|
|
3738
|
+
* console.log("oldValue ==> " + oldValue);
|
|
3739
|
+
* })
|
|
3740
|
+
* reactive.name = "测试";
|
|
3741
|
+
* > newValue ==> 测试
|
|
3742
|
+
* > oldValue ==>
|
|
3743
|
+
* reactive.name = "null";
|
|
3744
|
+
* > newValue ==> null
|
|
3745
|
+
* > oldValue ==> 测试
|
|
3746
|
+
* reactive.name = "null";
|
|
3747
|
+
* @example
|
|
3748
|
+
* const vue = new Utils.Vue();
|
|
3749
|
+
* const reactive = vue.reactive({
|
|
3750
|
+
* name: "",
|
|
3751
|
+
* });
|
|
3752
|
+
* vue.watch(()=>reactive.name, (newValue, oldValue)=>{
|
|
3739
3753
|
* console.log("newValue ==> " + newValue);
|
|
3740
3754
|
* console.log("oldValue ==> " + oldValue);
|
|
3755
|
+
* },{
|
|
3756
|
+
* triggerMethod: "set",
|
|
3741
3757
|
* })
|
|
3742
|
-
*
|
|
3743
|
-
* >
|
|
3758
|
+
* reactive.name = "测试";
|
|
3759
|
+
* > newValue ==> 测试
|
|
3760
|
+
* > oldValue ==>
|
|
3761
|
+
* reactive.name = "测试";
|
|
3762
|
+
* > newValue ==> 测试
|
|
3763
|
+
* > oldValue ==> 测试
|
|
3764
|
+
*
|
|
3744
3765
|
*/
|
|
3745
3766
|
Vue = Vue;
|
|
3746
3767
|
ModuleRaid = ModuleRaid;
|
|
@@ -3752,8 +3773,7 @@ class Utils {
|
|
|
3752
3773
|
workerSetTimeout(callback: (...args: any[]) => any, timeout: number = 0) {
|
|
3753
3774
|
try {
|
|
3754
3775
|
return WorkerSetTimeout(callback, timeout);
|
|
3755
|
-
|
|
3756
|
-
} catch (error) {
|
|
3776
|
+
} catch {
|
|
3757
3777
|
return this.windowApi.setTimeout(callback, timeout);
|
|
3758
3778
|
}
|
|
3759
3779
|
}
|
|
@@ -3766,10 +3786,7 @@ class Utils {
|
|
|
3766
3786
|
if (timeId != null) {
|
|
3767
3787
|
WorkerClearTimeout(timeId);
|
|
3768
3788
|
}
|
|
3769
|
-
|
|
3770
|
-
} catch (error) {
|
|
3771
|
-
// console.log(error);
|
|
3772
|
-
} finally {
|
|
3789
|
+
} catch {
|
|
3773
3790
|
this.windowApi.clearTimeout(timeId);
|
|
3774
3791
|
}
|
|
3775
3792
|
}
|
|
@@ -3781,8 +3798,7 @@ class Utils {
|
|
|
3781
3798
|
workerSetInterval(callback: (...args: any[]) => any, timeout: number = 0) {
|
|
3782
3799
|
try {
|
|
3783
3800
|
return WorkerSetInterval(callback, timeout);
|
|
3784
|
-
|
|
3785
|
-
} catch (error) {
|
|
3801
|
+
} catch {
|
|
3786
3802
|
return this.windowApi.setInterval(callback, timeout);
|
|
3787
3803
|
}
|
|
3788
3804
|
}
|
|
@@ -3795,10 +3811,7 @@ class Utils {
|
|
|
3795
3811
|
if (timeId != null) {
|
|
3796
3812
|
WorkerClearInterval(timeId);
|
|
3797
3813
|
}
|
|
3798
|
-
|
|
3799
|
-
} catch (error) {
|
|
3800
|
-
// console.log(error);
|
|
3801
|
-
} finally {
|
|
3814
|
+
} catch {
|
|
3802
3815
|
this.windowApi.clearInterval(timeId);
|
|
3803
3816
|
}
|
|
3804
3817
|
}
|
|
@@ -3853,6 +3866,65 @@ class Utils {
|
|
|
3853
3866
|
return new FunctionConstructor(...args);
|
|
3854
3867
|
}
|
|
3855
3868
|
}
|
|
3869
|
+
/**
|
|
3870
|
+
* 判断页面中是否存在`worker-src`的CSP规则
|
|
3871
|
+
*/
|
|
3872
|
+
hasWorkerCSP() {
|
|
3873
|
+
return new Promise<boolean>((resolve) => {
|
|
3874
|
+
let flag = true;
|
|
3875
|
+
let workerBlobUrl: string | undefined = void 0;
|
|
3876
|
+
|
|
3877
|
+
const workerJs = /*js*/ `
|
|
3878
|
+
(() => {
|
|
3879
|
+
this.addEventListener(
|
|
3880
|
+
"message",
|
|
3881
|
+
function () {
|
|
3882
|
+
this.postMessage({
|
|
3883
|
+
success: true,
|
|
3884
|
+
});
|
|
3885
|
+
},
|
|
3886
|
+
{
|
|
3887
|
+
capture: true,
|
|
3888
|
+
}
|
|
3889
|
+
);
|
|
3890
|
+
})();`;
|
|
3891
|
+
try {
|
|
3892
|
+
const workerScript = new Blob([workerJs], {
|
|
3893
|
+
type: "application/javascript",
|
|
3894
|
+
});
|
|
3895
|
+
workerBlobUrl = window.URL.createObjectURL(workerScript);
|
|
3896
|
+
// @ts-expect-error
|
|
3897
|
+
if (globalThis.trustedTypes && typeof globalThis.trustedTypes.createPolicy === "function") {
|
|
3898
|
+
// 使用这个后虽然不报错,但是仍会有blob错误
|
|
3899
|
+
// violates the following Content Security Policy directive: "worker-src 'self'". The action has been blocked.
|
|
3900
|
+
// 且这个错误无法使用try/catch捕捉,导致本该提醒使用手动匹配的结果并无提醒弹窗
|
|
3901
|
+
// @ts-expect-error
|
|
3902
|
+
const workerPolicy = globalThis.trustedTypes.createPolicy("workerPolicy", {
|
|
3903
|
+
createScriptURL: (url: string) => url,
|
|
3904
|
+
});
|
|
3905
|
+
workerBlobUrl = workerPolicy.createScriptURL(workerBlobUrl);
|
|
3906
|
+
}
|
|
3907
|
+
const worker = new Worker(workerBlobUrl!);
|
|
3908
|
+
worker.onmessage = (data) => {
|
|
3909
|
+
if (data.data.success) {
|
|
3910
|
+
flag = false;
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
setTimeout(() => {
|
|
3914
|
+
worker.terminate();
|
|
3915
|
+
resolve(flag);
|
|
3916
|
+
}, 500);
|
|
3917
|
+
worker.postMessage("test");
|
|
3918
|
+
} catch {
|
|
3919
|
+
flag = true;
|
|
3920
|
+
} finally {
|
|
3921
|
+
// 释放
|
|
3922
|
+
if (typeof workerBlobUrl === "string") {
|
|
3923
|
+
globalThis.URL.revokeObjectURL(workerBlobUrl);
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3856
3928
|
}
|
|
3857
3929
|
|
|
3858
3930
|
const utils = new Utils();
|
package/src/Vue.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
const VueUtils = {
|
|
3
2
|
/** 标签 */
|
|
4
3
|
ReactiveFlags: {
|
|
@@ -34,16 +33,39 @@ const VueUtils = {
|
|
|
34
33
|
},
|
|
35
34
|
};
|
|
36
35
|
|
|
36
|
+
type ObjectWatchOptionItem = {
|
|
37
|
+
/**
|
|
38
|
+
* 是否立即执行
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
immediate?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 是否仅触发一次
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
once?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 值改变触发监听器的条件
|
|
49
|
+
* @default "not-same"
|
|
50
|
+
* @desc
|
|
51
|
+
* + `not-same`: 值改变时触发
|
|
52
|
+
* + `set`: 值被设置时触发
|
|
53
|
+
*/
|
|
54
|
+
triggerMethod: "not-same" | "set";
|
|
55
|
+
};
|
|
56
|
+
|
|
37
57
|
class ReactiveEffect {
|
|
38
58
|
deps: any[] = [];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
active = true;
|
|
60
|
+
fn;
|
|
61
|
+
scheduler;
|
|
62
|
+
options;
|
|
63
|
+
constructor(fn: (...args: any[]) => any, scheduler: any, options: ObjectWatchOptionItem) {
|
|
43
64
|
this.fn = fn;
|
|
44
65
|
this.scheduler = scheduler;
|
|
66
|
+
this.options = options; // 默认值为'same'
|
|
45
67
|
}
|
|
46
|
-
run(cb
|
|
68
|
+
run(cb?: (activeEffect: any) => void) {
|
|
47
69
|
if (!this.active) {
|
|
48
70
|
this.fn();
|
|
49
71
|
}
|
|
@@ -58,6 +80,18 @@ class ReactiveEffect {
|
|
|
58
80
|
}
|
|
59
81
|
}
|
|
60
82
|
}
|
|
83
|
+
stop() {
|
|
84
|
+
if (this.active) {
|
|
85
|
+
// 清除依赖关系
|
|
86
|
+
if (this.deps && this.deps.length) {
|
|
87
|
+
this.deps.forEach((dep: any) => {
|
|
88
|
+
dep.delete(this);
|
|
89
|
+
});
|
|
90
|
+
this.deps.length = 0;
|
|
91
|
+
}
|
|
92
|
+
this.active = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
61
95
|
}
|
|
62
96
|
class RefImpl {
|
|
63
97
|
_value;
|
|
@@ -127,9 +161,7 @@ export class Vue {
|
|
|
127
161
|
set(target, key, value, receiver) {
|
|
128
162
|
const oldValue = target[key as keyof T];
|
|
129
163
|
const result = Reflect.set(target, key, value, receiver);
|
|
130
|
-
|
|
131
|
-
that.trigger(target, "set", key, oldValue, value);
|
|
132
|
-
}
|
|
164
|
+
that.trigger(target, "set", key, oldValue, value);
|
|
133
165
|
return result;
|
|
134
166
|
},
|
|
135
167
|
});
|
|
@@ -140,8 +172,13 @@ export class Vue {
|
|
|
140
172
|
* 观察被reactive的对象值改变
|
|
141
173
|
* @param source 被观察的对象,这里采用函数返回对象
|
|
142
174
|
* @param changeCallBack 值改变的回调
|
|
175
|
+
* @param options 配置项
|
|
143
176
|
*/
|
|
144
|
-
watch<T>(
|
|
177
|
+
watch<T>(
|
|
178
|
+
source: () => T,
|
|
179
|
+
changeCallBack: (newValue: T | undefined, oldValue: T | undefined) => void,
|
|
180
|
+
options?: ObjectWatchOptionItem
|
|
181
|
+
) {
|
|
145
182
|
let getter;
|
|
146
183
|
if (VueUtils.isReactive(source)) {
|
|
147
184
|
getter = () => this.traversal(source);
|
|
@@ -151,17 +188,35 @@ export class Vue {
|
|
|
151
188
|
return;
|
|
152
189
|
}
|
|
153
190
|
let oldValue: any;
|
|
191
|
+
const unwatch = () => {
|
|
192
|
+
effect.stop();
|
|
193
|
+
};
|
|
154
194
|
const job = () => {
|
|
155
195
|
const newValue = effect.run((activeEffect) => {
|
|
156
196
|
this.activeEffect = activeEffect;
|
|
157
197
|
});
|
|
158
198
|
changeCallBack(newValue, oldValue);
|
|
199
|
+
if (options?.once) {
|
|
200
|
+
// 仅触发一次
|
|
201
|
+
unwatch();
|
|
202
|
+
}
|
|
159
203
|
oldValue = newValue;
|
|
160
204
|
};
|
|
161
|
-
const effect = new ReactiveEffect(getter, job
|
|
205
|
+
const effect = new ReactiveEffect(getter, job, {
|
|
206
|
+
triggerMethod: "not-same",
|
|
207
|
+
...(options ?? {}),
|
|
208
|
+
});
|
|
162
209
|
oldValue = effect.run((activeEffect) => {
|
|
163
210
|
this.activeEffect = activeEffect;
|
|
164
211
|
});
|
|
212
|
+
if (options) {
|
|
213
|
+
if (options.immediate) {
|
|
214
|
+
job();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
unwatch,
|
|
219
|
+
};
|
|
165
220
|
}
|
|
166
221
|
toReactive(value: any) {
|
|
167
222
|
return VueUtils.isObject(value) ? this.reactive(value) : value;
|
|
@@ -179,26 +234,42 @@ export class Vue {
|
|
|
179
234
|
}
|
|
180
235
|
return result;
|
|
181
236
|
}
|
|
182
|
-
|
|
183
|
-
private trigger(target: any, type: string, key: string | symbol, oldValue: any, value: any) {
|
|
237
|
+
private trigger(target: any, type: "set", key: string | symbol, oldValue: any, value: any) {
|
|
184
238
|
const depsMap = this.targetMap.get(target);
|
|
185
239
|
if (!depsMap) return;
|
|
186
240
|
const effects = depsMap.get(key);
|
|
187
|
-
this.triggerEffect(effects, "effects");
|
|
241
|
+
this.triggerEffect(effects, type, "effects", oldValue, value);
|
|
188
242
|
}
|
|
189
|
-
|
|
190
|
-
|
|
243
|
+
private triggerEffect(
|
|
244
|
+
effects: (typeof ReactiveEffect)["prototype"][],
|
|
245
|
+
_type: "set",
|
|
246
|
+
_name: string,
|
|
247
|
+
oldValue: any,
|
|
248
|
+
value: any
|
|
249
|
+
) {
|
|
191
250
|
if (effects) {
|
|
251
|
+
const isSame = oldValue === value;
|
|
192
252
|
effects.forEach((effect) => {
|
|
193
|
-
if (effect.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
253
|
+
if (effect.options.triggerMethod === "not-same") {
|
|
254
|
+
if (isSame) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (effect.scheduler) {
|
|
258
|
+
effect.scheduler();
|
|
259
|
+
} else {
|
|
260
|
+
effect.run();
|
|
261
|
+
}
|
|
262
|
+
} else if (effect.options.triggerMethod === "set") {
|
|
263
|
+
if (effect.scheduler) {
|
|
264
|
+
effect.scheduler();
|
|
265
|
+
} else {
|
|
266
|
+
effect.run();
|
|
267
|
+
}
|
|
197
268
|
}
|
|
198
269
|
});
|
|
199
270
|
}
|
|
200
271
|
}
|
|
201
|
-
private track(target: WeakKey,
|
|
272
|
+
private track(target: WeakKey, _type: "get", key: string | symbol) {
|
|
202
273
|
if (!this.activeEffect) return;
|
|
203
274
|
let depsMap = this.targetMap.get(target);
|
|
204
275
|
if (!depsMap) {
|