当前位置:   article > 正文

Web Component入门

web component怎么写

本文作者为奇舞团前端开发工程师

引言

前端开发者,现在在进行项目的开发时,一般很少使用原生的js代码,往往都会依靠Vue,React等框架进行开发,而不同的框架都有自己不同的开发规则,但是目前所使用的主流框架,都是遵循组件化开发的模式,即把不同功能的代码,拆分成不同的组件,以此来达到高内聚,低耦合,减少代码量等目的。目前主流的框架,均为是有公司或者公司开源。自己制定了一套完整的开发规范。谷歌在2011年的时候就已经提出了组件化开发的概念,即Web Component ,这个方案现在是被纳入了w3c规范之中。

如何构建

构建一个Web Component,我们需要按照以下三个步骤

1.定义模板

  1. <template>
  2.       <div>web component</div>
  3.       <button>按钮</button>
  4. </template>

我们在<template>标签内部,编辑我们组件的结构样式,这里可以类比vue的模板写法。

2.组件逻辑编写

  1. class MyWebComponent extends HTMLElement {
  2.   constructor() {
  3.     super();
  4.     // 深度克隆一份template
  5.     const content = template.content.cloneNode(true);
  6.     // 将克隆的template添加到dom树上
  7.     this.attachShadow({ mode: "closed" }).appendChild(content);
  8.   }
  9. }

这里我们需要编写一个calss,该class并且要继承于HTMLElement,然后我们在该类的构造函数里面,将我们书写的组件添加到dom树上。这里我使用attachShadow方法,再把content节点添加到dom,attachShadow的作用就是创建shadow dom,这也是web component中很重要的一个概念——影子dom,它和我们一般的dom有所不同,我们可以通过这个方法创造一个相对封闭且独立的dom,这个方法他会接收一个对象,对象的mode键值如果为closed,那么这个dom就为与外界隔离,该dom以外的脚本也无法对其进行操控,下面的图片,就向我们展示了什么是shadow dom。

a1644a08b966613f198307baebe70de7.png
介绍

3.组件注册

window.customElements.define("My-webComponent",MyWebComponent );

我们需要调用customElements.define方法,该方法接收两个参数,第一个参数是我们给组件自定义的标签名(这里我们需要注意一下,用-连接),第二个参数就是组件对应的class。

案例演示,如何编写一个单文件组件

我们有了前面的基础知识,下面,我们就采用我们前面所介绍的知识,来编写一个独立的组件。这个组件的功能也非常简单,我们通过父组件传递给子组件初始数据,进行展示,也可以由子组件,点击添加,为列表添加数据。

d5c43938bdf4d66c7d529d5cf4a88aa7.gif

既然是采用组件化的写法,我们肯定要想办法把组件抽离成一个单文件的形式,方便我们进行复用,但是由于HTML imports这个方案已经被废弃,我们无法在一个html文件里面直接引入另外一个html页面。所以,如果我们想要实现原生组件复用,就需要把代码写在一个js文件里面,引入该js文件,就等于引入了组件。

  1. //index.html
  2. <!DOCTYPE html>
  3. <html lang="en">
  4.   <head>
  5.     <meta charset="UTF-8" />
  6.     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7.     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  8.     <title>Document</title>
  9.   </head>
  10.     //引入编写好的组件,在这里引入文件,注意要添加defer关键字
  11.   <script src="./MyList/index.js" defer></script>
  12.   <body>
  13.     <div>
  14.         //使用组件
  15.       <my-list id="node">
  16.           <!--原生支持插槽  -->
  17.         <slot>web component</slot>
  18.       </my-list>
  19.     </div>
  20.     <script>
  21.         //因为是原生,所以我们需要获取dom节点行后续操作
  22.       const node = document.getElementById("node");
  23.         //我们将变量转换一下格式,就能传递给子组件
  24.       node.dataset.arr = JSON.stringify(["吃饭""睡觉"]);
  25.     </script>
  26.   </body>
  27. </html>
  1. //index.js
  2. const template = document.createElement("template");
  3. //在js文件中,我们想要书写html和css就必须要借助innerHTML,在其内部书写我们的样式和结构
  4. template.innerHTML = `
  5.   <style>
  6.     #contain {
  7.       display: flex;
  8.       flex-direction: column
  9.     }
  10.     input {
  11.       width: 200px
  12.     }
  13.   </style>
  14.   <div id="contain">
  15.     <span><slot></slot></span>
  16.     <div>
  17.      <input type="text" id=input>
  18.      <button id="mybutton" data-text1="111111">添加</button>
  19.     </div>
  20.   </div>
  21. `;
  22. class MyList extends HTMLElement {
  23.   constructor() {
  24.     //因为我们的组件继承于HTMLElement,所以需要调用super关键字  
  25.     super();
  26.     // 获取标签
  27.     const content = template.content.cloneNode(true);
  28.     const mybutton = content.getElementById("mybutton");
  29.     const input = content.getElementById("input");
  30.     const contain = content.getElementById("contain");
  31.     // 获取props
  32.     const arr = JSON.parse(this.dataset.arr);
  33.    //进行事件的监听
  34.     mybutton.addEventListener("click", () => {
  35.       arr.push(input.value)
  36.       const li = document.createElement("li");
  37.       li.innerText = input.value;
  38.       contain.appendChild(li);
  39.     });
  40.     // 将数据渲染到页面
  41.     arr.forEach((item) => {
  42.       const li = document.createElement("li");
  43.       li.innerText = item;
  44.       contain.appendChild(li);
  45.     });
  46.      //初始化一个影子dom
  47.     this.attachShadow({ mode: "closed" }).appendChild(content);
  48.   }
  49. }
  50. // 注册组件
  51. window.customElements.define("my-list", MyList);

框架

通过前面,我们就可以感受到,编写一个Web Component组件,似乎并不是十分的方便,所以我要向大家推荐一个框架 stencil.js,通过它,我们就能使用jsx的语法,更加高效快速的来编写出一个Web Component组件。从而避免使用原始的js。

优缺点

通过前面的介绍,我想大家对Web Components应该有了最基本的了解,下面就给大家简单总结一下使用它的优缺点。

优点

  1. 浏览器原生支持,不用加入任何依赖

  2. 多种场景适用,天生组件隔离

缺点

  1. 跟主流的框架相比,书写较为复杂,需要开发者自己进行原生dom操作

  2. 若要写成单文件组件,需要采用模板字符串的写法,没有语法高亮,代码提示等

- END -

关于奇舞团

奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

5d3172c2bea17390700bd47c6b0a8a42.png

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号