子元素如何访问自定义 Web 组件 class 函数和变量?
How does a child element access custom web component class functions and vars?
在用<template>
和<slot>
标签定义的自定义组件中,子元素可以获取作为自定义组件的父元素,然后使用该元素引用访问class 定义变量和函数。
但是,子元素怎么知道哪个元素是自定义组件呢?
模板本身包含在阴影中 DOM。在页面上呈现自定义组件时,此阴影 DOM 被克隆并作为其宿主附加到自定义组件中。
插入到自定义组件中的元素似乎无法告诉它附加到的节点树来自被克隆的影子 DOM 节点,并且无法告诉哪个元素在当前的 DOM 树是顶级自定义组件,除非它遍历每个 parentNode
以检查它们是否有 shadowRoot
.
如何让自定义组件中的子元素访问自定义组件的 class 变量和函数?
customElements.define("my-comp", class extends HTMLElement {
creationTimestamp;
constructor() {
super();
let template = document.getElementById('my-template');
let templateContent = template.content;
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(templateContent.cloneNode(true));
this.creationTimestamp = Date.now();
}
})
<html>
<template id="my-template">
I'm a new custom component using slots with value <slot name="slot1">default</slot>
<button onclick="console.log(this.parentNode.host.creationTimestamp)">Print timestamp at Template level</button>
</template>
<my-comp>
<span slot="slot1">
slotted value
<div>
<button onclick="console.log(this.parentNode.parentNode.parentNode.creationTimestamp)">Print timestamp</button>
</div>
</span>
</my-comp>
</html>
现在我明白了。您要防止:
let timeStamp = this.parentNode.parentNode.parentNode.creationTimestamp;
有多个 Whosebug 答案可以解决这个问题:
让child找到一个parent
控制中:child
模仿标准 JS .closest(selector)
不穿透 shadowRoots!
使用自定义 closestElement(selector)
函数:
让parent告诉一些东西child
控制中:parent
通过 递归潜水 进入 shadowRoots:
让parent响应来自child
的呼叫
在控制中:Child都发送了Event,Parent需要监听
我用于解耦的简单规则是:
Parent到child:one-waydata-binding或HTML5 attributes传递数据调用child.func()
执行动作。
Child 到 parent:Child 触发一个事件。 parent(s) 监听该事件。由于 event bubbling,您可以让任意数量的 parent 不费吹灰之力地接收该事件。
标准网络组件也使用此模式(input
、textbox
等)。它还允许轻松测试,因为您不必模拟 parent.
这是 Polymer library 描述的推荐模式,was/is 是 WebComponents 的包装器。不幸的是,我找不到描述这种模式的具体文章。
在下面的示例中,parent 侦听来自 children 的事件并调用其自身的函数来影响其状态,或调用 children 上的函数来使它们执行某物。 None的child人知道了parent。
在用<template>
和<slot>
标签定义的自定义组件中,子元素可以获取作为自定义组件的父元素,然后使用该元素引用访问class 定义变量和函数。
但是,子元素怎么知道哪个元素是自定义组件呢?
模板本身包含在阴影中 DOM。在页面上呈现自定义组件时,此阴影 DOM 被克隆并作为其宿主附加到自定义组件中。
插入到自定义组件中的元素似乎无法告诉它附加到的节点树来自被克隆的影子 DOM 节点,并且无法告诉哪个元素在当前的 DOM 树是顶级自定义组件,除非它遍历每个 parentNode
以检查它们是否有 shadowRoot
.
如何让自定义组件中的子元素访问自定义组件的 class 变量和函数?
customElements.define("my-comp", class extends HTMLElement {
creationTimestamp;
constructor() {
super();
let template = document.getElementById('my-template');
let templateContent = template.content;
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(templateContent.cloneNode(true));
this.creationTimestamp = Date.now();
}
})
<html>
<template id="my-template">
I'm a new custom component using slots with value <slot name="slot1">default</slot>
<button onclick="console.log(this.parentNode.host.creationTimestamp)">Print timestamp at Template level</button>
</template>
<my-comp>
<span slot="slot1">
slotted value
<div>
<button onclick="console.log(this.parentNode.parentNode.parentNode.creationTimestamp)">Print timestamp</button>
</div>
</span>
</my-comp>
</html>
现在我明白了。您要防止:
let timeStamp = this.parentNode.parentNode.parentNode.creationTimestamp;
有多个 Whosebug 答案可以解决这个问题:
让child找到一个parent
控制中:child
模仿标准 JS.closest(selector)
不穿透 shadowRoots!
使用自定义closestElement(selector)
函数:
让parent告诉一些东西child
控制中:parent
通过 递归潜水 进入 shadowRoots:
让parent响应来自child
的呼叫 在控制中:Child都发送了Event,Parent需要监听
我用于解耦的简单规则是:
Parent到child:one-waydata-binding或HTML5 attributes传递数据调用
child.func()
执行动作。Child 到 parent:Child 触发一个事件。 parent(s) 监听该事件。由于 event bubbling,您可以让任意数量的 parent 不费吹灰之力地接收该事件。
标准网络组件也使用此模式(input
、textbox
等)。它还允许轻松测试,因为您不必模拟 parent.
这是 Polymer library 描述的推荐模式,was/is 是 WebComponents 的包装器。不幸的是,我找不到描述这种模式的具体文章。
在下面的示例中,parent 侦听来自 children 的事件并调用其自身的函数来影响其状态,或调用 children 上的函数来使它们执行某物。 None的child人知道了parent。