写给小白的教程之WebComponent(1)

简介: 写给小白的教程之WebComponent(1)

网络异常,图片无法展示
|

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、磨拳擦掌,怎么使用 ?

  1. 创建一个类或函数来指定 web 组件的功能,如果使用类,请使用 ECMAScript 2015 的类语法 (参阅获取更多信息)。
  2. 使用 CustomElementRegistry.define() 方法注册您的新自定义元素,并向其传递要定义的元素名称、指定元素功能的类、以及可选的其所继承自的元素。
  3. 如果需要的话,使用Element.attachShadow() 方法将一个 shadow DOM 附加到自定义元素上。使用通常的 DOM 方法向 shadow DOM 中添加子元素、事件监听器等等。
  4. 如果需要的话,使用 <template><slot> 定义一个 HTML 模板。再次使用常规 DOM 方法克隆模板并将其附加到您的 shadow DOM 中。
  5. 在页面任何位置使用自定义元素,就像使用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 点个赞吧 ! 祝大家暴富!
相关文章
|
4月前
|
存储 算法 JavaScript
IT基础知识入门:为IT小白打造的知识宝典
IT基础知识入门:为IT小白打造的知识宝典
124 4
|
6月前
|
JavaScript
小白也理解了v-on
小白也理解了v-on
|
存储 编译器 Linux
小白学习c++的的第一节课
小白学习c++的的第一节课
小白学习c++的的第一节课
|
IDE Unix Linux
小白学python(1)
小白学python(1)
|
JavaScript 前端开发 Java
【程序员小白入门】这几个宝藏菜鸟教程网站记得收藏!!!
其实菜鸟教程相关的网站内容都大同小异,推荐这几个原因是页面交互比较简单,重要的是没有任何广告。
|
存储 Serverless C++
高精度乘法(简单小白版)
高精度乘法(简单小白版)
113 0
|
Java 关系型数据库 MySQL
小白使用
一个小白怎么使用云服务器
176 1
小白使用
|
开发工具 git
小白初级入门Git教程(一)
声明:本篇文章适合刚要接触Git,使用Git的小伙伴们,大神们请轻喷。另外文章总结并参照了廖雪峰老师的讲解的知识点,有兴趣的小伙伴可以去了解了解。
119 0
|
Linux
小白使用2
远程服务器使用
133 0
|
数据采集 Java 数据挖掘
这五个坑,几乎每个学python的小白都跳过~
在私信问我该怎么学习 python,但网上这方面的资料攻略一抓一大把 例如那些知乎上年入百万已下飞机的 python 大佬,他们给的回答简直是八仙过海,各显神通
154 0
这五个坑,几乎每个学python的小白都跳过~

相关实验场景

更多