VueJS $set 没有在对象数组中创建新属性

Posted

技术标签:

【中文标题】VueJS $set 没有在对象数组中创建新属性【英文标题】:VueJS $set not making new property in array of objects reactive 【发布时间】:2021-01-21 23:34:33 【问题描述】:

在下面的 VueJS 2 组件中,我可以将 imgdata 属性添加到 area.questions 数组中的每个问题。它有效 - 我可以从 console.log 看到 imgdata 有价值的问题。但是尽管使用了 $set 它仍然不是响应式的,并且 imgdata 不在视图中!我怎样才能使这个反应?

var componentOptions = 
  props: ['area'],
  data: function() 
    return 
      qIndex: 0,
    ;
  ,
  mounted: function() 
    var that = this;
    that.init();
  ,
  methods: 
    init: function() 
      var that = this;
      if (that.area.questions.length > 0) 
        that.area.questions.forEach(function(q) 
          Util.HTTP('GET', '/api/v1/photos/' + q.id + '/qimage').then(function(response) 
            var thisIndex = (that.area.questions.findIndex(entry => entry.id === q.id));
            var thisQuestion = (that.area.questions.find(entry => entry.id === q.id));
            thisQuestion.imgdata = response.data;
            that.$set(that.area.questions, thisIndex, thisQuestion);
          )
        );
      
      console.log("area.questions", that.area.questions);
    ,

【问题讨论】:

不要改变 prop 值。见vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow 道具不能是反应式的。如果您仍在寻求帮助,请告诉我 @PunitPatel 道具绝对是被动的 @Phil 是的,Phil 你是对的,它不能从组件中变异。要更改它,我们应该使用 $emit。 【参考方案1】:

由于area 是一个道具,因此您不应尝试在此组件中对其进行更改。

总体思路是发出一个事件让父组件监听,以便更新传入的数据。

例如

export default 
  name: "ImageLoader",
  props: 
    area: Object
  ,
  data: () => ( qIndex: 0 ), // are you actually using this?
  mounted () 
    this.init()
  ,
  methods: 
    async init () 
      const questions = await Promise.all(this.area.questions.map(async q => 
        const res = await Util.HTTP("GET", `/api/v1/photos/$encodeURIComponent(q.id)/qimage`)
        return 
          ...q,
          imgdata: res.data
        
      ))
      this.$emit("loaded", questions)
    
  

在父级中

<image-loader :area="area" @loaded="updateAreaQuestions"/>
export default 
  data: () => (
    area: 
      questions: [/* questions go here */]
    
  ),
  methods: 
    updateAreaQuestions(questions) 
      this.area.questions = questions
    
  

【讨论】:

(y) 完美解释:)【参考方案2】:

这里变量的值是 this 但它被绑定在函数的范围内。因此,您可以在数据中创建响应式属性,如下所示:

data: function() 
    return 
        qIndex: 0,
        questions: []
    ;
道具不能是反应性的,所以使用:

that.$set(this.questions, thisIndex, thisQuestion);

并使用 this.questions 将您的 API 输出直接分配给问题。

【讨论】:

感谢您的回答 - 我认为这很有帮助,但会将一系列问题与其所属的区域对象分离。 PS。我没有投反对票 - 也许有办法融入这个想法 谢谢@jdoer1997 我知道这里有很多人只是为了得分和否决票。我不在乎那些人。我一直在帮助人们。如果您仍然卡住,请告诉我。 @PunitPatel 在这一点上我必须不同意。人们在这里不仅仅是为了分数,只有当有人认为你的答案不够好或无关紧要时,你才会被否决。

以上是关于VueJS $set 没有在对象数组中创建新属性的主要内容,如果未能解决你的问题,请参考以下文章

从对象数组中选择某些项目以在 Typescript 中创建新数组?

如何在 Python 中创建新的未知或动态/扩展对象

将对象存储到数组中,而不在 AWS AppSync 架构中创建新表

这是对在 Java 中创建新对象的过程的正确描述吗?

Sonata Admin:无法在产品中创建新对象

获取 SQL 在实体框架中创建新表