mirror of https://github.com/vuejs/core.git
fix(vapor): destructure in `v-for`
This commit is contained in:
parent
0c7817ceed
commit
81b3d36304
|
@ -7,7 +7,7 @@ const t0 = _template("<div></div>")
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const n0 = _createFor(() => (_ctx.list), _withDestructure(([[id, ...other], index]) => [id, other, index], (_ctx0) => {
|
const n0 = _createFor(() => (_ctx.list), _withDestructure(([[id, ...other], index]) => [id, other, index], (_ctx0) => {
|
||||||
const n2 = t0()
|
const n2 = t0()
|
||||||
_renderEffect(() => _setText(n2, _ctx0[0].value + _ctx0[1].value + _ctx0[2].value))
|
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
|
||||||
return n2
|
return n2
|
||||||
}), ([id, ...other], index) => (id))
|
}), ([id, ...other], index) => (id))
|
||||||
return n0
|
return n0
|
||||||
|
@ -87,7 +87,7 @@ const t0 = _template("<div></div>")
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const n0 = _createFor(() => (_ctx.list), _withDestructure(([{ id, ...other }, index]) => [id, other, index], (_ctx0) => {
|
const n0 = _createFor(() => (_ctx.list), _withDestructure(([{ id, ...other }, index]) => [id, other, index], (_ctx0) => {
|
||||||
const n2 = t0()
|
const n2 = t0()
|
||||||
_renderEffect(() => _setText(n2, _ctx0[0].value + _ctx0[1].value + _ctx0[2].value))
|
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
|
||||||
return n2
|
return n2
|
||||||
}), ({ id, ...other }, index) => (id))
|
}), ({ id, ...other }, index) => (id))
|
||||||
return n0
|
return n0
|
||||||
|
@ -101,7 +101,7 @@ const t0 = _template("<div></div>")
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const n0 = _createFor(() => (_ctx.list), _withDestructure(([{ foo = bar, baz: [qux = quux] }]) => [foo, qux], (_ctx0) => {
|
const n0 = _createFor(() => (_ctx.list), _withDestructure(([{ foo = bar, baz: [qux = quux] }]) => [foo, qux], (_ctx0) => {
|
||||||
const n2 = t0()
|
const n2 = t0()
|
||||||
_renderEffect(() => _setText(n2, _ctx0[0].value + _ctx.bar + _ctx.baz + _ctx0[1].value + _ctx.quux))
|
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux))
|
||||||
return n2
|
return n2
|
||||||
}))
|
}))
|
||||||
return n0
|
return n0
|
||||||
|
|
|
@ -130,7 +130,7 @@ describe('compiler: v-for', () => {
|
||||||
)
|
)
|
||||||
expect(code).matchSnapshot()
|
expect(code).matchSnapshot()
|
||||||
expect(code).contains(`([{ id, ...other }, index]) => [id, other, index]`)
|
expect(code).contains(`([{ id, ...other }, index]) => [id, other, index]`)
|
||||||
expect(code).contains(`_ctx0[0].value + _ctx0[1].value + _ctx0[2].value`)
|
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
|
||||||
expect(ir.block.operation[0]).toMatchObject({
|
expect(ir.block.operation[0]).toMatchObject({
|
||||||
type: IRNodeTypes.FOR,
|
type: IRNodeTypes.FOR,
|
||||||
source: {
|
source: {
|
||||||
|
@ -163,7 +163,7 @@ describe('compiler: v-for', () => {
|
||||||
)
|
)
|
||||||
expect(code).matchSnapshot()
|
expect(code).matchSnapshot()
|
||||||
expect(code).contains(`([[id, ...other], index]) => [id, other, index]`)
|
expect(code).contains(`([[id, ...other], index]) => [id, other, index]`)
|
||||||
expect(code).contains(`_ctx0[0].value + _ctx0[1].value + _ctx0[2]`)
|
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
|
||||||
expect(ir.block.operation[0]).toMatchObject({
|
expect(ir.block.operation[0]).toMatchObject({
|
||||||
type: IRNodeTypes.FOR,
|
type: IRNodeTypes.FOR,
|
||||||
source: {
|
source: {
|
||||||
|
@ -199,7 +199,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(code).matchSnapshot()
|
expect(code).matchSnapshot()
|
||||||
expect(code).contains(`([{ foo = bar, baz: [qux = quux] }]) => [foo, qux]`)
|
expect(code).contains(`([{ foo = bar, baz: [qux = quux] }]) => [foo, qux]`)
|
||||||
expect(code).contains(
|
expect(code).contains(
|
||||||
`_ctx0[0].value + _ctx.bar + _ctx.baz + _ctx0[1].value + _ctx.quux`,
|
`_ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux`,
|
||||||
)
|
)
|
||||||
expect(ir.block.operation[0]).toMatchObject({
|
expect(ir.block.operation[0]).toMatchObject({
|
||||||
type: IRNodeTypes.FOR,
|
type: IRNodeTypes.FOR,
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function genFor(
|
||||||
container,
|
container,
|
||||||
} = oper
|
} = oper
|
||||||
|
|
||||||
let isDestructureAssignment = false
|
let isDestructure = false
|
||||||
let rawValue: string | null = null
|
let rawValue: string | null = null
|
||||||
const rawKey = key && key.content
|
const rawKey = key && key.content
|
||||||
const rawIndex = index && index.content
|
const rawIndex = index && index.content
|
||||||
|
@ -39,7 +39,7 @@ export function genFor(
|
||||||
let blockFn = genBlockFn()
|
let blockFn = genBlockFn()
|
||||||
const simpleIdMap: Record<string, null> = genSimpleIdMap()
|
const simpleIdMap: Record<string, null> = genSimpleIdMap()
|
||||||
|
|
||||||
if (isDestructureAssignment) {
|
if (isDestructure) {
|
||||||
const idMap: Record<string, null> = {}
|
const idMap: Record<string, null> = {}
|
||||||
idsInValue.forEach(id => (idMap[id] = null))
|
idsInValue.forEach(id => (idMap[id] = null))
|
||||||
if (rawKey) idMap[rawKey] = null
|
if (rawKey) idMap[rawKey] = null
|
||||||
|
@ -82,7 +82,7 @@ export function genFor(
|
||||||
const idsInValue = new Set<string>()
|
const idsInValue = new Set<string>()
|
||||||
if (value) {
|
if (value) {
|
||||||
rawValue = value && value.content
|
rawValue = value && value.content
|
||||||
if ((isDestructureAssignment = !!value.ast)) {
|
if ((isDestructure = !!value.ast)) {
|
||||||
walkIdentifiers(
|
walkIdentifiers(
|
||||||
value.ast,
|
value.ast,
|
||||||
(id, _, __, ___, isLocal) => {
|
(id, _, __, ___, isLocal) => {
|
||||||
|
@ -103,12 +103,13 @@ export function genFor(
|
||||||
const idMap: Record<string, string | null> = {}
|
const idMap: Record<string, string | null> = {}
|
||||||
if (context.options.prefixIdentifiers) {
|
if (context.options.prefixIdentifiers) {
|
||||||
propsName = `_ctx${depth}`
|
propsName = `_ctx${depth}`
|
||||||
|
let suffix = isDestructure ? '' : '.value'
|
||||||
Array.from(idsInValue).forEach(
|
Array.from(idsInValue).forEach(
|
||||||
(id, idIndex) => (idMap[id] = `${propsName}[${idIndex}].value`),
|
(id, idIndex) => (idMap[id] = `${propsName}[${idIndex}]${suffix}`),
|
||||||
)
|
)
|
||||||
if (rawKey) idMap[rawKey] = `${propsName}[${idsInValue.size}].value`
|
if (rawKey) idMap[rawKey] = `${propsName}[${idsInValue.size}]${suffix}`
|
||||||
if (rawIndex)
|
if (rawIndex)
|
||||||
idMap[rawIndex] = `${propsName}[${idsInValue.size + 1}].value`
|
idMap[rawIndex] = `${propsName}[${idsInValue.size + 1}]${suffix}`
|
||||||
} else {
|
} else {
|
||||||
propsName = `[${[rawValue || ((rawKey || rawIndex) && '_'), rawKey || (rawIndex && '__'), rawIndex].filter(Boolean).join(', ')}]`
|
propsName = `[${[rawValue || ((rawKey || rawIndex) && '_'), rawKey || (rawIndex && '__'), rawIndex].filter(Boolean).join(', ')}]`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@ import {
|
||||||
ref,
|
ref,
|
||||||
renderEffect,
|
renderEffect,
|
||||||
shallowRef,
|
shallowRef,
|
||||||
|
template,
|
||||||
triggerRef,
|
triggerRef,
|
||||||
|
withDestructure,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import { makeRender } from './_utils'
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
|
@ -579,4 +581,27 @@ describe('createFor', () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expectCalledTimesToBe('Clear rows', 1, 0, 0, 0)
|
expectCalledTimesToBe('Clear rows', 1, 0, 0, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('withDestructure', () => {
|
||||||
|
const list = ref([{ name: 'a' }, { name: 'b' }, { name: 'c' }])
|
||||||
|
|
||||||
|
const { host } = define(() => {
|
||||||
|
const n1 = createFor(
|
||||||
|
() => list.value,
|
||||||
|
withDestructure(
|
||||||
|
([{ name }, index]) => [name, index],
|
||||||
|
ctx => {
|
||||||
|
const span = template(`<li>${ctx[1]}. ${ctx[0]}</li>`)()
|
||||||
|
return span
|
||||||
|
},
|
||||||
|
),
|
||||||
|
item => item.name,
|
||||||
|
)
|
||||||
|
return n1
|
||||||
|
}).render()
|
||||||
|
|
||||||
|
expect(host.innerHTML).toBe(
|
||||||
|
'<li>0. a</li><li>1. b</li><li>2. c</li><!--for-->',
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
import { shallowReactive } from '@vue/reactivity'
|
import {
|
||||||
|
type ShallowUnwrapRef,
|
||||||
|
proxyRefs,
|
||||||
|
shallowReactive,
|
||||||
|
} from '@vue/reactivity'
|
||||||
import { renderEffect } from './renderEffect'
|
import { renderEffect } from './renderEffect'
|
||||||
|
|
||||||
export function withDestructure<P extends any[], R>(
|
export function withDestructure<T extends any[], R>(
|
||||||
assign: (...args: P) => any[],
|
assign: (data: ShallowUnwrapRef<T>) => any[],
|
||||||
block: (ctx: any[]) => R,
|
block: (ctx: any[]) => R,
|
||||||
): (...args: P) => R {
|
): (data: T) => R {
|
||||||
return (...args: P) => {
|
return (data: T) => {
|
||||||
const ctx = shallowReactive<any[]>([])
|
const ctx = shallowReactive<any[]>([])
|
||||||
renderEffect(() => {
|
renderEffect(() => {
|
||||||
const res = assign(...args)
|
const res = assign(proxyRefs(data))
|
||||||
const len = res.length
|
const len = res.length
|
||||||
for (let i = 0; i < len; i++) {
|
for (let i = 0; i < len; i++) {
|
||||||
ctx[i] = res[i]
|
ctx[i] = res[i]
|
||||||
|
|
Loading…
Reference in New Issue