上下文:我有一个带有标签的帖子列表,来自wordpress api的类别。 我用Vue显示这些帖子,并使用computed与搜索框根据滴定,描述,标记和类别过滤结果
问题:我正尝试在用户点击可用标签列表时更新computed列表。 我为这样的computed数据添加get和set :
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 instanceconsole.log总是根据我在methods上写的函数输出新的数据,但Vue没有重新渲染视图。 我认为我没有做正确的方式,或者像Vue一样思考。 你能否提供一些见解?
编辑1添加完整代码。
我试图在data添加filterPosts但是我从Vue收到了这个错误: The computed property "filterPosts" is already defined in data.
Context: I have a list of posts with tags, categories from wordpress api. I display these posts with Vue and using computed with a search box to filter the result based on titre, description, tags, and categories
Problem: I am trying to update a computed list when user click on a list of tag available. I add the get and set for computed data like this:
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 instanceThe console.log always output new data based on the function I wrote on methods but Vue didn't re-render the view. I think I didn't do the right way or thought like Vue. Could you please give some insight?
Edit 1 Add full code.
I tried to add filterPosts in data but I received this error from Vue: The computed property "filterPosts" is already defined in data.
最满意答案
你的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); }, }, },底线是你必须触发setter中的数据更改,否则你的组件将不会更新,也不会触发任何重新渲染。
编辑(原始答案更新完整代码):
答案是,除非您想手动更改列表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变量, filteredPosts将得到重新计算,并且重新呈现将被触发。
After going around and around, I found a solution, I think it may be the right way with Vue now: Update the computed data through its dependencies properties or data.
The set method didn't work for this case so I add an activeTag in data, when I click on a tag, it will change the activeTag and notify the computed filterPost recheck and re-render. Please tell me if we have another way to update the computed data.
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
更多推荐
发布评论