什么是Custom Elements?

Custom Elements是Web Components的一部分,它允许开发者定义自己的HTML元素,扩展了标准的HTML元素集合。你可以为这些自定义元素定义自己的行为、样式和功能,就像你在使用原生HTML元素(如<div><p><input>等)一样。

自定义HTML标签或元素,可以把复杂html结构样式操作封装成一个独立的标签. 类似之前我们定义的<my-button>标签一样.我们详解一下自定义元素.

以下我们都用ES6语法,因为ES5没有完整的类支持.

如何创建自定义元素

自定义元素有两种方法:

  • 扩展内置元素(Customized built-in elements ): 扩展内置HTML元素,不可以直接使用自定义标签. 只能这样使用<button is="my-button>扩展的按扭</button>" ,注意Safari不支持.
  • 独立的元素(Autonomous custom elements ): 是独立的元素,它不继承其他内建的 HTML 元素.可以写成HTML标签. 如:<my-button>自定义元素</my-button>. 我们主要使用这种方法.

参考: https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_custom_elements

注册自定义元素的API.参考: https://developer.mozilla.org/zh-CN/docs/Web/API/CustomElementRegistry

主要使用到的方法,

  1. 注册标签到浏览器

    customElements.define(name, constructor, options);
  2. 通过标签名获取自定义元素实例

    customElements.get(name)
  3. 当一个元素被定义时

    customElements.whenDefined(name).then(()=>{})

后面再详解每个方法的使用.

创建扩展内置元素

扩展内置HTML元素(Customized built-in elements),这种方案不推荐使用. 因为内置元素本身就很少已经够完善,除了语义化要求.布局的话前端通常用一个div走天下. 除了chrome系很多浏览器不在乎这种方法.

以下示例,扩展内置button按扭.

创建:

// 扩展button元素
class MyButton extends HTMLButtonElement {
    constructor() {
        super();
        console.log("初始化");
    }
    connectedCallback() {
        console.log("渲染了");
    }
}
// 注册 my-button 标签
customElements.define("my-button", MyButton, { extends: "button" });

使用:

使用,有两种方式.

  1. html标签,添加is="xxx"
<button is="my-button">按扭1</button>
  1. 通过createElement("button",{is:"xxx"})
const btn=document.createElement("button",{is:"my-button"});
btn.textContent="通过JS创建"
document.body.appendChild(btn);
  1. 直接通过实例创建

    必须在customElements.define("my-button", MyButton, { extends: "button" }); 之后,否则不能直接new
const btn2=new MyButton();
btn.textContent="通过实例创建"
document.body.appendChild(btn2);

注意:

  1. 自定义标签名必须包含-小写,以区分内置标签和自定义标签. 通常命名"组织名-功能" ,如my-button;
  2. customElements.define 必须加{extends:xxx}配置

在线案例:

Safari 浏览器或低版本浏览器看不到预览效果,使用chrome内核浏览器查看

创建独立的元素

(Autonomous custom elements) 完全自定义组件. 只继承HTMLElement. 之后web component 组件都是这种方式.

创建:

// 定义类继承HTMLElement
class MyButton extends HTMLElement{
    constructor(){
        super();
    }
    connectedCallback() {
        this.innerHTML=`<button>${this.innerHTML}</button>`;
    }
}
// 注册标签到浏览器
customElements.define('my-button', MyButton);

使用:

  1. HTML标签方式
<my-button>按扭</my-button>
  1. 通过JS创建
const btn=document.createElement("my-button");
btn.textContent="通过JS创建"
document.body.appendChild(btn);

注意:

  1. 结构与扩展内置元素不一样

image-20230814171254268

  1. 创建时不能包含子元素

    既不能直接在constructor实例之前有子元素. 像上面例子我们在connectedCallback 回调中创建.

    但我们可以使用shadowRoot来影子元素来包.

index.html:26 Uncaught DOMException: Failed to construct 'CustomElement': The result must not have children

这里引入了生命周期的概念,类似vue.

  • constructor : 组件初始实例化,document.crateElement("my-button")时触发.
  • connectedCallback: 类似onMount,标签被挂载时.document.body.appendChild(btn)时触发.

在html中<my-button></my-button> 时两个事件同时触发.

有很多问题需要解决,比如.

  1. 样式被污染或污染全局样式怎么办?
  2. 组件属性变化如何处理?
  3. 事件如何处理?
  4. 如何做一个表单组件,如input?
  5. 如何把绑定外面元素?slot如何用?
  6. .....

新开一篇专门解决这些问题. 才能封装成一个生产可用的组件.

请查看下一篇: Web Component #3 - Shadow DOM(影子 DOM)

专题大纲

  1. Web Component #1 - 自定义组件简介
  2. Web Component #2 - 自定义元素
  3. Web Component #3 - Shadow DOM(影子 DOM)
  4. Web Component #4 - template模板和Slot插槽
  5. Web Component #5 - 样式
  6. Web Component #6 - 生命周期
  7. Web Component #7 - 属性getter/setter
  8. Web Component #8 - 自定义事件
  9. Web Component #9 - 组件module封装
  10. Web Component #10 - Form表单组件
  11. Web Component #11 - Seo优化
  12. Web Component #12 - 优秀组件库推荐

原作者:阿金
本文地址:https://hi-arkin.com/archives/web-components-2.html

标签: web components customElement

(本篇完)

评论