在前端开发中,随着 Web 页面越来越复杂,UI 组件也愈加多样化。如果在现有的组件库中没有找到适合的组件,或许可以考虑利用 Custom Elements 和 SVG 来创建可定制的 UI 组件。
Custom Elements
“Custom Elements” 是 Web Components 的核心技术之一。通过它,我们可以创建自定义的 HTML 标签,实现特定的功能需求。
创建 Custom Element
创建 Custom Element 需要分几步:
- 定义元素类
- 定义元素样式和模板
- 注册 Custom Element
例如,我们要创建一个名为 my-button
的按钮组件,可以按照下面的代码来实现。
class MyButton extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <style> button { font-size: 1rem; padding: 0.5rem 1rem; border-radius: 4px; color: #ffffff; background-color: #007bff; border: none; cursor: pointer; } </style> <button> <slot></slot> </button> `; } } customElements.define('my-button', MyButton);
在这个代码中,首先定义了一个 MyButton
类,继承了 HTMLElement
基类,并实现了 constructor
方法。
在 constructor
方法中:
- 调用
super
方法,继承基类的属性和方法 - 创建 Shadow DOM,即创建一个封闭的 DOM 树
- 将样式和模板插入到 Shadow DOM 中
注意到模板中包含了一个 <slot>
标签,这个标签是用来插入自定义内容的。
最后一句代码调用 customElements.define
方法,注册 Custom Element。
使用 Custom Element
在 HTML 文件中使用 Custom Element 和普通元素一样,只需要使用自定义标签名即可。
<my-button>Hello World!</my-button>
添加属性和事件
为了增强 Custom Element 的灵活性,我们可以为它添加属性和事件。
例如,为 my-button
组件添加 type
属性和 click
事件,代码如下:
class MyButton extends HTMLElement { constructor() { // ... this._type = 'button'; this._onClick = this._onClick.bind(this); } static get observedAttributes() { return ['type']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'type') { this._type = newValue; } } connectedCallback() { this.addEventListener('click', this._onClick); } disconnectedCallback() { this.removeEventListener('click', this._onClick); } _onClick() { const event = new CustomEvent('my-button-click', { bubbles: true, composed: true }); this.dispatchEvent(event); } // ... }
在这个代码中:
_type
是私有属性,用来存储type
属性的值,默认为'button'
_onClick
方法是私有方法,用来处理click
事件static get observedAttributes()
方法用来定义需要监听的属性列表attributeChangedCallback(name, oldValue, newValue)
方法用来监听属性值的变化connectedCallback()
方法和disconnectedCallback()
方法分别用来监听组件的生命周期_onClick()
方法中创建了一个自定义事件my-button-click
,并把它分发到组件的 DOM 树中
注意到在 _onClick()
方法中,我们使用了 bubbles
和 composed
选项,这样自定义事件可以冒泡到父组件,并且可以穿过 Shadow DOM 边界。
SVG
在前端开发中,使用 SVG 可以轻松地创建矢量图形。下面是一个简单的 SVG 图形:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor"> <path d="M22 12h-4l-3 9L9 3l-3 9H2" /> </svg>
上面的代码中,<svg>
标签定义了一个 SVG 元素。viewBox
属性用来定义 SVG 坐标系的大小和位置,stroke
属性用来定义路径的颜色和宽度。
<path>
标签定义了一个路径,d
属性用来描述路径的形状。
利用 Custom Elements 和 SVG 创建可定制的 UI 组件
现在,我们有了创建 Custom Element 和 SVG 的基本知识,可以开始实现一个可定制的 UI 组件了。
例如,我们可以创建一个 my-icon-button
组件,它可以接受一个 SVG 图标作为输入,并支持自定义样式和事件。
class MyIconButton extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); this._icon = this.querySelector('svg'); shadowRoot.innerHTML = ` <style> :host { display: inline-block; vertical-align: middle; cursor: pointer; } svg { width: 1.5rem; height: 1.5rem; } </style> <slot name="icon">${this._icon.outerHTML}</slot> `; } static get observedAttributes() { return ['fill']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'fill') { this._icon.style.setProperty('fill', newValue); } } connectedCallback() { this.addEventListener('click', this._onClick); } disconnectedCallback() { this.removeEventListener('click', this._onClick); } _onClick() { const event = new CustomEvent('my-icon-button-click', { bubbles: true, composed: true }); this.dispatchEvent(event); } } customElements.define('my-icon-button', MyIconButton);
在这个代码中,MyIconButton
类用来定义 my-icon-button
组件。在 constructor
方法中,它获取了传入的 SVG 图标,并使用 shadowRoot.innerHTML
方法渲染了组件的 HTML 和 CSS。
注意到在渲染时,我们使用了 <slot>
标签,用来插入传入的 SVG 图标。同时,我们还规定了传入的 SVG 图标要使用 <slot>
的 name
属性,如下所示:
<my-icon-button fill="#007bff"> <svg slot="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor"> <path d="M22 12h-4l-3 9L9 3l-3 9H2" /> </svg> </my-icon-button>
在 static get observedAttributes()
方法中,我们定义了需要监听的属性为 fill
,这个属性用来定义 SVG 的颜色。
在 attributeChangedCallback(name, oldValue, newValue)
方法中,我们通过设置 SVG 的 fill
属性来响应属性值的变化。
最后,我们使用 connectedCallback()
和 disconnectedCallback()
方法来监听组件的生命周期,并在 _onClick()
方法中创建自定义事件 my-icon-button-click
,并把它分发到组件的 DOM 树中。
总结
通过本文,我们了解了如何利用 Custom Elements 和 SVG 来创建可定制的 UI 组件。Custom Elements 提供了创建自定义 HTML 标签的能力,而 SVG 提供了创建矢量图形的能力。通过结合这两个技术,我们可以创建更加灵活和可定制的 UI 组件,满足不同的业务需求。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a4f028add4f0e0ffd4c327