Skip to content

Commit

Permalink
feat: readonly api
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixiaorui committed Aug 21, 2021
1 parent bb1d543 commit 4cacb1c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@
- [x] 支持最基础的 slots
- [x] 支持 Text 类型节点
- [x] proxyRefs
- [ ] shallowReadonly

#### reactivity

目标是用自己的 reactivity 支持现有的 demo 运行

- [x] reactive 的实现
- [x] ref 的实现
- [x] readonly 的实现
- [x] computed 的实现
- [x] track 依赖收集
- [x] trigger 触发依赖
Expand All @@ -78,6 +78,9 @@
- [x] 支持 toRaw
- [x] 支持 effect.scheduler
- [x] 支持 effect.stop
- [x] 支持 isReadonly
- [x] 支持 isProxy
- [ ] shallowReadonly

### build

Expand Down
20 changes: 20 additions & 0 deletions src/reactivity/__tests__/readonly.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { isProxy, isReactive, isReadonly, readonly } from "../src/reactive";

describe("readonly", () => {
it("should make nested values readonly", () => {
const original = { foo: 1, bar: { baz: 2 } };
const wrapped = readonly(original);
expect(wrapped).not.toBe(original);
expect(isProxy(wrapped)).toBe(true);
expect(isReactive(wrapped)).toBe(false);
expect(isReadonly(wrapped)).toBe(true);
expect(isReactive(original)).toBe(false);
expect(isReadonly(original)).toBe(false);
expect(isReactive(wrapped.bar)).toBe(false);
expect(isReadonly(wrapped.bar)).toBe(true);
expect(isReactive(original.bar)).toBe(false);
expect(isReadonly(original.bar)).toBe(false);
// get
expect(wrapped.foo).toBe(1);
});
});
22 changes: 18 additions & 4 deletions src/reactivity/src/reactive.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import { mutableHandlers } from "./baseHandlers";
import { mutableHandlers, readonlyHandlers } from "./baseHandlers";

export const reactiveMap = new WeakMap();
export const readonlyMap = new WeakMap();

export const enum ReactiveFlags {
IS_REACTIVE = "__v_isReactive",
IS_READONLY = "__v_isReadonly",
RAW = "__v_raw",
}

export function reactive(target) {
return createReactiveObject(target, reactiveMap);
return createReactiveObject(target, reactiveMap, mutableHandlers);
}

export function readonly(target) {
return createReactiveObject(target, readonlyMap, readonlyHandlers);
}

export function isProxy(value) {
return isReactive(value) || isReadonly(value);
}

export function isReadonly(value) {
return !!value[ReactiveFlags.IS_READONLY];
}

export function isReactive(value) {
Expand All @@ -33,7 +47,7 @@ export function toRaw(value) {
return value[ReactiveFlags.RAW];
}

function createReactiveObject(target, proxyMap) {
function createReactiveObject(target, proxyMap, baseHandlers) {
// 核心就是 proxy
// 目的是可以侦听到用户 get 或者 set 的动作

Expand All @@ -44,7 +58,7 @@ function createReactiveObject(target, proxyMap) {
return existingProxy;
}

const proxy = new Proxy(target, mutableHandlers);
const proxy = new Proxy(target, baseHandlers);

// 把创建好的 proxy 给存起来,
proxyMap.set(target, proxy);
Expand Down

0 comments on commit 4cacb1c

Please sign in to comment.