未加星标

理解Angular2的样式和view封装

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二04 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

Angular2是一个组件化的前端框架,通过编写一个个组件组合成一个整体的应用。他的组件是一种 Web Component 的实现方式。每一个组件的定义都包括模板和样式,Angular2在生成和渲染这个组件的时候,需要将解析后的模板的内容插入到html中,也就是将这个模板的视图view封装以后插入页面中。并且将样式的定义也插入到页面中,使它应用到组件上。在这篇文章中,我们就看看组件的样式是怎么起作用的,并且视图view是如何封装的。我们使用之前的文章 Angular2入门教程-2 实现TodoList App 的例子,来看看样式和视图。

先来看看我们的组件 TodoItemComponent 的定义:

@Component({ selector: 'todo-item', templateUrl: 'app/todo/item/item.component.html', styleUrls: ['app/todo/item/item.component.css'], styles: ['.completed { background: lightblue; }'] }) exportclassTodoItemComponent{ ... }

这个定义中,为了演示,我同时使用 styleUrls 和 styles 来定义样式。在 styles 中,加了一个class .completed { background: lightblue; } 。同时,在 styleUrls 里面的css文件里,也加了一个class:

.completed{ background: lightyellow; }

然后,打开页面,看到的效果如下:


理解Angular2的样式和view封装

完成的任务,它的颜色是浅黄色,也就是说,是css文件里面定义的样式在起作用。即使我们替换 styleUrls 和 styles 的顺序,也是css文件里的样式起作用。所以,当使用2种方式同时定义样式的时候,css文件的样式会覆盖 styles 里面定义的。

下面我们使用chrome的开发工具,看看生成html是什么样。


理解Angular2的样式和view封装

我们可以看到在这个页面的html的header里面,有几个style元素,都是各个组件中定义的样式文件,被加到了index.html里面。根据之前的实例,我们的这个应用的组件的树形结构是这样的:


理解Angular2的样式和view封装

根组件是 AppComponent , TodoListComponent 是它的子组件,列表组件又有一个子组件 TodoItemComponent 。再对应到上面的图中,有4个 style ,其中3个就是对应的 TodoItemComponent 组件的css文件样式,和它的上面2级的组件的样式,另外一个,就是上面我们为了演示加的

styles: ['.completed { background: lightblue; }']

从这个生成的页面,我们可以看出,我们的组件在显示到页面上的时候,组件定义的样式就会被添加到页面头部里面。而且,同一个组件,如果即定义了 styleUrls 的样式,也定义了 styles 的样式,通过 styleUrls 定义的样式会放在后面。如果有定义的一样的class,后面的会覆盖前面的。

在上面的开发工具看到的页面的DOM里,我们看到样式是这样的:

.completed[_ngcontent-qka-4]{ background: lightyellow; }

然后再看看DOM,找到完成的那个任务对应的元素:


理解Angular2的样式和view封装

当前完成的这个任务,用红框标出来,看到里面的DOM都包含一些属性:

<div_ngcontent-qka-4class="todo-item completed">

实际上,Angular2就是通过这些属性来实现各个组件的样式之间的隔离。因为每个组件都会根据一定的规则分配一个属性,然后在样式上,也是通过属性加class的方式来设置这个组件的某一个class的样式。从而达到的样式隔离的效果。这就是Angular2的视图封装。

实际上,Angular2提供了3种视图封装的方式,我们上面看到的效果,也就是默认的方式,我们可以在组件上添加 encapsulation 属性来设置。默认的封装方式是 ViewEncapsulation.Emulated ,完整的定义如下:

@Component({ selector: 'todo-item', templateUrl: 'app/todo/item/item.component.html', styleUrls: ['app/todo/item/item.component.css'], styles: ['.completed { background: lightblue; }'], encapsulation: ViewEncapsulation.Emulated }) exportclassTodoItemComponent{ ... }

Emulated 顾名思义就是’模拟的’,是用模拟的方式实现组件之间的隔离。在实现上,他通过给组件添加一个属性,通过属性+class的方式定义样式,不同的组件会有不同的属性值,这样就能实现样式的隔离。这显然是一个很聪明的做法。

Angular2还提供了另外两种封装方式。分别是:ViewEncapsulation.None 和ViewEncapsulation.Native。

先来看看 None :

@Component({ selector: 'todo-item', templateUrl: 'app/todo/item/item.component.html', styleUrls: ['app/todo/item/item.component.css'], styles: ['.completed { background: lightblue; }'], encapsulation: ViewEncapsulation.None }) exportclassTodoItemComponent{ ... }

然后看看页面:


理解Angular2的样式和view封装

我们看到DOM里面这个完成的任务上面没有属性了,在头部的 style 里面,定义的class上也没有属性。这就是 None 的实现方式,也就是不实现什么隔离,如果你的两个组件中,有同一个class的定义,那个这两个定义就会冲突,后面的那个就会覆盖前面的。这显然不是一个好的实现方式。

最后,我们再来看看 Native ,修改组件的封装方式:

encapsulation: ViewEncapsulation.Native

再看看页面是什么样的:


理解Angular2的样式和view封装

完成的那个任务的DOM,也就是一个 <todo-item> 的元素里面,出现了一个 shadow-root ,所有的样式和模板都在这个 shadow-root 里面。在头部,只有2个 style 元素,没有这个 TodoItemComponent 组件的样式了。

那么这个 shadow-root 是什么东西呢?它是一个 Shadow DOM 。可以阅读 这篇文章 做一个简单的了解。简单来说,它就是把html、样式,甚至脚本都封装在一个 Shadow DOM ,插入到这个组件所在的位置,然后,它里面的样式、甚至脚本都只能够在这个 Shadow DOM 里面起作用。

Shadow DOM 有些地方被翻译为影子DOM,但是还是英文的称呼更能体现它的精髓,一切只在’shadow’中进行。

有些人可能会觉得, Shadow DOM 跟 iframe 很像。iframe是把整个页面插入到一个页面中,包括完整的document和上下文,所以从实现上是非常重的,性能也不好。但是 Shadow DOM 的实现很轻量,只是添加需要的DOM元素,应用样式,同时又能实现隔离。

在Angular2中使用 Shadow DOM 还有一个性能上的优势,是在数据绑定的修改检测上。因为 Shadow DOM 把它的逻辑都封装到一个DOM里,这个DOM里面的数据修改的检测,也只是在这个DOM中。如果我们使用不可变的数据,再结合合理的数据绑定和事件,就能够大大减少数据的修改检测。

但是,这么好的东西,Angular2为什么不默认就使用呢,原因是兼容性,我们可以在这里看到 Shadow DOM 在各个浏览器中的兼容性 。IE不支持也就算了,连Firefox都不支持,Safari9的版本和iOS上的Safari也都不支持。而且 Shadow DOM 还不是W3C的正式标准,还只是处于草案阶段,所以,目前我们也只能在有限的平台去使用它,比如你用Angular2开发一个内置网页的应用,对于Android版本,就可以使用 Shadow DOM 封装视图去发布。

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: 浏览器AndroidiOS数据Firefox冲突
分页:12
转载请注明
本文标题:理解Angular2的样式和view封装
本站链接:http://www.codesec.net/view/484989.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(130)