网络异常,图片无法展示
|
1、为啥会有这一篇 ?
前两天有个同学问我,然后组内同学也即将分享相关实践内容,此处 在他之前发出(早一天发布的发布会),good!
2、是何物?
组件化
是前端非常重要的一块内容,现在流行的 React 和 Vue 都是组件框架。
谷歌 Chrome 一直在推动浏览器的原生组件,即 Web Components API。相比第三方框架,原生组件简单直接,不用加载任何外部模块,代码量小。当前发展较为成熟,在很多项目中被使用
广受好评!
3、基本概念早知道
Web Components主要由三项技术组成,分别为
- Custom elements(自定义元素)
- Shadow DOM(影子DOM)
- HTML templates(HTML模板)
- 自定义元素实例
customElements.define( 'test-custom', // name class TestCustom extends HTMLParagraphElement { // 这个类定义功能 constructor() { super(); // 功能代码 ... } }, { extends: 'p' }); // 继承自哪个元素 此处 p 复制代码
- 影子 DOM
Shadow DOM 可将隐藏的 DOM挂到一个元素上:且 shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的 DOM 元素一样
- 如下图
网络异常,图片无法展示
|
- 想将一个 Shadow DOM
附加到 custom element 怎么做?
class Button extends HTMLElement { constructor() { super(); let shadow = this.attachShadow({mode: 'open'}); // 挂到 构造函数上 } } 复制代码
- 操作一下 也是 ok 的
class Button extends HTMLElement { constructor() { super(); let shadow = this.attachShadow({mode: 'open'}); let p = document.createElement('p'); shadow.appendChild(p); } } 复制代码
- 我想添加样式 怎么办 ?
let mySelfStyle = document.createElement('style'); mySelfStyle.textContent = ` .btn-container { position: relative; } .btn { // ... } ` shadow.appendChild(mySelfStyle); 复制代码
- good !
- HTML模版
- 类似于 html 结构 和 vue slot
<html> <template> <h1><slot name="title"></slot></h1> <p><slot name="description"></slot></p> </template> </html> 复制代码
4、磨拳擦掌,怎么使用 ?
- 创建一个类或函数来指定 web 组件的功能,如果使用类,请使用 ECMAScript 2015 的类语法 (参阅类获取更多信息)。
- 使用
CustomElementRegistry.define()
方法注册您的新自定义元素,并向其传递要定义的元素名称、指定元素功能的类、以及可选的其所继承自的元素。 - 如果需要的话,使用
Element.attachShadow()
方法将一个 shadow DOM 附加到自定义元素上。使用通常的 DOM 方法向 shadow DOM 中添加子元素、事件监听器等等。 - 如果需要的话,使用
<template>
和<slot>
定义一个 HTML 模板。再次使用常规 DOM 方法克隆模板并将其附加到您的 shadow DOM 中。 - 在页面任何位置使用自定义元素,就像使用HTML DIV一样(为例)
5、实现一个 Button
- 上面那段话 请忘掉!!! , 我们 写给 Button 试试
1、创建一个类来指定 web 组件的功能
customElements.define('mark-button', Button); 复制代码
2、使用Element.attachShadow()
方法将一个 shadow DOM 附加到自定义元素上
const shadowRoot = this.attachShadow({ mode: 'open' }); const btn = document.createlement('button'); btn.appendChild(templateContent.cloneNode(true)); btn.setAttribute('class', 'mark-button'); 复制代码
3、使用 <template>
和<slot>
定义一个 HTML 模板
<template id="btn_tpl"> <slot name="btn-content">button content xxx</slot> </template> 复制代码
4、使用
<mark-button type="primary"><span slot="btn-content" id="btn_show">button test1</span></mark-button> <mark-button type="warning"><span slot="btn-content">button test2</span></mark-button> <mark-button type="default"><span slot="btn-content">button test3</span></mark-button> 复制代码
5、添加点击事件
document.querySelector('#btn_show').addEventListener('click', () => { modal.setAttribute('visible', 'true'); }, false) 复制代码
6、效果
网络异常,图片无法展示
|
- 完整代码
// index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Web Component</title> </head> <body style="padding: 60px"> <h1>Web Component 马克付</h1> <h2>1. Button</h2> <mark-button type="primary" ><span slot="btn-content" id="btn_primary" >button test1</span ></mark-button > <mark-button type="warning" ><span slot="btn-content" id="btn_danger">button test2</span></mark-button > <mark-button type="default" ><span slot="btn-content">button test3</span></mark-button > <!-- template定义区 --> <template id="btn_tpl"> <slot name="btn-content">button content xxx</slot> </template> <script src="components/button.js"></script> <script> document.querySelector('#btn_primary').addEventListener( 'click', () => { alert('我是 btn_primary ,我被点击了') }, false ) document.querySelector('#btn_danger').addEventListener( 'click', () => { alert('我是 btn_danger 我很危险') }, false ) </script> </body> </html> 复制代码
// Button.js class Button extends HTMLElement { constructor() { super(); // 获取模板内容 let template = document.getElementById('btn_tpl'); let templateContent = template.content; const shadowRoot = this.attachShadow({ mode: 'open' }); const btn = document.createElement('button'); btn.appendChild(templateContent.cloneNode(true)); btn.setAttribute('class', 'mark-button'); // 定义类型 primary | warning | default const type = { 'primary': '#06c', 'warning': 'red', 'default': '#f0f0f0' } const btnType = this.getAttribute('type') || 'default'; const btnColor = btnType === 'default' ? 'pink' : '#fff'; // 创建样式 const style = document.createElement('style'); // 为shadow Dom添加样式 style.textContent = ` .mark-button { position: relative; display: inline-block; padding:8px 20px; border-radius: 50px; margin-right: 3px; background-color: ${type[btnType]}; color: ${btnColor}; box-shadow: inset 0 5px 10px rgba(0,0,0, .3); cursor: pointer; } ` shadowRoot.appendChild(style); shadowRoot.appendChild(btn); } } customElements.define('mark-button', Button); 复制代码
- 感谢 支持 点个 star 点个赞吧 ! 祝大家暴富!