diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap
index da4d0ad4c..9ad83079a 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap
@@ -1,8 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`comile > bindings 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, createTextNode, insert, setText } from 'vue/vapor';
+"import { template, children, createTextNode, insert, effect, setText } from 'vue/vapor';
const t0 = template('
count is .
');
export function render() {
const n0 = t0();
@@ -16,7 +15,7 @@ export function render() {
} = children(n0);
const n1 = createTextNode(count.value);
insert(n1, n3, n2);
- watchEffect(() => {
+ effect(() => {
setText(n1, undefined, count.value);
});
return n0;
@@ -25,15 +24,14 @@ export function render() {
`;
exports[`comile > directives > v-bind > simple expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setAttr } from 'vue/vapor';
+"import { template, children, effect, setAttr } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setAttr(n1, 'id', undefined, id.value);
});
return n0;
@@ -42,15 +40,14 @@ export function render() {
`;
exports[`comile > directives > v-html > no expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setHtml } from 'vue/vapor';
+"import { template, children, effect, setHtml } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setHtml(n1, undefined, '');
});
return n0;
@@ -59,15 +56,14 @@ export function render() {
`;
exports[`comile > directives > v-html > simple expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setHtml } from 'vue/vapor';
+"import { template, children, effect, setHtml } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setHtml(n1, undefined, code.value);
});
return n0;
@@ -76,15 +72,14 @@ export function render() {
`;
exports[`comile > directives > v-on > simple expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, on } from 'vue/vapor';
+"import { template, children, effect, on } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
on(n1, 'click', handleClick);
});
return n0;
@@ -93,15 +88,14 @@ export function render() {
`;
exports[`comile > directives > v-once > as root node 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setAttr } from 'vue/vapor';
+"import { template, children, effect, setAttr } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setAttr(n1, 'id', undefined, foo);
});
return n0;
@@ -132,15 +126,14 @@ export function render() {
`;
exports[`comile > directives > v-text > no expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setText } from 'vue/vapor';
+"import { template, children, effect, setText } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setText(n1, undefined, '');
});
return n0;
@@ -149,15 +142,14 @@ export function render() {
`;
exports[`comile > directives > v-text > simple expression 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, setText } from 'vue/vapor';
+"import { template, children, effect, setText } from 'vue/vapor';
const t0 = template('');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
- watchEffect(() => {
+ effect(() => {
setText(n1, undefined, str.value);
});
return n0;
@@ -166,18 +158,17 @@ export function render() {
`;
exports[`comile > dynamic root 1`] = `
-"import { watchEffect } from 'vue';
-import { fragment, createTextNode, append, setText } from 'vue/vapor';
+"import { fragment, createTextNode, append, effect, setText } from 'vue/vapor';
export function render() {
const t0 = fragment();
const n0 = t0();
const n1 = createTextNode(1);
const n2 = createTextNode(2);
append(n0, n1, n2);
- watchEffect(() => {
+ effect(() => {
setText(n1, undefined, 1);
});
- watchEffect(() => {
+ effect(() => {
setText(n2, undefined, 2);
});
return n0;
@@ -196,8 +187,7 @@ export function render() {
`;
exports[`comile > static + dynamic root 1`] = `
-"import { watchEffect } from 'vue';
-import { template, children, createTextNode, prepend, insert, append, setText } from 'vue/vapor';
+"import { template, children, createTextNode, prepend, insert, append, effect, setText } from 'vue/vapor';
const t0 = template('369');
export function render() {
const n0 = t0();
@@ -217,28 +207,28 @@ export function render() {
insert([n3, n4], n0, n9);
insert([n5, n6], n0, n10);
append(n0, n7, n8);
- watchEffect(() => {
+ effect(() => {
setText(n1, undefined, 1);
});
- watchEffect(() => {
+ effect(() => {
setText(n2, undefined, 2);
});
- watchEffect(() => {
+ effect(() => {
setText(n3, undefined, 4);
});
- watchEffect(() => {
+ effect(() => {
setText(n4, undefined, 5);
});
- watchEffect(() => {
+ effect(() => {
setText(n5, undefined, 7);
});
- watchEffect(() => {
+ effect(() => {
setText(n6, undefined, 8);
});
- watchEffect(() => {
+ effect(() => {
setText(n7, undefined, 'A');
});
- watchEffect(() => {
+ effect(() => {
setText(n8, undefined, 'B');
});
return n0;
diff --git a/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap
index f90d49cf6..f2e8a3f99 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap
@@ -2,8 +2,7 @@
exports[`fixtures 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
-import { watchEffect } from 'vue'
-import { template, children, createTextNode, append, setText, on, setHtml } from 'vue/vapor'
+import { template, children, createTextNode, append, setText, effect, on, setHtml } from 'vue/vapor'
const t0 = template(\\"Counter
Count:
Double:
once:
{{ count }}
\\")
import { ref, computed } from 'vue'
@@ -28,16 +27,16 @@ append(n4, n3)
const n7 = createTextNode(count.value)
setText(n7, undefined, count.value)
append(n8, n7)
-watchEffect(() => {
+effect(() => {
setText(n1, undefined, count.value)
})
-watchEffect(() => {
+effect(() => {
setText(n3, undefined, double.value)
})
-watchEffect(() => {
+effect(() => {
on(n5, \\"click\\", increment)
})
-watchEffect(() => {
+effect(() => {
setHtml(n6, undefined, html)
})
return n0
diff --git a/packages/compiler-vapor/__tests__/compile.test.ts b/packages/compiler-vapor/__tests__/compile.test.ts
index 979bb094f..7d0c1d774 100644
--- a/packages/compiler-vapor/__tests__/compile.test.ts
+++ b/packages/compiler-vapor/__tests__/compile.test.ts
@@ -129,7 +129,7 @@ describe('comile', () => {
test.fails('as root node', async () => {
const code = await compile(``)
expect(code).toMatchSnapshot()
- expect(code).not.contains('watchEffect')
+ expect(code).not.contains('effect')
})
})
})
diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts
index f87f5fab5..0af9d764b 100644
--- a/packages/compiler-vapor/src/generate.ts
+++ b/packages/compiler-vapor/src/generate.ts
@@ -45,9 +45,8 @@ export function generate(
code += genOperation(operation)
}
for (const [_expr, operations] of Object.entries(ir.effect)) {
- // TODO don't use watchEffect from vue/core, implement `effect` function in runtime-vapor package
- let scope = `watchEffect(() => {\n`
- helpers.add('watchEffect')
+ let scope = `effect(() => {\n`
+ vaporHelpers.add('effect')
for (const operation of operations) {
scope += genOperation(operation)
}
diff --git a/packages/runtime-vapor/package.json b/packages/runtime-vapor/package.json
index 7015bd167..a2f218cbf 100644
--- a/packages/runtime-vapor/package.json
+++ b/packages/runtime-vapor/package.json
@@ -34,6 +34,8 @@
"url": "https://github.com/vuejs/core-vapor/issues"
},
"homepage": "https://github.com/vuejs/core-vapor/tree/dev/packages/runtime-vapor#readme",
- "dependencies": {},
- "devDependencies": {}
+ "dependencies": {
+ "@vue/shared": "workspace:*",
+ "@vue/reactivity": "workspace:*"
+ }
}
diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts
index 8553412a3..d6c95e437 100644
--- a/packages/runtime-vapor/src/index.ts
+++ b/packages/runtime-vapor/src/index.ts
@@ -1,3 +1,4 @@
export * from './on'
export * from './render'
export * from './template'
+export * from './scheduler'
diff --git a/packages/runtime-vapor/src/on.ts b/packages/runtime-vapor/src/on.ts
index a1502a800..d4192b354 100644
--- a/packages/runtime-vapor/src/on.ts
+++ b/packages/runtime-vapor/src/on.ts
@@ -1,8 +1,8 @@
-export const on = (
+export function on(
el: any,
event: string,
handler: () => any,
options?: EventListenerOptions
-) => {
+) {
el.addEventListener(event, handler, options)
}
diff --git a/packages/runtime-vapor/src/render.ts b/packages/runtime-vapor/src/render.ts
index ed276c356..a120412fe 100644
--- a/packages/runtime-vapor/src/render.ts
+++ b/packages/runtime-vapor/src/render.ts
@@ -1,10 +1,10 @@
import {
- effectScope,
normalizeClass,
normalizeStyle,
- toDisplayString
-} from 'vue'
-import { isArray } from '@vue/shared'
+ toDisplayString,
+ isArray
+} from '@vue/shared'
+import { effectScope } from '@vue/reactivity'
export type Block = Node | Fragment | Block[]
export type ParentBlock = ParentNode | Node[]
diff --git a/packages/runtime-vapor/src/scheduler.ts b/packages/runtime-vapor/src/scheduler.ts
new file mode 100644
index 000000000..1af662e25
--- /dev/null
+++ b/packages/runtime-vapor/src/scheduler.ts
@@ -0,0 +1,30 @@
+import { ReactiveEffect } from '@vue/reactivity'
+
+const p = Promise.resolve()
+
+let queued: any[] | undefined
+
+const queue = (fn: any) => {
+ if (!queued) {
+ queued = [fn]
+ p.then(flush)
+ } else {
+ queued.push(fn)
+ }
+}
+
+function flush() {
+ for (let i = 0; i < queued!.length; i++) {
+ queued![i]()
+ }
+ queued = undefined
+}
+
+export const nextTick = (fn: any) => p.then(fn)
+
+export const effect = (fn: any) => {
+ let run: () => void
+ const e = new ReactiveEffect(fn, () => queue(run))
+ run = e.run.bind(e)
+ run()
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4496dfcd9..ef2662c47 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -348,7 +348,14 @@ importers:
specifier: workspace:*
version: link:../shared
- packages/runtime-vapor: {}
+ packages/runtime-vapor:
+ dependencies:
+ '@vue/reactivity':
+ specifier: workspace:*
+ version: link:../reactivity
+ '@vue/shared':
+ specifier: workspace:*
+ version: link:../shared
packages/server-renderer:
dependencies: