一个表单用于提交文本,两个选项告诉 vue 在哪一列中显示文本。当选中 col2 单选按钮时,提交的文本应显示在第 2 列中。这种情况不会发生,在第 1 列上显示文本。
我有两个单选按钮,应将值“一”或“二”传递给 newInfo.option 在 submnit 上,方法将表单数据推送到数组“info”。
<input type="radio" id="col1" value="one" v-model="newInfo.col">
<input type="radio" id="col2" value="two" v-model="newInfo.col">
此数据已正确推送到数组“info”,我可以迭代它。我知道这是有效的,因为我可以迭代数组,一个控制台,记录其中的所有数据。所有提交的表单数据都在那里。
接下来我在模板中迭代该数组两次。一次用于 info.col==="one",另一次迭代仅应在 info.col==="two" 时显示。我同时使用 v-for 和 v-if,vue.js 文档说可以这样做,
https://v2.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 这里
它正在 gh-pages 上运行here
来自 Vue 文档:
当它们存在于同一节点时,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 中保留为“display:none”您可以将 v-show 与 v-for 结合使用。
您还可以在模板中使用 JavaScript 来过滤 v-for 的数组元素。您可以将信息数组缩小到
v-for="item in infos"
,而不是 v-for="item in infos.filter(info => info.col === 'one')"
。
由于在回调中使用了 info,因此我将您的信息数组重命名为 infos 以提高我的建议的可读性。
<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 infos.filter(({ col }) => col === 'two')">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
<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-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>
如果由于某种原因无法过滤列表,您可以将同时具有
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>'
})
已计算
在大多数情况下,
computed
属性确实是最好的方法,就像DobleL所说的那样,但在我自己的情况下,我在另一个v-for
中有一个v-for
,所以计算出来的没有意义对于第二个 v-for。
V秀
因此,与其使用优先级高于
v-if
的v-for
(如Mithsew所述),另一种选择是使用没有更高优先级的v-show
。
它基本上具有相同的功能,并且适用于您的情况。
无包装
使用
v-show
可以避免添加无用的包装元素,就像我在一些答案中看到的那样,在我的例子中,这是避免弄乱 CSS 选择器和 html 结构的要求。
v-show 的缺点
使用
v-show
的唯一缺点是该元素仍会添加到 HTML 中,例如,在我自己的情况下,这仍然会弄乱 CSS :first 选择器。所以我个人实际上选择了 inTheFlow提到的
.filter()
解决方案。但在大多数基本情况下,你绝对可以使用v-show
来解决这个问题。
<div class="row">
<div class="col-md-6">
<ol>
<li v-for="item in info" v-show="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-show="item.col!=='two'">
text: {{ item.text }}, col: {{ item.col }}
</li>
</ol>
</div>
</div>
如果您好奇为什么我要在另一个
v-for
中使用 v-for
,这里是我的用例的精简版本:
它是一个对话列表(这是一个计算属性),然后显示每个对话中所有参与者的头像,但当前正在查看它的用户的头像除外。
<a v-for="convo in filteredConversations" class="card">
<div class="card-body">
<div class="row">
<div class="col-auto">
<div class="avatar-group">
<div class="avatar" v-for="participant in convo.participants.filter(info => !thatsMe(info))">
<img :src="userAvatarUrl(participant)" :alt="participant.name" class="avatar-img">
</div>
</div>
</div> ...
您的第二个检查是
!item.col==='two'
,并且只有在 not 等于“二”时才会显示。
编辑:! not 运算符可能比 === 绑定更紧密,因此总是返回 false。添加括号来控制应用顺序。我说可能是因为这可能是我不熟悉的 Vue 魔法,而不是纯粹的 JavaScript 表达式。
我想你想删除那个感叹号。或者使其
!(item.col==='one')
显示“one”以外的任何值。
对我来说,最好的选择是使用过滤器。
<div v-for="target in targets.filter((target) => target.zone_id == zone.id)">
{{ target.id}}
</div>