赞
踩
本文作者为奇舞团前端开发工程师
前端开发者,现在在进行项目的开发时,一般很少使用原生的js代码,往往都会依靠Vue,React等框架进行开发,而不同的框架都有自己不同的开发规则,但是目前所使用的主流框架,都是遵循组件化开发的模式,即把不同功能的代码,拆分成不同的组件,以此来达到高内聚,低耦合,减少代码量等目的。目前主流的框架,均为是有公司或者公司开源。自己制定了一套完整的开发规范。谷歌在2011年的时候就已经提出了组件化开发的概念,即Web Component ,这个方案现在是被纳入了w3c规范之中。
构建一个Web Component,我们需要按照以下三个步骤
- <template>
- <div>web component</div>
- <button>按钮</button>
- </template>
我们在<template>
标签内部,编辑我们组件的结构样式,这里可以类比vue的模板写法。
- class MyWebComponent extends HTMLElement {
- constructor() {
- super();
- // 深度克隆一份template
- const content = template.content.cloneNode(true);
- // 将克隆的template添加到dom树上
- this.attachShadow({ mode: "closed" }).appendChild(content);
- }
- }
这里我们需要编写一个calss,该class并且要继承于HTMLElement,然后我们在该类的构造函数里面,将我们书写的组件添加到dom树上。这里我使用attachShadow方法,再把content节点添加到dom,attachShadow的作用就是创建shadow dom,这也是web component中很重要的一个概念——影子dom,它和我们一般的dom有所不同,我们可以通过这个方法创造一个相对封闭且独立的dom,这个方法他会接收一个对象,对象的mode键值如果为closed,那么这个dom就为与外界隔离,该dom以外的脚本也无法对其进行操控,下面的图片,就向我们展示了什么是shadow dom。
window.customElements.define("My-webComponent",MyWebComponent );
我们需要调用customElements.define方法,该方法接收两个参数,第一个参数是我们给组件自定义的标签名(这里我们需要注意一下,用-连接),第二个参数就是组件对应的class。
我们有了前面的基础知识,下面,我们就采用我们前面所介绍的知识,来编写一个独立的组件。这个组件的功能也非常简单,我们通过父组件传递给子组件初始数据,进行展示,也可以由子组件,点击添加,为列表添加数据。
既然是采用组件化的写法,我们肯定要想办法把组件抽离成一个单文件的形式,方便我们进行复用,但是由于HTML imports这个方案已经被废弃,我们无法在一个html文件里面直接引入另外一个html页面。所以,如果我们想要实现原生组件复用,就需要把代码写在一个js文件里面,引入该js文件,就等于引入了组件。
- //index.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Document</title>
- </head>
- //引入编写好的组件,在这里引入文件,注意要添加defer关键字
- <script src="./MyList/index.js" defer></script>
- <body>
- <div>
- //使用组件
- <my-list id="node">
- <!--原生支持插槽 -->
- <slot>web component</slot>
- </my-list>
- </div>
- <script>
- //因为是原生,所以我们需要获取dom节点行后续操作
- const node = document.getElementById("node");
- //我们将变量转换一下格式,就能传递给子组件
- node.dataset.arr = JSON.stringify(["吃饭", "睡觉"]);
- </script>
- </body>
- </html>
- //index.js
- const template = document.createElement("template");
- //在js文件中,我们想要书写html和css就必须要借助innerHTML,在其内部书写我们的样式和结构
- template.innerHTML = `
- <style>
- #contain {
- display: flex;
- flex-direction: column
- }
- input {
- width: 200px
- }
- </style>
- <div id="contain">
- <span><slot></slot></span>
- <div>
- <input type="text" id=input>
- <button id="mybutton" data-text1="111111">添加</button>
- </div>
- </div>
- `;
- class MyList extends HTMLElement {
- constructor() {
- //因为我们的组件继承于HTMLElement,所以需要调用super关键字
- super();
- // 获取标签
- const content = template.content.cloneNode(true);
- const mybutton = content.getElementById("mybutton");
- const input = content.getElementById("input");
- const contain = content.getElementById("contain");
-
- // 获取props
- const arr = JSON.parse(this.dataset.arr);
- //进行事件的监听
- mybutton.addEventListener("click", () => {
- arr.push(input.value)
- const li = document.createElement("li");
- li.innerText = input.value;
- contain.appendChild(li);
- });
- // 将数据渲染到页面
- arr.forEach((item) => {
- const li = document.createElement("li");
- li.innerText = item;
- contain.appendChild(li);
- });
- //初始化一个影子dom
- this.attachShadow({ mode: "closed" }).appendChild(content);
- }
- }
- // 注册组件
- window.customElements.define("my-list", MyList);
通过前面,我们就可以感受到,编写一个Web Component组件,似乎并不是十分的方便,所以我要向大家推荐一个框架 stencil.js,通过它,我们就能使用jsx的语法,更加高效快速的来编写出一个Web Component组件。从而避免使用原始的js。
通过前面的介绍,我想大家对Web Components应该有了最基本的了解,下面就给大家简单总结一下使用它的优缺点。
浏览器原生支持,不用加入任何依赖
多种场景适用,天生组件隔离
跟主流的框架相比,书写较为复杂,需要开发者自己进行原生dom操作
若要写成单文件组件,需要采用模板字符串的写法,没有语法高亮,代码提示等
- END -
奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。