StencilJS中查询另一个组件的阴影DOM是否存在问题?

huangapple go评论71阅读模式
英文:

Is there an issue with querying the shadow DOM of another component in StencilJS?

问题

以下是翻译好的代码部分:

const breadcrumbItems = this.el.querySelectorAll('.ifx-breadcrumb-item')
let label = breadcrumbItems[i].querySelector('.ifx-breadcrumb-item-label')
let container = label.shadowRoot.querySelector('.breadcrumb-item-label-container')
container.classList.add('margin')

不要回答问题部分。

英文:

Example:

const breadcrumbItems = this.el.querySelectorAll('ifx-breadcrumb-item')
let label = breadcrumbItems[i].querySelector('ifx-breadcrumb-item-label')
let container = label.shadowRoot.querySelector('.breadcrumb-item-label-container')
container.classList.add('margin')

Is there an issue with this code? Is querying the shadowDOM of another component problematic, or is it a normal practice?

And if querying the shadow DOM of another component is wrong, then how do you suggest I do the above instead?

From the parent breadcrumb component, on componentDidLoad, I am getting all the nested breadcrumb-items, and then adding the class margin to the breadcrumb-item-label-container element.
How else would I do that?

答案1

得分: 0

IMO(In My Opinion),这种做法/设计有点不好。你实际上是试图从组件外部影响组件的影子DOM的样式。为了使其工作,你应该使用组件内部可以访问的类 - 这意味着不是全局样式表,因为全局样式表不能穿透影子DOM。因此,该类必须存在于你要样式化的组件内部。但是影子DOM使用的样式类应被视为“私有” - 不是公共API的一部分(这是使用影子DOM的整个目的)。

如果你需要影响Web组件如何样式化其影子内容,你应该通过适当的公共API来实现 - 在Stencil中,这要么是@Prop,要么是@Method。

唯一的例外是可能会穿透影子DOM的东西,比如可继承属性或CSS自定义属性。但是组件如何使用这些属性的设计应允许它们在主机元素上设置,因此不需要访问影子DOM。

还需要考虑组件的设计。如果按设计,影子内容的样式应该由上下文(来自外部使用)确定,那么也许它应该被插槽化而不是嵌入在组件内部。或者也许对于主要提供逻辑(如控制器)而不是样式或布局的组件,根本不需要影子DOM。这在使用其他组件的复杂组件中有时是一个问题。

在我所做的工作中,我们使用各种内部共享的组件库,我曾经看到其他开发人员偶尔尝试采用这种策略,以绕过他们认为是组件限制的问题(通常是因为他们不知道更好的方法或者懒得提交对组件的更改请求)。在每种情况下,正确的解决方案都是要么通过公共API增强组件以支持新的用例/要求,要么执行当前组件提供的模式(即不允许用于新样式/行为的绕过/黑客)。

英文:

IMO, that's kind of bad practice/design. You are essentially trying to affect styling of the shadow DOM of a component from outside the component. In order for that to work, the class you are applying must be accessible by the component's shadow - which means not a global style sheet because that doesn't pierce shadow DOM. So that class would have to exist inside the component you are trying to style. But style classes used by shadow DOM should be considered "private" - not part of public API (this is the whole point of using shadow DOM).

If you need to affect how a web component styles its shadow content, you should do it through a proper public API - in Stencil that's either @Prop or @Method.

The exception to this is whatever might pierce shadow DOM such as inheritable properties or CSS custom properties. But the design of how your component uses those kinds of properties should allow for them to be set on the host element which therefore does not require accessing shadow DOM.

Component design also needs to be considered. If by design the style of shadow content is meant to be determined by context (from outside usage), then perhaps it should be slotted rather that embedded within the component. Or perhaps shadow DOM is not necessary at all for a component that is mainly providing logic (like a controller) rather than style or layout. This is sometimes a problem with complex components that use other components.

In the work that I do where various in-house shared component libraries are used, I've seen other developers occasionally try to resort to this kind of tactic in order to get around what they perceive as limitations in components (usually because they don't know any better or are too lazy to submit a change request against the component). In every case, the proper solution is to either enhance the component to support new use cases/requirements via public API, or enforce the pattern currently provided by the component (i.e. don't allow the workaround/hack for new style/behavior to be used).

huangapple
  • 本文由 发表于 2023年6月12日 15:23:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76454387.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定