Skip to content

Commit e77081d

Browse files
authored
Fixed no-use-v-if-with-v-for error when using destructuring for iteration or using iteration of expression (#1071)
1 parent ab3bf36 commit e77081d

File tree

2 files changed

+124
-4
lines changed

2 files changed

+124
-4
lines changed

lib/rules/no-use-v-if-with-v-for.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function getVForUsingIterationVar (vIf) {
3737
variable.kind === 'v-for'
3838
)
3939
if (targetVFor) {
40-
return targetVFor.id.parent
40+
return targetVFor
4141
}
4242
}
4343
return undefined
@@ -76,13 +76,20 @@ module.exports = {
7676
if (utils.hasDirective(element, 'for')) {
7777
if (isUsingIterationVar(node)) {
7878
if (!allowUsingIterationVar) {
79-
const vFor = getVForUsingIterationVar(node)
79+
const vForVar = getVForUsingIterationVar(node)
80+
81+
let targetVForExpr = vForVar.id.parent
82+
while (targetVForExpr.type !== 'VForExpression') {
83+
targetVForExpr = targetVForExpr.parent
84+
}
85+
const iteratorNode = targetVForExpr.right
8086
context.report({
8187
node,
8288
loc: node.loc,
83-
message: "The '{{iteratorName}}' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
89+
message: "The '{{iteratorName}}' {{kind}} inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
8490
data: {
85-
iteratorName: vFor.right.name
91+
iteratorName: iteratorNode.type === 'Identifier' ? iteratorNode.name : context.getSourceCode().getText(iteratorNode),
92+
kind: iteratorNode.type === 'Identifier' ? 'variable' : 'expression'
8693
}
8794
})
8895
}

tests/lib/rules/no-use-v-if-with-v-for.js

+113
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,55 @@ tester.run('no-use-v-if-with-v-for', rule, {
7373
</ul>
7474
</template>
7575
`
76+
},
77+
{
78+
filename: 'test.vue',
79+
code: '<template><div><div v-for="{x} in list" v-if="x"></div></div></template>',
80+
options: [{ allowUsingIterationVar: true }]
81+
},
82+
{
83+
filename: 'test.vue',
84+
code: '<template><div><div v-for="{x,y,z} in list" v-if="y.foo"></div></div></template>',
85+
options: [{ allowUsingIterationVar: true }]
86+
},
87+
{
88+
filename: 'test.vue',
89+
code: '<template><div><div v-for="({x,y,z},i) in list" v-if="i%2==0"></div></div></template>',
90+
options: [{ allowUsingIterationVar: true }]
91+
},
92+
{
93+
filename: 'test.vue',
94+
code: '<template><div v-if="shown"><div v-for="({x,y,z},i) in list"></div></div></template>'
95+
},
96+
{
97+
filename: 'test.vue',
98+
code: `
99+
<template>
100+
<ul>
101+
<li
102+
v-for="{user} in activeUsers"
103+
:key="user.id"
104+
>
105+
{{ user.name }}
106+
<li>
107+
</ul>
108+
</template>
109+
`
110+
},
111+
{
112+
filename: 'test.vue',
113+
code: `
114+
<template>
115+
<ul v-if="shouldShowUsers">
116+
<li
117+
v-for="{user} in users"
118+
:key="user.id"
119+
>
120+
{{ user.name }}
121+
<li>
122+
</ul>
123+
</template>
124+
`
76125
}
77126
],
78127
invalid: [
@@ -139,6 +188,70 @@ tester.run('no-use-v-if-with-v-for', rule, {
139188
message: "This 'v-if' should be moved to the wrapper element.",
140189
line: 6
141190
}]
191+
},
192+
{
193+
filename: 'test.vue',
194+
code: '<template><div><div v-for="{x,y,z} in list" v-if="z.isActive"></div></div></template>',
195+
errors: [{
196+
message: "The 'list' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
197+
line: 1
198+
}]
199+
},
200+
{
201+
filename: 'test.vue',
202+
code: `
203+
<template>
204+
<ul>
205+
<li
206+
v-for="{foo, bar, user} in users"
207+
v-if="user.isActive"
208+
:key="user.id"
209+
>
210+
{{ user.name }}
211+
<li>
212+
</ul>
213+
</template>
214+
`,
215+
errors: [{
216+
message: "The 'users' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
217+
line: 6
218+
}]
219+
},
220+
{
221+
filename: 'test.vue',
222+
code: `
223+
<template>
224+
<ul>
225+
<li
226+
v-for="{foo, bar, user} in users"
227+
v-if="shouldShowUsers"
228+
:key="user.id"
229+
>
230+
{{ user.name }}
231+
<li>
232+
</ul>
233+
</template>
234+
`,
235+
errors: [{
236+
message: "This 'v-if' should be moved to the wrapper element.",
237+
line: 6
238+
}]
239+
},
240+
{
241+
filename: 'test.vue',
242+
code: '<template><div><div v-for="{x} in list()" v-if="x.isActive"></div></div></template>',
243+
errors: [{
244+
message: "The 'list()' expression inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
245+
line: 1
246+
}]
247+
},
248+
{
249+
filename: 'test.vue',
250+
code: '<template><div><div v-for="i in 5" v-if="i"></div></div></template>',
251+
errors: [{
252+
message: "The '5' expression inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.",
253+
line: 1
254+
}]
142255
}
143256
]
144257
})

0 commit comments

Comments
 (0)