vue.js - VueJS - 数据更改后选择列表不更新
问题描述
我开始使用 Vuejs,但我很难做一些我认为简单的事情。总而言之,我有一个过滤器列表,其中包含有关过滤器的所有信息(名称、可供选择的项目、选择的女巫项目以及是否选择了过滤器)。在我的页面中,我有一个表格,列出了所有选择的过滤器和下拉列表,其余的过滤器未选择。
为了干净,我在计算部分有两种方法:
- filtersSelected(返回所有“isSelected”为真的过滤器)
- filtersNoSelected(返回所有带有“isSelected”的过滤器为假)
Vue.component('filter-item', {
props: ['filter'],
template:
'<tr>' +
'<th scope="row">{{ filter.id }}</th>' +
'<td>' +
'{{ filter.name }}' +
'</td>' +
'<td>' +
'<button type="button" class="btn btn-sm btn-info">></button>' +
'</td>' +
'<td>' +
'<button type="button" class="btn btn-sm btn-danger" v-on:click="$emit(\'remove\', filter)">X</button>' +
'</td>' +
'</tr>'
})
Vue.component('filter-panel', {
props: ['allfilters'],
data: function () {
return {
filters: this.allfilters
}
},
methods: {
removeFilter: function (filter) {
filter.isSelected = false;
}
},
template:
'<table class="table table-sm">' +
'<thead>' +
'<tr>' +
'<th scope="col">#</th>' +
'<th scope="col">Name</th>' +
'<th scope="col">Update</th>' +
'<th scope="col">Delete</th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'<filter-item v-for="filter in filters" v-bind:key="filter.id" v-bind:filter="filter" @remove="removeFilter">' +
'</filter-item>' +
'</tbody>' +
'</table>'
})
Vue.component('filter-select', {
props: ['allfilters'],
data: function () {
return {
selectedItem: 0,
filters: this.allfilters
}
},
methods: {
},
template:
'<div><select class="selectpicker" data-live-search="true" v-model="selectedItem" v-on:change="$emit(\'selected\', selectedItem)"> ' +
'<option disabled value="0" selected>Select</option>' +
'<option v-for="filter in filters" v-bind:key="filter.id" v-bind:value="filter.id">{{ filter.name }}' +
'</option>' +
'</select>' +
'<span>{{selectedItem}}</span></div>'
})
var app = new Vue({
el: '#app',
data: {
filters:
[
{
id: 1,
name: "Country",
type: "List",
isSelected: false,
listItem: [
{
value: "1",
text: "France"
},
{
value: "2",
text: "United States"
},
{
value: "3",
text: "China"
}
],
selectedItem: ["1", "3"]
},
{
id: 2,
name: "Product category",
type: "List",
isSelected: false,
listItem: [
{
value: "1",
text: "Food"
},
{
value: "2",
text: "Drink"
},
{
value: "3",
text: "Home"
}
],
selectedItem: ["1"]
}
],
filterSelected: 2
},
methods:
{
AddFilter: function (filterId) {
var filter = this.filters.find(function (f) { return f.id === filterId });
filter.isSelected = true;
$('#FilterModal').modal('hide');
}
},
computed:
{
filtersSelected: function () {
var list = this.filters.filter(function (f) { return f.isSelected });
return list;
},
filtersNoSelected: function () {
var list = this.filters.filter(function (f) { return !f.isSelected });
return list;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<filter-panel v-bind:allfilters="filtersSelected"></filter-panel>
<filter-select v-bind:allfilters="filtersNoSelected" v-on:selected="filterSelected = $event"></filter-select>
<button type="button" class="btn btn-primary" v-on:click="AddFilter(filterSelected)">Add the filter</button>
所以逻辑很简单,当我们选择一个过滤器并单击添加按钮时,该方法会将“isSelected”设置为true。如果我们单击删除,该方法会将“isSelected”设置为 false。之后,计算方法将与我的组件共享过滤列表。但它不起作用。
我在浏览器中一步一步检查逻辑,我们通过计算方法,计算方法每次发送不同的列表,但我的页面没有变化。
我尝试了另一种解决方案,将所有列表共享到我的组件并添加“v-if”或“v-show”,但它仅适用于表格,不适用于下拉列表。此外,我不喜欢这个解决方案。
对于我在这个论坛上阅读的所有帖子,我还没有找到解决问题的方法。(在 v-for 中使用键或使用反应性)
因为我正处于学习阶段,所以我想知道什么是好的方法。我想使用最佳实践!
提前感谢您的帮助!
解决方案
我遇到了类似的问题。这也可能对您的情况有所帮助。当您在其中使用数组或对象时data
,如果您更改该数组/对象中的数据,则 Vue 无法识别它。
Vue 可以识别您是否将某些数据推送到数组中并重新渲染组件,但如果某些嵌套数据发生更改,它就无法做到这一点。
我们lodash.cloneDeep()
在项目中使用来克服这个问题。
突变应该在新副本上执行,你可以尝试这样的事情:
AddFilter: function (filterId) {
var index = this.filters.findIndex(function (f) { return f.id === filterId });
let newFilters = _.cloneDeep(this.filters);
newFilters[index].isSelected = true;
this.filters = newFilters;
$('#FilterModal').modal('hide');
}
这个概念类似于 react 中的 state,你不应该直接改变 state(它的相似性不完全相同)
您可以在Official docs中阅读它,这表明
对象必须是普通的
推荐阅读
- c++ - 没有 void_t 的 SFINAE(可能是模板专业化问题)
- python - BeautifulSoup 不采用完整的 HTML 代码
- c++ - 将音频流写入循环缓冲区但分段错误读取值
- button - 单击按钮时打印图像
- android - 如何在 android 中使用 onSelectedDayChange() 为 CalendarView 显示月份名称
- swift - 结构体的 Swift 枚举
- .net - 从 Xamarin 项目中的文件夹中获取所有对象
- python - 如何在OpenCV中合并两个不同颜色的位掩码
- react-native - 如何在 React Native 中使用 AsyncStorage 数据更新状态挂钩?
- hadoop - 是否可以将 orc 托管表位置或文件用于外部表?