Skip to content

Commit 769f46f

Browse files
committed
support v-once
1 parent 2fe6386 commit 769f46f

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ Check out the [examples directory](https://github.com/vuejs/petite-vue/tree/main
309309
- `v-html`
310310
- `v-text`
311311
- `v-pre`
312+
- `v-once`
312313
- `v-cloak`
313314
- `reactive()`
314315
- `nextTick()`
@@ -324,7 +325,6 @@ Some features are dropped because they have a relatively low utility/size ratio
324325
- Transition, KeepAlive, Teleport, KeepAlive
325326
- `v-for` deep destructure
326327
- `v-on="object"`
327-
- `v-once`
328328
- `v-is` & `<component :is="xxx">`
329329
- `v-bind:style` auto-prefixing
330330

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ <h2>Tests</h2>
1717
<li><a href="/tests/if.html">v-if</a></li>
1818
<li><a href="/tests/for.html">v-for</a></li>
1919
<li><a href="/tests/model.html">v-model</a></li>
20+
<li><a href="/tests/once.html">v-once</a></li>
2021
<li><a href="/tests/multi-mount.html">Multi mount</a></li>
2122
</ul>
2223

src/walk.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export const createContext = (parent?: Context): Context => {
2929
blocks: [],
3030
cleanups: [],
3131
effect: (fn) => {
32+
if (inOnce) {
33+
queueJob(fn)
34+
return fn as any
35+
}
3236
const e: ReactiveEffect = rawEffect(fn, {
3337
scheduler: () => queueJob(e)
3438
})
@@ -42,6 +46,7 @@ export const createContext = (parent?: Context): Context => {
4246
const dirRE = /^(?:v-|:|@)/
4347
const modifierRE = /\.([\w-]+)/g
4448
const interpolationRE = /\{\{([^]+?)\}\}/g
49+
let inOnce = false
4550

4651
export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
4752
const type = node.nodeType
@@ -73,6 +78,12 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
7378
}
7479
}
7580

81+
// v-once
82+
const hasVOnce = checkAttr(el, 'v-once') != null
83+
if (hasVOnce) {
84+
inOnce = true
85+
}
86+
7687
// process children first before self attrs
7788
walkChildren(el, ctx)
7889

@@ -92,6 +103,10 @@ export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
92103
if (deferredModel) {
93104
processDirective(el, 'v-model', deferredModel, ctx)
94105
}
106+
107+
if (hasVOnce) {
108+
inOnce = false
109+
}
95110
} else if (type === 3) {
96111
// Text
97112
const data = (node as Text).data

tests/once.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script type="module">
2+
import { createApp } from '../src'
3+
createApp().mount()
4+
</script>
5+
6+
<div v-scope="{ count: 5 }">
7+
{{ count }}
8+
<div v-once>
9+
<h2>Once</h2>
10+
{{ count }}
11+
<span v-text="count"></span>
12+
<span v-for="i in count">{{ i }}</span>
13+
</div>
14+
<span v-text="count"></span>
15+
<button @click="count++">++</button>
16+
</div>

0 commit comments

Comments
 (0)