Custom Elements 的原理与实践

前言

随着 Web 技术的不断发展,越来越多的前端开发者开始注重代码组件化、模块化,而 Custom Elements 就是其中的一个重要实现。本文将详细介绍 Custom Elements 的原理、用法以及实践经验,希望能给大家带来一些指导意义。

什么是 Custom Elements

Custom Elements 是 Web Components 的一个重要组成部分,它允许我们自定义 HTML 元素,从而更好地组织和管理 Web 页面的内容。

正常的 HTML 元素都是浏览器内置支持的,由浏览器渲染和处理。但 Custom Elements 是完全由开发者自己定义的,它包含了自己的样式和行为。可以理解为是一种自定义的、可重用的 HTML 组件。

Custom Elements 的原理

Custom Elements 的实现原理涉及到三个 API:

  1. CustomElementRegistry.define():定义 Custom Element。

  2. HTMLElement.prototype.connectedCallback():元素被插入到文档中时触发的函数。

  3. HTMLElement.prototype.disconnectedCallback():元素从文档中删除时触发的函数。

其中,CustomElementRegistry.define() 是定义 Custom Element 的最关键 API。它的作用是告诉浏览器我们要定义一个新的 Custom Element,并将其与一个 JavaScript 类或原型相关联。

class MyCustomElement extends HTMLElement {
    connectedCallback() {
        console.log('Custom element added to the page');
    }

    disconnectedCallback() {
        console.log('Custom element removed from the page');
    }
}

customElements.define('my-custom-element', MyCustomElement);

上面的代码中,我们定义了一个名为 MyCustomElement 的 Custom Element,并将其与 HTMLElement 相关联。然后我们可以使用 customElements.define() 方法将其注册到浏览器中。

现在我们可以在 HTML 中创建一个名为 my-custom-element 的元素,它将自动与我们定义的 MyCustomElement 相关联。

<my-custom-element></my-custom-element>

这个时候,我们在浏览器控制台中就可以看到 connectedCallback() 函数执行的结果,即打印出 "Custom element added to the page"。

Custom Elements 的实践

下面我们来看一个具体的 Custom Elements 实践例子,它会实现自定义的带复选框的列表项。

<!-- 自定义列表项元素 -->
<template id="list-item">
    <style>
        :host {
            display: block;
            margin: 10px 0;
        }
        .checkbox {
            display: inline-block;
            width: 20px;
            height: 20px;
            margin-right: 10px;
            border-radius: 50%;
            border: 2px solid #aaa;
            cursor: pointer;
        }
        .checked {
            background-color: #1abc9c;
        }
        span {
            display: inline-block;
            vertical-align: middle;
        }
    </style>
    <div class="checkbox"></div>
    <span></span>
</template>

<!-- 使用自定义列表项元素 -->
<my-list>
    <my-list-item checked>Item 1</my-list-item>
    <my-list-item>Item 2</my-list-item>
    <my-list-item>Item 3</my-list-item>
</my-list>

CodePen 示例:https://codepen.io/cocoon-yu/pen/poEZJRL。

我们可以看到,我们首先通过 元素定义了一个自定义的列表项元素,它包含了一个复选框和一个显示文字的元素。

然后我们使用 MyList 和 MyListItem 两个自定义元素,分别代表一个列表和其子项。

class MyListItem extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' }); // 使用 Shadow DOM
        this.shadowRoot.appendChild(document.getElementById('list-item').content.cloneNode(true));
        this.checkbox = this.shadowRoot.querySelector('.checkbox');
        this.text = this.shadowRoot.querySelector('span');
        this.checkbox.addEventListener('click', this.toggle.bind(this));
    }

    static get observedAttributes() {
        return ['checked'];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if (name === 'checked') {
            this.checkbox.classList.toggle('checked', newValue !== null);
        }
    }

    toggle() {
        this.setAttribute('checked', this.getAttribute('checked') === null ? '' : null);
    }

    set textContent(value) {
        this.text.textContent = value;
    }

    get textContent() {
        return this.text.textContent;
    }
}
customElements.define('my-list-item', MyListItem);

class MyList extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' }); // 使用 Shadow DOM
        this.shadowRoot.innerHTML = '<slot></slot>';
    }
}
customElements.define('my-list', MyList);

上面的代码中,我们定义了两个 Custom Element:MyListItem 和 MyList。

MyListItem 继承自 HTMLElement,并使用 Shadow DOM 技术创建了一个完全自主的 DOM 节点。在 constructor 构造函数中,我们使用了 document.getElementById('list-item').content.cloneNode() 方法将 元素复制到了 shadowRoot 中。

同时,我们还使用了 attributeChangedCallback() 方法来响应 checked 属性的变化,并使用 setAttribute() 方法来更新该属性值。

MyList 则相对简单,它只是基本的占位元素,用于容纳 MyListItem 元素。

最后,我们可以在 HTML 中如下使用自定义元素:

<my-list>
    <my-list-item checked>Item 1</my-list-item>
    <my-list-item>Item 2</my-list-item>
    <my-list-item>Item 3</my-list-item>
</my-list>

这将创建一个带有三个复选框的列表,展示内容为 "Item 1"、"Item 2" 和 "Item 3"。

总结

Custom Elements 是一个非常有用的前端技术,可以让我们更好地组织代码,并提高可重用性。本文介绍了 Custom Elements 的原理和使用方法,并给出了一个具体实例,相信读者能够通过本文掌握 Custom Elements 技术,更好地运用于实际开发中。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6590c582eb4cecbf2d6096a9


纠错
反馈