# e-web-components
**Repository Path**: ymcdhr/e-web-components
## Basic Information
- **Project Name**: e-web-components
- **Description**: Web components 相关知识点:自定义组件规范
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2021-09-02
- **Last Updated**: 2022-06-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# e-web-components
## Web Components
原生的 HTML 组件化技术;https://developer.mozilla.org/zh-CN/docs/Web/Web_Components
#### 常用的库
1. [css-doodle](css-doodle.com):
- 基于 web-components 的 css 库,用于写一些很炫酷的 css 动画效果
2. fancy-component:
- 基于 web-components 的 ui 组件库,实现了一些很炫酷的 ui 组件;
- https://unpkg.com/fancy-components@0.0.19/index.js
## Web Components 常用的几个常用概念
1. HTML Imports(已废弃)
2. HTML Modules 替代 HTML Imports(但是目前浏览器都还没实现!)
3. Custom elements 自定义元素
4. Shadow Dom
#### Custom elements 自定义元素
1. 使用场景:自定一个原生的HTML组件
2. 主要API:
- defaine:定义一个新的组件,名字里面必须要有横杠 -,用于区别HTML原生的标签
- (1)参数1:name
- (2)参数2:定义组件的class
- (3)参数3:继承的类(可选)
- get:获取指定组件
```html
// customElements.define 用于定义一个新的组件
```
- upgrade:更新一个组件
```js
const el = document.createElement('vue-react')
class MyComponent extends HTMLElement {
constructor(){
super()
// this 就是组件自己
console.log(this)
this.innerHTML = "自定义组件内容"
this.onclick = () => {
console.log("compoent:", customElements.get("my-component"))
}
}
}
// 1、自定义一个组件
// 名字里面必须要有横杠 -,用于区别HTML原生的标签
setTimeout(()=>{
customElements.define("my-component", MyComponent)
}, 2000)
// 4、upgrade
console.log(el instanceof MyComponent) // false
customElements.upgrade(el)
console.log(el instanceof MyComponent) // true
```
- whenDefined:返回组件定义成功的 Promise
```js
// 3、whenDefined 返回组件定义成功的 Promise
customElements.whenDefined('my-component')
.then(() => {
document.querySelector('my-component').innerHTML = "修改组件的内容"
})
.catch(err => console.log(err))
```
3. 针对自定义元素的 CSS 选择器
```html
Document
```
4. 自定义元素的生命周期
- connectedCallback,类似于mounted
- disconnectedCallback,类似于unMounted
- adoptedCallback,可以将某个页面的元素剪切到其他页面,例如:将iframe里面元素移到外层页面;(有跨域要求)
- update,使用 attributeChangedCallback 来进行更新数据
```js
class MyComponent extends HTMLElement {
constructor(){
super()
// this 就是组件自己
console.log(this)
this.innerHTML = "自定义组件内容"
this.onclick = () => {
console.log("compoent:", customElements.get("my-component"))
}
}
// 生命周期:类似于mounted
connectedCallback () {
}
// 生命周期:类似于unMounted
disconnectedCallback () {
}
// 生命周期:如果把自定义组件里面的内容剪切到其它地方后执行
adoptedCallback () {
}
}
// 定义组件
customElements.define("my-component", MyComponent)
// 剪切组件
const c = document.querySelector("my-component")
document.body.append(document.adoptNode(c))
```
5. 自定义元素的生命周期:update
- 使用 attributeChangedCallback 来监听组件的变化
- 它有 3 个参数:name,oldValue,newValue
```js
class MyComponent extends HTMLElement {
// 监听属性:底层使用观察者模式实现的
static observedAttributes = ['color']
constructor(){
super()
// this 就是组件自己
console.log(this)
this.innerHTML = "自定义组件内容"
this.onclick = () => {
console.log("compoent:", customElements.get("my-component"))
}
}
// 生命周期:可以实现的update方案,类似于watch了组件属性
attributeChangedCallback (name, oldValue, newValue) {
// attribute
// property
if(name === "color"){
this.style.color = newValue
}
}
}
// 定义组件
customElements.define("my-component", MyComponent)
```
6. 使用setter、getter更新组件:
```js
class MyComponent extends HTMLElement {
get color () {
return this.getAttribute("color")
}
// 触发 attributeChangedCallback
set color () {
this.setAttribute("color")
}
// 监听属性:底层使用观察者模式实现的
static observedAttributes = ['color']
constructor(){
super()
// this 就是组件自己
console.log(this)
this.innerHTML = "自定义组件内容"
this.onclick = () => {
console.log("compoent:", customElements.get("my-component"))
}
}
// 生命周期:可以实现的update方案
attributeChangedCallback (name, oldValue, newValue) {
// attribute
// property
if(name === "color"){
this.style.color = newValue
}
}
}
// 定义组件
customElements.define("my-component", MyComponent)
```
7. 自定义元素可以继承的类:
- 获取元素类名:

- 可以使用更准确的类名,提供它特有的方法(注意写法如下示例,具体可以查看MDN):

- (1)注意 define 的时候需要传递第三个参数进行 extends;
- (2)这种继承内置组件类的自定义元素不能写成自定义的名称,必须写成原标签名结合 is 属性;因为有些元素不被识别(例如自定义Option,如果写成别的名称就不会被Select识别);
- (3) **safari 不支持自定义元素继承内置组件** ,但是可以使用 [polyfill](https://gitee.com/zhangxinxu/build-in-custom-element-polyfill/) 进行兼容;
- (4)可以使用 js document 创建自定义节点,如下代码示例:
```html
```
#### Shadow DOM

#### HTML templates
