html原生元素/标签有<div>、<span>、<p>、<img>、<video>等等..., 除了这些原生元素之外, W3C还制定了Custom Elements(自定义元素)标准, 它允许用户自定义注册元素, 例如定义fl-tree来渲染树形数据, 之后就可以在原生html使用<fl-tree>来渲染数据了, 由于自定义元素是原生支持的, 所以它天然跨框架, 不管是vue还是react亦或是angular都可以使用
这里简单用原生js实现一个自定义元素fl-button
新建一个xxx.html文件, 复制下面代码, 用浏览器打开即可看到效果
<!DOCTYPE html>
<html>
<head>
<title>FL-Button Demo</title>
</head>
<body>
<!-- 默认按钮 -->
<fl-button>默认按钮</fl-button>
<!-- 主要按钮 -->
<fl-button type="primary">主要按钮</fl-button>
<!-- 成功按钮 -->
<fl-button type="success">成功按钮</fl-button>
<!-- 危险按钮 -->
<fl-button type="danger">危险按钮</fl-button>
<!-- 禁用状态 -->
<fl-button disabled>禁用按钮</fl-button>
<script>
class FlButton extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
this.attachShadow({ mode: 'open' });
// 初始化样式和结构
this.render();
}
// 监听的属性
static get observedAttributes() {
return ['type', 'disabled'];
}
// 属性变化时的回调
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.render();
}
}
// 渲染方法
render() {
const type = this.getAttribute('type') || 'default';
const disabled = this.hasAttribute('disabled');
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-block;
}
.fl-button {
padding: 8px 16px;
border-radius: 4px;
border: none;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.fl-button:hover {
opacity: 0.8;
}
.fl-button:active {
opacity: 0.6;
}
.fl-button[disabled] {
cursor: not-allowed;
opacity: 0.5;
}
/* 类型样式 */
.fl-button.default {
background-color: #e0e0e0;
color: #333;
}
.fl-button.primary {
background-color: #1976d2;
color: white;
}
.fl-button.success {
background-color: #4caf50;
color: white;
}
.fl-button.danger {
background-color: #f44336;
color: white;
}
</style>
<button
class="fl-button ${type}"
?disabled="${disabled}"
>
<slot></slot>
</button>
`;
}
}
// 注册fl-button组件
customElements.define('fl-button', FlButton);
</script>
</body>
</html>
Custom Elements和HTML Imports、HTML Template、Shadow DOM标准统称为Web component规范, 自定义元素也称为web component
这里我们一般只需关注Custom Elements和Shadow DOM, 后面再详细讲解.
web component和我们平常时用到的组件库(例如Element Plus)是有本质上的区别的:
- web component
不依赖框架, 而Element Plus只能在vue3项目中使用 - web component一般搭配Shadow DOM一起使用, 使用Shadow DOM后,
样式将被隔离, 普通的样式穿透不会影响web component的样式 (这个特性有好有坏) - web component的插槽和vue3的插槽有较大差别, web component
不支持作用域插槽 - web component是
真实注册了自定义元素, 在渲染到页面也会保留自定义元素名称, 而Element Plus的组件最后通通会被编译成原生元素
下一章讲解: 2.跨框架webcomponent组件库