将 Splidejs 集成到 Grapesjs 中:失败的 HTMLElement 实例
Integrate Splidejs into Grapesjs: failing instanceof HTMLElement
我正在尝试集成 Splidejs into a Grapesjs 编辑器。
安装幻灯片时,我得到 Uncaught Error: [splide] A track/list element is missing.
经过调试,我发现Splide 没有找到需要正确挂载的曲目或列表HTML 元素。但是,它们存在于 Grapes 组件的 HTML 中。
...
<div class="splide__track">
<ul class="splide__list">
...
Splide找不到它们的原因似乎与HTML元素基类型不同有关,导致我的元素无法识别。
下面的测试(Splide 3.6.9)returns false
在 Chrome 开发工具控制台 中进行调查时,instanceof
评估的 __proto__
链乍一看似乎是正确的。然而,仔细观察会发现 subject
具有额外的 __zone_symbol__onxxx
属性。
> subject.__proto__.__proto__
HTMLElement {…}
...
__zone_symbol__ononabortpatched: true
__zone_symbol__ononanimationendpatched: true
__zone_symbol__ononanimationiterationpatched: true
...
> HTMLElement.prototype
HTMLElement {…}
...
none of the __zone_symbol __onxxx present
...
> subject.__proto__.__proto__ == HTMLElement.prototype
false
这可以用这两个参考文献来解释:
instanceof
and multiple context (e.g. frames or windows)
Different scopes have different execution environments. This means that they
have different built-ins (different global object, different
constructors, etc.). This may result in unexpected results. For
instance, [] instanceof window.frames[0].Array
will return false
,
(2) https://grapesjs.com/docs/modules/Components-js.html#important-caveat
Keep in mind that all component scripts are executed inside the iframe
of the canvas (isolated, just like your final template), and therefore
are NOT part of the current document.
我怀疑我的 Splide 内容被 zone.js 增强了。
因此,我开始在 Angular 区域
之外创建 Grapes 组件
this.zone.runOutsideAngular(() => {
this.initGrapesEditor()
})
但错误仍然存在。
关于如何解决这个问题,你有什么提示吗?
- 在我的托管组件 Grapes.js
中完全禁用 zone.js
- modify/fix Splide 搜索(过滤)所需 HTML 元素的方式?
- 其他建议?
我也在 grapesjs 上报告了这个问题github
https://github.com/artf/grapesjs/discussions/4062
并添加了两个解决方法
- 按如下方式修补 splidejs(未提交 PR)。
这允许 splidejs 被我的新组件类型的脚本正确加载。
如
/**
* Tests to see if the given TypeName appears anywhere
* in the prototype chain of the given subject.
* This is a lose version of the instanceof operator
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof)
* required when checking the type of elements that cross window and iframe bouderies.
*
* @param subject
* @param typeName
* @returns `true` if
*/
function isInstanceOf(subject: any, typeName: string) {
if (subject === null) {
return false;
}
let p = subject.__proto__;
while (p !== null) {
if (p.constructor.name === typeName) {
return true;
}
p = p.__proto__;
}
return false;
}
export function isHTMLElement( subject: unknown ): subject is HTMLElement {
return isInstanceOf( subject, 'HTMLElement' );
}
export function isHTMLButtonElement( subject: unknown ): subject is HTMLButtonElement {
return isInstanceOf( subject, 'HTMLButtonElement' );
}
我正在尝试集成 Splidejs into a Grapesjs 编辑器。
安装幻灯片时,我得到 Uncaught Error: [splide] A track/list element is missing.
经过调试,我发现Splide 没有找到需要正确挂载的曲目或列表HTML 元素。但是,它们存在于 Grapes 组件的 HTML 中。
...
<div class="splide__track">
<ul class="splide__list">
...
Splide找不到它们的原因似乎与HTML元素基类型不同有关,导致我的元素无法识别。
下面的测试(Splide 3.6.9)returns false
在 Chrome 开发工具控制台 中进行调查时,instanceof
评估的 __proto__
链乍一看似乎是正确的。然而,仔细观察会发现 subject
具有额外的 __zone_symbol__onxxx
属性。
> subject.__proto__.__proto__
HTMLElement {…}
...
__zone_symbol__ononabortpatched: true
__zone_symbol__ononanimationendpatched: true
__zone_symbol__ononanimationiterationpatched: true
...
> HTMLElement.prototype
HTMLElement {…}
...
none of the __zone_symbol __onxxx present
...
> subject.__proto__.__proto__ == HTMLElement.prototype
false
这可以用这两个参考文献来解释:
instanceof
and multiple context (e.g. frames or windows)Different scopes have different execution environments. This means that they have different built-ins (different global object, different constructors, etc.). This may result in unexpected results. For instance,
[] instanceof window.frames[0].Array
will returnfalse
,
(2) https://grapesjs.com/docs/modules/Components-js.html#important-caveat
Keep in mind that all component scripts are executed inside the iframe of the canvas (isolated, just like your final template), and therefore are NOT part of the current document.
我怀疑我的 Splide 内容被 zone.js 增强了。 因此,我开始在 Angular 区域
之外创建 Grapes 组件this.zone.runOutsideAngular(() => {
this.initGrapesEditor()
})
但错误仍然存在。
关于如何解决这个问题,你有什么提示吗?
- 在我的托管组件 Grapes.js 中完全禁用 zone.js
- modify/fix Splide 搜索(过滤)所需 HTML 元素的方式?
- 其他建议?
我也在 grapesjs 上报告了这个问题github https://github.com/artf/grapesjs/discussions/4062
并添加了两个解决方法
- 按如下方式修补 splidejs(未提交 PR)。 这允许 splidejs 被我的新组件类型的脚本正确加载。
如
/**
* Tests to see if the given TypeName appears anywhere
* in the prototype chain of the given subject.
* This is a lose version of the instanceof operator
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof)
* required when checking the type of elements that cross window and iframe bouderies.
*
* @param subject
* @param typeName
* @returns `true` if
*/
function isInstanceOf(subject: any, typeName: string) {
if (subject === null) {
return false;
}
let p = subject.__proto__;
while (p !== null) {
if (p.constructor.name === typeName) {
return true;
}
p = p.__proto__;
}
return false;
}
export function isHTMLElement( subject: unknown ): subject is HTMLElement {
return isInstanceOf( subject, 'HTMLElement' );
}
export function isHTMLButtonElement( subject: unknown ): subject is HTMLButtonElement {
return isInstanceOf( subject, 'HTMLButtonElement' );
}