Vuejs将类绑定到行然后隐藏/显示行?
Posted
技术标签:
【中文标题】Vuejs将类绑定到行然后隐藏/显示行?【英文标题】:Vuejs bind class to row then later hide/show the row? 【发布时间】:2018-05-31 23:19:32 【问题描述】:我正在尝试创建一个表,用户可以在其中隐藏行,并在删除其他行时保持隐藏。
在我的html中,我在渲染表格时使用vuejs绑定一个类:
<tr v-for="item in mylist" :class="'noFruits': (item.fruits.length == 0)">
有一个用户复选框可以隐藏该类的行:
<label><input type="checkbox" v-model="showBlankFruits" @change="setBlankDisplay">Show Blank Fruits</label>
在我的 Vue 实例中,复选框执行一个方法来通过 jquery 隐藏/显示该类的行以附加 css 显示属性:
methods:
setBlankDisplay: function()
if (this.showBlankFruits)
$('.noFruits').css('display', '');
else
$('.noFruits').css('display', 'none');
,
在我的jsfiddle 中,当用户删除一行时,隐藏的行会重新出现。我看到在这种情况下使用 jquery 附加样式并不好......有人对更好的方法有建议吗?
【问题讨论】:
vuejs 中有用于类/样式绑定的组件。 vuejs.org/v2/guide/class-and-style.html 【参考方案1】:这是一个很好的例子,展示了声明式渲染的强大功能,而不是在组件中使用 DOM 操作。您遇到的问题是当 Vue 引擎重新呈现您的列表时,它不知道您在 setBlankDisplay
方法中对元素进行的手动操作。解决这个问题的方法是在视图本身的定义中使用组件逻辑,有点像您首先设置 noFruits
类。
所以,我建议你把setBlankDisplay
去掉,换成方法:
itemDisplay(item)
if (item.fruits.length === 0 && !this.showBlankFruits)
return 'none';
return '';
,
然后您可以在链接到 css display
属性的 tr
元素的定义中引用它,如下所示:
<tr v-for="item in mylist" :class="'noFruits': (item.fruits.length == 0)" :style="display: itemDisplay(item)">
我已经用这个修改更新了jsfiddle,显示当其他项目被删除时隐藏水果的状态仍然存在。
以此作为使用 jquery 更改视图状态的危险的一般示例。应尽一切努力根据组件逻辑定义整个视图。
【讨论】:
【参考方案2】:不建议混合使用 Vue 和 jQuery,因为您几乎可以使用 Vue 完成所有事情,而且您不会遇到任何不知道其他库/框架在做什么的冲突操作。
如果 fruits 数组长度为真,即不为 0,或者 showBlankFruits 为真,则以下将显示该行:
<tr v-for="item in mylist" v-show="item.fruits.length || showBlankFruits">
单击复选框时,以下内容将切换 showBlankFruits:
<label><input type="checkbox" v-model="showBlankFruits">Show Blank Fruits</label>
完整代码示例:
JSFiddle
【讨论】:
【参考方案3】:你也可以这样写。 我已经完全使用了计算并删除了 jQuery 部分。 您必须将数据声明为函数而不是数据对象 (https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function)
您不需要调用 mounted 方法来设置初始状态。它已经用你的数据对象设置好了。 在您的代码中,您必须调用mounted,因为jQuery 只能在加载DOM 时隐藏结果。
new Vue(
el: '#app',
data()
return
showBlankFruits: true,
mylist: [
'user': 'Alice', 'fruits': ['name': 'apple'],
'user': 'Bob', 'fruits': ['name': 'orange'],
'user': 'Charlie', 'fruits': [],
'user': 'Denise', 'fruits': ['name': 'apple', 'name': 'orange'],
]
,
computed:
list()
return this.mylist.filter(item => (item.fruits.length > 0 && !this.showBlankFruits) || (item.fruits.length === 0 && this.showBlankFruits))
,
,
methods:
delItem(item)
let index = this.mylist.indexOf(item);
if (index > -1)
this.mylist.splice(index, 1);
)
<script src="https://unpkg.com/vue"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="app">
<label><input type="checkbox" v-model="showBlankFruits">Show Blank Fruits</label>
<br> <br>
<table>
<tr> <th class="col">User</th> <th class="col">Fruits</th> <th class="col"></th> </tr>
<tr v-for="item in list">
<td> item.user </td>
<td> <span v-for="f in item.fruits"> f.name </span> </td>
<td> <button @click="delItem(item)">Delete</button> </td>
</tr>
</table>
</div>
【讨论】:
比起@cstricklan 解决方案中的样式绑定,我更喜欢这样做。使用计算过滤数据使组件更具可测试性。 数据必须成为组件的函数。据我所知,对于根 Vue 实例,不“推荐”它是任何地方的函数。事实上,文档会引导您使用来自 very beginning 的对象。 我写了“推荐”,因为在这个例子中他使用的是单个实例,它不会破坏应用程序。但你是对的!我会更新我的答案。 过滤条件可以简化,item.fruits.length || this.showBlankFruits
@LeeComstock 是的,你是对的,如果你想每次都显示完整的列表,无论是否有空水果。我坚持认为 Andrew 不能同时想要两者,因为复选框标签上写着“显示空白水果”而不是“显示空白水果”以上是关于Vuejs将类绑定到行然后隐藏/显示行?的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin 如何将类属性(来自另一个项目)绑定到 Picker.ItemDisplayBinding 属性