Web Component #2 - 自定义元素
什么是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
主要使用到的方法,
注册标签到浏览器
customElements.define(name, constructor, options);
通过标签名获取自定义元素实例
customElements.get(name)
当一个元素被定义时
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" });
使用:
使用,有两种方式.
- html标签,添加
is="xxx"
<button is="my-button">按扭1</button>
- 通过
createElement("button",{is:"xxx"})
const btn=document.createElement("button",{is:"my-button"});
btn.textContent="通过JS创建"
document.body.appendChild(btn);
直接通过实例创建
必须在
customElements.define("my-button", MyButton, { extends: "button" });
之后,否则不能直接new
const btn2=new MyButton();
btn.textContent="通过实例创建"
document.body.appendChild(btn2);
注意:
- 自定义标签名必须包含
-
小写,以区分内置标签和自定义标签. 通常命名"组织名-功能" ,如my-button
; 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);
使用:
- HTML标签方式
<my-button>按扭</my-button>
- 通过JS创建
const btn=document.createElement("my-button");
btn.textContent="通过JS创建"
document.body.appendChild(btn);
注意:
- 结构与扩展内置元素不一样
创建时不能包含子元素
既不能直接在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>
时两个事件同时触发.
有很多问题需要解决,比如.
- 样式被污染或污染全局样式怎么办?
- 组件属性变化如何处理?
- 事件如何处理?
- 如何做一个表单组件,如input?
- 如何把绑定外面元素?slot如何用?
- .....
新开一篇专门解决这些问题. 才能封装成一个生产可用的组件.
请查看下一篇: Web Component #3 - Shadow DOM(影子 DOM)
专题大纲
- Web Component #1 - 自定义组件简介
- Web Component #2 - 自定义元素
- Web Component #3 - Shadow DOM(影子 DOM)
- Web Component #4 - template模板和Slot插槽
- Web Component #5 - 样式
- Web Component #6 - 生命周期
- Web Component #7 - 属性getter/setter
- Web Component #8 - 自定义事件
- Web Component #9 - 组件module封装
- Web Component #10 - Form表单组件
- Web Component #11 - Seo优化
- Web Component #12 - 优秀组件库推荐
原作者:阿金
本文地址:https://hi-arkin.com/archives/web-components-2.html