组件化这个词 应该你们耳朵都听起茧巴了 在 Vue
React
Angular
三个大佬 的带领下 , 咱们前端 是否终于告别了 粘贴复制的 "组件化" 时代css
Antd
ElementUi
这些高质量 且开箱即用 的 ui 库更是让组件化开发更上一层楼. 若是不编译 或者 原生能够实现所谓的组件化吗? w3c 给了咱们 web component
的解决方案html
mdn 文档前端
做为开发者,咱们都知道尽量多的重用代码是一个好主意。这对于自定义标记结构来讲一般不是那么容易 — 想一想复杂的HTML(以及相关的样式和脚本),有时您不得不写代码来呈现自定义UI控件,而且若是您不当心的话,屡次使用它们会使您的页面变得一团糟。git
Web Components旨在解决这些问题 — 它由四项主要技术组成,它们能够一块儿使用来建立封装功能的定制元素,能够在你喜欢的任何地方重用,没必要担忧代码冲突。github
核心的四大要素web
Custom elements(自定义元素)
:一组JavaScript API,容许您定义custom elements及其行为,而后能够在您的用户界面中按照须要使用它们。canvas
Shadow DOM(影子DOM)
:一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。经过这种方式,您能够保持元素的功能私有,这样它们就能够被脚本化和样式化,而不用担忧与文档的其余部分发生冲突。api
HTML templates(HTML模板)
:<template>
和 <slot>
元素使您能够编写不在呈现页面中显示的标记模板。而后它们能够做为自定义元素结构的基础被屡次重用。浏览器
HTML Imports(HTML导入)
:一旦定义了自定义组件,最简单的重用它的方法就是使其定义细节保存在一个单独的文件中,而后使用导入机制将其导入到想要实际使用它的页面中。HTML 导入就是这样一种机制,尽管存在争议 — Mozilla 根本不一样意这种方法,并打算在未来实现更合适的。bash
浏览器为咱们内置了不少组件 , 好比 最经常使用的
input,button,select, 这也是最屌的 兼容三大框架的 ui 库 :)
以 一个 范围选择条为例
<input type="range"/> 复制代码
那么问题来了 调试器上面只显示了一个元素 它的拖拽把手(小圆点) 是哪来的呢?
接下来 打开 控制面版 (Settings) => Elements => 勾选 (Show user agent shadow DOM)
能够清楚的看到 有一些额外的 div 元素 被隐藏掉了 小圆点 和 silder 这些样式就是从这里来的 这就是所谓的 shadow DOM
,
在网页中 咱们能够写 一些内置的标记 ,他们有自带的一些样式 padding ,margin 之类的
<div/>
<p/>
复制代码
也能够写 自定义的 ,好比
<lijinke>666</lijinke>
复制代码
仍是能够被正常解析 只不过没有任何样式
认识了 上面两点, 咱们就能够 开始动手写代码了,咱们以一个卡片 (Card) 组件为例
<template id="my-card-template"> <div class="my-card"> <div class="title"> <slot name="title">代码标题</slot> </div> <pre> <slot name="content">代码内容</slot> </pre> </div> </template> 复制代码
定义一个 template 模板 再定义两个 slot 用于占位 , 能够理解成 调用组件的时候 里面的值会被替换,放心 这不是在写 Vue
这时候 保存 刷新网页, 大功告成
固然 这是不可能 接下来就是 利用 Vue-loader
new Vue({ el:"#my-card-template" }) 复制代码
好吧, 这是不可能的 ,这时候页面时一片空白
template
渲染出来首先 写一个类
class MyCard extends HTMLElement {
constructor(props) {
super();
}
}
复制代码
第一步: 而后 拿到 template 里面的内容 注意这里 不是 innerHTML,
第二步: 将template 挂载在 shadow DOM 上面 (默认打开)
若是 mode 设为 false 会没有样式
class MyCard extends HTMLElement { constructor(props) { super(); const {content:temp} = document.querySelector('#my-card-template') this.attachShadow({mode: 'open'}).appendChild(temp.cloneNode(true)); } } 复制代码
customElements.define('my-card',MyCard) 复制代码
以后就能够在 html 里面写
<my-card> <span slot="title">我是代码标题</span> <p slot="content"> const a = 1; console.log(a) </p> </my-card> 复制代码
能够看到 template 里面的 元素 变成了 shadow DOM 实现了 和 同样的 shadow DOM 的效果 , 只是尚未样式
接下来编写样式 写一点简单的 style
<template id="my-card-template"> <style> .my-card { width: 300px; height: 300px; background: #fff; box-shadow: 1px 2px 10px rgba(0, 0, 0, .3); margin: 10px } .title { height:40px; background: #dcdcdc; line-height: 40px; text-align: center; } pre { padding: 20px; } </style> <div class="my-card"> <div class="title"> <slot name="title">代码标题</slot> </div> <pre> <slot name="content">代码内容</slot> </pre> </div> </template> 复制代码
说真的 像 Vue
的三段式代码 哈哈.
Web Component 我也是出于好奇玩了玩 感受 API 很不稳定 ,兼容性不好
好比 导入组件的 方法 随时存在废除的可能性
<link type="import" href="./xx.html"> 复制代码
不过这确实是一个新的方向 和 新的可能性 做为前端 应该了解, 最近 w3c 推出来了不少新东西 , --自定义变量, css 版的 canvas api, 叫啥子我忘了, 自定义组件 , 原生模块加载, 前端的生态 是愈来愈好了, 因此
我仍是用 React
+ Node.js
哈哈