为啥这个 Vue 计算属性不是响应式的?

Posted

技术标签:

【中文标题】为啥这个 Vue 计算属性不是响应式的?【英文标题】:Why is this Vue computed property not reactive?为什么这个 Vue 计算属性不是响应式的? 【发布时间】:2019-07-09 23:08:02 【问题描述】:

我希望我的视图使用作为道具传递的 id 在商店中查找对象的属性。存储中的对象异步显示,因此该对象可能不会立即出现。我希望视图对对象的最终外观做出反应。

<template>
  <div>
    <h1> title </h1>
  </div>
</template>

<script>
export default 
  props: ['id'],
  computed: 
    widget () 
      let path = `widget/$this.id`
      return this.$store.state.widgets[path]
    ,
    title () 
      let widget = this.widget
      return (widget) ? widget.data().fullName : 'nothing to see here'
    
  

</script>

使用 vuex 调试工具,我可以看到商店小部件对象一开始是空的,然后设置为 widgets: 'widgets/someId': ... ,但我的 vue 似乎没有接受更改。标题仍然 == 'nothing...'。

我尝试制作这些方法,但我得到了相同的行为。我还尝试替换商店中的整个 widgets 对象,而不是一次替换一个道具(我认为这是一个要求),但仍然没有运气。

我认为我的问题与this one 非常相似,但那里的答案过于简洁。它只是说“使用数据项”,但我真的不知道那是什么或如何使用它(或者为什么这会使 vue 反应)。

【问题讨论】:

你能显示小部件的 vuex 存储代码吗? 你考虑过使用getters吗?它们的优点是仅根据商店变化进行重新评估。您可以使用公开其他吸气剂的第二个参数“链接”吸气剂。您可以根据各自计算的widget 评估title。 ***.com/a/53993174/5059657 是的,计算属性不是很被动。前段时间我遇到了同样的问题。我最终使用了watchers:vuejs.org/v2/guide/computed.html#Watchers @AlexanderStaroselsky - 我确实尝试了一个具有相同结果的吸气剂。我认为原因是我的 getter 需要一个参数(path),所以我的 getter 需要返回一个函数,并且(也许??)阻止它反应? 【参考方案1】:

您的小部件很可能没有反应,因为widget 本身不会改变,widget.data 也不会改变,因为它是您定义的函数。 Vue 在调用data 时不会“看到”数据的变化,因为它是一个函数。

您有多种方法可以使您的小部件具有响应性。一种是预先计算您的数据并返回一个没有函数的对象。当您拥有大量小部件时,这可能意味着性能下降,即使您不需要其中的大部分数据。

另一个可能是使用相对较新的getter 函数/方法。您将使用 widget.data 获取数据并拥有类似

的小部件

  id: 1,
  get data() 
    // Whatever was in your function before
  

请记住,这是(我相信)Ecmascript 6 的一项功能,因此您可能需要通过 babel 运行它才能与所有相关浏览器兼容。

【讨论】:

谢谢。我被那个 data() 函数困住了,因为这些对象来自 google firestore。事实证明,使用 Vue.set() 足以让我的 vue 看到变化(并再次调用 data() 函数)。【参考方案2】:

Mutations Follow Vue's Reactivity Rules

由于您看到它从空置到有一些成员,因此您正在与 Vue 的 change detection caveats 发生冲突。

Vue 无法检测到属性添加或删除。

添加或删除成员时需要使用Vue.set,即使在Vuex中也是如此。

【讨论】:

谢谢。那解决了它!澄清一下,我的商店设置器中有几段代码写着state.someWidget.someProp = 'foobar'。要变得被动,我应该将所有这些更改为Vue.set(state.someWidget, 'someProp', 'foobar') 吗?? 如果您设置的属性已经存在,它将是反应性的。如果添加或删除属性(在创建包含对象之后),则只需要 set

以上是关于为啥这个 Vue 计算属性不是响应式的?的主要内容,如果未能解决你的问题,请参考以下文章

用计算属性来响应改变

vue的计算属性 是怎么关联某个数据

为啥要在 vue.js 中计算属性?

vue图书小案例

谈谈 Vue toRef 和 reactive

VUE 计算属性 vs 侦听属性