Custom Elements 是 Web Components API 的一部分,它可以让我们创建自定义的 HTML 元素,并在需要的时候在页面上使用。它不仅提供了一种更好的组织代码的方式,还可以提高代码的复用性和可维护性。在本文中,我们将深入 Custom Elements,介绍它的使用方法和示例,帮助你快速构建定制化的 Web 组件。
Custom Elements 的基础
Custom Elements 允许我们创建一个自定义的 HTML 元素,例如 <my-component>
,并定义其外观和行为。在定义一个 Custom Element 之前,需要先定义一个类:
class MyComponent extends HTMLElement { constructor() { super(); } }
这个类继承自 HTMLElement,代表着将要创建的元素类型。接下来,我们需要调用 window.customElements.define
函数来注册这个 Custom Element:
window.customElements.define('my-component', MyComponent);
这里的第一个参数 'my-component'
,是我们将要创建的元素的标签名称,可以是任意有效的 HTML 标签名称,但必须包含一个连字符。
至此,我们就创建了一个最简单的 Custom Element,此时我们可以在 HTML 中使用 <my-component>
标签来创建这个元素。但是,这个元素并没有什么实际的作用,因为我们还没有为它添加任何 UI 或逻辑。
Custom Elements 的生命周期
Custom Elements 拥有自己的生命周期,当 Custom Element 第一次创建时,将会依次调用以下生命周期函数:
1. constructor()
在 Custom Element 创建时调用,用来初始化元素。如果定义了多个构造函数,则将只调用最后一个构造函数。
2. connectedCallback()
在 Custom Element 加载至页面 DOM 时调用,用来添加 UI 和逻辑。这是添加 UI 和初始化数据的最佳时机,因为这时元素已被 DOM 解析,可以直接操作 HTML 和 CSS。
3. disconnectedCallback()
在 Custom Element 从页面 DOM 中移除时调用,用来释放资源和清除引用。例如,取消订阅事件和清除内存缓存等。
4. attributeChangedCallback(name, oldValue, newValue)
当 Custom Element 中指定的属性发生变化时调用,可以用于更新元素的 UI 和数据。此时可以通过 this.attributes
来获取所有的属性值。
Custom Elements 的属性
通过使用 class Properties
或 observedAttributes
来为 Custom Element 添加属性。
1. 使用 class Properties
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------ --- -------------------- - ------ -------- ---------- - ------------- - -------- - --- ------ - ------ -------------------------- - --- ----------- - ------------------------- ------- - --- -------- - ------ ---------------------------- - --- ------------- - --------------------------- ------- - -
在上面的代码中,我们通过 observedAttributes
定义了需要观察的属性,在这里是 name
和 amount
。在类中我们又定义了 getter 和 setter 函数,可以用来设置或获取相应的属性值。在 Custom Element 的 connectedCallback()
函数中,我们可以自由地使用这些属性:
connectedCallback() { this.innerHTML = `<h3>${this.name}</h3>`; }
2. 使用 observedAttributes
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------ --- -------------------- - ------ -------- ---------- - ------------- - -------- - ------------------------------ --------- --------- - ------ ------ - ---- ------- ---------- - --------- ------ ---- --------- ------------ - --------- ------ - - --- ------ - ------ ----------- - --- ----------- - ------------------------- ------- - --- -------- - ------ ------------- - --- ------------- - --------------------------- ------- - -
在这个例子中,我们也定义了 name
和 amount
两个属性,但是使用了另一种方式来为它们添加观察。在 attributeChangedCallback(name, oldValue, newValue)
函数中,我们可以通过 name
参数来判断属性名称,并将新值赋给相应的类变量。
Custom Elements 的样式
Custom Elements 可以包含自己的样式表,这些样式表可以是内嵌样式、外部样式表或 Shadow DOM 样式表。
1. 内嵌样式
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------------- - -------- ----- ----- - -------------------------------- ----------------- - - -- - ------ ----- - -- ------------------- ----- ------ ----------------- - ------------------- - ------------------------- - ---------- ------------ - - ------------------------------------- -------------
在这个例子中,我们使用 attachShadow({ mode: 'open' })
来为 Custom Element 创建 Shadow DOM,并通过 shadowRoot
引用来获取 Shadow DOM 的根节点。接着我们在 Shadow DOM 中添加了一个内嵌样式表,并在 connectedCallback()
中添加了 UI。
2. 外部样式表
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------------- - -------- ----- ---- - ------------------------------- ------------------------ -------------- ------------------------- -------------------- ------------------- ----- ------ ---------------- - ------------------- - ------------------------- - ---------- ------------ - - ------------------------------------- -------------
在这个例子中,我们创建了一个外部样式表,并将其添加到了 Shadow DOM 中。在 HTML 中,我们可以通过以下方式来添加这个 Custom Element:
<head> <link rel="stylesheet" href="my-component.css"> <script src="my-component.js"></script> </head> <body> <my-component></my-component> </body>
3. Shadow DOM 样式表
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------------- - -------- ----- ----- - -------------------------------- ----------------- - - ----- - -------- ------ ------- --- ----- ----- -------- ------ - -- - ------ ----- - -- ------------------- ----- ------ ----------------- - ------------------- - ------------------------- - ---------- ------------ - - ------------------------------------- -------------
在这个例子中,我们在 Shadow DOM 中添加了一个 Shadow DOM 样式表,通过 :host
选择器来选择 Custom Element 的根元素,并为其应用 CSS 样式。
Custom Elements 的事件
Custom Elements 可以接收和发出自定义事件,这些事件可以通过自定义的 dispatchEvent()
函数和自定义的 addEventListener()
函数来创建和监听。
1. dispatchEvent()
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------------- - -------- - ------------------- - ----- ------ - --------------------------------- ------------------ - ------ ----- -------------------------------- -- -- - ---------------------- ----------------------- - -------- ----- --------- ----- ------- - -------- ------ ------ - ---- --- ------------------------- - - ------------------------------------- -------------
在这个例子中,当 <button>
被点击时,我们使用 dispatchEvent()
函数来触发一个自定义事件 my-event
。这个函数接受一个 CustomEvent
对象作为参数,它可以在其 detail
属性中传递自定义的数据。在这个例子中,我们传递了一个 message: 'Hello World'
的对象。
2. addEventListener()
-- -------------------- ---- ------- ----- ----------- ------- ----------- - ------------- - -------- - ------------------- - ----- ------ - --------------------------------- ------------------ - ------ ----- -------------------------------- -- -- - ---------------------- ----------------------- - -------- ----- --------- ----- ------- - -------- ------ ------ - ---- --- ------------------------- --------------------------------- - -- - ------------------------------ --- - - ------------------------------------- -------------
在这个例子中,我们在 Custom Element 中添加了一个 my-event
的事件监听器,通过 e.detail
来获取事件的详情数据。当 <button>
被点击时,我们触发了这个自定义事件,并在控制台中输出了 Hello World
。
Custom Elements 的示例
接下来,我们将以一个实例来演示 Custom Elements 的应用。
1. 创建一个 TodoList
我们将创建一个 TodoList 组件,这个组件可以添加、删除和完成任务。首先我们需要一个 HTML 模板:
-- -------------------- ---- ------- --------- ------------------------ ------- ----- - -------- ------ ------- --- ----- ----- -------- ------ - -- - ----------- -- - ----- - -------- ------ - ----------------------- ------------------- ------ - ------- ------ -------- ------ - ------------------- ------ - ------ ----- - ---------- - ---------------- ------------- - -------- ----------------- ------ ------- ------ --------------- -------------- -- ---- --- -- -------- -------- --------- ------------------------ ------- ------ --------------- ---------------- -- ----- ----------------------- ------ ----------- ------------ -- ------- ------------------------------ -------- ----------- --- --------------- ------ ----------- --------- ---------------- - --- ----- -- ------- ------------ ------------- ------- -----------
这个 HTML 展示了一个 TodoList 的样式,它包含了:
- 一个
<h3>
标题; - 一个 Mark all as complete 复选框;
- 一个
<ul>
列表,用来显示所有的任务; - 一个添加任务的输入框和按钮。
接下来,我们将通过 Custom Elements 来完成 TodoList 的逻辑部分。
2. 完成 TodoItem 的逻辑
首先我们先定义 TodoItem 这个组件:
-- -------------------- ---- ------- ----- -------- ------- ----------- - ------------- - -------- ----- -------- - ------------------------------------------------------ ------------------- ----- ------ ----------------------------------------- ------------- - ------------------------------------------- ------------ - ------------------------------------------ --------- - --------------------------------------- ----------- - ----------------------------------------- ---------------------------------------- -- -- - ---------------------- --------------------- - -------- ----- --------- ----- ------- - -------- --------------------- - ---- --- ----------------------------------------- -- -- - -------------------------- - ------- ----------------------- - --------------- ------------------- --- ---------------------------------- -- -- - ----------------------- - ------- -------------------------- - --- ------------------------ - ---------------- --- ------------------------------------- -- -- - ---------------------- --------------------- - -------- ----- --------- ---- ---- --- - ------ --- -------------------- - ------ -------------- - ------------------------------ --------- --------- - -- ----- --- ------------ - --------------------- - --------- --- -------- ------------------- - - --- ----------- - ------ ------------------------------- - --- ---------------- - ------------------------------ ------- ------------------- - ------------- - -- ----------------------- - ---------------------------------------- - ---- - ------------------------------------------- - - - ---------------------------------- ----------
在这个组件中,我们利用了一些事件来处理 TodoItem 的逻辑:
change
事件用来触发选中状态的变化;dblclick
事件用来触发编辑状态的变化;blur
事件用于处理编辑状态的取消操作;click
事件用来触发任务的删除操作。
同时,我们也提供了一些属性:
completed
属性,用于表示任务的选中状态。
最后,我们需要为 TodoItem 的 CSS 样式添加额外的样式,以实现选中状态:
:host(.completed) .content { text-decoration: line-through; }
3. 完成 TodoList 的逻辑
接下来我们使用 TodoItem 来定义 TodoList:
-- -------------------- ---- ------- ----- -------- ------- ----------- - ------------- - -------- ----- -------- - ------------------------------------------------------ ------------------- ----- ------ ----------------------------------------- ------------- - -------------------------------------------- -------------- - --- ---------------------------------------------------------------- - -- - ------------------- ----- ---- - ---------------------------------------------------- -- ------ - ------------------- -------------------------------------------- - --- ---------------------- - --- ---------------------------------------- -- -- - ----- ------- - ---------------------- --------------------------- -- - -------------- - -------- --- --- - ------------- - ----- ---- - ---------------------------- - --- ----------- --- ----- -- - --------------------------------------- --------- - ----- -------------- - ------ ------------------------ - ----- ------------------------------- -- -- - ---------------------- --- ------------------------------- -- -- - ---------------------- --- -------------------------- --------------------- - ---------------- - ----- ----- - ----------------------------- --------- - ----- ---------------------------- --- -------------- ---------------------- - ---------------- - ----- -------------- - -------------------------- -- ---------------- -- ---------------------- --- ---------------------- - --------------------- - ----- - ---- - --------------------- - ------ - - - ---------------------------------- ----------
在这个组件中,我们也使用了一些事件,例如:
submit
事件用来触发添加操作;change
事件用来触发选中状态的变化。
同时,我们在 TodoList 中也使用了 TodoItem,我们通过 TodoList 的 addItem()
函数来添加 TodoItem,并将其加入到任务列表中。
最后,在 TodoList 中我们也提供了一些属性:
value
属性,用于获取和设置 TodoList 的值;items
属性,用于获取 TodoList 中的任务列表。
-- -------------------- ---- ------- ----------------------------------------- -------- - ---- ---------- - ------ ----------------------- -- ------------------------------------ -- ---- --------------- - ----------------------------- -- - -- ------ - ------------------- - --- - --- ----------------------------------------- -------- - ---- ---------- - ------ --------------- - ---
4. 使用 <todo-list> 元素
现在我们已经完成了 TodoList 的逻辑,我们可以通过以下的 HTML 来使用它:
-- -------------------- ---- ------- --------- ----- ----- ---------- ------ ----- --------------- -- ----------------------- ------- ---- - ------------ ---------- ------ ---------- ------ ----------- - -------- - ------- ----- - ------------------- ------ - -------- ------ ------- ----- -- - ------ - ------ ------ ------- ----- -- - ---- - ------ ----- - -------- ------- ------ ---------- ------------------------- ----------------------- ----------- ---------- --------------------------- --------- ------- --------------------- ------- ------------------------------------ ----------- ---------- ----------------------- ---- ------------------ ----------- ------- --------------------------- -------- -------- --------- - ----- -- - ------------------------------------ ----- ------ - ---------------------------------- --- - ------------------ - --------- - ----- --- - ------------------ - ---------- - - --------- ------- -------
这里我们通过 <todo-list>
标签来添加一个 TodoList,在某些浏览器中,我们还需要在注释中加上一些 hack,例如:
<todo-list><!-- fix bug for some browser --></todo-list>
5. 示例效果
最后,我们来看一下示例的效果:
- 添加任务:
- 编辑任务:
- 完成任务:
- 删除任务:
总结
Custom Elements 可以让我们创建自定义的 HTML 元素,并在页面上使用它们,从而可以提高代码的可维护性和复用性。在本文中,我们深入介绍了 Custom Elements 的使用方法和示例,并帮助你快速构建定制化的 Web 组件。希望这篇文章对你有所帮助,谢谢阅读!
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651cf5d095b1f8cacd47988d