Skip to content

Commit

Permalink
feat: proxyRefs
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixiaorui committed Aug 19, 2021
1 parent 7da54fb commit bb1d543
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
- [x] 支持 provide/inject
- [x] 支持最基础的 slots
- [x] 支持 Text 类型节点
- [ ] proxyRefs
- [x] proxyRefs
- [ ] shallowReadonly

#### reactivity
Expand Down
16 changes: 15 additions & 1 deletion src/reactivity/__tests__/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { effect } from "../src/effect";
import { ref } from "../src/ref";
import { proxyRefs, ref } from "../src/ref";
describe("ref", () => {
it("should be reactive", () => {
const a = ref(1);
Expand Down Expand Up @@ -32,4 +32,18 @@ describe("ref", () => {
a.value.count = 2;
expect(dummy).toBe(2);
});

it("proxyRefs", () => {
const user = {
age: ref(10),
name: "xiaohong",
};
const proxyUser = proxyRefs(user);
expect(user.age.value).toBe(10);
expect(proxyUser.age).toBe(10);
expect(proxyUser.name).toBe("xiaohong");

proxyUser.age = 20
expect(proxyUser.age).toBe(20);
});
});
39 changes: 39 additions & 0 deletions src/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export class RefImpl {
private _rawValue: any;
private _value: any;
public dep;
public __v_isRef = true;

constructor(value) {
this._rawValue = value;
Expand Down Expand Up @@ -58,3 +59,41 @@ export function trackRefValue(ref) {
trackEffects(ref.dep);
}
}

// 这个函数的目的是
// 帮助解构 ref
// 比如在 template 中使用 ref 的时候,直接使用就可以了
// 例如: const count = ref(0) -> 在 template 中使用的话 可以直接 count
// 解决方案就是通过 proxy 来对 ref 做处理

const shallowUnwrapHandlers = {
get(target, key, receiver) {
// 如果里面是一个 ref 类型的话,那么就返回 .value
// 如果不是的话,那么直接返回value 就可以了
return unRef(Reflect.get(target, key, receiver));
},
set(target, key, value, receiver) {
const oldValue = target[key];
if (isRef(oldValue) && !isRef(value)) {
return (target[key].value = value);
} else {
return Reflect.set(target, key, value, receiver);
}
},
};

// 这里没有处理 objectWithRefs 是 reactive 类型的时候
// TODO reactive 里面如果有 ref 类型的 key 的话, 那么也是不需要调用 ref .value 的
// (but 这个逻辑在 reactive 里面没有实现)
export function proxyRefs(objectWithRefs) {
return new Proxy(objectWithRefs, shallowUnwrapHandlers);
}

// 把 ref 里面的值拿到
export function unRef(ref) {
return isRef(ref) ? ref.value : ref;
}

function isRef(value) {
return value.__v_isRef;
}

0 comments on commit bb1d543

Please sign in to comment.