PageKit — 可自托管的 GrapesJS 建站工具,附完整源码。 获取抢先体验

问题 #5199💬 已回答提出于 2023年6月23日作者 rmadeiraneto0 个反应

组件属性的变化会在所有实例中重现,而不仅仅是一个实例

快速解答作者 artf

感谢@rmadeiraneto的报告。是的,不幸的是,如果你以这种方式变异数组/对象属性,这就是个问题,为了避免这种情况,你有两个选择:避免直接变异(更新时分配新引用)将“默认值”定义为函数 “''js 默认值: () => ({ customArray: [1,2,3] }), ``` 但不幸的是......第二个选项现在😅不行,我会在下一个版本修复它

阅读下方完整回答 ↓

问题

GrapesJS 版本 [X] 我确认使用最新版本 GrapesJS 你用的是什么浏览器? Chrome v114 可复制演示链接 https://jsfiddle.net/rmadeiraneto/t659usxv/39/ 描述一下那个虫子 如何复现这个漏洞?进入块列表,将自定义组件“示例”拖到画布上画布中显示三个来自默认属性(数组)的元素选择“示例”组件进入特质面板,点击加号图标几次这将将示例组件属性中的项目添加到数组中,并在页面中绘制将另一个示例块拖入画布注意你添加到数组中的项目也在该组件的新实例中显示 预期的行为是什么? 在更改第一个组件的属性后创建第二个组件实例时,预期第二个组件的属性会是默认值 [1,2,3] 中在 customArray 道具有定义的第一个数组,而不是操作后的数组 [1,2,3,4,5]。 目前的行为是什么? 当我们更改组件实例的属性时,因为默认对象的引用可能会被保留,我们也在改变组件的默认值,使得在同一组件的所有实例中都重复了对单个组件的修改。当 GrapesJs 为组件属性分配自定义默认值时,需要创建一个对象的浅表副本。当用字符串或整数创建相同内容,而不是对象或数组时,这个问题没有被验证,所以我认为关键是分配组件属性时要保留 defaults'对象的引用。行为准则 [X] 我同意遵守本项目的行为准则

回答(3)

artf• 2023年7月4日

感谢@rmadeiraneto的报告。是的,不幸的是,如果你以这种方式变异数组/对象属性,这就是个问题,为了避免这种情况,你有两个选择:

  1. 避免直接变异(更新时分配新引用)
  2. 将“默认值”定义为函数 “''js 默认值: () => ({ customArray: [1,2,3] }),
但不幸的是......第二个选项现在😅不行,我会在下一个版本修复它
rmadeiraneto• 2023年7月17日

@artf使用默认值作为函数是可行的,感谢你的快速回复和提供解决这个问题的替代方案。 关于第一个建议,我认为问题不在于人们是否应该变异或不变异对象,因为我们讨论的是使用提供的方法(集合)。抱歉我没时间看源代码,但你很可能在“set”方法里变了默认对象,可能是因为引用来自组件生命周期的早期。同样,没有深入看代码,我假设当你将默认值与组件属性合并时,你保留了对默认对象的引用,而不是使用会返回副本的合并方法,比如 from immutable。 我会尽量找时间研究代码,并提出更具体的建议

再次感谢你提供的替代方案和这个了不起的图书馆,继续保持出色的工作!

GJS Helper• 2026年5月17日

你描述的问题是 JavaScript 中常见的一个陷阱,涉及当可变对象(如数组和对象)被分配为默认值时的处理方式。在 GrapesJS中,当你定义包含数组或对象的defaults组件时,这些组件是通过引用分配给新的组件实例。如果你在某个实例上修改了这样的属性,实际上是在修改原始默认引用,这会影响该组件类型创建的所有后续实例。 根本原因 当你在组件的defaults中定义customArray: [1, 2, 3]时,这个数组[1, 2, 3]只创建一次。每当一个新的“示例”组件实例化时,它的customArray属性都会指向内存中的这个同一个数组。因此,当你修改一个实例的customArra...

相关问答

通过相似的问题讨论继续研究。

与此问题匹配的付费插件

根据问题关键词和标签相关性精选,助你更快交付。

查看全部插件

正在加载付费插件推荐……

免费方案

在以下平台查看开源 GrapesJS 插件: GitHub 或在我们的免费目录中快速搜索。

浏览免费插件 →
高级方案

高级插件提供支持、定期更新和生产就绪的功能——为你节省数天的集成工作。

浏览高级插件 →

相关教程

关于同一主题的深入指南。

全部教程 →

浏览插件分类

直接跳转到市场上的插件分类页面。