Web Components 是一种使用封装的、可重用的 HTML 标签、样式和行为来创建自定义元素的 Web 技术。
Web Components 自己本身不是一个规范,而是一套整体技术,包含下面3个独立规范:
但是,我觉得还应该包含:ES Modules。
Custom Elements 和 Shadow DOM 的可靠性是确定的,毕竟是标准的一部分。
在2008年W3C 发布了第一个HTML公开草案,其是就是可以使用自定义标签的——2000年W3C准备用XHTML来替代HTML4,结果被抛弃!
XHTML,或者更准确地说是 XHTML 1.0,是一种基于 XML 的标记语言,旨在在网页设计中取代HTML 4.01。它由 W3C 推出,其规范在2000年1月成为官方的推荐标准。XHTML1.0实际上是HTML 4.01的严格版本,并要求开发者遵循更加严格的语法规则——XHTML基于XML,它对标记的正确性有更高的要求:
在 HTML5 之前,使用非标准标签通常会被视为不良实践,因为这可能导致不可预测的行为,尤其是在不同的浏览器之间。
然而,HTML5 引入了一种更加宽容的解析规则,允许这些非标准标签存在,浏览器不会因为碰到未知标签而破坏整个页面。即使如此,这些自定义标签没有任何默认的样式或行为,它们就像普通的 HTML 元素(默认为内联元素),除非通过 CSS 或 JavaScript 给予样式和行为。
自定义标签和自定义元素是两个相关但不同的概念。它们代表着 web 开发中自定义组件的不同方面和不同阶段的发展。
自定义标签(非标准标签)
自定义标签:Custom Tags、Non-standard Tags、User-defined Tags……
自定义标签仅在语义上是自定义的,而没有附加任何特殊的行为;
自定义元素是 Web Components 规范的一部分,它允许开发者创建完全定制化和可重用的 HTML 元素。
与仅仅创建一个新的标签名不同,自定义元素能够拥有自己独特的行为和属性。
Custom Elements 规范定义了如何注册新的元素、如何附加行为、以及如何处理元素的生命周期事件(如创建、连接到文档、断开连接和属性更改时)。
自定义元素通常使用 customElements.define() 方法在 JavaScript 中注册,这样,当元素被添加到 DOM 时,就会与一个 JavaScript 类关联起来。这个类继承自 HTMLElement,允许它具备 DOM 接口的所有特性,并添加自定义的逻辑和样式。这意味着自定义元素不仅仅是形式上的定制,而是实现了真正的封装和功能拓展。
在custom element的构造函数中,可以指定多个不同的回调函数,它们将会在元素的不同生命时期被调用:
具体参看:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_custom_elements
Shadow DOM 主要目的:封装与隔离——相比iframe、frame更加轻量级。
Shadow DOM接口是关键所在:它可以将一个隐藏的、独立的DOM附加到一个元素上,它以shadow root节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的DOM元素一样,但是这棵子树不在主DOM树中——即影子DOM是一种不属于主DOM树的独立的结构,所以Shadow DOM内部的元素始终不会影响到它外部的元素(除了:focus-within),这就为封装提供了便利!
Shadow DOM都不是一个新事物,在过去的很长一段时间里,浏览器用它来封装一些元素的内部结构,以一个有着默认播放控制按钮的<video>元素为例,我们所能看到的只是一个<video>标签,实际上,在它的Shadow DOM中,包含来一系列的按钮和其他控制器。
其结构如下:
而现在,我们可以来自己制造相关的标签(如video类似的功能模块)
看这个就好:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM
但是,https://github.com/Tencent/omi等框架应该更加适合你!
这个用过vue的理解应该不难:
但是真的要用的话,还是用omi等类似的框架。
这个问题就是,为什么要用jQuery?为什么放弃jQuery使用vue或react?
其是Web Components 了解一下就好。
React 和 Vue 在组件化开发方面有自己的实现,并没有直接采用 Web Components 作为内部实现——不过,它们两者都提供了与 Web Components 兼容的接口。
下面是我个人感觉他们放弃Web Components的原因:
尽管 React 和 Vue 没有直接采用 Web Components 作为内部实现,但它们都提供了对 Web Components 的支持
2011年,Alex Russel首次提出了Web Components的概率并首次演示了demo,这时候整套技术包括三个方面:scoped css,shadow DOM和Web components。W3C也在此时开始推进Web Components规范。 2012年,HTML Template很快被实现,作为wrapper包裹内容,在页面加载时不使用,在之后运行时实例化。同时Shadow DOM V0标准发布并被实现,并且Ember和Angular开始计划支持Web Components,甚至基于它去做改造,但最终没有结果。 至2018年,Web Components在主流浏览器中均被支持,但是并未达到普及程度,具体参看:https://caniuse.com/?search=Web%20Components%20
但是,比如视频播放器、sql编辑器等超大件,还是非常适合Web Components的。不过这里还是推荐使用框架来做。
Vue 和 Web Components 是互补的技术,具体可以看官方文档:https://cn.vuejs.org/guide/extras/web-components
Vue 在 Custom Elements Everywhere 测试中取得了 100% 的分数。在 Vue 应用中使用自定义元素基本上与使用原生 HTML 元素的效果相同! Vue 提供了一个和定义一般 Vue 组件几乎完全一致的 defineCustomElement 方法来支持创建自定义元素。这个方法接收的参数和 defineComponent 完全相同。 import { defineCustomElement } from 'vue' const MyVueElement = defineCustomElement({ // 同平常一样的 Vue 组件选项——正常的 Vue 组件选项都有 props: {}, emits: {}, template: `...`, // defineCustomElement 特有的:注入进 shadow root 的 CSS styles: [`/* inlined css */`] }) // 注册自定义元素,注册之后,所有此页面中的 `<my-vue-element>` 标签 都会被升级 customElements.define('my-vue-element', MyVueElement) // 你也可以编程式地实例化元素(必须在注册之后) : document.body.appendChild( new MyVueElement({ // 初始化 props(可选) }) ) // 也可以直接使用 export default defineComponent({ setup(){ return ()=>(<my-vue-element/>) } }) 这样用,是不是非常爽!
默认情况下,Vue 会优先尝试将一个非原生的 HTML 标签解析为一个注册的 Vue 组件,如果失败则会将其渲染为自定义元素。这种行为会导致在开发模式下的 Vue 发出“failed to resolve component”的警告。所以需要告诉 Vue 将某些确切的元素作为自定义元素处理并跳过组件解析。在 vite.config.ts 配置:
{resolve: {
alias: {//组件提供模板选项,但是在 Vue 这个构建中不支持运行时编译
'vue': 'vue/dist/vue.esm-bundler.js',//需要配置你的 bundler 别名 vue: vue/dist/vue.esm-bundler.js
'@': resolve(__dirname, 'src')
}
},
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('cus-')// 以 cus- 开头的作为自定义元素处理
}
}
})]}
Provide / Inject API 和相应的组合式 API 在 Vue 定义的自定义元素中都可以正常工作。但是请注意,依赖关系只在自定义元素之间起作用。
但是为推荐费必要
在组件内部,可以像往常一样使用 <slot/> 渲染插槽。但是在解析最终生成的元素时,它只接受原生插槽语法:
说实话,react原生来写干嘛呢?
如果要在react项目里面写,推荐使用 https://lit.dev/
或者使用https://github.com/Tencent/omi/ 来写个项目,打包成组件库,然后再业务里面使用!
Lit:Lit是一个轻量的库,但它依然保留了web组件的所有特性。
Omi:Web Components 框架.
Vaadin: Vaadin 是以java作为开发语言的前端框架,它提供了一套以Web Components为基础的丰富的企业级UI组件库,关键他和spring结合的非常爽,比GWT用起来。
Ionic Framework: 本来是为Angular构建的(4.x适配Angular、Vue 、React),Ionic4 Web端基于Web Components——具有更好的运行速度,相比以前版本的Ionic框架性能提升很多!优异的性能则让 Ionic 成为了构建高性能 PWA 的最佳 UI 框架。
说实话吧,Web Components 相比周边生态还是没有起来。可以作为大型项目某些模块的补充技术!
svelte:前端框架新秀,原生支持Web Components。个人不是很了解,跳过!
Google 从 2013 年开始一直在持续推进的基于 Web Components 封装的类库,同时还开放了基于 Polymer 开发的组件集合 PolymerElements · GitHub 和开发周边。 2015 年 Google 正式发布 Polymer 1.0 ,注意时间点,当时还是Custom Elements v0 版标准 2017年Custom Elements v1 版标准在各大浏览器落地,Polymer 发布了 2.0,并且不再封装 Custom Elements API,不再默认使用shadowDOM、目标兼容各种框架,开始变成轻量级类库。
但个人觉得总体上相比与彼时流行的其他框架 Polymer 还是不温不火,Google 似乎也有同感、随着 Polymer 的轻量化升级,于是在 2018 年又发布了更现代化的 lit GitHub - lit/lit: Lit is a simple library for building fast, lightweight web components.包括 lit-html 模板渲染库 lit/packages/lit-html at main · lit/lit · GitHub和基于 lit-html 的 lit-element lit/packages/lit-element at main · lit/lit · GitHub 创建 Web Component 的 base class 。 Lit-html 基于 ES 的模板自变量和 template 标签,用注释节点去动态填充,没有JSX 转换虚拟 dom的过程,把大部分模板创建渲染的事都交给浏览器去做,提供了轻量的 api 让我们可以在 JS 中写 HTML-Templates。 Lit-Element 的 Reactive properties 、Scoped styles 等面向现代化 JS 语法的特点让他现在很受欢迎。 Google 推荐新用户使用 lit,但也将 Polymer 推到了 3.0 版本,放弃了 HTML Imports 转向 JS modules,并且支持 Polymer 跟 lit 混用,目前持续又维护和支持,Slack Channel 上一直很活跃。 除了 Google 自己, 微软的 PWA stater GitHub - pwa-builder/pwa-starter: Welcome to the PWABuilder pwa-starter! Looking to build a new Progressive Web App and not sure where to get started? This is what you are looking for!,选择 lit 框架和 封装的 Web Components 作为基础库。 Adobe 基于 LitElement 封装并开放了 Spectrum Web ComponentsSap 基于 Lit-html 封装并开源了 ui5-webcomponents/02-custom-UI5-Web-Components.md at master · SAP/ui5-webcomponents · GitHubRed hat GitHub - 1-Platform/op-components: One platform component library.等众多公司使用了 lit 开发自己的组件库或平台。 另一个类库 GitHub - skatejs/skatejs: Effortless custom elements powered by modern view libraries. 也是基于 lit-html 的。
目前生成环境使用Web Components 的案例有这些(非全部使用!)
Twitter 2016 年开始将自己的嵌入式推文 从 iframe 切换成 ShadowDOM,减少了内存消耗、加快了渲染速度,并批量渲染的时候保持丝滑。Upcoming Change to Embedded Tweet Display on Web
Youtube 作为 google 系的产品,很早就在全站用上了 Web Cmponents,并且开源了自己播放器组件 GitHub - GoogleWebComponents/google-youtube: YouTube video playback web component此外 google 开源的 Web Components 还是很多的,Google Web Components · GitHub ,包括地图、drive、日历等等。
Google Earth:
Google Earth 的网页版使用了Web Components技术来创建用户交互界面的一部分。
EA 的游戏工作室分布在全球各地,为了保证不同团队和工作室的设计开发体验统一,EA 基于 Web Components 构建了自己的 Network Design System,同时也支持这自己的 UIaaS。
github 对 Web Components 的使用很早,具体可以看: How we use Web Components at GitHub | The GitHub Blog2014 年 Custom Elements v0 specification 出现的时候 github 就开始关注:Search · topic:web-components org:github · GitHub,并且开源了其中一系列 Web Components GitHub - github/github-elements: GitHub’s Web Component collection.2017 年 Custom Elements v1 版本在 chrome 和 safari 上相继实现之后,github 开始大范围使用
要知道 github 2018 年才刚刚完全移除 jqueryRemoving jQuery from GitHub.com frontend | The GitHub Blog 这既得益于 github 自身项目组件化的架构,也 Web Components 本身与框架无关的特性非常识合作老项目升级。
github 还开源了 用于开发Web Components 的库 Catalyst:GitHub - github/catalyst: Catalyst is a set of patterns and techniques for developing components within a complex application.
而他的思路借鉴了 Stimulus 和 LitElement。
同时 github 还开源了一个 View Component 框架用来在 ruby on rails 里面构建同构应用GitHub - github/view_component: A framework for building reusable, testable & encapsulated view components in Ruby on Rails.
SalesForce 作为一家 ToB 服务的公司,面对各种不同技术栈的客户,选择 Web Components 原因有两点,一是需要一套统一的通用组件面向所有客户,二是在很多特定领域,很多客户很难对他们的传统技术体系做大规模升级,而引入 Web Components 可以避免这类技术改造风险。
他们开源了自己的 Web Components 组件库 Component Library,并提供一整套基于 的企业级研发工具 GitHub - salesforce/lwc: LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation除了通过 LWC,让客户可以在自己的环境中基于组件库配置、开发、部署应用,SalesForce 还开放了自己的 SalesForce 工作平台 ,平台为所有客户提供一站式配置、部署和升级的能力。
Oracle 在 2017 年开始在自己的 GitHub - oracle/oraclejet: Oracle JET is a modular JavaScript Extension Toolkit for developers working on client-side applications. 构建工具中增加了对 CustomElement 的支持,在此之前是用的是 jQueryUI。Oracle 对 WebComponents 对态度其实很值得 ToB 同行学习,他并没有刻意想拜托 jQuery,而是让 WebComponents 与现有的 jQuery、Knockout 并行使用,只在新功能上推进 WebComponents ,保持老项目稳定,在历史遗留和新技术之间保持了合理的平衡。而在 jet 的生态方面,他们也在持续建设 Web Component 驱动的共享组件中心 Building the future of Oracle JET Ecosystem | by João Tiago | Digital Transformation Research Group | Medium
ING:
荷兰国际集团(ING)在他们的网站和网上银行平台中大量使用了 Web Components,他们通过使用 Lion Web Components 库共享跨项目的UI组件。
Comcast 的 Xfinity产品线中的某些web应用使用了 Web Components。
该站点是一个基于 Web Components 的 UI 框架产品
参考文章:
神奇的Shadow DOM https://jelly.jd.com/article/6006b1045b6c6a01506c87ac
Vue3.2 实现 Web Components https://ainyi.com/125
https://www.albertaz.com/blog/web-components-ststus
转载本站文章《Web Components从技术解析到生态应用个人心得指北》, 请注明出处:https://www.zhoulujun.cn/html/webfront/SGML/htmlBase/2012_0823_9020.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。