Web Component组件化

Web Component组件化

1.什么是Web Component?

你可能听过一些框架例如:Vue/React,你也可能会知道一些组件库例如: Element-UI/Ant Design.

拿Vue举例,每一个.vue文件就是一个组件,其中每一个.vue文件中都会有一个模板<template>,最终代码会将这些模板压缩打包在一起形成一个.html文件

拿Element来说,每一个组件就是一个Web Component,可以多个合用,多次复用!

对比来说,Web Component就像是一个.vue文件,可复用/拓展性强!


2.我能用Web Component做什么?

直接上手,我们来写一个最基本的Web Component!

2.1.1自定义HTML标签

<el-dialog></el-dialog>

仿照Element-UI组件,我们自定义一个HTML标签,这就是一个自定义元素.

这里要注意:自定义元素名称要求在子其中使用破折号,不能只是一个单词!

2.1.2定义一个javascript类

自定义元素有了,接下来我们要定义一个javascript类,用来扩展HTMLElement类.

<script>
class ElDialog extends HTMLElement {
  constructor() {
    super();
  }
}
</script>

以上代码包括了:

  • 定义一个ElDialog类继承了HTML元素的特性

  • constructor()调用这个类

  • super()建立正确的原型链.

  • 你可以在这里使用javascript语法

Web文档上自定义元素的控制者是CustomElementRegistry对象-该对象允许您在页面上注册自定义元素,返回有关已注册哪些自定义元素的信息,等等.

要在页面上注册自定义元素,请使用CustomElementRegistry.define()方法.

接下来我们来注册这个自定义元素

window.customElements.define('el-dialog', ElDialog);

这样一来,我们就完成了一个自定义元素的注册了!

But~ 这个自定义元素是空的, 我们向里面加入内容

<body>
<el-dialog></el-dialog>
    
<script>
class ElDialog extends HTMLElement {
  constructor() {
    super();
      this.render();
  }
    
  render() {
      this.obj = document.createElement('div')
      this.obj.innerHTML = `
      <div class="box">
        <div class="title">这是一个标题</div>
        <div class="content">这是内容</div>
      </div>
      `
      this.append(this.obj)
  }
}
window.customElements.define('el-dialog', ElDialog);
</script>
</body>
  • 定义一个javascript函数render(),这个函数在javascript类创建时调用

  • 这个函数创建了一个<div></div>元素

  • 使用模板字符串向创建的这个div元素中插入了HTML元素,

  • this.append(this.obj): 将整个DOM结构插入了自定义元素实例

现在,你已经实现了基本的Web Component!

可是,这些数据是写死的怎么能行呢?

我们来实现动态数据:

<body>
  <el-dialog title="这是动态标题" content="这是动态内容"></el-dialog>
​
  <script>
    class ElDialog extends HTMLElement {
      constructor() {
        super();
        // 获得自定义元素的属性
        let attr = this.attributes;
        // 定义数据对象,使用三元表达式
        this._data = {
          title: attr.title ? attr.title.value : '默认的标题',
          content: attr.content ? attr.content.value : '默认内容'
        }
        this.render()
      }
​
      render() {
        this.obj = document.createElement('div')
        // 动态渲染数据
        this.obj.innerHTML = `
          <div class="box">
        <div class="title">${ this._data.title }</div>
        <div class="content">${ this._data.content }</div>
          </div>
          `
        this.append(this.obj)
      }
    }
    window.customElements.define('el-dialog', ElDialog);
  </script>
</body>

哇喔~~~现在数据已经动态渲染出来了,使用谷歌浏览器打开看一下,是不是很酷!

2.1.3进阶 template

使用上面的DOM结构,你可能会感觉有点麻烦

别急~

上面我说过 Web Component就像是一个.vue文件,可复用/拓展性强!为什么这么说呢, 一起来看接下来的代码~~~

<body>
  <el-dialog
  title="这是动态标题"
  content="这是动态内容"
  img="http://wuliwu.top/logo.png"
  ></el-dialog>
  <template id="myElDialog">
    <style>
      .box {
        display: inline-block;
        text-align: center;
        border: 1px solid #dedede;
        padding: 40px;
      }
​
      .title {
        font-size: 24px;
        color: #333;
      }
​
      .content {
        font-size: 16px;
        color: #666;
      }
    </style>
    <div class="box">
      <img>
      <div class="title"></div>
      <div class="content"></div>
    </div>
  </template>
​
  <script>
    class ElDialog extends HTMLElement {
      constructor() {
        super();
​
        var templateElem = document.getElementById('myElDialog');
        // 深度克隆
        var content = templateElem.content.cloneNode(true);
        content.querySelector('img').setAttribute('src', this.getAttribute('img'));
        content.querySelector('.title').innerHTML = this.getAttribute('title')
        content.querySelector('.content').innerText = this.getAttribute('content')
        this.appendChild(content);
      }
    }
​
    window.customElements.define('el-dialog', ElDialog);
  </script>
</body>

哦呵~~~出现了很熟悉的的东西<template> 模板标签, 里面有style样式,有DOM结构

我们来看一下效果图和DOM结构:

 

 

这样一看,是不是和.vue文件很像?

  • 有模板<template>, 有样式<style>, 有脚本<script>

  • 哪里需要哪里调用,只需调用<el-dialog>自定义元素就行了

  • 数据放在自定义元素的属性值中, 是不是感觉和 vue 中的 slot 插槽类似?

2.1.4 Shadow Dom

将Web Component的代码隐藏起来,DOM与外部DOM隔离,内部任何代码都无法影响外部.

使用方法this.attachShadow()开启Shadow DOM

<script>
class ElDialog extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow( { mode: 'closed' } );
​
    var templateElem = document.getElementById('myElDialog');
    // 深度克隆
    var content = templateElem.content.cloneNode(true);
    content.querySelector('img').setAttribute('src', this.getAttribute('img'));
    content.querySelector('.title').innerHTML = this.getAttribute('title')
    content.querySelector('.content').innerText = this.getAttribute('content')
    shadow.appendChild(content);
  }
}
​
window.customElements.define('el-dialog', ElDialog);
</script>

这样,一个完整的Web Component组件就已经完成了, 是不是很简单,没有像vue框架那么复杂.


3.Web Component的好处是什么?

Web组件是一套不同的技术,允许您创建可重用的自定义元素(其功能与其他代码封装在一起),并在Web应用程序中使用它们.

使用简单, 能够提升开发效率!


4.Web Component未来的发展方向如何?

目前而言:

  • Firefox(版本63),Chrome和Opera中默认支持Web组件。

  • Safari支持许多Web组件功能,但少于上述浏览器。

  • Edge正在实施。

  • 可以使用一些第三方库实现支持!

接下来, 让我们静待佳音,相信在不久的将来Web Component将会普及!

 

posted @ 2021-06-05 23:23  chalkbox  阅读(340)  评论(0编辑  收藏  举报