带有对象常量的Vue.js子组件在其父对象呈现时意外更新

时间:2019-05-30 14:36:39

标签: javascript vue.js

我已经传递了几个Vue组件以及一些对象文字作为道具,例如

<child :prop1="{ foo: 'bar' }"></child>

但是,当父组件重新渲染时,如下面的最小代码和框示例所示,prop1发生更改(由观察者检测到)并导致Child进行更新。如果prop是对象引用,则保持不变。

为什么会发生这种情况,这是否意味着使用对象文字(可能是数组文字)作为道具可能并不“安全”?

https://codesandbox.io/s/vue-template-jj0tb

1 个答案:

答案 0 :(得分:2)

每次模板运行时,它将在命中该部分时创建一个新对象。相同的适用于任何引用类型,因此数组,函数等。

它类似于用JavaScript代码创建的对象等。例如

function getObject() {
    return {};
}

console.log(getObject() === getObject()); // false

每次调用getObject时,它将返回一个新对象,并且对象相等性基于引用而不是对象是否包含相同的值。这实际上是Vue在检查道具变更时所做的事情。请记住,Vue模板已编译为render函数,而这只是普通的JavaScript。在该render函数中,任何对象文字都将仍然是对象文字。

在您的示例中,假设模板中没有其他内容,则父级的渲染函数将如下所示:

function render(h) {
    return h('child', {
        props: {
            prop1: {foo: 'bar'}
        }
    })
}

因此,每次运行时,prop1都会有一个新对象。

正如您已经提到的那样,将对象移至data并按名称进行引用将确保每次使用同一对象,从而避免子级更新。

是否值得担心将取决于您的方案的具体情况,但是如果有足够的子代被更新,这可能会对性能产生影响。子渲染不需要更新实际的DOM,但是如果任何计算的属性,监视或模板依赖于该道具,则它们将运行。