【问题标题】:When is a computed property not reactive?计算属性何时不是反应性的?
【发布时间】:2020-05-07 12:12:54
【问题描述】:

我有一个 Vue 页面,它从外部 JSON 源收集信息,然后使用它来计算属性。

问题:此属性不是反应性的(= 当基础数据更改时不会重新计算)

<div id="app">
    <div v-for="tag in filteredTags">{{tag}}</div>
</div>

<script>
new Vue({
    el: "#app",
    data: {
        tags: {},
        allTags: {},
    },
    computed: {
        // provides an Array of tags which are selected
        filteredTags() {
            let t = Object.keys(this.allTags).filter(x => this.allTags[x])
            console.log(t)
            return t
        }
    },
    mounted() {
        // get source tags
        fetch("tags.json")
        .then(r => r.json())
        .then(r => {
            this.tags = r
            console.log(JSON.stringify(this.tags))
            // bootstrap a tags reference where all the tags are selected
            Object.keys(this.tags).forEach(t => {
                this.allTags[t] = true
            });
            console.log(JSON.stringify(this.allTags))
        })
    }
})
</script>

提取的文件({"tag1":["/posts/premier/"],"post":["/posts/premier/","/posts/second/"]})在mounted()中正确处理,控制台输出为

{"tag1":["/posts/premier/"],"post":["/posts/premier/","/posts/second/"]}
{"tag1":true,"post":true}

filteredTags 是空的。在控制台上,我看到它在页面处理开始时显示(如[]),最初很好(第一次计算,当allTags 为空时),但当@987654328 时不再计算@ 更改(在 tags.json 被提取、处理和 allTags 正确更新之后)。

为什么这不是反应式的?

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    当对象被添加到data时,Vue 不会响应不存在的属性

    由于您的 tagallTags 是没有属性的空对象(还没有),因此添加的任何属性都不会自动响应。

    要解决这个问题,您必须使用 Vue 提供的 Vue.Setthis.$set 函数。 Set 函数接受值 this.$set(object, key, value)

    new Vue({
      el: "#app",
      data: {
        tags: {},
        allTags: {},
      },
      computed: {
        // provides an Array of tags which are selected
        filteredTags() {
          let t = Object.keys(this.allTags).filter(x => this.allTags[x])
          return t
        }
      },
      mounted() {
        const r = '{"tag1":["/posts/premier/"],"post":["/posts/premier/","/posts/second/"]}';
        const rJson = JSON.parse(r);
        // You shouldn't need to use $set here as you replace the entire object, instead of adding properties
        this.tags = rJson;
        
        Object.keys(this.tags).forEach(t => {
          // Change this
          //this.allTags[t] = true;
          
          // To this
          this.$set(this.allTags, t, true);
        });
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
    
    <div id="app">
      <div v-for="tag in filteredTags">{{tag}}</div>
    </div>

    【讨论】:

    • 谢谢。我刚刚又读了一遍reactivity in depth,并准备用与你相同的发现来更新我的问题。而你关于this.tags = rJson 的更新刚刚回答了我剩下的问题:)
    猜你喜欢
    • 2018-10-12
    • 2020-03-02
    • 2018-08-24
    • 2019-06-22
    • 2017-06-10
    • 2018-11-02
    • 2018-08-21
    • 2018-06-13
    • 2021-09-06
    相关资源
    最近更新 更多