Skip to content

Commit b2135c5

Browse files
committed
support simple v-for destructure
1 parent 7077a7b commit b2135c5

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

demos/for.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
<button @click="list.pop()">pop</button>
2525
<button @click="splice">splice</button>
2626
<ul>
27-
<li v-for="(item, index) in list" :key="item.id">
28-
<div>{{ index }} {{ item }}</div>
29-
<input v-model="item.text" />
27+
<li v-for="({ id, text }, index) in list" :key="id">
28+
<div>{{ index }} {{ { id, text } }}</div>
29+
<input v-model="text" />
3030
</li>
3131
</ul>
3232
</div>

src/directives/for.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { createScopedContext } from './scope'
77
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
88
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
99
const stripParensRE = /^\(|\)$/g
10+
const destructureRE = /^[{[]\s*((?:[\w_$]+\s*,?\s*)+)[\]}]$/
1011

1112
interface ChildScope {
1213
ctx: Context
@@ -31,6 +32,8 @@ export const _for = (el: Element, exp: string, ctx: Context) => {
3132

3233
const sourceExp = inMatch[2].trim()
3334
let valueExp = inMatch[1].trim().replace(stripParensRE, '').trim()
35+
let destructureBindings: string[] | undefined
36+
let isArrayDestructure = false
3437
let indexExp: string | undefined
3538
let objIndexExp: string | undefined
3639

@@ -44,15 +47,20 @@ export const _for = (el: Element, exp: string, ctx: Context) => {
4447
if (keyAttr === 'key') keyExp = JSON.stringify(keyExp)
4548
}
4649

47-
const iteratorMatch = valueExp.match(forIteratorRE)
48-
if (iteratorMatch) {
50+
let match
51+
if ((match = valueExp.match(forIteratorRE))) {
4952
valueExp = valueExp.replace(forIteratorRE, '').trim()
50-
indexExp = iteratorMatch[1].trim()
51-
if (iteratorMatch[2]) {
52-
objIndexExp = iteratorMatch[2].trim()
53+
indexExp = match[1].trim()
54+
if (match[2]) {
55+
objIndexExp = match[2].trim()
5356
}
5457
}
5558

59+
if ((match = valueExp.match(destructureRE))) {
60+
destructureBindings = match[1].split(',').map((s) => s.trim())
61+
isArrayDestructure = valueExp[0] === '['
62+
}
63+
5664
let mounted = false
5765
let blocks: Block[]
5866
let scopes: ChildScope[]
@@ -69,8 +77,14 @@ export const _for = (el: Element, exp: string, ctx: Context) => {
6977
index: number,
7078
objKey?: string
7179
): ChildScope => {
72-
// TODO destructure
73-
const data = { [valueExp]: value }
80+
const data: any = {}
81+
if (destructureBindings) {
82+
destructureBindings.forEach(
83+
(b, i) => (data[b] = value[isArrayDestructure ? i : b])
84+
)
85+
} else {
86+
data[valueExp] = value
87+
}
7488
if (objKey) {
7589
indexExp && (data[indexExp] = objKey)
7690
objIndexExp && (data[objIndexExp] = index)

src/directives/on.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const on: Directive = ({ el, get, exp, arg, modifiers }) => {
5757
}
5858

5959
listen(el, arg, handler, modifiers)
60-
} else {
61-
// TODO warn
60+
} else if (import.meta.env.DEV) {
61+
console.error(`v-on="obj" syntax is not supported in petite-vue.`)
6262
}
6363
}

0 commit comments

Comments
 (0)