Vue:如何在 v-for 中执行响应式对象更改检测?
Posted
技术标签:
【中文标题】Vue:如何在 v-for 中执行响应式对象更改检测?【英文标题】:Vue: How to perform reactive object change detection in v-for? 【发布时间】:2019-05-02 13:59:06 【问题描述】:我阅读了this 文档,但无法使用建议的解决方案。
我有一个v-for
循环对象。这些对象随时间动态变化,我需要这种变化在 v-for 循环中反应性地显示。
<b-row lg="12" v-for="data in objects" :key="data.id">
<div v-if="data.loading">
loading...
data.loading
</div>
<div v-else>
loaded, done
data.loading
</div>
</b-row>
在我的方法中,我有一个 for 循环,它为每个对象下载数据并像这样更改对象值:
for(var i = 0; i<response.ids.length; i++)
var newId = response.ids[i].id
this.objects.newId = "loading":true, "id": newId
downloadSomething(newId).then(res =>
this.objects.newId = res[0] //<-- this change needs to be shown reactively.
)
根据 Vue 文档,对象更改不是反应性的:
var vm = new Vue(
data:
a: 1
)
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive
Vue 提出了一些这样的解决方法:
Vue.set(vm.userProfile, 'age', 27)
更新
但对我来说,这只是在对象中创建一个具有相同 ID 的新参数,并创建重复键警告和其他问题。
我也在 Vue.set 之前尝试了Vue.delete
,但它实际上并没有删除。
有没有办法不替换键/值对,而是向 ID 为 newID
的根的第一个子节点添加更多/更改参数
谢谢!
【问题讨论】:
【参考方案1】:解决方案:将this.objects.newId = res[0]
替换为this.$set(this.objects, 'newId', res[0])
,它应该可以工作。
解释: this.$set
只是 Vue.set
的别名,可在任何 Vue 实例中使用。请记住,示例中的vm
(代表视图模型)与this
相同,相当于Vue 组件实例。同样由于 ES5 JS 的限制,您必须通过 Vue.set/this.$set
显式设置对象的属性才能手动触发重新渲染。这个问题会在 Vue 3.0 发布后解决。
希望这会有所帮助,如果您需要任何说明,请随时提问。
【讨论】:
我没有明确提到我的“对象”是一个对象而不是数组。 Vue.set/vm.$set 在 'objects' 中创建一个具有相同 ID 的新参数,并且不会替换现有参数。这会产生重复键警告和其他问题。我也在 Vue.set 之前尝试了 Vue.delete,但 Vue.delete 不起作用。 想通了。我在没有 Vue.set 的情况下为子对象设置初始键值,然后期望它随着 Vue.set 改变。事实证明,还需要使用 Vue.set 设置初始值(加载值)。我还有助于提高可读性。【参考方案2】:
当您想为现有对象(而不是直接定义数据)定义 新属性 时,您需要Vue.set()
,并且此函数会将新属性分配给内置观察程序,它会也变得被动。
这一切都在文档中进行了解释:https://vuejs.org/v2/guide/reactivity.html
在你的情况下,这似乎是你让它工作所需要的。在我的示例中:https://jsfiddle.net/efrat19/eywraw8t/484131/ 一个异步函数获取数据并定义一个新属性以包含响应。
new Vue(
el: "#app",
data:
objects:
property1:12
,
methods:
fetchDataAndAddProperty(response)
fetch('https://free.currencyconverterapi.com/api/v6/countries').then(res =>
res.json()).then(data => Vue.set(this.objects,'property2',data))
)
和模板:
<div id="app">
<div lg="12" v-for="(val,key,index) in objects" :key="index">
key:val
</div>
<button @click="fetchDataAndAddProperty()">fetch</button>
</div>
正如您在小提琴中看到的那样,新属性变为反应性并被显示。
【讨论】:
【参考方案3】:试试看:
downloadSomething(newId).then(res =>
this.$set(this.objects, 'newId', res[0])
)
【讨论】:
以上是关于Vue:如何在 v-for 中执行响应式对象更改检测?的主要内容,如果未能解决你的问题,请参考以下文章