我有几个 Vue 组件传递了一些对象文字作为道具,例如
<child :prop1="{ foo: 'bar' }"></child>
Run Code Online (Sandbox Code Playgroud)
但是,当父组件重新渲染时,如下面的最小代码和框示例所示,prop1更改(由观察者检测)并导致Child更新。如果 prop 是一个对象引用,它保持不变。
为什么会发生这种情况,这是否意味着使用对象字面量(可能还有数组字面量)作为道具可能不“安全”?
每次模板运行时,它都会在遇到该部分时创建一个新对象。这同样适用于任何引用类型,因此数组、函数等。
它类似于在 JavaScript 代码中创建的对象等。例如
function getObject() {
return {};
}
console.log(getObject() === getObject()); // false
Run Code Online (Sandbox Code Playgroud)
每次getObject调用它都会返回一个新对象,对象相等性基于引用而不是对象是否包含相同的值。这实际上是 Vue 在检查更改的 props 时所做的。请记住,Vue 模板被编译为一个render函数,而这只是普通的 JavaScript。任何对象文字仍将是该render函数中的对象文字。
在您的示例中,父级的渲染函数看起来像这样,假设模板中没有其他内容:
function render(h) {
return h('child', {
props: {
prop1: {foo: 'bar'}
}
})
}
Run Code Online (Sandbox Code Playgroud)
所以每次运行时都会有一个新的对象prop1。
正如您已经提到的,将对象移动到您的对象data然后按名称引用它可以确保每次都使用相同的对象,从而避免子更新。
是否值得担心取决于您的场景的具体情况,但如果有足够多的孩子像这样更新,它可能会对性能产生影响。子渲染不应该需要更新实际的 DOM,但如果它们依赖于该 prop,任何计算属性、监视或模板都将运行。