diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index b71d17e..63e269b 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1,6 +1,9 @@ +import { reactive } from "@mini-vue/reactivity"; +import { watchEffect } from "../src/apiWatch"; +import { nextTick } from "../src/scheduler"; + describe("api: watch", () => { - it.todo("effect", async () => { - // 先实现个 watchEffect 玩一玩 + it("effect", async () => { const state = reactive({ count: 0 }); let dummy; watchEffect(() => { diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts new file mode 100644 index 0000000..8903a27 --- /dev/null +++ b/packages/runtime-core/src/apiWatch.ts @@ -0,0 +1,29 @@ +import { ReactiveEffect } from "@mini-vue/reactivity"; +import { queuePreFlushCb } from "./scheduler"; + +// Simple effect. +export function watchEffect(effect) { + doWatch(effect); +} + +function doWatch(source) { + // 把 job 添加到 pre flush 里面 + // 也就是在视图更新完成之前进行渲染(待确认?) + // 当逻辑执行到这里的时候 就已经触发了 watchEffect + const job = () => { + effect.run(); + }; + + // 这里用 scheduler 的目的就是在更新的时候 + // 让回调可以在 render 前执行 变成一个异步的行为(这里也可以通过 flush 来改变) + const scheduler = () => queuePreFlushCb(job); + + const getter = () => { + source(); + }; + + const effect = new ReactiveEffect(getter, scheduler); + + // 这里执行的就是 getter + effect.run(); +} diff --git a/packages/runtime-core/src/scheduler.ts b/packages/runtime-core/src/scheduler.ts index 1abaa10..b8e197d 100644 --- a/packages/runtime-core/src/scheduler.ts +++ b/packages/runtime-core/src/scheduler.ts @@ -1,10 +1,10 @@ const queue: any[] = []; -const activePreFlushCbs:any = []; +const activePreFlushCbs: any = []; const p = Promise.resolve(); let isFlushPending = false; -export function nextTick(fn) { +export function nextTick(fn?) { return fn ? p.then(fn) : p; } @@ -37,6 +37,9 @@ function queueCb(cb, activeQueue) { // todo 这里没有考虑 activeQueue 是否已经存在 cb 的情况 // 然后在执行 flushJobs 的时候就可以调用 activeQueue 了 activeQueue.push(cb); + + // 然后执行队列里面所有的 job + queueFlush() } function flushJobs() { @@ -60,6 +63,6 @@ function flushJobs() { function flushPreFlushCbs() { // 执行所有的 pre 类型的 job for (let i = 0; i < activePreFlushCbs.length; i++) { - activePreFlushCbs[i]() + activePreFlushCbs[i](); } }