上下文:我有一个带有标签的帖子列表,来自wordpress api的类别。我使用Vue
显示这些帖子,并使用带有搜索框的computed
根据效果,说明,标签和类别过滤结果
问题:当用户点击可用标记列表时,我正在尝试更新computed
列表。我为get
数据添加set
和computed
,如下所示:
var vm = new Vue({
el: '#blogs',
data: {
search: '',
posts: [],
filterPosts: []
},
beforeMount: function() {
// It should call the data and update
callData();
},
computed: {
filterPosts: {
get: function() {
var self = this;
return self.posts.filter(function(post){
var query = self.search.toLowerCase();
var title = post.title.toLowerCase();
var content = post.content.toLowerCase();
var date = post.date.toLowerCase();
var categories = '';
post.categories.forEach(function(category) {
categories += category.name.toLowerCase();
});
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
return title.indexOf(query) !== -1 ||content.indexOf(query) !== -1 || date.indexOf(query) !== -1 || categories.indexOf(query) !== -1 || tags.indexOf(query) !== -1;
});
},
set: function (newValue) {
console.log(newValue);
this.filterPosts = Object.assign({}, newValue);
}
}
},
methods: {
filterByTag: function(tag, event) {
event.preventDefault();
var self = this;
self.filterPosts = self.posts.filter(function(post){
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
return tags.indexOf(tag.toLowerCase()) !== -1;
});
}
}
}); // Vue instance
console.log
总是根据我在methods
上写的函数输出新数据,但Vue
没有重新渲染视图。我想我没有采取正确的方式或想法Vue
。你能提供一些见解吗?
修改1 添加完整代码。
我尝试在filterPosts
中添加data
,但我从Vue收到此错误:The computed property "filterPosts" is already defined in data.
答案 0 :(得分:1)
你的setter实际上没有设置任何东西,它只记录新值。你需要把它存放在某个地方。
例如,您可以将其存储在组件的数据中:
data: {
value: 'foo',
},
computed: {
otherValue: {
get() { /*...*/ },
set(newVal) { this.value = newVal },
},
},
但这绝对不是唯一的可能性,如果你使用Vuex,setter可以调度一个动作然后使计算值得到更新。该组件最终将捕获更新并显示新值。
computed: {
value: {
get() {
return this.$store.getters.externalData;
},
set(newVal) {
return this.$store.dispatch('modifyingAction', newVal);
},
},
},
底线是您必须在设置器中触发数据更改,否则您的组件将不会更新,也不会触发任何重新渲染。
编辑(原始答案已更新为完整代码):
答案是,除非您想在不改变filteredPosts
的情况下手动更改列表posts
,否则您的计算变量不需要get
和set
函数。您可以通过以下方式实现您想要的行为:
const vm = new Vue({
data() {
return {
search: '',
posts: [],
// these should probably be props, or you won't be able to edit the list easily. The result is the same anyway.
};
},
computed: {
filteredPosts() {
return this.posts.filter(function(post) {
... // do the filtering
});
},
},
template: "<ul><li v-for='post in filteredPosts'>{{ post.content }}</li></ul>",
});
这样,如果您更改posts
中的search
或data
变量,filteredPosts
将重新计算,并会触发重新渲染。
答案 1 :(得分:0)
尝试类似:
data: {
myValue: 'OK'
},
computed: {
filterPosts: {
get: function () {
return this.myValue + ' is OK'
}
set: function (newValue) {
this.myValue = newValue
}
}
}
更多: https://vuejs.org/v2/guide/computed.html#Computed-Setter
答案 2 :(得分:0)
在四处走动之后,我找到了一个解决方案,我认为它现在可能是Vue的正确方法:通过其依赖属性或数据更新计算数据。
set
方法对于这种情况不起作用,因此我在activeTag
中添加data
,当我点击标记时,它会更改activeTag
并通知计算出的filterPost
重新检查并重新渲染。如果我们有其他方式更新computed
数据,请告诉我。
var vm = new Vue({
el: '#blogs',
data: {
search: '',
posts: [],
tags: [],
activeTag: ''
},
beforeMount: function() {
// It should call the data and update
callData();
},
computed: {
filterPosts: {
get: function() {
var self = this;
return self.posts.filter(function(post){
var query = self.search.toLowerCase();
var title = post.title.toLowerCase();
var content = post.content.toLowerCase();
var date = post.date.toLowerCase();
var categories = '';
post.categories.forEach(function(category) {
categories += category.name.toLowerCase();
});
var tags = '';
post.tags.forEach(function(tag){
tags += tag.name.toLowerCase();
});
var activeTag = self.activeTag;
if (activeTag !== '') {
return tags.indexOf(activeTag.toLowerCase()) !== -1;
}else{
return title.indexOf(query) !== -1 ||content.indexOf(query) !== -1 || date.indexOf(query) !== -1 || categories.indexOf(query) !== -1 || tags.indexOf(query) !== -1;
}
});
},
set: function (newValue) {
console.log(newValue);
}
}
},
methods: {
filterByTag: function(tag, event) {
event.preventDefault();
var self = this;
self.activeTag = tag;
}
}
}); // Vue instance
&#13;