diff --git a/lib/rules/valid-v-for.js b/lib/rules/valid-v-for.js
index 47d8f5029..8e20f9e66 100644
--- a/lib/rules/valid-v-for.js
+++ b/lib/rules/valid-v-for.js
@@ -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 &&
@@ -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.
@@ -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
diff --git a/tests/lib/rules/valid-v-for.js b/tests/lib/rules/valid-v-for.js
index e3da7c5ed..6fe1f0f1c 100644
--- a/tests/lib/rules/valid-v-for.js
+++ b/tests/lib/rules/valid-v-for.js
@@ -82,6 +82,32 @@ tester.run('valid-v-for', rule, {
{
filename: 'test.vue',
code: 'foo'
+ },
+ {
+ filename: 'test.vue',
+ code: ''
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ 123
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ 123
+
+
+ `
}
],
invalid: [
@@ -179,6 +205,48 @@ tester.run('valid-v-for', rule, {
filename: 'test.vue',
code: '',
errors: ["'v-for' directives require that attribute value."]
+ },
+ {
+ filename: 'test.vue',
+ code: '',
+ 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: `
+
+
+
+ 123
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
+ code: `
+
+
+
+ 123
+
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ errors: ["Expected 'v-bind:key' directive to use the variables which are defined by the 'v-for' directive."],
+ code: `
+
+
+
+ 123
+
+
+ `
}
+
]
})