Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 85137c9

Browse files
HerringtonDarkholmemysticatea
authored andcommitted
Fix: polish template v-for error report (fixes #164)(#168)
* polish template v-for error report Fix #164, don't report error when nested v-for refers iterator. Do report error when nested v-for doesn't refer iterator. * update jsdoc * check iterator usage in new way * add more test cases * fix code style * cosmetic indentation
1 parent a73f5e2 commit 85137c9

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

‎lib/rules/valid-v-for.js‎

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ function isUsingIterationVar (vFor, vBindKey) {
2727
}
2828
const references = vBindKey.value.references
2929
const variables = vFor.parent.parent.variables
30-
3130
return references.some(reference =>
3231
variables.some(variable =>
3332
variable.id.name === reference.id.name &&
@@ -36,6 +35,34 @@ function isUsingIterationVar (vFor, vBindKey) {
3635
)
3736
}
3837

38+
/**
39+
* Check the child element in tempalte v-for about `v-bind:key` attributes.
40+
* @param {RuleContext} context The rule context to report.
41+
* @param {ASTNode} vFor The attribute node of `v-for` to check.
42+
* @param {ASTNode} child The child node to check.
43+
*/
44+
function checkChildKey (context, vFor, child) {
45+
const childFor = utils.getDirective(child, 'for')
46+
// if child has v-for, check if parent iterator is used in v-for
47+
if (childFor != null) {
48+
const childForRefs = childFor.value.references
49+
const variables = vFor.parent.parent.variables
50+
const usedInFor = childForRefs.some(cref =>
51+
variables.some(variable =>
52+
cref.id.name === variable.id.name &&
53+
variable.kind === 'v-for'
54+
)
55+
)
56+
// if parent iterator is used, skip other checks
57+
// iterator usage will be checked later by child v-for
58+
if (usedInFor) {
59+
return
60+
}
61+
}
62+
// otherwise, check if parent iterator is directly used in child's key
63+
checkKey(context, vFor, child)
64+
}
65+
3966
/**
4067
* Check the given element about `v-bind:key` attributes.
4168
* @param {RuleContext} context The rule context to report.
@@ -46,7 +73,7 @@ function checkKey (context, vFor, element) {
4673
if (element.name === 'template') {
4774
for (const child of element.children) {
4875
if (child.type === 'VElement') {
49-
checkKey(context, vFor, child)
76+
checkChildKey(context, vFor, child)
5077
}
5178
}
5279
return

‎tests/lib/rules/valid-v-for.js‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,32 @@ tester.run('valid-v-for', rule, {
8282
{
8383
filename: 'test.vue',
8484
code: '<template v-for="x of list">foo<div></div></template>'
85+
},
86+
{
87+
filename: 'test.vue',
88+
code: '<template><div><template v-for="x of list"><div v-for="foo of x" :key="foo"></div></template></div></template>'
89+
},
90+
{
91+
filename: 'test.vue',
92+
code: `
93+
<template v-for="x in xs">
94+
<template v-for="y in x.ys">
95+
<li v-for="z in y.zs" :key="z.id">
96+
123
97+
</li>
98+
</template>
99+
</template>`
100+
},
101+
{
102+
filename: 'test.vue',
103+
code: `
104+
<template v-for="x in xs">
105+
<template v-for="y in ys">
106+
<li v-for="z in zs" :key="x.id + y.id + z.id">
107+
123
108+
</li>
109+
</template>
110+
</template>`
85111
}
86112
],
87113
invalid: [
@@ -179,6 +205,48 @@ tester.run('valid-v-for', rule, {
179205
filename: 'test.vue',
180206
code: '<template><div><template v-for="xin list"><div></div></template></div></template>',
181207
errors: ["'v-for' directives require that attribute value."]
208+
},
209+
{
210+
filename: 'test.vue',
211+
code: '<template><div><template v-for="x of list"><div v-for="foo of y" :key="foo"></div></template></div></template>',
212+
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."]
213+
},
214+
{
215+
filename: 'test.vue',
216+
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
217+
code: `
218+
<template v-for="x in xs">
219+
<template v-for="y in a.ys">
220+
<li v-for="z in y.zs" :key="z.id">
221+
123
222+
</li>
223+
</template>
224+
</template>`
225+
},
226+
{
227+
filename: 'test.vue',
228+
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
229+
code: `
230+
<template v-for="x in xs">
231+
<template v-for="y in x.ys">
232+
<li v-for="z in a.zs" :key="z.id">
233+
123
234+
</li>
235+
</template>
236+
</template>`
237+
},
238+
{
239+
filename: 'test.vue',
240+
errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
241+
code: `
242+
<template v-for="x in xs">
243+
<template v-for="y in x.ys">
244+
<li v-for="z in x.zs" :key="z.id">
245+
123
246+
</li>
247+
</template>
248+
</template>`
182249
}
250+
183251
]
184252
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /