Vue: 子组件props没有及时更新

Created on 18 Jul 2018  ·  9Comments  ·  Source: vuejs/vue

Version

2.5.16

Reproduction link

https://jsfiddle.net/eywraw8t/181151/

Steps to reproduce

点击click,观察tempArr, tempObj

What is expected?

可以在tempArr, tempObj看到及时更新的数据

What is actually happening?

数据更新滞后(PS:可以用nextTick解决)


1.点击click可以看到在同步调用子组件的log方法时,tempArr和tempObj没有及时更新
2.如果是 修改对象的属性时 可以及时更新
3.两者行为不一致导致需要额外的代码来解决差异

Most helpful comment

类似于这样,比如说:

var data = { a: 4, b: 5, c: 6 } // 这个代表父组件的 data
var props // 这个代表子组件的 props

完成第一次渲染后,子组件得到 props,相当于:

props = data

你会发现 props 和 data 实际上指向同一个对象。如果你更新对象的某一个属性的话,自然就是他们两个同时都得到更新了。如果是更新整个对象的话,则相当于:

data = { a: 7, b: 8, c: 9 }

此时 data 指向一个新的对象,props 却还是指向旧的对象。

data === props // => false

再等到下一次渲染,子组件得到新的 props,才变成:

props = data

此时两者就又指向同一个对象了。

All 9 comments

这个不是 bug,而是因为 child 只有在下次渲染的时候才能得到更新过的 props。这就是为什么你用 nextTick 就是正常的。

和这个的原因是类似的:https://cn.vuejs.org/v2/guide/reactivity.html#%E5%BC%82%E6%AD%A5%E6%9B%B4%E6%96%B0%E9%98%9F%E5%88%97

如果我更新的不是整个对象,而只是对象的一个属性的话,就是及时更新,而不需要等待下次渲染。这两者之间的差异在哪

类似于这样,比如说:

var data = { a: 4, b: 5, c: 6 } // 这个代表父组件的 data
var props // 这个代表子组件的 props

完成第一次渲染后,子组件得到 props,相当于:

props = data

你会发现 props 和 data 实际上指向同一个对象。如果你更新对象的某一个属性的话,自然就是他们两个同时都得到更新了。如果是更新整个对象的话,则相当于:

data = { a: 7, b: 8, c: 9 }

此时 data 指向一个新的对象,props 却还是指向旧的对象。

data === props // => false

再等到下一次渲染,子组件得到新的 props,才变成:

props = data

此时两者就又指向同一个对象了。

简单理解为

  1. props属性更新的话就是简单的变更。
  2. props替换的话,是放在了任务队列里(期间应该是重新设置了属性的get set吧),等待调用栈完成。(PS:那么如果有DOM渲染应该是在props更新之后的下一次渲染吧)
    不知道我理解的对么?

@qxzm 是的!就是这样的

实际上直接改 props 的属性,应该也会走任务队列,只是在任务队列之前,子组件那边 props 已经更新了。但是,真正要让渲染出来的内容得到更新,也还是得走任务队列。

嗯,DOM的渲染永远是滞后的
谢谢大佬解答

What @riophae said. You can use a nextTick() in the toggle function before calling the log function to get the up to date values

也可以在子组件的watch里面这样写
arr: function(n, o){this.tempArr= JSON.parse(JSON.stringify(n))},

Was this page helpful?
0 / 5 - 0 ratings