首页 > 解决方案 > 动态创建组件的 Vue 响应性

问题描述

我们使用 TypeScript 和vue-property-decorator用 VueJS 构建了一个所见即所得的编辑器。我无法真正详细说明,提取一段代码以显示该问题几乎是不可能的。因此,我希望我能充分解释这个问题,也许有人可以给出一些指示,我们可能有错误。

根组件是布局编辑器,它有一个布局面板和一个属性面板,类似于胖客户端。您可以使用拖放组件在此布局面板中排列元素。组件层次结构是这样的:LayoutEditor -> BaseElement(包含拖放组件)-> Actual Element(位于拖放组件的槽中)。一些简化的代码示例:

<layout-editor>
    <base-element v-for="(element) in elements" :element="element" :key="element.id"></base-element>
</layout-editor>

基本元素:

<vue-draggable-resizable>
    <component
        :is="element.componentType"
        :data="element.componentData"
</vue-draggable-resizable>

问题

将新元素添加到布局编辑器中,方法是将其推入elements数组并保存属性。然后组件会根据其属性正确呈现,但对属性的任何进一步更改都不会反映在布局面板中。数据存储在 mongodb 中,因此当整个页面被刷新并且布局编辑器及其所有子元素挂载时,可以根据需要更改属性并立即反映更改。只有新添加的行为不同,如果elements数组是通过 axios 加载的,或者如果我们将元素推入,一旦加载,我们就看不到有什么不同。如果新元素不能正确渲染,会更容易理解,但是第一次保存到属性有效,只有后续的无效。

添加新元素时有什么想法可能是我们的错误吗?

标签: typescriptvue.js

解决方案


对于您所描述的,这可能是复杂对象嵌套的问题,已知存在反应性问题

有时您可能希望为现有对象分配多个属性,例如使用 Object.assign() 或 _.extend()。但是,添加到对象的新属性不会触发更改。在这种情况下,使用原始对象和 mixin 对象的属性创建一个新对象。

现在,我看到当从数据库中获取属性时,您没有这个问题,因此可以了解如何将属性添加到新创建的元素;因为当您从数据库中下拉所有属性时,您的后端代码很可能已经实例化了所有属性。

作为我所说的例子,让我们以一个用户为例。

如果我从数据库中拉出一个用户,在非常简单的情况下,它有一个 ID、一个电子邮件和一个 psw。

但是,如果我在前端创建用户(例如,在注册表单中),我将没有 id,直到我将它添加到用户以防创建成功。根据我在商店中定义我的用户的方式,以及我添加新属性的方式,这些是否会是反​​应性的。

通常使用 Vue API 方法Vue.set(obj,prop,value)或从存储的对象中创建一个新对象来解决这个问题。

this.modifiedElement = {
    ...this.modifiedElement,
    foo: 'fresh-foo',
    bar: 'fresh-bar',
};

推荐阅读