web component
如今的前端开发几乎已经离不开组件化开发了,不管是vue
中的模板语法仍是react
中的JSX
,都是把结构、样式和逻辑封装成一个组件,采用组件复用来提升开发效率。可是这一类组件在引入后可能对页面其余代码或者样式产生影响,好比引入第三方组件库elementUI
,若是页面中某个元素样式类在elementUI
样式库中存在,那么这个元素的样式就会受到elementUI
样式库的影响。WebComponents
是这类问题最好的良药,经过一种标准化的非侵入的方式封装一个组件,每一个组件能组织好它自身的 HTML
结构、CSS
样式、javascript
代码,而且不会干扰页面上的其余代码。javascript
开发者能经过 shadow DOM
在文档流中建立一些彻底独立于其余元素的子 DOM
树(sub-DOM trees)
, 因为这个特性,使得咱们能够封装一个具备独立功能的组件,而且能够保证不会在不无心中干扰到其它 DOM
元素。shadow DOM
和标准的 DOM
同样,能够设置它的样式,也能够用 javascript
操做它的行为。主文档流和基于 shadow DOM
建立的独立组件之间的互不干扰,因此组件的复用也就变得异常简单方便。html
WebComponents
除了是一个独立组件以外,还有一个很重要的优势,那就是WebComponents
能够跨语音、跨框架使用,好比咱们封装了一个WebComponent
,就能够用在vue、react
等框架中。前端
这里咱们采用vue-cli3
构建一个webcomponent
vue
建立组件comA
java
<template> <div> <span>这是组件A</span> <slot name="default"></slot>// webcomponent还支持slot </div> </template> <script> export default { name: 'comA', data() { return {} }, } </script>
建立组件comB
react
<template> <div>这是组件B</div> </template> <script> export default { name: 'comB', data() { return {} }, } </script>
配置打包脚本git
// package.json { "name": "vue", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "lib": "vue-cli-service build --target wc --name foo src/components/*/*.vue" }, "dependencies": { "core-js": "^3.4.4", "vue": "^2.6.10" }, "devDependencies": { "@vue/cli-plugin-babel": "^4.1.0", "@vue/cli-plugin-eslint": "^4.1.0", "@vue/cli-service": "^4.1.0", "@vue/eslint-config-prettier": "^6.0.0", "babel-eslint": "^10.0.3", "eslint": "^5.16.0", "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-vue": "^5.0.0", "prettier": "^1.19.1", "vue-template-compiler": "^2.6.10" }, "browserslist": [ "> 1%", "last 2 versions" ] }
执行npm run lib
,打包效果:
打包生成目录:
检验组件是否独立,咱们往demo.html
加上样式看能不能影响到comA
组件github
<meta charset="utf-8"> <title>foo demo</title> <script src="https://unpkg.com/vue"></script> <script src="./foo.js"></script> <style> span { color: red; } </style> <span>222222222</span> <foo-com-a><span slot="default">11111111</span></foo-com-a> <foo-com-b></foo-com-b>
效果:
能够看到外部样式并不能影响到独立组件web
这里调用了window
的customElements
接口来注册一个 custom element
连接:https://developer.mozilla.org...vue-cli
vue_wc_wrapper(external_Vue_default.a, comAshadow)// 返回一个继承HTMLElment的类,该类定义了元素行为 // external_Vue_default.a === Vue // comAshadow自定义的vue组件
当指定多个 Web Components 组件做为目标时,这个包可能会变得很是大,而且用户可能只想使用你的包中注册的一部分组件。这时异步 Web Components 模式会生成一个 code-split 的包,带一个只提供全部组件共享的运行时,并预先注册全部的自定义组件小入口文件。一个组件真正的实现只会在页面中用到自定义元素相应的一个实例时按需获取:
vue-cli-service build --target wc-async --name foo 'src/components/*.vue'
File Size Gzipped dist/foo.0.min.js 12.80 kb 8.09 kb dist/foo.min.js 7.45 kb 3.17 kb dist/foo.1.min.js 2.91 kb 1.02 kb dist/foo.js 22.51 kb 6.67 kb dist/foo.0.js 17.27 kb 8.83 kb dist/foo.1.js 5.24 kb 1.64 kb
如今用户在该页面上只须要引入 Vue 和这个入口文件便可:
<script src="https://unpkg.com/vue"></script> <script src="path/to/foo.min.js"></script> <!-- foo-one 的实现的 chunk 会在用到的时候自动获取 --> <foo-one></foo-one>
项目地址:https://github.com/Revelation...
参考:
https://www.cnblogs.com/vider...
https://www.cnblogs.com/Adiod...
https://developer.mozilla.org...