【问题标题】:add class dynamically in web components from JavaScript using classList使用 classList 从 JavaScript 在 Web 组件中动态添加类
【发布时间】:2017-05-30 09:15:44
【问题描述】:

如何为 shadow DOM 添加动态样式

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Document</title>
    <link rel="import" href="nav-component.html">
</head>
<body>
    <app-nav></app-nav>
</body>
</html>

导航组件.html

<template>
  <style>
    .btn {
        background-color: green;
        padding: 10px 20px;
    }
  </style>
    <button onclick="getstyles()">ENTER</button>
</template>
<script src="nav-component.js"></script>

导航组件.js

let template = document.currentScript.ownerDocument.querySelector('template');
let clone = document.importNode(template.content, true);
let proto = Object.create(HTMLElement.prototype);

proto.createdCallback = function () {
    let root = this.createShadowRoot();
    root.appendChild(clone);
}
document.registerElement('app-nav', {
    prototype: proto
});

function getstyles() {
    console.log('it works');
    document.querySelector('button').classList.add('btn');
    // document.currentScript.ownerDocument.querySelector('button').classList.add('btn');
}

必须将 btn 类添加到 button 元素 ,以便将其样式添加到 button 元素中

出错了 未捕获的类型错误:无法读取 null 的属性“classList”

Demo

【问题讨论】:

标签: javascript web-component shadow-dom custom-element


【解决方案1】:

首先document.registerElement 已被弃用,所以我在这里回答了基于类的自定义元素解决方案...

解决办法是从document.currentScript.ownerDocument获取文档

class AppNavElement extends HTMLElement {
    constructor() {
        super()

        // import from ownerDocument
        const importDoc = document.currentScript.ownerDocument;
        let shadowRoot = this.attachShadow({mode: 'open'});
        const template = importDoc.querySelector('#template');
        const instance = template.content.cloneNode(true);
        shadowRoot.appendChild(instance);

        // Event Listener
        this.addEventListener('click', e => this.changeStyle());
    }

    changeStyle() {
        this.shadowRoot.querySelector('button').classList.add('btn')
    }
}

customElements.define('app-nav', AppNavElement)

更新:

要收听按钮元素,请仅使用connectedCallback 感谢@bhv

connectedCallback() { 
    let btn = this.shadowRoot.querySelector('button') 
    // Event Listener 
    btn.addEventListener('click', e => this.changeStyle()); 
}

【讨论】:

  • 感谢@Raja - 你能通过在 html 中添加事件来测试同一个应用吗&lt;button onclick="changeStyle()"&gt;ENTER&lt;/button&gt;
  • @bhv 在 React 或其他框架中有方法。但我不知道自定义元素。对不起...
  • 这里的问题是,我们没有选择按钮元素..this.addEventListener - 选择整个模板..
  • 您能否提及如何从 app-nav 向按钮元素添加事件(模板可能有多个元素,如何从中选择按钮元素) - 很抱歉问您更多问题 :)
  • connectedCallback 必须使用从 shadowroot 中选择元素 connectedCallback() { let btn = this.shadowRoot.querySelector('button') // Event Listener btn.addEventListener('click', e =&gt; this.changeStyle()); }
【解决方案2】:

您也可以简单地从event.target 属性中获取&lt;button&gt; 元素:

function changeStyle() {
    console.log('it works');
    event.target.classList.add('btn');
}

...

<button onclick="changeStyle()">ENTER</button>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 2015-11-18
    相关资源
    最近更新 更多