尝试更改对象属性并保持反应性。属性或方法“vm”未在实例上定义,但在渲染期间被引用

Posted

技术标签:

【中文标题】尝试更改对象属性并保持反应性。属性或方法“vm”未在实例上定义,但在渲染期间被引用【英文标题】:Trying to change object property and keep reactivity. Property or method "vm" is not defined on the instance but referenced during render 【发布时间】:2019-09-07 05:37:33 【问题描述】:

到目前为止,我一直在尝试使用 @click='review.isActive = true' 将对象属性的值更改为 false,然而,事实证明 Vue 无法检测到此类更改,这意味着该属性不会是被动的。

根据文档https://vuejs.org/v2/guide/list.html#Caveats,可以使用以下方法之一来避免这种情况:

Vue.set(vm.reviews, index, true)

vm.reviews.splice(index, 1, true)

遗憾的是,无论使用哪种方式,我都会遇到错误。我假设我不太了解 Vue 实例的工作原理,并且在无法访问时尝试访问它。

我假设 Vue/vm 应该是 Vue 实例,但我似乎无法访问它。

在这两种情况下,我都会收到错误“属性或方法“vm”/“Vue”未在实例上定义,但在渲染期间被引用。”

我正在使用 Vue webpack-simple webpack 模板,我的 Vue 实例似乎在 main.js 文件中初始化,如下所示:

var vm = new Vue(
    el: '#app',
    router: router,
    store: store,
    render: h => h(App)
);

发生数组操作的文件是不同的,并且是一个组件。

【问题讨论】:

“原来 Vue 无法检测到这样的变化” ????仅当 reviewisActive 属性最初未在 data 中定义时才适用 “我正在使用 Vue webpack-simple webpack 模板” ????也称为旧的/过时的/遗留的 Vue CLI v2 实现。 Vue CLI v3是新热点 您的问题显示reviewreviews。有v-for 参与吗? 是的,@click='review.isActive = true' 在 v-for 中。 【参考方案1】:

假设您的 review 对象是您的 reviews 数组中的一个项目,并且它们最初没有 isActive 属性但您想添加一个,您可以使用 vm.$set 添加一个新的反应式属性。

例如

new Vue(
  el: '#app',
  data: 
    reviews: [
      id: 1,
      name: 'Review #1'
    ,
      id: 2,
      name: 'Review #2'
    ,
      id: 3,
      name: 'Review #3'
    ]
  
)
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
  <div v-for="review in reviews" :key="review.id">
    <p>
      Review  review.name  status: 
      <code> review.isActive ? 'ACTIVE' : 'INACTIVE' </code>
    </p>
    <button @click="$set(review, 'isActive', true)">Activate</button>
  </div>
</div>

注意$set@click 处理程序中的使用。


从下面的评论中,如果您想在检索数据后添加新属性,请在将值分配给您的数据属性之前执行此操作,例如

this.reviews = data.from.somewhere.map(review => (...review, isActive: false))

如果必须在分配数据后添加新属性,则需要使用vm.$set 使其具有反应性

this.reviews.forEach(review => 
  this.$set(review, 'isActive', false)
)

响应式添加这些属性后,您可以返回简单地更改它们而无需$set

<button @click="review.isActive = true">

【讨论】:

好吧,我的所有评论都来自谷歌,所以我为评论发出 GET 请求,然后执行此操作 --- this.reviews = response.data.result.result.reviews ---和 --- this.reviews.map(o => o.isActive = false)。他们最初没有 isActive 属性,我只是自己映射它。 什么意思?这些对象最初没有 isActive 属性,在我运行 map 函数后,它们会收到一个。我通过在 map 函数之前运行 console.log(this.reviews) 来确认它,然后查看是否创建了属性。 @Bobimaru 我误解了你在做什么(cmets 不适合添加代码)但我现在已经更新了我的答案 感谢您的解释和代码,我意识到自己做错了什么。您的代码还通过删除多余的东西(例如 map 函数)帮助我清理了我的代码。非常感谢您,感谢您的帮助。

以上是关于尝试更改对象属性并保持反应性。属性或方法“vm”未在实例上定义,但在渲染期间被引用的主要内容,如果未能解决你的问题,请参考以下文章

VueJS路由器查看反应道具未定义

即使对象已定义,也无法读取“未定义”的属性! [反应]

如何更新反应性对象(和一般属性)?

属性或方法“$v”未使用 Vuelidate 定义

[Vue 警告]:未定义属性或方法“$v”

Vue 警告我无法在未定义、null 或原始值上设置反应属性:null