v-for 和 v-if 在 vue.js 中不能协同工作
v-for and v-if not working together in vue.js
一个表单用于提交文本和两个选项,告诉 vue 在哪一列显示文本。选中 col2 单选按钮时,提交的文本应显示在第 2 列。这不会发生在第 1 列正在显示文字。
我有两个单选按钮,它们应该将值 'one' 或 'two' 传递给 newInfo.option 在提交时,一个方法将表单数据推送到数组 'info'。
<input type="radio" id="col1" value="one" v-model="newInfo.col">
<input type="radio" id="col2" value="two" v-model="newInfo.col">
此数据已正确推送到数组 'info',我可以遍历它。我知道这是有效的,因为我可以遍历数组,console.log 中的所有数据。所有提交的表单数据都在那里。
接下来我在模板中遍历这个数组两次。一次用于 info.col==="one",另一次迭代应仅在 info.col==="two" 时显示。我同时使用 v-for 和 v-if,vue.js 文档说可以这样做,
https://vuejs.org/v2/guide/conditional.html#v-if-with-v-for
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in info" v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info" v-if="!item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
完整的 vue.js 代码在 github here
在 gh-pages here
上是 运行
您的第二次检查是 !item.col==='two'
,只有当它 不 等于 'two'.
时才会显示
编辑:! not 运算符可能比 === 绑定得更紧密,所以它总是 return false。添加括号以控制应用程序的顺序。我说可能是因为它可能有点我不熟悉的 Vue 魔法,而不是纯粹的 JavaScript 表达式。
我想你想删除那个感叹号。或者使其 !(item.col==='one')
显示 'one'.
以外的任何值
如果 v-if="item.col==='two'"
从第二个开始删除 !
你最好这样做(只迭代一次):
<div class="row" v-for="item in info">
<div class="col-md-6">
<ol>
<li v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-if="item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
为什么不用Computed Properties的力量?
computed: {
infoOne: function () {
return this.info.filter(i => i.col === 'one')
},
infoTwo: function () {
return this.info.filter(i => i.col === 'two')
}
}
然后在每个列表上只遍历其各自的 属性 而无需检查。例子
<ol>
<li v-for="item in infoOne">{{item}}</li>
</ol>
这里是工作fiddle
<div v-for="item in items">
<div v-if="checkThis(item.computeThisProperty)" />
<div v-else />
</div>
methods: {
checkThis(i) {
return this[i];
}
},
computed: {
myComputedProperty() {
return this.$store.state.something ? true : false;
}
}
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in info">
<template v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
<template>
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info">
<template v-if="!item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
<template>
</li>
</ol>
</div>
</div>
如果出于某种原因无法过滤列表,您可以将同时具有 v-for
和 v-if
的元素转换为组件并将 v-if
移至组件。
原始示例
原始循环
<li v-for="item in info" v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
建议重构
重构循环
<custom-li v-for="item in info" :visible="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</custom-li>
新组件
Vue.component('custom-li', {
props: ['visible'],
template: '<li v-if="visible"><slot/></li>'
})
来自Vue docs:
存在于同一个节点时,v-if优先级高于
v-for。这意味着 v-if 条件将无法访问变量
从v-for的范围:
<!--
This will throw an error because property "todo"
is not defined on instance.
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
这可以通过将 v-for 移动到包装标签(
也更明确):
<template v-for="todo in todos">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
如果您不介意在 html 中使用“显示:none”继续您的视图 您可以将 v-show 与 [=28= 一起使用]没有任何问题。
您也可以在模板中使用 JavaScript 来过滤 v-for 的数组元素。您可以将 info-array 缩小为 v-for="item in infos.filter(info => info.col === 'one')"
。
,而不是 v-for="item in infos"
我将你的 info-array 重命名为 infos 以提高我的建议的可读性,因为在回调中使用了 info。
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in infos.filter(info => info.col === 'one')">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info.filter(info => info.col === 'two')">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
一个表单用于提交文本和两个选项,告诉 vue 在哪一列显示文本。选中 col2 单选按钮时,提交的文本应显示在第 2 列。这不会发生在第 1 列正在显示文字。
我有两个单选按钮,它们应该将值 'one' 或 'two' 传递给 newInfo.option 在提交时,一个方法将表单数据推送到数组 'info'。
<input type="radio" id="col1" value="one" v-model="newInfo.col">
<input type="radio" id="col2" value="two" v-model="newInfo.col">
此数据已正确推送到数组 'info',我可以遍历它。我知道这是有效的,因为我可以遍历数组,console.log 中的所有数据。所有提交的表单数据都在那里。
接下来我在模板中遍历这个数组两次。一次用于 info.col==="one",另一次迭代应仅在 info.col==="two" 时显示。我同时使用 v-for 和 v-if,vue.js 文档说可以这样做,
https://vuejs.org/v2/guide/conditional.html#v-if-with-v-for
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in info" v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info" v-if="!item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
完整的 vue.js 代码在 github here
在 gh-pages here
上是 运行您的第二次检查是 !item.col==='two'
,只有当它 不 等于 'two'.
编辑:! not 运算符可能比 === 绑定得更紧密,所以它总是 return false。添加括号以控制应用程序的顺序。我说可能是因为它可能有点我不熟悉的 Vue 魔法,而不是纯粹的 JavaScript 表达式。
我想你想删除那个感叹号。或者使其 !(item.col==='one')
显示 'one'.
如果 v-if="item.col==='two'"
!
你最好这样做(只迭代一次):
<div class="row" v-for="item in info">
<div class="col-md-6">
<ol>
<li v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-if="item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
为什么不用Computed Properties的力量?
computed: {
infoOne: function () {
return this.info.filter(i => i.col === 'one')
},
infoTwo: function () {
return this.info.filter(i => i.col === 'two')
}
}
然后在每个列表上只遍历其各自的 属性 而无需检查。例子
<ol>
<li v-for="item in infoOne">{{item}}</li>
</ol>
这里是工作fiddle
<div v-for="item in items">
<div v-if="checkThis(item.computeThisProperty)" />
<div v-else />
</div>
methods: {
checkThis(i) {
return this[i];
}
},
computed: {
myComputedProperty() {
return this.$store.state.something ? true : false;
}
}
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in info">
<template v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
<template>
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info">
<template v-if="!item.col==='two'">
text: {{ item.text }}, col: {{ item.col }}
<template>
</li>
</ol>
</div>
</div>
如果出于某种原因无法过滤列表,您可以将同时具有 v-for
和 v-if
的元素转换为组件并将 v-if
移至组件。
原始示例
原始循环
<li v-for="item in info" v-if="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</li>
建议重构
重构循环
<custom-li v-for="item in info" :visible="item.col==='one'">
text: {{ item.text }}, col: {{ item.col }}
</custom-li>
新组件
Vue.component('custom-li', {
props: ['visible'],
template: '<li v-if="visible"><slot/></li>'
})
来自Vue docs:
存在于同一个节点时,v-if优先级高于 v-for。这意味着 v-if 条件将无法访问变量 从v-for的范围:
<!--
This will throw an error because property "todo"
is not defined on instance.
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
这可以通过将 v-for 移动到包装标签( 也更明确):
<template v-for="todo in todos">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
如果您不介意在 html 中使用“显示:none”继续您的视图 您可以将 v-show 与 [=28= 一起使用]没有任何问题。
您也可以在模板中使用 JavaScript 来过滤 v-for 的数组元素。您可以将 info-array 缩小为 v-for="item in infos.filter(info => info.col === 'one')"
。
v-for="item in infos"
我将你的 info-array 重命名为 infos 以提高我的建议的可读性,因为在回调中使用了 info。
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in infos.filter(info => info.col === 'one')">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
<div class="col-md-6">
<ol>
<li v-for="item in info.filter(info => info.col === 'two')">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>