Skip to content

polish template v-for error report #168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions lib/rules/valid-v-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ function isUsingIterationVar (vFor, vBindKey) {
}
const references = vBindKey.value.references
const variables = vFor.parent.parent.variables

return references.some(reference =>
variables.some(variable =>
variable.id.name === reference.id.name &&
Expand All @@ -36,6 +35,34 @@ function isUsingIterationVar (vFor, vBindKey) {
)
}

/**
* Check the child element in tempalte v-for about `v-bind:key` attributes.
* @param {RuleContext} context The rule context to report.
* @param {ASTNode} vFor The attribute node of `v-for` to check.
* @param {ASTNode} child The child node to check.
*/
function checkChildKey (context, vFor, child) {
const childFor = utils.getDirective(child, 'for')
// if child has v-for, check if parent iterator is used in v-for
if (childFor != null) {
const childForRefs = childFor.value.references
const variables = vFor.parent.parent.variables
const usedInFor = childForRefs.some(cref =>
variables.some(variable =>
cref.id.name === variable.id.name &&
variable.kind === 'v-for'
)
)
// if parent iterator is used, skip other checks
// iterator usage will be checked later by child v-for
if (usedInFor) {
return
}
}
// otherwise, check if parent iterator is directly used in child's key
checkKey(context, vFor, child)
}

/**
* Check the given element about `v-bind:key` attributes.
* @param {RuleContext} context The rule context to report.
Expand All @@ -46,7 +73,7 @@ function checkKey (context, vFor, element) {
if (element.name === 'template') {
for (const child of element.children) {
if (child.type === 'VElement') {
checkKey(context, vFor, child)
checkChildKey(context, vFor, child)
}
}
return
Expand Down
68 changes: 68 additions & 0 deletions tests/lib/rules/valid-v-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,32 @@ tester.run('valid-v-for', rule, {
{
filename: 'test.vue',
code: '<template v-for="x of list">foo<div></div></template>'
},
{
filename: 'test.vue',
code: '<template><div><template v-for="x of list"><div v-for="foo of x" :key="foo"></div></template></div></template>'
},
{
filename: 'test.vue',
code: `
<template v-for="x in xs">
<template v-for="y in x.ys">
<li v-for="z in y.zs" :key="z.id">
123
</li>
</template>
</template>`
},
{
filename: 'test.vue',
code: `
<template v-for="x in xs">
<template v-for="y in ys">
<li v-for="z in zs" :key="x.id + y.id + z.id">
123
</li>
</template>
</template>`
}
],
invalid: [
Expand Down Expand Up @@ -179,6 +205,48 @@ tester.run('valid-v-for', rule, {
filename: 'test.vue',
code: '<template><div><template v-for="xin list"><div></div></template></div></template>',
errors: ["'v-for' directives require that attribute value."]
},
{
filename: 'test.vue',
code: '<template><div><template v-for="x of list"><div v-for="foo of y" :key="foo"></div></template></div></template>',
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."]
},
{
filename: 'test.vue',
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
code: `
<template v-for="x in xs">
<template v-for="y in a.ys">
<li v-for="z in y.zs" :key="z.id">
123
</li>
</template>
</template>`
},
{
filename: 'test.vue',
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
code: `
<template v-for="x in xs">
<template v-for="y in x.ys">
<li v-for="z in a.zs" :key="z.id">
123
</li>
</template>
</template>`
},
{
filename: 'test.vue',
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
code: `
<template v-for="x in xs">
<template v-for="y in x.ys">
<li v-for="z in x.zs" :key="z.id">
123
</li>
</template>
</template>`
}

]
})