Browse Source

fix(v-for): support array and nested destructuring in v-for

dev
Evan You 7 years ago
parent
commit
f5ce6b50cf
  1. 14
      src/compiler/parser/index.js
  2. 10
      test/unit/features/directives/for.spec.js
  3. 76
      test/unit/modules/compiler/parser.spec.js

14
src/compiler/parser/index.js

@ -22,7 +22,7 @@ import {
export const onRE = /^@|^v-on:/
export const dirRE = /^v-|^@|^:/
export const forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/
export const forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/
export const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
const stripParensRE = /^\(|\)$/g
const argRE = /:(.*)$/
@ -356,16 +356,16 @@ export function processFor (el: ASTElement) {
return
}
el.for = inMatch[2].trim()
const alias = inMatch[1].trim()
const alias = inMatch[1].trim().replace(stripParensRE, '')
const iteratorMatch = alias.match(forIteratorRE)
if (iteratorMatch) {
el.alias = iteratorMatch[1].trim()
el.iterator1 = iteratorMatch[2].trim()
if (iteratorMatch[3]) {
el.iterator2 = iteratorMatch[3].trim()
el.alias = alias.replace(forIteratorRE, '')
el.iterator1 = iteratorMatch[1].trim()
if (iteratorMatch[2]) {
el.iterator2 = iteratorMatch[2].trim()
}
} else {
el.alias = alias.replace(stripParensRE, '')
el.alias = alias
}
}
}

10
test/unit/features/directives/for.spec.js

@ -472,12 +472,20 @@ describe('Directive v-for', () => {
})()
if (supportsDestructuring) {
it('should support destructuring syntax in alias position', () => {
it('should support destructuring syntax in alias position (object)', () => {
const vm = new Vue({
data: { list: [{ foo: 'hi', bar: 'ho' }] },
template: '<div><div v-for="({ foo, bar }, i) in list">{{ foo }} {{ bar }} {{ i }}</div></div>'
}).$mount()
expect(vm.$el.textContent).toBe('hi ho 0')
})
it('should support destructuring syntax in alias position (array)', () => {
const vm = new Vue({
data: { list: [[1, 2], [3, 4]] },
template: '<div><div v-for="([ foo, bar ], i) in list">{{ foo }} {{ bar }} {{ i }}</div></div>'
}).$mount()
expect(vm.$el.textContent).toBe('1 2 03 4 1')
})
}
})

76
test/unit/modules/compiler/parser.spec.js

@ -314,12 +314,88 @@ describe('parser', () => {
expect(liAst.alias).toBe('{ foo }')
expect(liAst.iterator1).toBe('i')
// with key + index
ast = parse('<ul><li v-for="({ foo }, i, j) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('{ foo }')
expect(liAst.iterator1).toBe('i')
expect(liAst.iterator2).toBe('j')
// multi-var destructuring with index
ast = parse('<ul><li v-for="({ foo, bar, baz }, i) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('{ foo, bar, baz }')
expect(liAst.iterator1).toBe('i')
// array
ast = parse('<ul><li v-for="[ foo ] in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo ]')
// multi-array
ast = parse('<ul><li v-for="[ foo, bar, baz ] in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo, bar, baz ]')
// array with paren
ast = parse('<ul><li v-for="([ foo ]) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo ]')
// multi-array with paren
ast = parse('<ul><li v-for="([ foo, bar, baz ]) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo, bar, baz ]')
// array with index
ast = parse('<ul><li v-for="([ foo ], i) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo ]')
expect(liAst.iterator1).toBe('i')
// array with key + index
ast = parse('<ul><li v-for="([ foo ], i, j) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo ]')
expect(liAst.iterator1).toBe('i')
expect(liAst.iterator2).toBe('j')
// multi-array with paren
ast = parse('<ul><li v-for="([ foo, bar, baz ]) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo, bar, baz ]')
// multi-array with index
ast = parse('<ul><li v-for="([ foo, bar, baz ], i) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo, bar, baz ]')
expect(liAst.iterator1).toBe('i')
// nested
ast = parse('<ul><li v-for="({ foo, bar: { baz }, qux: [ n ] }, i, j) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('{ foo, bar: { baz }, qux: [ n ] }')
expect(liAst.iterator1).toBe('i')
expect(liAst.iterator2).toBe('j')
// array nested
ast = parse('<ul><li v-for="([ foo, { bar }, baz ], i, j) in items"></li></ul>', baseOptions)
liAst = ast.children[0]
expect(liAst.for).toBe('items')
expect(liAst.alias).toBe('[ foo, { bar }, baz ]')
expect(liAst.iterator1).toBe('i')
expect(liAst.iterator2).toBe('j')
})
it('v-for directive invalid syntax', () => {

Loading…
Cancel
Save