【shadow dom入UI】web components思想如何应用于实际项目

简介:

回顾

经过昨天的优化处理(【前端优化之拆分CSS】前端三剑客的分分合合),我们在UI一块做了几个关键动作:

① CSS入UI

② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀,形成的组件如图所示:

这样做基本可以规避css污染的问题,解决绝大多数问题,但是更优的方案总是存在,比如web components中的shadow dom!

javascript的组件基本是不可重用的,几个核心原因是:

① 组件实例与实例之间的html、css、Javascript很容易互相污染(id污染、class污染、js变量污染......)
② 一个组件依赖于HTML、CSS、Javascript,而三者之间是分离的,而组件内部控制于js,更改后外部可能出问题
通过昨天的处理,我们将一个组件所用到的全部合到了一起,却又分离成了三个文件:

① ui.js
② ui.html
③ ui.css

这种处理一方面透露着解耦的思想,另一方面体现着解依赖的想法,在这个基础上想引入shadow dom技术,变得非常轻易。

什么是shadow dom

shadow dom是一种浏览器行为,他允许在document文档中渲染时插入一个独立的dom子树,但这个dom树与主dom树完全分离的,不会互相影响。
从一张图来看:

shadow dom事实上也是一个文档碎片,我们甚至可以将之作为jQuery包装对象处理:

存在在shadow dom中的元素是不可被选择器找到的,比如这种做法会徒劳无功:

$('沙箱中的一个元素') => []

另一个比较重要的差别是,外部为组件定义的事件,比如click事件的e.target便只能是组件div了,也就是这个组件事实上只有一层,一个标签,内部的结构不会被暴露!

引入框架

原来我们的组件是这样的结构:

1 <div id="ui-view-16" style="">
2   <div class="cm-num-adjust">
3     <div class="cm-num-adjust">
4       <span class="cm-adjust-minus js_num_minus disabled "></span><span class="cm-adjust-view js_cur_num "
5         contenteditable="true">1个</span> <span class="cm-adjust-plus js_num_plus "></span>
6     </div>
7   </div>
8 </div>

框架会主动创建一个包裹层,包裹层内才是组件dom,经过昨天的处理,组件变成了这样:

 1 <!--组件生成的包裹层-->
 2 <div id="wrapper" >
 3   <!--组件格式化后的样式-->
 4   <style>
 5   #wrapper { ......}
 6   </style>
 7 
 8   <!--组件真实的dom结构-->
 9   <div></div>
10 <div>

如果这里我们使用shadow dom技术的话,整个结构会变成这样:

1 <div id="wrapper">
2   #shadow-root
3   <style></style>
4   <div>
5   </div>
6 <div>

组件自动创建的dom包裹层,里面神马都没有了,因为事件代理是进不去的,所以开启shadow dom方式的组件需要将事件绑定至shadow节点

当然,并不是所有浏览器都支持shadow dom技术,当此之时,也不是所有的shadow dom都合适;所以UI基类需要做一个开关,最大限度的避免生产风险,而又能引入新的技术

 1 //与模板对应的css文件,默认不存在,需要各个组件复写
 2   this.uiStyle = null;
 3 
 4   //保存样式格式化结束的字符串
 5   //      this.formateStyle = null;
 6 
 7   //保存shadow dom的引用,用于事件代理
 8   this.shadowDom = null;
 9   this.shadowStyle = null;
10   this.shadowRoot = null;
11 
12   //框架统一开关,是否开启shadow dom
13   this.openShadowDom = true;
14 
15 //      this.openShadowDom = false;
16 
17   //不支持创建接口便关闭,也许有其它因素导致,这个后期已接口放出
18   if (!this.wrapper[0].createShadowRoot) {
19     this.openShadowDom = false;
20   }

基类会多出几个属性处理,shadow逻辑,然后在创建UI dom节点时候需要进行特殊处理

 1 createRoot: function (html) {
 2 
 3   this.$el = $('<div class="view" style="display: none; " id="' + this.id + '"></div>');
 4   var style = this.getInlineStyle();
 5 
 6   //如果存在shadow dom接口,并且框架开启了shadow dom
 7   if (this.openShadowDom) {
 8     //在框架创建的子元素层面创建沙箱
 9     this.shadowRoot = $(this.$el[0].createShadowRoot());
10 
11     this.shadowDom = $('<div class="js_shadow_root">' + html + '</div>');
12     this.shadowStyle = $(style);
13 
14     //开启shadow dom情况下,组件需要被包裹起来
15     this.shadowRoot.append(this.shadowStyle);
16     this.shadowRoot.append(this.shadowDom);
17 
18   } else {
19 
20     this.$el.html(style + html);
21   }
22 },

在开启shadow dom功能的情况下,便会为根节点创建shadow root,将style节点与html节点装载进去,这个时候UI结构基本出来了,事件便绑定至shadow root即可,这里是全部代码:

  View Code

基类代码改动结束,一旦开启shadow dom开关,每个组件便会走shadow逻辑,否则走原逻辑:

关闭接口的话,又变成了这个样子了:

引入shadow dom的意义

web components的提出,旨在解决UI重用的问题、解决相同功能接口各异的问题,大规模的用于生产似乎不太接地气,但是shadow dom技术对于webapp却是个好东西。

上文还只是在UI层面上应用shadow dom技术,webapp中每个view页面片如果可以应用shadow dom技术的话,各个View将不必考虑id重复污染、css样式污染、javascript变量污染,并且效率还比原来高多了,因为对于页面来说,他就仅仅是一个标签而已,如此一来,大规模的webapp的网站可能真的会到来了!

demo地址:http://yexiaochai.github.io/cssui/demo/debug.html#num

代码地址:https://github.com/yexiaochai/cssui/tree/gh-pages

博主正在学习web components技术,并且尝试将之用于项目,文中有误或者有不妥的地方请您提出




本文转自叶小钗博客园博客,原文链接:http://www.cnblogs.com/yexiaochai/p/4167554.html,如需转载请自行联系原作者

相关文章
|
14天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
20天前
|
前端开发 编解码 数据格式
浅谈响应式编程在企业级前端应用 UI 开发中的实践
浅谈响应式编程在企业级前端应用 UI 开发中的实践
20 0
浅谈响应式编程在企业级前端应用 UI 开发中的实践
|
29天前
|
机器学习/深度学习 人工智能 前端开发
机器学习PAI常见问题之web ui 项目启动后页面打不开如何解决
PAI(平台为智能,Platform for Artificial Intelligence)是阿里云提供的一个全面的人工智能开发平台,旨在为开发者提供机器学习、深度学习等人工智能技术的模型训练、优化和部署服务。以下是PAI平台使用中的一些常见问题及其答案汇总,帮助用户解决在使用过程中遇到的问题。
|
30天前
|
监控 Serverless 测试技术
Serverless 应用引擎常见问题之做的web服务计费如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
401 3
|
1月前
|
JavaScript 前端开发 算法
js开发:请解释什么是虚拟DOM(virtual DOM),以及它在React中的应用。
虚拟DOM是React等前端框架的关键技术,它以轻量级JavaScript对象树形式抽象表示实际DOM。当状态改变,React不直接操作DOM,而是先构建新虚拟DOM树。通过高效diff算法比较新旧树,找到最小变更集,仅更新必要部分,提高DOM操作效率,降低性能损耗。虚拟DOM的抽象特性还支持跨平台应用,如React Native。总之,虚拟DOM优化了状态变化时的DOM更新,提升性能和用户体验。
23 0
|
7天前
|
缓存 负载均衡 数据库
优化后端性能:提升Web应用响应速度的关键策略
在当今数字化时代,Web应用的性能对于用户体验至关重要。本文探讨了如何通过优化后端架构和技术手段,提升Web应用的响应速度。从数据库优化、缓存机制到异步处理等多个方面进行了深入分析,并提出了一系列实用的优化策略,以帮助开发者更好地应对日益增长的用户访问量和复杂的业务需求。
10 1
|
7天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
8天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
12天前
|
JavaScript 前端开发 API
Vue.js:构建高效且灵活的Web应用的利器
Vue.js:构建高效且灵活的Web应用的利器
|
20天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。