gtavcss原理

html-css013

gtavcss原理,第1张

探究 CSS 解析原理

吃早饭的时候,同事随意问了一句:你知道 CSS 是怎么解析的吗?我一头雾水。对哦,作为前端,每天都在与 CSS 打交道,我竟然忽视了最基本的原理。

一、浏览器渲染

开篇,我们还是不厌其烦的回顾一下浏览器的渲染过程,先上图:

正如上图所展示的,我们浏览器渲染过程分为了两条主线:

其一,HTML Parser 生成的 DOM 树;

其二,CSS Parser 生成的 Style Rules ;

在这之后,DOM 树与 Style Rules 会生成一个新的对象,也就是我们常说的 Render Tree 渲染树,结合 Layout 绘制在屏幕上,从而展现出来。

本文的重点也就集中在第二条分支上,我们来探究一下 CSS 解析原理。

二、Webkit CSS 解析器

浏览器 CSS 模块负责 CSS 脚本解析,并为每个 Element 计算出样式。CSS 模块虽小,但是计算量大,设计不好往往成为浏览器性能的瓶颈。

CSS 模块在实现上有几个特点:CSS 对象众多(颗粒小而多),计算频繁(为每个 Element 计算样式)。这些特性决定了 webkit 在实现 CSS 引擎上采取的设计,算法。如何高效的计算样式是浏览器内核的重点也是难点。

先来看一张图:

Webkit 使用 Flex 和 Bison 解析生成器从 CSS 语法文件中自动生成解析器。

它们都是将每个 CSS 文件解析为样式表对象,每个对象包含 CSS 规则,CSS 规则对象包含选择器和声明对象,以及其他一些符合 CSS 语法的对象,下图可能会比较明了:

Webkit 使用了自动代码生成工具生成了相应的代码,也就是说词法分析和语法分析这部分代码是自动生成的,而 Webkit 中实现的 CallBack 函数就是在 CSSParser 中。

CSS 的一些解析功能的入口也在此处,它们会调用 lex , parse 等生成代码。相对的,生成代码中需要的 CallBack 也需要在这里实现。

举例来说,现在我们来看其中一个回调函数的实现,createStyleRule(),该函数将在一般性的规则需要被建立的时候调用,代码如下:

CSSRule* CSSParser::createStyleRule(CSSSelector* selector) { CSSStyleRule* rule = 0 if (selector) { rule = new CSSStyleRule(styleElement) m_parsedStyleObjects.append(rule) rule->setSelector(sinkFloatingSelector(selector)) rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties)) } clearProperties() return rule }

从该函数的实现可以很清楚的看到,解析器达到某条件需要创建一个 CSSStyleRule 的时候将调用该函数,该函数的功能是创建一个 CSSStyleRule ,并将其添加已解析的样式对象列表 m_parsedStyleObjects 中去,这里的对象就是指的 Rule 。

那么如此一来,经过这样一番解析后,作为输入的样式表中的所有 Style Rule 将被转化为 Webkit 的内部模型对象 CSSStyleRule 对象,存储在 m_parsedStyleObjects 中,它是一个 Vector。

但是我们解析所要的结果是什么?

通过调用 CSSStyleSheet 的 parseString 函数,将上述 CSS 解析过程启动,解析完一遍后,把 Rule 都存储在对应的 CSSStyleSheet 对象中;

由于目前规则依然是不易于处理的,还需要将之转换成 CSSRuleSet。也就是将所有的纯样式规则存储在对应的集合当中,这种集合的抽象就是 CSSRuleSet;

CSSRuleSet 提供了一个 addRulesFromSheet 方法,能将 CSSStyleSheet 中的 rule 转换为 CSSRuleSet 中的 rule ;

基于这些个 CSSRuleSet 来决定每个页面中的元素的样式;

这里描述了大致过程,深入阅读可以查看如下链接:

Webkit CSS 引擎分析CSS 样式表解析过程Webkit CSS实现

三、CSS 选择器解析顺序

可能很多同学都知道排版引擎解析 CSS 选择器时是 从右往左 解析,这是为什么呢?

1.HTML 经过解析生成 DOM Tree(这个我们比较熟悉);而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。Render Tree 中的元素(WebKit 中称为「renderers」,Firefox 下为「frames」)与 DOM 元素相对应,但非一一对应:一个 DOM 元素可能会对应多个 renderer,如文本折行后,不同的「行」会成为 render tree 种不同的 renderer。也有的 DOM 元素被 Render Tree 完全无视,比如 display:none 的元素。

2.在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 renderer。对于每个 DOM 元素,必须在所有 Style Rules 中找到符合的 selector 并将对应的规则进行合并。选择器的「解析」实际是在这里执行的,在遍历 DOM Tree 时,从 Style Rules 中去寻找对应的 selector。

3.因为所有样式规则可能数量很大,而且绝大多数不会匹配到当前的 DOM 元素(因为数量很大所以一般会建立规则索引树),所以有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。

4.如果正向解析,例如「div div p em」,我们首先就要检查当前元素到 html 的整条路径,找到最上层的 div,再往下找,如果遇到不匹配就必须回到最上层那个 div,往下再去匹配选择器中的第一个 div,回溯若干次才能确定匹配与否,效率很低。

对于上述描述,我们先有个大概的认知。接下来我们来看这样一个例子,参考地址:

<div> <div class="jartto"> <p><span>111 </span></p> <p><span>222 </span></p> <p><span>333 </span></p> <p><span class='yellow'>444 </span></p> </div></div>

CSS 选择器:

div >div.jartto p span.yellow{ color:yellow}

对于上述例子,如果按从左到右的方式进行查找:

1.先找到所有 div 节点;

2.在 div 节点内找到所有的子 div ,并且是 class = “jartto”;

3.然后再依次匹配 p span.yellow 等情况;

4.遇到不匹配的情况,就必须回溯到一开始搜索的 div 或者 p 节点,然后去搜索下个节点,重复这样的过程。

这样的搜索过程对于一个只是匹配很少节点的选择器来说,效率是极低的,因为我们花费了大量的时间在回溯匹配不符合规则的节点。

如果换个思路,我们一开始过滤出跟目标节点最符合的集合出来,再在这个集合进行搜索,大大降低了搜索空间。来看看从右到左来解析选择器:

1.首先就查找到 的元素;

2.紧接着我们判断这些节点中的前兄弟节点是否符合 P 这个规则,这样就又减少了集合的元素,只有符合当前的子规则才会匹配再上一条子规则。

结果显而易见了,众所周知,在 DOM 树中一个元素可能有若干子元素,如果每一个都去判断一下显然性能太差。而一个子元素只有一个父元素,所以找起来非常方便。

试想一下,如果采用从左至右的方式读取 CSS 规则,那么大多数规则读到最后(最右)才会发现是不匹配的,这样会做费时耗能,最后有很多都是无用的;而如果采取从右向左的方式,那么只要发现最右边选择器不匹配,就可以直接舍弃了,避免了许多无效匹配。

浏览器 CSS 匹配核心算法的规则是以从右向左方式匹配节点的。这样做是为了减少无效匹配次数,从而匹配快、性能更优。

深入阅读,请移步:

jQuery 源码解析CSS 选择器从右向左的匹配规则CSS 选择器

四、CSS 语法解析过程

CSS 样式表解析过程中讲解的很细致,这里我们只看 CSS 语法解释器,大致过程如下:

1.先创建 CSSStyleSheet 对象。将 CSSStyleSheet 对象的指针存储到 CSSParser 对象中。

2.CSSParser 识别出一个 simple-selector ,形如 “div” 或者 “.class”。创建一个 CSSParserSelector 对象。

3.CSSParser 识别出一个关系符和另一个 simple-selecotr ,那么修改之前创建的 simple-selecotr, 创建组合关系符。

4.循环第3步直至碰到逗号或者左大括号。

5.如果碰到逗号,那么取出 CSSParser 的 reuse vector,然后将堆栈尾部的 CSSParserSelector 对象弹出存入 Vecotr 中,最后跳转至第2步。如果碰到左大括号,那么跳转至第6步。

6.识别属性名称,将属性名称的 hash 值压入解释器堆栈。

7.识别属性值,创建 CSSParserValue 对象,并将 CSSParserValue 对象存入解释器堆栈。

8.将属性名称和属性值弹出栈,创建 CSSProperty 对象。并将 CSSProperty 对象存入 CSSParser 成员变量m_parsedProperties 中。

9.如果识别处属性名称,那么转至第6步。如果识别右大括号,那么转至第10步。

10.将 reuse vector 从堆栈中弹出,并创建 CSSStyleRule 对象。CSSStyleRule 对象的选择符就是 reuse vector, 样式值就是 CSSParser 的成员变量 m_parsedProperties 。

11.把 CSSStyleRule 添加到 CSSStyleSheet 中。

12.清空 CSSParser 内部缓存结果。

13.如果没有内容了,那么结束。否则跳转值第2步。

五、内联样式如何解析?

通过上文的了解,我们知道,当 CSS Parser 解析完 CSS 脚本后,会生成 CSSStyleSheetList ,他保存在Document 对象上。为了更快的计算样式,必须对这些 CSSStyleSheetList 进行重新组织。

计算样式就是从 CSSStyleSheetList 中找出所有匹配相应元素的 property-value 对。匹配会通过CSSSelector 来验证,同时需要满足层叠规则。将所有的 declaration 中的 property 组织成一个大的数组。数组中的每一项纪录了这个 property 的selector,property 的值,权重(层叠规则)。

可能类似如下的表现:

p >a { color : red background-color:black} a { color : yellow} div { margin : 1px}

重新组织之后的数组数据为(weight我只是表示了他们之间的相对大小,并非实际值。)

selector property weight 1, a color:yellow 1 2, p >a color:red 2 3, p >a background-color:black 2 4, div margin:1px 3

好了,到这里,我们来解决上述问题:

首先,要明确,内敛样式只是 CSS 三种加载方式之一;

其次,浏览器解析分为两个分支,HTML Parser 和 CSS Parser,两个 Parser 各司其职,各尽其责;

最后,不同的 CSS 加载方式产生的 Style rule ,通过权重来确定谁覆盖谁;

到这里就不难理解了,对浏览器来说,内联样式与其他的加载样式方式唯一的区别就是权重不同。

深入了解,请阅读Webkit CSS 引擎分析

六、何谓 computedStyle ?

到这里,你以为完了?Too young too simple, sometimes naive!

浏览器还有一个非常棒的策略,在特定情况下,浏览器会共享 computedStyle,网页中能共享的标签非常多,所以能极大的提升执行效率!如果能共享,那就不需要执行匹配算法了,执行效率自然非常高。

也就是说:如果两个或多个 element 的 computedStyle 不通过计算可以确认他们相等,那么这些 computedStyle 相等的 elements 只会计算一次样式,其余的仅仅共享该 computedStyle 。

那么有哪些规则会共享 computedStyle 呢?

该共享的 element 不能有 id 属性且 CSS 中还有该 id 的 StyleRule,哪怕该 StyleRule 与 Element 不匹配。

tagName 和 class 属性必须一样

mappedAttribute 必须相等

不能使用 sibling selector,譬如:first-child, :last-selector, + selector

不能有 style 属性。哪怕 style 属性相等,他们也不共享

当然,知道了共享 computedStyle 的规则,那么反面我们也就了解了:不会共享 computedStyle 的规则,这里就不展开讨论了。

深入了解,请参考:Webkit CSS 引擎分析 - 高效执行的 CSS 脚本

七、眼见为实

如上图,我们可以看到不同的 CSS 选择器的组合,解析速度也会受到不同的影响,你还会轻视 CSS 解析原理吗?

感兴趣的同学可以参考这里:speed/validity selectors test for frameworks

八、有何收获?

1.使用 id selector 非常的高效。在使用 id selector 的时候需要注意一点:因为 id 是唯一的,所以不需要既指定 id 又指定 tagName:

Badp#id1 {color:red} Good #id1 {color:red}

当然,你非要这么写也没有什么问题,但这会增加 CSS 编译与解析时间,实在是不值当。

2.避免深层次的 node ,譬如:

Bad div >div >div >p {color:red} Good p-class{color:red}

3.慎用 ChildSelector ;

4.不到万不得已,不要使用 attribute selector,如:p[att1=”val1”]。这样的匹配非常慢。更不要这样写:p[id=”id1”]。这样将 id selector 退化成 attribute selector。

Bad p[id="id1"]{color:red} p[class="class1"]{color:red} Good #id1{color:red} .class1{color:red}

5.理解依赖继承,如果某些属性可以继承,那么自然没有必要在写一遍;

6.规范真的很重要,不仅仅是可读性,也许会影响你的页面性能。这里推荐一个CSS 规范,可以参考一下。

更多资源

CSS 解析顺序优先级详细探索简单剖析 CSS 的解析规则

24个金币已到账

金币可兑换现金

立即提现

子宫肌瘤怎么办?告诉你一个调理方法!直达病灶!

第一个页面:一句话:<a href="k2.html" target="_blank">第二个页面</a>

第二个页面:一句话:<a href="k3.html" target="_blank">第三个页面</a>

第三个页面:一句话:<a href="k4.html" target="_blank">第四个页面</a>

第四个页面:一句话:<a href="k5.html" target="_blank">第五个页面</a>

第物个页面:一句话:<a href="k1.html" target="_blank">第一个页面</a>

========================================================

好啦。搞定,给分!

电子商务专业的学生或许对未来总是感到迷茫,但实际上脚下的路很宽广,机会也很多,把握住了就能受益一生。 本文将从电子商务专业学生就业机会、就业层次、就业岗位三个纬度进行描述,希望能对教师的教学和学生的学习有所启发。

电子商务专业学生的就业机会

如下四种企业类型最值得关注。

1、电子商务服务企业

包括硬件(研发、生产、销售、集成)、软件(研发、销售、实施)、咨询等。随着电子商务应用的普及,相关的硬件、软件开发和销售对专业人员的需求是确定的,不过这种需求可能是显性的,也可能是隐性的。显性情况下,用人单位会明确招聘懂得电子商务的专业人才,隐性情况下,用人单位人力资源部面对市场客户的电子商务需求并不一定明确知道招聘到电子商务专业背景的人才是否正好适用,而只能让计算机等相关学科背景的人勉强应付,或要求其补充学习电子商务知识。而咨询行业因为其“与生俱来”的专业广度和深度,需求一般都比较明确。

2、 电子商务企业

对这样的企业来说,无论是纯粹专业的电子商务企业还是和其他主业结合而开辟的全新的运营模式的企业(例如西单商场),对电子商务专业人才的需求是最对口的。

3、 传统企业

对于传统企业来讲,电子商务意味着新增的运营工具(比如企业网站,现在恐怕很难找到没有网站的公司)。运行新增的运营工具的人,无非是从使用老运营工具的员工中培养和招聘来的专业人才。当然培养原来老员工的工作恐怕还是得内行的专家来进行。

4、 传统行业

对传统行业来讲,电子商务就是新的业务手段。无论贸易、物流、加工行业还是农业等都会使用到电子商务。把传统行业专门提出来讲,目的就在于,如果你有志于从事某一行业,就应该深入了解这个行业的发展状况、发展趋势、新技术、新产品,从专业的角度判断这个行业的电子商务发展水平和发展潜力。当然,要能独立做出这些判断必须对专业知识和实践能力达到一定的高度才行。

电子商务专业学生的就业层次

如下图所示,从实务层、实施层、到策划、决策层是一个从简单到复杂的过程。可以看出来,人才数量越往上越少。

实务层是指一个电子商务项目运营中的实务操作层次。

实施层是指电子商务项目的实施过程,在这个层次中,具备项目实施能力是主要要求。需要明确的是,并不是项目由一个人来全部完成,而是指能够参与甚至领导项目的某一项工作,比如流程策划、界面设计、内容架构。

策划、决策层,是指能够根据环境和企业的具体条件策划其电子商务规划,并能辅助论证、决策重大项目问题,比如采用何种支付方式、何种配送方式。

电子商务专业学生的就业岗位

以下岗位要求是对51job、电子商务人才网www.echr.com.cn)等几个网站岗位汇总整理的。并不是所有能力要求都要具备才能胜任,但是这些对岗位技能要求的描述很值得学生平时学习和训练的时候作为参考。

1、网站运营经理/主管

一般要求:熟悉网络营销常用方法,具有电子商务全程运营管理的经验;能够制定网站短、中、长期发展计划、执行与监督;能够完成整体网站及频道的运营、市场推广、广告与增值产品的经营与销售;能够完成网站运营团队的建设和管理,实现网站的战略目标、流量提升与盈利。

2、网站策划/编辑

一般要求:熟悉网站策划、实施、运营、宣传等业务流程;熟悉电子商务运营与操作流程,能够洞悉电子商务的发展方向;对企业上网有比较深的理解,熟悉企业网站的功能要求;有较强的中文功底和文字处理能力,具有一定的网站栏目策划、运营管理知识;具有较强的选题、策划、采编能力、归纳能力;熟悉电脑操作,掌握基本网络知识。

3、网站推广

一般要求:负责网站内容/网站网页设计/网站企划/网站营销企划;网站社群相关服务,内容规划及经营;会员维护及管理工作;文笔好,能够独立作市场宣传策划及文案的撰写;能够熟练运用各种宣传媒介进行宣传推广工作;

4、网站开发人员

一般要求:负责网站WEB页面的开发与后台的技术支持;能够满足运作层对技术层的需要;精通ASP/PHP/CGI 3种开发工具的一种,能够独立开发后台;精通SQL server、Access 能够独立完成数据库的开发。有1年开发经验;能后读懂常用JSP的代码,并且能够编写基本的JSP程序;精通HTML语言,完全能手写HTML代码;熟练掌握ASP、ASP.Net、JAVA、javascript、SQL SERVER、等技术;熟练掌握Windows 2000/2003、Linux/Unix其中一种操作系统;熟练掌握SQL Server,熟悉Oracle数据库管理系统;熟悉网站的管理、设计规划、前台制作、后台程序制作与数据库管理流程与技术。

这个要求是汇总了几家公司的岗位描述,应聘者不一定要具备所有的技术技能,这些技术能力是包含在几个技术体系里的。Java、.net、php等体系在实际开发中都是比较主流的,技术开发公司一般都不会采用这么多体系,会根据项目的具体要求结合各个体系的特点选择采用,也会在人才招聘和储备时从中吸收熟悉自己所采用的体系。所以,在技能学习和训练中除了把熟悉和了解各个体系作为基础外,更重要的是选择一种体系进行深入研究和开发训练。哪个体系更有前景似乎根本没有答案,现在各个体系都在被采用,甚至一个开发团队中经常会配备分别熟悉各个体系的开发人员。

5、网站设计

一般要求:能熟练的应用Flash、Dreamweaver、Photoshop、css+div、xml+xsl(不包括程序)等编辑网页;精通平面设计,熟悉FrontPage,DreamWeaver,Flash等网页制作工具,能够承担大型商业网站制作;熟悉Photoshop、Coreldraw等图形设计、制作软件,熟悉HTML、ASP语言;具备一定的视觉传达设计功底,擅长广告创意、设计在网络广告、传统媒体广告上的应用;对网站建设,VI的设计及应用有一定的经验,具有沟通、合作精神,有创造力;熟悉javascript,能够了解jsp或servlet或php,能够独立完成动态网页;掌握HTML、javascript,了解网站程序实现原理,有与程序员配合的经验。

同时我认为刚毕业的学生只要是为了学习东西,吸收经验,不能老看工资做事。

自2002年以来,最早是在网络上逐渐出现一些文章,对电子商务专业课程设置,尤其对电子商务专业大学生未来的就业前景提出质疑。这些质疑者认为:高校电子商务专业课程设置脱离了企业电子商务的实际应用情况;电子商务专业学生很难适应企业用人的实际需求 ;中国企业电子商务进程将受到人才缺乏“瓶颈”的制约 ;高校电子商务专业将会因为低就业率而失去学科发展的推动力 ;最严重的后果是:在当前中国就业形势严峻、就业压力增大的情况下,尽管国家和政府一再引导、鼓励、支持、推动大学生就业,但是数十万电子商务在读学生中的不少人将面临整体的“尚未毕业,就已失业”的现状。

2003年1月,《扬子晚报》发表了集学术机构、用人企业、高校代表、在读学生四方在内的对话文章,探讨电子商务专业人才教育与电子商务人才就业问题。当时,对话已经显示了对电子商务专业大学生未来就业前景的隐忧。时任江苏爱涛信息产业有限公司电子商务总监的方保华先生表示:“我同意电子商务专业学生就业状况不乐观的说法。我们公司目前就没有聘用大专院校输送的电子商务专业学生。但是社会需求已处于紧缺阶段,比如我们公司,企业正在扩展,这方面的人才缺口就很大。问题的关键在于院校教育现状与企业需求有一定差距。”

自2004年3月起,笔者率领的研究团队开始对高校电子商务专业学生、自学考试电子商务专业学生进行就业情况调查。通过在线调查与进入高校调查,结果显示:从整体上来看, 我国电子商务专业学生就业形势不容乐观。

截止到2004年6月15日,电子商务专业应届毕业生就业率为20%,但2003年6月中旬教育部公布的全国普通高校毕业生就业签约率已达47%,可见,电子商务专业应届毕业生就业率远远低于全国大学生就业平均水平。与此同时,劳动和社会保障部部长郑斯林在京表示 :劳动和社会保障部门将力争2004年全国应届毕业生在9月1日前平均就业率达到70%以上,而电子商务专业应届毕业生就业率距此目标还有很大差距。