# 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. 自定义元素可以继承的类: - 获取元素类名: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0902/225413_192c6a34_9130428.png "屏幕截图.png") - 可以使用更准确的类名,提供它特有的方法(注意写法如下示例,具体可以查看MDN): ![输入图片说明](https://images.gitee.com/uploads/images/2021/0902/225525_1c9ce9ec_9130428.png "屏幕截图.png") - (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 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0902/232235_5656b192_9130428.png "屏幕截图.png") #### HTML templates ![输入图片说明](https://images.gitee.com/uploads/images/2021/0902/232516_ed7a0db4_9130428.png "屏幕截图.png")