Match-id-9cf015cb84b803fe47e7daadbbd3a1ca9797d67e
This commit is contained in:
parent
11bad3bbf9
commit
d3d1a2c175
|
@ -13,12 +13,6 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createProxy } from './proxy/RProxyHandler';
|
|
||||||
import { getRNodeVal, setRNodeVal } from './RNodeAccessor';
|
|
||||||
import { preciseCompare } from './comparison/InDepthComparison';
|
|
||||||
import { isObject } from './Utils';
|
|
||||||
|
|
||||||
|
|
||||||
let runningRNode: RNode<any> | undefined = undefined; // 当前正执行的RNode
|
let runningRNode: RNode<any> | undefined = undefined; // 当前正执行的RNode
|
||||||
let calledGets: RNode<any>[] | null = null;
|
let calledGets: RNode<any>[] | null = null;
|
||||||
let sameGetsIndex = 0; // 记录前后两次运行RNode时,调用get顺序没有变化的节点
|
let sameGetsIndex = 0; // 记录前后两次运行RNode时,调用get顺序没有变化的节点
|
||||||
|
@ -53,34 +47,21 @@ function defaultEquality(a: any, b: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RNode<T = any> {
|
export class RNode<T = any> {
|
||||||
private _value: T;
|
_value: T;
|
||||||
private fn?: () => T;
|
fn?: () => T;
|
||||||
|
|
||||||
// 维护数据结构
|
|
||||||
root: Root<T> | null;
|
|
||||||
parent: RNode | null = null;
|
|
||||||
key: KEY | null;
|
|
||||||
children: Map<KEY, RNode> | null = null;
|
|
||||||
|
|
||||||
proxy: any = null;
|
|
||||||
|
|
||||||
extend: any; // 用于扩展,放一些自定义属性
|
|
||||||
|
|
||||||
private observers: RNode[] | null = null; // 被谁用
|
private observers: RNode[] | null = null; // 被谁用
|
||||||
private sources: RNode[] | null = null; // 使用谁
|
private sources: RNode[] | null = null; // 使用谁
|
||||||
|
|
||||||
private state: State;
|
private state: State;
|
||||||
private isEffect = false;
|
private isEffect = false;
|
||||||
private isComputed = false;
|
|
||||||
private isProxy = false;
|
|
||||||
|
|
||||||
cleanups: ((oldValue: T) => void)[] = [];
|
cleanups: ((oldValue: T) => void)[] = [];
|
||||||
equals = defaultEquality;
|
equals = defaultEquality;
|
||||||
|
|
||||||
constructor(fnOrValue: (() => T) | T, options?: RNodeOptions) {
|
constructor(fnOrValue: (() => T) | T, options?: RNodeOptions) {
|
||||||
this.isEffect = options?.isEffect || false;
|
this.isEffect = options?.isEffect || false;
|
||||||
this.isProxy = options?.isProxy || false;
|
|
||||||
this.isComputed = options?.isComputed || false;
|
|
||||||
|
|
||||||
if (typeof fnOrValue === 'function') {
|
if (typeof fnOrValue === 'function') {
|
||||||
this.fn = fnOrValue as () => T;
|
this.fn = fnOrValue as () => T;
|
||||||
|
@ -95,19 +76,6 @@ export class RNode<T = any> {
|
||||||
this._value = fnOrValue;
|
this._value = fnOrValue;
|
||||||
this.state = Fresh;
|
this.state = Fresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
// large object scene
|
|
||||||
if (this.isProxy) {
|
|
||||||
this.proxy = createProxy(this);
|
|
||||||
this.parent = options?.parent || null;
|
|
||||||
this.key = options?.key as KEY;
|
|
||||||
this.root = options?.root || null;
|
|
||||||
|
|
||||||
if (this.parent && !this.parent.children) {
|
|
||||||
this.parent.children = new Map();
|
|
||||||
this.parent.children.set(this.key, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get value(): T {
|
get value(): T {
|
||||||
|
@ -119,6 +87,12 @@ export class RNode<T = any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get(): T {
|
get(): T {
|
||||||
|
this.track();
|
||||||
|
|
||||||
|
return this.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
track() {
|
||||||
if (runningRNode) {
|
if (runningRNode) {
|
||||||
// 前后两次运行RNode,从左到右对比,如果调用get的RNode相同就calledGetsIndex加1
|
// 前后两次运行RNode,从左到右对比,如果调用get的RNode相同就calledGetsIndex加1
|
||||||
if (!calledGets && runningRNode.sources && runningRNode.sources[sameGetsIndex] == this) {
|
if (!calledGets && runningRNode.sources && runningRNode.sources[sameGetsIndex] == this) {
|
||||||
|
@ -131,8 +105,6 @@ export class RNode<T = any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.read();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read(): T {
|
read(): T {
|
||||||
|
@ -154,39 +126,18 @@ export class RNode<T = any> {
|
||||||
|
|
||||||
const value = typeof fnOrValue === 'function' ? fnOrValue(prevValue) : fnOrValue;
|
const value = typeof fnOrValue === 'function' ? fnOrValue(prevValue) : fnOrValue;
|
||||||
|
|
||||||
const isObj = isObject(value);
|
this.compare(prevValue, value);
|
||||||
const isPrevObj = isObject(prevValue);
|
|
||||||
|
|
||||||
// 新旧数据都是 对象或数组
|
|
||||||
if (isObj && isPrevObj) {
|
|
||||||
preciseCompare(this, value, prevValue, false);
|
|
||||||
|
|
||||||
this.setDirty();
|
|
||||||
|
|
||||||
this.setValue(value);
|
|
||||||
} else {
|
|
||||||
if (!this.equals(prevValue, value)) {
|
|
||||||
this.setDirty();
|
|
||||||
|
|
||||||
this.setValue(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 运行EffectQueue
|
// 运行EffectQueue
|
||||||
runEffects();
|
runEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
setByArrayModified(value: T) {
|
compare(prevValue: T, value: T) {
|
||||||
const prevValue = this.getValue();
|
if (!this.equals(prevValue, value)) {
|
||||||
|
this.setDirty();
|
||||||
|
|
||||||
preciseCompare(this, value, prevValue, true);
|
this.setValue(value);
|
||||||
|
}
|
||||||
this.setDirty();
|
|
||||||
|
|
||||||
this.setValue(value);
|
|
||||||
|
|
||||||
// 运行EffectQueue
|
|
||||||
runEffects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setDirty() {
|
setDirty() {
|
||||||
|
@ -215,7 +166,7 @@ export class RNode<T = any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private update(): void {
|
update(): void {
|
||||||
const prevValue = this.getValue();
|
const prevValue = this.getValue();
|
||||||
|
|
||||||
const prevReaction = runningRNode;
|
const prevReaction = runningRNode;
|
||||||
|
@ -233,11 +184,7 @@ export class RNode<T = any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行 reactive 函数
|
// 执行 reactive 函数
|
||||||
if (this.isComputed) {
|
this.execute();
|
||||||
this.root = { $: this.fn!() };
|
|
||||||
} else {
|
|
||||||
this._value = this.fn!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calledGets) {
|
if (calledGets) {
|
||||||
// remove all old sources' .observers links to us
|
// remove all old sources' .observers links to us
|
||||||
|
@ -285,6 +232,10 @@ export class RNode<T = any> {
|
||||||
this.state = Fresh;
|
this.state = Fresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
execute() {
|
||||||
|
// 执行 reactive 函数
|
||||||
|
this._value = this.fn!();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1、如果this是check,就去找dirty的parent
|
* 1、如果this是check,就去找dirty的parent
|
||||||
|
@ -321,17 +272,14 @@ export class RNode<T = any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getValue() {
|
getValue() {
|
||||||
return this.isProxy ? getRNodeVal(this) : this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setValue(value: any) {
|
setValue(value: any) {
|
||||||
this.isProxy ? setRNodeVal(this, value) : (this._value = value);
|
this._value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private qupdate() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onCleanup<T = any>(fn: (oldValue: T) => void): void {
|
export function onCleanup<T = any>(fn: (oldValue: T) => void): void {
|
||||||
|
|
|
@ -13,11 +13,10 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RNode } from './RNode';
|
|
||||||
import { isFunction } from './Utils';
|
import { isFunction } from './Utils';
|
||||||
|
import { RProxyNode } from './RProxyNode';
|
||||||
|
|
||||||
|
export function getRNodeVal(node: RProxyNode<any>): any {
|
||||||
export function getRNodeVal(node: RNode<any>): any {
|
|
||||||
let currentNode = node;
|
let currentNode = node;
|
||||||
const keys: (string | symbol)[] = [];
|
const keys: (string | symbol)[] = [];
|
||||||
while (currentNode.key !== null && currentNode.parent !== null) {
|
while (currentNode.key !== null && currentNode.parent !== null) {
|
||||||
|
@ -35,7 +34,7 @@ export function getRNodeVal(node: RNode<any>): any {
|
||||||
return rawObj;
|
return rawObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setRNodeVal(rNode: RNode<any>, value: unknown): void {
|
export function setRNodeVal(rNode: RProxyNode<any>, value: unknown): void {
|
||||||
const parent = rNode.parent;
|
const parent = rNode.parent;
|
||||||
const key = rNode.key!;
|
const key = rNode.key!;
|
||||||
const isRoot = parent === null;
|
const isRoot = parent === null;
|
||||||
|
@ -54,12 +53,22 @@ export function setRNodeVal(rNode: RNode<any>, value: unknown): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setExtendProp(rNode: RNode, key: string, value: any) {
|
export function getRootRNode(node: RProxyNode<any>): RProxyNode {
|
||||||
|
let currentNode = node;
|
||||||
|
const keys: (string | symbol)[] = [];
|
||||||
|
while (currentNode.parent !== null) {
|
||||||
|
currentNode = currentNode.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setExtendProp(rNode: RProxyNode, key: string, value: any) {
|
||||||
rNode.extend = rNode.extend || {};
|
rNode.extend = rNode.extend || {};
|
||||||
rNode.extend[key] = value;
|
rNode.extend[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExtendProp(rNode: RNode, key: string, defaultValue: any) {
|
export function getExtendProp(rNode: RProxyNode, key: string, defaultValue: any) {
|
||||||
rNode.extend = rNode.extend || {};
|
rNode.extend = rNode.extend || {};
|
||||||
if (key in rNode.extend) {
|
if (key in rNode.extend) {
|
||||||
return rNode.extend[key];
|
return rNode.extend[key];
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
import { isPrimitive } from './Utils';
|
import { isPrimitive } from './Utils';
|
||||||
import { RNode } from './RNode';
|
import { RNode } from './RNode';
|
||||||
import { ProxyRNode } from './Types';
|
import { ProxyRNode } from './Types';
|
||||||
|
import { RProxyNode } from './RProxyNode';
|
||||||
|
import {getRNodeVal, getRootRNode} from "./RNodeAccessor";
|
||||||
|
|
||||||
export type Reactive<T = any> = RNode<T> | Atom<T>;
|
export type Reactive<T = any> = RNode<T> | Atom<T>;
|
||||||
|
|
||||||
|
@ -23,8 +25,7 @@ export function createReactive<T extends any>(raw?: T): ReactiveProxy<T> {
|
||||||
if (isPrimitive(raw) || raw === null || raw === undefined) {
|
if (isPrimitive(raw) || raw === null || raw === undefined) {
|
||||||
return new RNode(raw, { isSignal: true });
|
return new RNode(raw, { isSignal: true });
|
||||||
} else {
|
} else {
|
||||||
const node = new RNode(null, {
|
const node = new RProxyNode(null, {
|
||||||
isProxy: true,
|
|
||||||
root: { $: raw },
|
root: { $: raw },
|
||||||
});
|
});
|
||||||
return node.proxy as ReactiveProxy<T>;
|
return node.proxy as ReactiveProxy<T>;
|
||||||
|
@ -32,7 +33,7 @@ export function createReactive<T extends any>(raw?: T): ReactiveProxy<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createComputed<T>(fn: T) {
|
export function createComputed<T>(fn: T) {
|
||||||
const rNode = new RNode(fn, { isProxy: true, isComputed: true });
|
const rNode = new RProxyNode(fn, { isComputed: true });
|
||||||
return rNode.proxy;
|
return rNode.proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,23 +45,37 @@ export function createWatch<T>(fn: T) {
|
||||||
rNode.get();
|
rNode.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOrCreateChildProxy(value: unknown, parent: RNode<any>, key: string | symbol): ProxyRNode<any> {
|
export function getOrCreateChildProxy(value: unknown, parent: RProxyNode<any>, key: string | symbol): ProxyRNode<any> {
|
||||||
const child = getOrCreateChildRNode(parent, key);
|
const child = getOrCreateChildRNode(parent, key);
|
||||||
|
|
||||||
return child.proxy;
|
return child.proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOrCreateChildRNode(node: RNode<any>, key: string | symbol): RNode<any> {
|
export function getOrCreateChildRNode(node: RProxyNode<any>, key: string | symbol): RProxyNode<any> {
|
||||||
let child = node.children?.get(key);
|
let child = node.children?.get(key);
|
||||||
|
|
||||||
if (!child) {
|
if (!child) {
|
||||||
child = new RNode(null, {
|
// child = new RProxyNode(null, {
|
||||||
isProxy: true,
|
// parent: node,
|
||||||
|
// key: key,
|
||||||
|
// root: node.root,
|
||||||
|
// });
|
||||||
|
|
||||||
|
child = new RProxyNode(() => {
|
||||||
|
const rootRNode = getRootRNode(node);
|
||||||
|
// 依赖根
|
||||||
|
rootRNode.get();
|
||||||
|
|
||||||
|
return getRNodeVal(node)[key];
|
||||||
|
}, {
|
||||||
|
isComputed: true,
|
||||||
parent: node,
|
parent: node,
|
||||||
key: key,
|
key: key,
|
||||||
root: node.root,
|
root: node.root,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
child.track();
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||||
|
*
|
||||||
|
* openGauss is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createProxy } from './proxy/RProxyHandler';
|
||||||
|
import {getRNodeVal, getRootRNode, setRNodeVal} from './RNodeAccessor';
|
||||||
|
import { preciseCompare } from './comparison/InDepthComparison';
|
||||||
|
import { isObject } from './Utils';
|
||||||
|
import {RNode, Root, runEffects} from "./RNode";
|
||||||
|
|
||||||
|
export interface RNodeOptions {
|
||||||
|
root?: Root<any> | null;
|
||||||
|
isSignal?: boolean;
|
||||||
|
isEffect?: boolean;
|
||||||
|
isComputed?: boolean;
|
||||||
|
isProxy?: boolean;
|
||||||
|
parent?: RNode<any> | null;
|
||||||
|
key?: KEY | null;
|
||||||
|
equals?: (a: any, b: any) => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type KEY = string | symbol;
|
||||||
|
|
||||||
|
export class RProxyNode<T = any> extends RNode<T> {
|
||||||
|
// 维护数据结构
|
||||||
|
root: Root<T> | null;
|
||||||
|
parent: RProxyNode | null = null;
|
||||||
|
key: KEY | null;
|
||||||
|
children: Map<KEY, RProxyNode> | null = null;
|
||||||
|
|
||||||
|
proxy: any = null;
|
||||||
|
|
||||||
|
extend: any; // 用于扩展,放一些自定义属性
|
||||||
|
|
||||||
|
isComputed = false;
|
||||||
|
|
||||||
|
constructor(fnOrValue: (() => T) | T, options?: RNodeOptions) {
|
||||||
|
super(fnOrValue, options);
|
||||||
|
|
||||||
|
this.isComputed = options?.isComputed || false;
|
||||||
|
|
||||||
|
this.proxy = createProxy(this);
|
||||||
|
this.parent = options?.parent || null;
|
||||||
|
this.key = options?.key as KEY;
|
||||||
|
this.root = options?.root || {};
|
||||||
|
|
||||||
|
if (this.parent && !this.parent.children) {
|
||||||
|
this.parent.children = new Map();
|
||||||
|
this.parent.children.set(this.key, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isComputed) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(prevValue: any, value: any) {
|
||||||
|
const isObj = isObject(value);
|
||||||
|
const isPrevObj = isObject(prevValue);
|
||||||
|
|
||||||
|
// 新旧数据都是 对象或数组
|
||||||
|
if (isObj && isPrevObj) {
|
||||||
|
// preciseCompare(this, value, prevValue, false);
|
||||||
|
|
||||||
|
this.setDirty();
|
||||||
|
|
||||||
|
this.setValue(value);
|
||||||
|
} else {
|
||||||
|
if (!this.equals(prevValue, value)) {
|
||||||
|
this.setDirty();
|
||||||
|
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
execute() {
|
||||||
|
// 执行 reactive 函数
|
||||||
|
if (this.isComputed) {
|
||||||
|
setRNodeVal(this, this.fn!());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setByArrayModified(value: T) {
|
||||||
|
const prevValue = this.getValue();
|
||||||
|
|
||||||
|
preciseCompare(this, value, prevValue, true);
|
||||||
|
|
||||||
|
this.setDirty();
|
||||||
|
|
||||||
|
this.setValue(value);
|
||||||
|
|
||||||
|
// 运行EffectQueue
|
||||||
|
runEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return getRNodeVal(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(value: any) {
|
||||||
|
setRNodeVal(this, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,9 +14,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RNode } from './RNode';
|
import { RNode } from './RNode';
|
||||||
|
import { RProxyNode } from './RProxyNode';
|
||||||
|
|
||||||
export function isReactiveObj(obj: any) {
|
export function isReactiveObj(obj: any) {
|
||||||
return obj instanceof RNode;
|
return obj instanceof RNode || obj instanceof RProxyNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isObject(obj: unknown): boolean {
|
export function isObject(obj: unknown): boolean {
|
||||||
|
|
|
@ -19,9 +19,10 @@ import { ArrayState } from '../Types';
|
||||||
import { getOrCreateChildRNode } from '../RNodeCreator';
|
import { getOrCreateChildRNode } from '../RNodeCreator';
|
||||||
import { RNode } from '../RNode';
|
import { RNode } from '../RNode';
|
||||||
import {getExtendProp, setExtendProp} from "../RNodeAccessor";
|
import {getExtendProp, setExtendProp} from "../RNodeAccessor";
|
||||||
|
import {RProxyNode} from "../RProxyNode";
|
||||||
|
|
||||||
// 递归触发依赖这reactive数据的所有RContext
|
// 递归触发依赖这reactive数据的所有RContext
|
||||||
export function preciseCompare(rNode: RNode<any>, value: any, prevValue: any, isFromArrModify?: boolean) {
|
export function preciseCompare(rNode: RProxyNode<any>, value: any, prevValue: any, isFromArrModify?: boolean) {
|
||||||
preciseCompareChildren(rNode, value, prevValue, isFromArrModify);
|
preciseCompareChildren(rNode, value, prevValue, isFromArrModify);
|
||||||
|
|
||||||
// 触发父数据的RContext,不希望触发组件刷新(只触发computed和watch)
|
// 触发父数据的RContext,不希望触发组件刷新(只触发computed和watch)
|
||||||
|
@ -30,7 +31,7 @@ export function preciseCompare(rNode: RNode<any>, value: any, prevValue: any, is
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当value和prevValue都是对象或数组时,才触发
|
// 当value和prevValue都是对象或数组时,才触发
|
||||||
function preciseCompareChildren(rNode: RNode, value: any, prevValue: any, isFromArrModify?: boolean): boolean {
|
function preciseCompareChildren(rNode: RProxyNode, value: any, prevValue: any, isFromArrModify?: boolean): boolean {
|
||||||
// 可以精准更新
|
// 可以精准更新
|
||||||
let canPreciseUpdate = true;
|
let canPreciseUpdate = true;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { getOrCreateChildProxy } from '../RNodeCreator';
|
||||||
import { getRNodeVal } from '../RNodeAccessor';
|
import { getRNodeVal } from '../RNodeAccessor';
|
||||||
import { isArray } from '../Utils';
|
import { isArray } from '../Utils';
|
||||||
import { RNode } from '../RNode';
|
import { RNode } from '../RNode';
|
||||||
|
import {RProxyNode} from "../RProxyNode";
|
||||||
|
|
||||||
const GET = 'get';
|
const GET = 'get';
|
||||||
const SET = 'set';
|
const SET = 'set';
|
||||||
|
@ -57,7 +58,7 @@ const FNS: Record<typeof GET | typeof READ | typeof DELETE | typeof ONCHANGE, (a
|
||||||
[ONCHANGE]: onChangeFn,
|
[ONCHANGE]: onChangeFn,
|
||||||
};
|
};
|
||||||
|
|
||||||
function get(rNode: RNode, key: string | symbol): any {
|
function get(rNode: RProxyNode, key: string | symbol): any {
|
||||||
// 处理 get, read, delete, onchange 方法
|
// 处理 get, read, delete, onchange 方法
|
||||||
const fn = FNS[key];
|
const fn = FNS[key];
|
||||||
if (fn) {
|
if (fn) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ describe('test reactive', () => {
|
||||||
|
|
||||||
const c = computed(() => {
|
const c = computed(() => {
|
||||||
callCount++;
|
callCount++;
|
||||||
return a.get() * b.get();
|
return { a: a.get() * b.get() };
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(() => {
|
watch(() => {
|
||||||
|
@ -18,14 +18,14 @@ describe('test reactive', () => {
|
||||||
expect(a.read()).toBe(7);
|
expect(a.read()).toBe(7);
|
||||||
|
|
||||||
a.set(2);
|
a.set(2);
|
||||||
expect(c.read()).toBe(2);
|
expect(c.a.read()).toBe(2);
|
||||||
|
|
||||||
b.set(3);
|
b.set(3);
|
||||||
expect(c.get()).toBe(6);
|
expect(c.a.get()).toBe(6);
|
||||||
|
|
||||||
expect(callCount).toBe(2);
|
expect(callCount).toBe(3);
|
||||||
c.read();
|
c.read();
|
||||||
expect(callCount).toBe(2);
|
expect(callCount).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reactive is a obj', () => {
|
it('reactive is a obj', () => {
|
||||||
|
@ -65,4 +65,38 @@ describe('test reactive', () => {
|
||||||
|
|
||||||
expect(doubleId.get()).toBe(22);
|
expect(doubleId.get()).toBe(22);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('return obj computed', () => {
|
||||||
|
const a = reactive(7);
|
||||||
|
|
||||||
|
const c = computed(() => {
|
||||||
|
return { a: a.get() };
|
||||||
|
});
|
||||||
|
|
||||||
|
a.set(2);
|
||||||
|
expect(c.a.read()).toBe(2);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reactive is a array, watch', () => {
|
||||||
|
const rObj = reactive({
|
||||||
|
items: [
|
||||||
|
{ name: 'p1', id: 1 },
|
||||||
|
{ name: 'p2', id: 2 },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
console.log(rObj.items[0].id.get());
|
||||||
|
});
|
||||||
|
|
||||||
|
rObj.items.set([
|
||||||
|
{ name: 'p1', id: 1 },
|
||||||
|
{ name: 'p2', id: 2 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
rObj.items.set([{ name: 'p11', id: 11 }]);
|
||||||
|
|
||||||
|
rObj.items[0].id.set(111);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue