计算数据更改时,Vue不会更新

时间:2017-11-23 09:00:41

标签: wordpress vue.js vuejs2

上下文:我有一个带有标签的帖子列表,来自wordpress api的类别。我使用Vue显示这些帖子,并使用带有搜索框的computed根据效果,说明,标签和类别过滤结果

问题:当用户点击可用标记列表时,我正在尝试更新computed列表。我为get数据添加setcomputed,如下所示:

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.

3 个答案:

答案 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,否则您的计算变量不需要getset函数。您可以通过以下方式实现您想要的行为:

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中的searchdata变量,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数据,请告诉我。

&#13;
&#13;
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;
&#13;
&#13;

相关问题