feat: watch

main
CCherry07 8 months ago
parent cff02e6911
commit 61aefead9c
  1. 1
      src/index.ts
  2. 25
      src/test/index.test.ts
  3. 64
      src/test/watch.test.ts
  4. 41
      src/utils.ts
  5. 45
      src/watch.ts

@ -1,2 +1,3 @@
export * from "./core";
export * from "./deepSignal";
export * from "./watch"

@ -1,7 +1,6 @@
import { deepSignal, peek, RevertDeepSignal, shallow } from "../index"
import { describe, it, expect, beforeEach, test } from "vitest"
import { describe, it, expect, beforeEach } from "vitest"
import { signal, Signal, effect } from "..";
import { watch } from "../watch";
type Store = {
a?: number;
nested: { b?: number };
@ -1112,25 +1111,3 @@ describe("deepsignal/core", () => {
});
});
});
describe('watch', () => {
test('abc', () => {
const store = deepSignal({
userinfo: {
name: "tom"
}
})
const stop = watch(store, (newValue, oldValue) => {
console.log('newValue', newValue);
console.log('oldValue', oldValue);
}, {
immediate: true,
deep: true,
})
store.userinfo.name = "jon"
stop()
store.userinfo.name = 'jon2'
})
})

@ -0,0 +1,64 @@
import { describe, expect, it } from "vitest";
import { deepSignal } from "../deepSignal";
import { watch } from "../watch";
describe('watch', () => {
it('watch immediate', () => {
const store = deepSignal({
userinfo: {
name: "tom"
}
})
let val!: string
watch(store, (newValue) => {
val = newValue.userinfo.name
}, {
immediate: true,
deep: true
})
expect(val).toEqual('tom')
})
it('watch deep', () => {
const store = deepSignal({
userinfo: {
name: "tom"
}
})
let val!: string
watch(store, (newValue) => {
val = newValue.userinfo.name
}, {
immediate: true,
deep: true
})
let value2!: string
watch(store, (newValue) => {
value2 = newValue.userinfo.name
}, { immediate: true })
expect(val).toEqual('tom')
store.userinfo.name = "jon"
expect(val).toEqual('jon')
expect(value2).toEqual('tom')
})
it('watch once', () => {
const store = deepSignal({
userinfo: {
name: "tom"
}
})
let val!: string
watch(store, (newValue) => {
val = newValue.userinfo.name
}, {
immediate: true,
deep: true,
once: true
})
expect(val).toEqual("tom")
store.userinfo.name = "jon"
expect(val).not.toEqual("jon")
expect(val).toEqual("tom")
})
})

@ -1,6 +1,3 @@
import { ReactiveFlags } from "./contents"
import { isSignal } from "./core"
export const objectToString: typeof Object.prototype.toString =
Object.prototype.toString
export const toTypeString = (value: unknown): string =>
@ -40,41 +37,3 @@ export const isPlainObject = (val: unknown): val is object =>
export const hasChanged = (value: any, oldValue: any): boolean =>
!Object.is(value, oldValue)
export function traverse(
value: unknown,
depth: number = Infinity,
seen?: Set<unknown>,
): unknown {
if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
return value
}
seen = seen || new Set()
if (seen.has(value)) {
return value
}
seen.add(value)
depth--
if (isSignal(value)) {
traverse(value.value, depth, seen)
} else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
traverse(value[i], depth, seen)
}
} else if (isSet(value) || isMap(value)) {
value.forEach((v: any) => {
traverse(v, depth, seen)
})
} else if (isPlainObject(value)) {
for (const key in value) {
traverse(value[key], depth, seen)
}
for (const key of Object.getOwnPropertySymbols(value)) {
if (Object.prototype.propertyIsEnumerable.call(value, key)) {
traverse(value[key as any], depth, seen)
}
}
}
return value
}

@ -1,6 +1,7 @@
import { Computed, Effect, isSignal, Signal, } from './core';
import { hasChanged, isArray, traverse } from './utils';
import { Computed, Effect, isSignal, Signal } from './core';
import { hasChanged, isArray, isMap, isObject, isPlainObject, isSet } from './utils';
import { isDeepSignal, isShallow } from "./deepSignal"
import { ReactiveFlags } from './contents';
export type OnCleanup = (cleanupFn: () => void) => void
export type WatchEffect = (onCleanup: OnCleanup) => void
@ -38,7 +39,6 @@ export function watch(
let effect!: Effect
let getter!: () => any
// let boundCleanup: typeof onWatcherCleanup
let forceTrigger = false
let isMultiSource = false
@ -150,3 +150,42 @@ export function watch(
}
return watchHandle
}
export function traverse(
value: unknown,
depth: number = Infinity,
seen?: Set<unknown>,
): unknown {
if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
return value
}
seen = seen || new Set()
if (seen.has(value)) {
return value
}
seen.add(value)
depth--
if (isSignal(value)) {
traverse(value.value, depth, seen)
} else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
traverse(value[i], depth, seen)
}
} else if (isSet(value) || isMap(value)) {
value.forEach((v: any) => {
traverse(v, depth, seen)
})
} else if (isPlainObject(value)) {
for (const key in value) {
traverse(value[key], depth, seen)
}
for (const key of Object.getOwnPropertySymbols(value)) {
if (Object.prototype.propertyIsEnumerable.call(value, key)) {
traverse(value[key as any], depth, seen)
}
}
}
return value
}

Loading…
Cancel
Save