【问题标题】:unable to access styles with getComputedStyle in connectedCallback of webcomponent无法在 webcomponent 的 connectedCallback 中使用 getComputedStyle 访问样式
【发布时间】:2020-07-23 19:39:55
【问题描述】:

我对 javascript 还很陌生,并且一直在玩网络组件。我想访问 web 组件的 shadow DOM 中元素的 CSS color 属性。当我使用 getComputedStyle() 方法时,我无法在 connectedCallback 中运行样式属性。

在这里我试图访问颜色属性,在将值记录到控制台时它显示 RGB(0, 0, 0) 而在等待一毫秒然后记录时,RGB(0, 128, 0) 出现。为什么会这样?

我认为这是因为我第一次运行该函数时尚未计算样式?对此有什么更优雅的解决方案?我如何才能完全等到样式被计算出来才能运行我的函数,而不是我现在指定的任意时间?

JS

document.addEventListener('DOMContentLoaded',()=>{

    class CustomComponent extends HTMLElement{
        constructor(){
            super();

            this.attachShadow({mode:'open'});

            const template=document.querySelector('#component');
            this.shadowRoot.appendChild(template.content.cloneNode(true));
        };

        connectedCallback(){
            console.log('Element added to DOM');

            let text=this.shadowRoot.querySelector('.text');
            console.log(getComputedStyle(text).getPropertyValue('color'));
            setTimeout(()=>{console.log(getComputedStyle(text).getPropertyValue('color'))},1)
        };
    };

    customElements.define('custom-component',CustomComponent);
});

CSS

.container{
    --color-variable:#f2c846;
}

.text{
    color:green;
}
  

HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Random title</title>
        <script src='./CustomComponent.js'></script>
    </head>
    <body>
        <template id='component'>
            <link rel='stylesheet' href='./CustomComponent.css'/>
            <div class=container>
                <div class='text'>
                    Colored Text
                </div>
            </div>
        </template>
        <custom-component>

        </custom-component>
    </body>
</html>

【问题讨论】:

    标签: javascript web-component shadow-dom getcomputedstyle


    【解决方案1】:

    哎呀,令人沮丧。我认为您在这里的直觉可能是正确的,即样式没有立即准备好,而您的等待本能也是我的想法。

    我认为看到setTimeout(callback)(在这种情况下second argument 是多余的)作为您正在等待事件循环运行一次的信号(从而允许计算样式)并不罕见. requestAnimationFrame(callback) 可能具有额外的优势,即表明您也在等待一些视觉准备,尽管为此目的它不会胜过 setTimeout。我会是第一个说我觉得这些解决方案不如内置回调或监听事件那么令人满意的人,我会假设 connectedCallback 就是那个东西。

    此外,如果您不介意使用有助于使用 Web 组件的框架(如 Stencil),则该框架会提供回调,让您知道组件何时完全呈现。

    【讨论】:

    • 谢谢朋友。是的,我最终打算使用一些框架,我只是想通过使用 vanilla web-components 来体验一下。
    • 有趣的是,您想加载额外的框架代码只是为了避免自己使用一种技术,该技术会延迟 connectedCallback 的代码执行,直到 Eventloop 被清除;框架也使用了相同的技术在后台connectedCallback 可以在 FireFox 中访问 DOM,但在基于 Webkit 的浏览器中不能(并且正确地如此):stackoverflow.com/questions/61971919/…
    • 注意:setTimeout(()=&gt;{ code }); 是完全有效的代码并且足够了。不需要 0。就像 RAF (requestAnimationFrame) 一样,它一直等到 Eventloop 为空(因此您的 DOM 存在)。我还没有看到 RAF 实际上比 setTimeout 更好的项目。如果您确实使用了非常重的动画,请参阅:stackoverflow.com/questions/38709923/…)
    • @Danny'365CSI'Engelman,关于执行相同操作的额外框架代码的公平点。框架的结构更易于使用,这绝对是一种主观感觉。 setTimeout 多余的第二个参数是代码库的个人痕迹,该代码库期望显式参数传递作为保护措施并作为对其他开发人员的意图说明。不过,我不应该用我自己的条件行为来折磨别人,所以我会进行编辑。 :)
    • 我用我的意见给别人添麻烦。所以不要编辑任何东西。库是工具,如果您了解该工具的作用,请务必使用它们。唉,大多数工具用户对底层技术一无所知。我们大多数人在 jQuery 时代也是如此......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多