javascript - 如何在 Web 组件中使用子元素

标签 javascript web-component native-web-component

我正在构建用于教育目的的普通 Web 组件。这是我的自定义复选框。

class Checkbox extends HTMLElement {
    constructor() {
        super();
        this.shadow = this.attachShadow({mode:'open'});
        this.shadow.innerHTML = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path /></svg><label></label>";
        this._checked = false;

        this.addEventListener("click", this.onClickHandler.bind(this));
    }

    set checked(value) {
        if(value != this._checked) {
            this._checked = value;
            this.update();
        }
    }

    get checked() {
        return this._checked
    }

    onClickHandler(event) {
        this.checked = !this.checked;
    }

    update() {
        let svg = this.shadow.querySelector("svg");

        if(this._checked)
            svg.querySelector("path").setAttribute("d", "M19 0h-14c-2.762 0-5 2.239-5 5v14c0 2.761 2.238 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.959 17l-4.5-4.319 1.395-1.435 3.08 2.937 7.021-7.183 1.422 1.409-8.418 8.591z");
        else
            svg.querySelector("path").setAttribute("d", "M5 2c-1.654 0-3 1.346-3 3v14c0 1.654 1.346 3 3 3h14c1.654 0 3-1.346 3-3v-14c0-1.654-1.346-3-3-3h-14zm19 3v14c0 2.761-2.238 5-5 5h-14c-2.762 0-5-2.239-5-5v-14c0-2.761 2.238-5 5-5h14c2.762 0 5 2.239 5 5z");    
    }

    connectedCallback() {
        this.update();
        if(this.hasAttribute("checked"))
            this.checked = true;
        else
            this.checked = false;
    }

}

customElements.define("yasar-checkbox", Checkbox);

我想这样使用它

<yasar-checkbox>MY LABEL</yasar-checkbox>

但是,MY LABEL 部分在浏览器上不可见。我想让它可见并反射(reflect)通过 javascript 所做的更改。我怎样才能实现这个目标?

最佳答案

使用 Shadow DOM 时,您需要use a <slot> 当您将组件放入 DOM 中时拉入子内容。这会将所有内容放入您的标签中。 Read more about the <slot> tag了解它如何将子节点导入到影子 DOM 组件中。

在下面的示例中,我采用了您的代码并添加了一些 CSS 和 <slot>让它按照您想要的方式工作。

class Checkbox extends HTMLElement {
    constructor() {
        super();
        this.shadow = this.attachShadow({mode:'open'});
        this.shadow.innerHTML = "<style>div, svg, label { vertical-align: middle;}label {display: inline-block;margin-left: 5px;</style><div><svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path /></svg><label><slot></slot></label></div>";
        this._checked = false;

        this.addEventListener("click", this.onClickHandler.bind(this));
    }

    set checked(value) {
        if(value != this._checked) {
            this._checked = value;
            this.update();
        }
    }

    get checked() {
        return this._checked
    }

    onClickHandler(event) {
        this.checked = !this.checked;
    }

    update() {
        let svg = this.shadow.querySelector("svg");

        if(this._checked)
            svg.querySelector("path").setAttribute("d", "M19 0h-14c-2.762 0-5 2.239-5 5v14c0 2.761 2.238 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-8.959 17l-4.5-4.319 1.395-1.435 3.08 2.937 7.021-7.183 1.422 1.409-8.418 8.591z");
        else
            svg.querySelector("path").setAttribute("d", "M5 2c-1.654 0-3 1.346-3 3v14c0 1.654 1.346 3 3 3h14c1.654 0 3-1.346 3-3v-14c0-1.654-1.346-3-3-3h-14zm19 3v14c0 2.761-2.238 5-5 5h-14c-2.762 0-5-2.239-5-5v-14c0-2.761 2.238-5 5-5h14c2.762 0 5 2.239 5 5z");    
    }

    connectedCallback() {
        this.update();
        if(this.hasAttribute("checked"))
            this.checked = true;
        else
            this.checked = false;
    }

}

customElements.define("yasar-checkbox", Checkbox);
<yasar-checkbox>MY LABEL</yasar-checkbox>

请注意,如果您想支持盲人用户使用的屏幕阅读器,那么您需要向组件添加其他内容才能使其正常工作。

例如,您需要 support tab-index 和几个 aria tags .

关于javascript - 如何在 Web 组件中使用子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49027807/

相关文章:

javascript - 是否可以保留自定义元素的内部 html?

javascript - 我的 WP 应用程序具有不受我控制的外部依赖项,我该如何解决问题而不重新提交到市场?

javascript - 哪种 Angular 1.5 组件绑定(bind)类型更昂贵? '=' 还是 '<'?

javascript - 标签中的自定义 web 组件事件回调函数

javascript - Web Components(原生 UI)之间如何通信?

javascript - 将 Bootstrap 模板与普通 Web 组件一起使用

javascript - 在 Javascript 中使用类名禁用文本框

javascript - 添加 cookie 仅显示一次弹出窗口

javascript - Discord.js : Cannot read property 'set' of undefined

html - Web Components - 扩展原生元素的样式