Skip to content

Commit c6fe9f9

Browse files
committed
wip(vapor): new impl + test for vapor custom directive
1 parent 1b50feb commit c6fe9f9

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

packages-private/vapor-e2e-test/todomvc/App.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
import {
33
reactive,
44
computed,
5-
watchEffect,
65
onMounted,
76
onUnmounted,
8-
next,
9-
nextTick,
7+
watchPostEffect,
108
} from 'vue'
119
1210
const STORAGE_KEY = 'todos-vuejs-3.x'
@@ -72,7 +70,7 @@ const state = reactive({
7270
}),
7371
})
7472
75-
watchEffect(() => {
73+
watchPostEffect(() => {
7674
todoStorage.save(state.todos)
7775
})
7876
@@ -138,8 +136,8 @@ function removeCompleted() {
138136
}
139137
140138
// vapor custom directive
141-
const vTodoFocus = (el, value) => () => {
142-
if (value()) nextTick(() => el.focus())
139+
const vTodoFocus = (el, value) => {
140+
watchPostEffect(() => value() && el.focus())
143141
}
144142
</script>
145143

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { effectScope, ref } from '@vue/reactivity'
2+
import { type VaporDirective, withVaporDirectives } from '../../src'
3+
import { nextTick, watchEffect } from '@vue/runtime-dom'
4+
5+
describe('custom directive', () => {
6+
it('should work', async () => {
7+
const teardown = vi.fn()
8+
const dir: VaporDirective = vi.fn((el, source) => {
9+
watchEffect(() => {
10+
el.textContent = source()
11+
})
12+
return teardown
13+
})
14+
const scope = effectScope()
15+
const el = document.createElement('div')
16+
const n = ref(1)
17+
const source = () => n.value
18+
const modifiers = { mod: true }
19+
scope.run(() => {
20+
withVaporDirectives(el, [[dir, source, undefined, modifiers]])
21+
})
22+
expect(dir).toHaveBeenCalledWith(el, source, undefined, modifiers)
23+
expect(teardown).not.toHaveBeenCalled()
24+
25+
expect(el.textContent).toBe('1')
26+
27+
n.value = 2
28+
await nextTick()
29+
expect(el.textContent).toBe('2')
30+
31+
scope.stop()
32+
expect(teardown).toHaveBeenCalled()
33+
34+
n.value = 3
35+
await nextTick()
36+
// should be stopped and not update
37+
expect(el.textContent).toBe('2')
38+
})
39+
})

packages/runtime-vapor/src/directives/custom.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { DirectiveModifiers } from '@vue/runtime-dom'
1+
import { type DirectiveModifiers, onScopeDispose } from '@vue/runtime-dom'
22
import type { VaporComponentInstance } from '../component'
3-
import { renderEffect } from '../renderEffect'
43

54
// !! vapor directive is different from vdom directives
65
export type VaporDirective = (
@@ -13,11 +12,11 @@ export type VaporDirective = (
1312
type VaporDirectiveArguments = Array<
1413
| [VaporDirective | undefined]
1514
| [VaporDirective | undefined, () => any]
16-
| [VaporDirective | undefined, () => any, argument: string]
15+
| [VaporDirective | undefined, (() => any) | undefined, argument: string]
1716
| [
1817
VaporDirective | undefined,
19-
value: () => any,
20-
argument: string,
18+
value: (() => any) | undefined,
19+
argument: string | undefined,
2120
modifiers: DirectiveModifiers,
2221
]
2322
>
@@ -30,7 +29,7 @@ export function withVaporDirectives(
3029
for (const [dir, value, argument, modifiers] of dirs) {
3130
if (dir) {
3231
const ret = dir(node, value, argument, modifiers)
33-
if (ret) renderEffect(ret)
32+
if (ret) onScopeDispose(ret)
3433
}
3534
}
3635
}

0 commit comments

Comments
 (0)