- 浏览: 962543 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
sscsacdsadcsd:
mike8625 写道react还要自己的一些标签 还得编译 ...
对于React体系的一点想法 -
mike8625:
说的都是给大公司听的,国内很多还是小公司,做个小项目, 说实话 ...
关于国内前端和JS技术发展的乱想 -
mike8625:
react还要自己的一些标签 还得编译 编译吧浏览器端说还慢 ...
对于React体系的一点想法 -
u012814086:
下意识想到了Golang
JavaScript语句后应该加分号么? -
xueduanyang:
我是水羊,年轻的时候觉得只要有好斧子就能做成好产品,各种产品都 ...
关于国内前端和JS技术发展的乱想
fins同志向我提了个问题。因这个问题其实可以展开讨论,所以提出来大家共同探讨。
在同类元素 例如 td 很多的情况下, "一次性改变元素的class对应的styleSheet"
和 "在循环里改变每一个元素style" 哪个更好
ext的代码不知道你看过没
在ext 1 里 改变表格列宽的方式 就是用的 改变那一列的 td对应的class里的 width
而ext 2里变成了 用循环 依次改变每一个 td的style.width
两种方法哪个好呢? 我一直喜欢第一种
不过实在不明白为什么 ext 2里换了方式
对于这一问题,我的意见是,就这个个例来说,两种方式都不好。因为table中一个column的width不应该在每个td上都做设置,而应该设置在table的col或colgroup元素上。注意,col元素上有效的css prop是很少的,这关系到另一个问题,这里不做展开,不过,width恰好属于那少数几个有效的css prop之一。
当然,我对ext不熟,不知道在ext上是否能做这件事情。比方说如果ext产生的datagrid并不用col/colgroup,那你就干不了这个事情。但是有个变通方式。对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。所以,可以把width设在第一行对应的td上。
本身,这个问题大体就是这样了。但是我想fins提出的这个问题,其实有更广泛的意义。那就是对于批量动态修改style,到底采取哪种方式好。
批量修改style的具体形式千变万化,但是万变不离其宗,归根到底就是两种:
A. 动态修改多个元素。
B. 动态修改stylesheet上的单个cssdeclaration。
差别就是,前者选择待修改元素的集合(符合条件的snapshot)的过程是由脚本完成的(比如用一个getElementsByTagName选出一批元素,现在有了jQuery之类的,就更方便了,直接拿css selector来选择元素集合),并需要遍历所有元素一一进行修改;而后者选择待修改对象集合(这个集合是live的)的过程是由css selector自动完成的,然后style的变更也是自动分发到所有对象的。
这两种方式本身,在具体实践时还有一些可以注意的地方。
比如对于A方式来说,直接修改inline style实际上是把style混入了script中,味道通常不好,可考虑在stylesheet中创建若干个class来表示几组不同的style,然后script中只要修改className就好。这适合那些样式切换的需求,因为样式切换往往隐含语义,所以确实也应该用class来显式的标记这些语义。但是对于修改width这样的例子,就并不适合了。修改width,是一个纯粹UI上的操作,它并不带有语义价值(我指对应用的功能来说UI并不significant——当然某些应用除外,例如UI编辑器)。
又如对于B方式来说,我们应该记得,selector很好很强大,因此不要老是给许多元素码上无数的class,完全可以用其他的selector方式,例如父子关系的,不必每个li都li class=mylist,完全可以ul class=mylist,然后样式表写ul.mylist>li{...}。
如果这些地方都注意了,你会发现,真正需要批量修改的地方其实很少。大多数场合,只需要修改某个父级元素的className就可以了。
我们下面谈论的是除了这些情况之外,真正需要批量修改style的地方。
一种比较理论化的方案,是判断真正的需求,是要批量修改符合特定模式(实际是根据语义来匹配)的某些元素的样式(采用方式B),还是批量修改只是临时碰巧符合某个结构的(实际上没有持久有效的语义,甚至可能是随机的,比如由用户临时指定的)一批元素的属性(采用方式A)。但是许多时候,这个界限并不清楚,或者难以明确。就好象,在写样式表的时候,我是写
div#div1 {font-size:small}
div#div2 {font-size:small}
div#div3 {font-size:small}
还是抽象出一个div.class1,然后
div.class1 {font-size:small}
这个事情脱离环境,是无法判断的!因为有时候你知道这里要达到这个效果,但是你并没有花精力去判断,font-size为small这个事情是纯粹偶然,还是这三个div真的具有某种一体的联系?况且,很多时候,追究这一点是不经济的(或者根本不可能,比如身为程序员的你无法找到真正懂需求的人,或者做UI设计的人根本没有这个概念,无法回答你的问题)。
撇开对“需求的真正含义”的判断,我们假设,就个案来说已经存在确定的匹配模式(不管它有语义还是碰巧),也就是说不考虑你进行额外抽象的负担(比如原来页面上并没有某个class,而你决定额外加入一个class,并给一些元素加上class——这不仅是一种额外负担,在匹配模式其实是碰巧的情况下,长久来看其实可能是起了反作用),然后来关注纯技术层面的问题,那么:
通常来说,B方式看上去更好一些。fins同志也是这样认为的。因为它只修改了一处,而且这个修改是单点可控的,不可能受到外部因素的破坏。而方式A则没有那么安全,因为样式与元素的匹配,只是一次性的,不存在始终有效的绑定。如果在完成批量改变style的操作之后,我们可能某个时候要再做一次操作批量去除所附加的style。其潜台词是在这个期间,这些元素仍旧符合原先所设的条件。
如果元素由于某种外部因素的影响,不再符合原始的条件(例如一个元素被移动到了DOM树的其他地方),或者有新的符合条件的元素出现(例如插入了一个新元素),既有的约定就被破坏了,结果自然是可能出现bug,而且几乎无法跟踪。即使你可以监听某些变化,成本也非常之高。使用css selector的jQuery之类的,尤其如此,因为css selector的模式匹配是如此强大,以至于完全无法track一个元素是否发生了一个变化就不再匹配既定模式了。
所以实际上,采用A方式,意味着DOM结构(包括所有影响你选择元素集合的因素)至少在一定范围内最好是静态的。幸好,这个需求在许多应用中还是符合的,在受控的框架中通常也是可以保证的。还有一个例子是组件库,组件内部的DOM结构一般是确定不变的,然后可变的部分已经被封装为它的外部接口了。对于组件来说,使用A方式还有一个副作用是,它能隔绝外部css对它内部元素的样式的影响,因为inline style优先级最高。当然组件可以正常工作的前提是,你的代码(或者你用的第三方代码)不会破坏它的封装,比如不破坏它内部的DOM结构。这一点其实存在一点隐患,比如假设你搞来一个自动圆角的库,然后加诸于某个组件之上,因为这个圆角库会自动插入一堆b啦i啦的元素,结果你的脆弱的组件就完蛋了。
而B方式,因为它依赖的是声明性的selector,模式匹配是自动的,所以没有A方式的问题。DOM结构你随便变吧。但是B方式并不是没有自己的问题。首先,stylesheet是全局的,对于一个rule修改所产生的影响也是全局的。在现有的CSS中缺乏将一部分style局域化的能力(CSS 3有草案http://www.w3.org/TR/css-style-attr,html5中有对style元素的局域化定义,但是得到浏览器普遍支持还需时日)。而组件需要局域化style。现在我们需要用id或者class来限定stylesheet的scope。就ext的例子来说,它需要td上有一个class,而且每个table上的class都不能一样。维护局域化标识,同时在全局stylesheet中维护局域化的style,这样的操作,其实是较为复杂的一件事情,目前似乎还没有一个库提供这方面的支持。
其次,A方式的stylesheet是静态的,而B方式的stylesheet是动态的。既然stylesheet是一种声明性的东西,那么通常stylesheet本身就倾向于保持静态。这允许一些针对stylesheet的前处理和后处理。比如dean edwards的IE7,它会重新解析stylesheets。而我之前也写过预编译stylesheet来产生兼容ie的css的思路。然而,如果stylesheet是动态可变的,对这些方案就存在很大的挑战。因为监听stylesheet的变化如果不是不可能,那至少是非常非常困难的。而且无论是跟踪你修改的rules对应哪些实际的rules,还是整个重新编译样式表,成本可能都很巨大。要解决这个问题,需要投入很大的努力。(dean edwards的IE7还有更严重的问题,因为它实际上内部是使用A方式的,所以是对AJAX不友好的,不过这与这里的讨论关系不大。)
以上,就是我对fins所提出的问题所做的一些考虑。结论其实是,首先看看是否你真的需要批量修改style。也许有90%的情况,你应该改为修改单一元素上的一个className。又有90%的情况,你可能只需修改单一元素上的inline style。虽然jquery、mootools、prototype等框架先后提供了css selector的功能,未来浏览器甚至会提供原生的querySelector功能,但是没有必要滥用这个能力。
剩下1%的情形,那就要根据你的情况进行权衡。理想上,方式B更好一些,但是也存在一些现实问题。更多时候,我们见到的是大量方式A的写法,因为带有selector query功能的工具使得这样做更容易,而且在绝大多数时候,方式A也是可行的。
其实,我们期望的理想的编程方式也许是这样:http://hax.iteye.com/blog/164614。
Great question.
我也想过这个问题,比如我修改了body上的一个class,到底会发生什么事情。这实际上得去看浏览器的CSS引擎是怎么实现的。我没看过,所以回答不能算权威。
现在我只能做一些大体定性的判断。
首先native调用通常比js调用要快上几个数量级。
其次,我原文也加上了“同等条件下”,如果浏览器需要遍历所有元素来判断class的话,那js程序也一样,如果js程序自己存着一个数组,而不做任何模式匹配,这个比较就不是同等条件了。不过考虑到native调用实在比js快,比如js做一个循环就要花上不少时间,所以基本上可以肯定还是native的快。
其三,CSS本来就是一个很复杂的机制(虽然用的人很爽),所以引擎必然做了很多优化,不会每次变化都去遍历所有元素,重新计算所有的规则和最终的样式。
比如,如果我来实现引擎的话,可能会让每个cssrule对象内部保持着所有适用rule的selector的元素的引用数组,然后如果rule的cssdeclaration发生变化,就通知每个元素重新计算cascade后的样式。按照我之前写的selector api,也许代码类似这样(用JS表示):
rule.selector.getAll().forEach(function(e){e.recalcStyle()});
而recalcStyle肯定也可以做优化,而不必重新计算所有该元素适用的rule。比如只需要计算原来的cssdeclaration和现在的cssdeclaration中有不同的css properties。计算完成之后,再把变更部分通知到render引擎,render引擎进行页面的重绘。注意,这里recalcStyle的计算过程,以及页面重绘过程都可以是异步的。
假如selector部分发生变化,就复杂一点,因为要重新匹配。然而,考虑到这件事情JS也能做,比如所有的JS类库的querySelector功能干的都是这个事情,他们的算法在不断优化性能不断提高,那native的实现不用说干起来肯定快上不知多少!比如说,有些优化,JS做不到或者很难办的,对于native来说却轻而易举,例如,你可以给所有的class做索引,从一个hashmap里根据className反查,这样一个带有class的selector匹配起来根本不用遍历所有元素。总之,这个selector查询问题,就跟sql查询一样,有很多优化可以做。
相比较而言,最困难的一点,大概是我所说的问题,修改了body上的一个class,也就是DOM元素或属性的结构变化,也就是我前面说的selector match/unmatch的监听问题。因为理论上,一个元素发生某种结构变化时,它本身,它的所有子节点,它的sibling节点(主要是后续的兄弟节点)及其子节点,所有这些节点的匹配都可能发生变化。所有这些节点的所有selector匹配都要重新计算。当然也可能存在某种优化方式,例如如果只是一个class变更,那么只需要计算所有selector中包含这个class条件的那些selector,但是窃以为这种优化如果超出class之外就实在非常的困难,也许反而不美。
然而这样困难的问题,在现在所有浏览器中都得到了解决,而且我们日常所最常用的方式,恰恰是修改class这样的操作。所以其他问题跟这个比起来,也许不值一提了。
顺便说一句,至少IE中,class确实是受到特殊待遇的。比如通过CSS绑定的htc,当selector匹配生效或失效的时候,样式虽然会立即生效或失效(实际是异步的),但是htc并不会被自动attach和detach,这一点有些奇怪,也许是出于性能考虑,也许根本就是一个bug。为了强制进行重新计算,你可以这样:
也就是,className的变更,会触发元素对于其本身适用的样式进行刷新。
FF早就支持了。但是正如我之前所说的,它对于col/colgroup上的css prop的支持有限,比如它不支持col/colgroup上的text-align。它也不支持html规范中所列出的align属性,因为本质上,FF是一个CSS浏览器而不是一个HTML浏览器,所以如果一个属性的格式化要求无法被转化为CSS,则就不可能得到支持。也许因此造成你有印象FF不支持col。
但是这是有原因的,我一直想写一篇blog来分析一下这个问题,不过一直没写。各位可直接看https://bugzilla.mozilla.org/show_bug.cgi?id=915,你可以注意到这个bug的编号是915,也就是很老很老很老很老的一个问题,实际上日期是1998-09-26,也就是说,至少10年以前那个时候(那时候我还在用386混DOS,根本上不了网,要用浏览器还得钻学校机房2块钱1小时啊),Mozilla已经支持col,否则就没有这个bug了。简单的原因可以看CSS21作者hixie的解说。各位不喜看英文的朋友,可暂时看看这个:http://forum.moztw.org/viewtopic.php?t=3905。
fins 写道
在同类元素 例如 td 很多的情况下, "一次性改变元素的class对应的styleSheet"
和 "在循环里改变每一个元素style" 哪个更好
ext的代码不知道你看过没
在ext 1 里 改变表格列宽的方式 就是用的 改变那一列的 td对应的class里的 width
而ext 2里变成了 用循环 依次改变每一个 td的style.width
两种方法哪个好呢? 我一直喜欢第一种
不过实在不明白为什么 ext 2里换了方式
对于这一问题,我的意见是,就这个个例来说,两种方式都不好。因为table中一个column的width不应该在每个td上都做设置,而应该设置在table的col或colgroup元素上。注意,col元素上有效的css prop是很少的,这关系到另一个问题,这里不做展开,不过,width恰好属于那少数几个有效的css prop之一。
当然,我对ext不熟,不知道在ext上是否能做这件事情。比方说如果ext产生的datagrid并不用col/colgroup,那你就干不了这个事情。但是有个变通方式。对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。所以,可以把width设在第一行对应的td上。
本身,这个问题大体就是这样了。但是我想fins提出的这个问题,其实有更广泛的意义。那就是对于批量动态修改style,到底采取哪种方式好。
批量修改style的具体形式千变万化,但是万变不离其宗,归根到底就是两种:
A. 动态修改多个元素。
B. 动态修改stylesheet上的单个cssdeclaration。
差别就是,前者选择待修改元素的集合(符合条件的snapshot)的过程是由脚本完成的(比如用一个getElementsByTagName选出一批元素,现在有了jQuery之类的,就更方便了,直接拿css selector来选择元素集合),并需要遍历所有元素一一进行修改;而后者选择待修改对象集合(这个集合是live的)的过程是由css selector自动完成的,然后style的变更也是自动分发到所有对象的。
这两种方式本身,在具体实践时还有一些可以注意的地方。
比如对于A方式来说,直接修改inline style实际上是把style混入了script中,味道通常不好,可考虑在stylesheet中创建若干个class来表示几组不同的style,然后script中只要修改className就好。这适合那些样式切换的需求,因为样式切换往往隐含语义,所以确实也应该用class来显式的标记这些语义。但是对于修改width这样的例子,就并不适合了。修改width,是一个纯粹UI上的操作,它并不带有语义价值(我指对应用的功能来说UI并不significant——当然某些应用除外,例如UI编辑器)。
又如对于B方式来说,我们应该记得,selector很好很强大,因此不要老是给许多元素码上无数的class,完全可以用其他的selector方式,例如父子关系的,不必每个li都li class=mylist,完全可以ul class=mylist,然后样式表写ul.mylist>li{...}。
如果这些地方都注意了,你会发现,真正需要批量修改的地方其实很少。大多数场合,只需要修改某个父级元素的className就可以了。
我们下面谈论的是除了这些情况之外,真正需要批量修改style的地方。
一种比较理论化的方案,是判断真正的需求,是要批量修改符合特定模式(实际是根据语义来匹配)的某些元素的样式(采用方式B),还是批量修改只是临时碰巧符合某个结构的(实际上没有持久有效的语义,甚至可能是随机的,比如由用户临时指定的)一批元素的属性(采用方式A)。但是许多时候,这个界限并不清楚,或者难以明确。就好象,在写样式表的时候,我是写
div#div1 {font-size:small}
div#div2 {font-size:small}
div#div3 {font-size:small}
还是抽象出一个div.class1,然后
div.class1 {font-size:small}
这个事情脱离环境,是无法判断的!因为有时候你知道这里要达到这个效果,但是你并没有花精力去判断,font-size为small这个事情是纯粹偶然,还是这三个div真的具有某种一体的联系?况且,很多时候,追究这一点是不经济的(或者根本不可能,比如身为程序员的你无法找到真正懂需求的人,或者做UI设计的人根本没有这个概念,无法回答你的问题)。
撇开对“需求的真正含义”的判断,我们假设,就个案来说已经存在确定的匹配模式(不管它有语义还是碰巧),也就是说不考虑你进行额外抽象的负担(比如原来页面上并没有某个class,而你决定额外加入一个class,并给一些元素加上class——这不仅是一种额外负担,在匹配模式其实是碰巧的情况下,长久来看其实可能是起了反作用),然后来关注纯技术层面的问题,那么:
通常来说,B方式看上去更好一些。fins同志也是这样认为的。因为它只修改了一处,而且这个修改是单点可控的,不可能受到外部因素的破坏。而方式A则没有那么安全,因为样式与元素的匹配,只是一次性的,不存在始终有效的绑定。如果在完成批量改变style的操作之后,我们可能某个时候要再做一次操作批量去除所附加的style。其潜台词是在这个期间,这些元素仍旧符合原先所设的条件。
如果元素由于某种外部因素的影响,不再符合原始的条件(例如一个元素被移动到了DOM树的其他地方),或者有新的符合条件的元素出现(例如插入了一个新元素),既有的约定就被破坏了,结果自然是可能出现bug,而且几乎无法跟踪。即使你可以监听某些变化,成本也非常之高。使用css selector的jQuery之类的,尤其如此,因为css selector的模式匹配是如此强大,以至于完全无法track一个元素是否发生了一个变化就不再匹配既定模式了。
所以实际上,采用A方式,意味着DOM结构(包括所有影响你选择元素集合的因素)至少在一定范围内最好是静态的。幸好,这个需求在许多应用中还是符合的,在受控的框架中通常也是可以保证的。还有一个例子是组件库,组件内部的DOM结构一般是确定不变的,然后可变的部分已经被封装为它的外部接口了。对于组件来说,使用A方式还有一个副作用是,它能隔绝外部css对它内部元素的样式的影响,因为inline style优先级最高。当然组件可以正常工作的前提是,你的代码(或者你用的第三方代码)不会破坏它的封装,比如不破坏它内部的DOM结构。这一点其实存在一点隐患,比如假设你搞来一个自动圆角的库,然后加诸于某个组件之上,因为这个圆角库会自动插入一堆b啦i啦的元素,结果你的脆弱的组件就完蛋了。
而B方式,因为它依赖的是声明性的selector,模式匹配是自动的,所以没有A方式的问题。DOM结构你随便变吧。但是B方式并不是没有自己的问题。首先,stylesheet是全局的,对于一个rule修改所产生的影响也是全局的。在现有的CSS中缺乏将一部分style局域化的能力(CSS 3有草案http://www.w3.org/TR/css-style-attr,html5中有对style元素的局域化定义,但是得到浏览器普遍支持还需时日)。而组件需要局域化style。现在我们需要用id或者class来限定stylesheet的scope。就ext的例子来说,它需要td上有一个class,而且每个table上的class都不能一样。维护局域化标识,同时在全局stylesheet中维护局域化的style,这样的操作,其实是较为复杂的一件事情,目前似乎还没有一个库提供这方面的支持。
其次,A方式的stylesheet是静态的,而B方式的stylesheet是动态的。既然stylesheet是一种声明性的东西,那么通常stylesheet本身就倾向于保持静态。这允许一些针对stylesheet的前处理和后处理。比如dean edwards的IE7,它会重新解析stylesheets。而我之前也写过预编译stylesheet来产生兼容ie的css的思路。然而,如果stylesheet是动态可变的,对这些方案就存在很大的挑战。因为监听stylesheet的变化如果不是不可能,那至少是非常非常困难的。而且无论是跟踪你修改的rules对应哪些实际的rules,还是整个重新编译样式表,成本可能都很巨大。要解决这个问题,需要投入很大的努力。(dean edwards的IE7还有更严重的问题,因为它实际上内部是使用A方式的,所以是对AJAX不友好的,不过这与这里的讨论关系不大。)
以上,就是我对fins所提出的问题所做的一些考虑。结论其实是,首先看看是否你真的需要批量修改style。也许有90%的情况,你应该改为修改单一元素上的一个className。又有90%的情况,你可能只需修改单一元素上的inline style。虽然jquery、mootools、prototype等框架先后提供了css selector的功能,未来浏览器甚至会提供原生的querySelector功能,但是没有必要滥用这个能力。
剩下1%的情形,那就要根据你的情况进行权衡。理想上,方式B更好一些,但是也存在一些现实问题。更多时候,我们见到的是大量方式A的写法,因为带有selector query功能的工具使得这样做更容易,而且在绝大多数时候,方式A也是可行的。
其实,我们期望的理想的编程方式也许是这样:http://hax.iteye.com/blog/164614。
评论
13 楼
storm119
2008-02-25
实在是看不完。
12 楼
hax
2008-02-25
fins 写道
问题再次延伸!
当 styleSheet 里的 class的内容变化时
浏览器内部是怎么刷新响应的页面元素的?
会不会是 遍历所有的 页面元素, 如果元素的class含有被改变的class那么就刷新?
如果是这样 那页面元素非常多非常多的时候 会不会出现比 js调用更慢的情况呢?
毕竟js调用是有目的的, 例如一个列表1000行 那么js遍历的就是1000个td
而native调用是遍历所有的页面元素.
也就是说 当页面复杂到一定程度 会不会出现native调用比js调用更慢的情况呢?
hax 写道
同等条件下,性能应该是改样式表要快。因为这个变更分发是由浏览器做的,肯定是native调用,比JS调用要快。
当 styleSheet 里的 class的内容变化时
浏览器内部是怎么刷新响应的页面元素的?
会不会是 遍历所有的 页面元素, 如果元素的class含有被改变的class那么就刷新?
如果是这样 那页面元素非常多非常多的时候 会不会出现比 js调用更慢的情况呢?
毕竟js调用是有目的的, 例如一个列表1000行 那么js遍历的就是1000个td
而native调用是遍历所有的页面元素.
也就是说 当页面复杂到一定程度 会不会出现native调用比js调用更慢的情况呢?
Great question.
我也想过这个问题,比如我修改了body上的一个class,到底会发生什么事情。这实际上得去看浏览器的CSS引擎是怎么实现的。我没看过,所以回答不能算权威。
现在我只能做一些大体定性的判断。
首先native调用通常比js调用要快上几个数量级。
其次,我原文也加上了“同等条件下”,如果浏览器需要遍历所有元素来判断class的话,那js程序也一样,如果js程序自己存着一个数组,而不做任何模式匹配,这个比较就不是同等条件了。不过考虑到native调用实在比js快,比如js做一个循环就要花上不少时间,所以基本上可以肯定还是native的快。
其三,CSS本来就是一个很复杂的机制(虽然用的人很爽),所以引擎必然做了很多优化,不会每次变化都去遍历所有元素,重新计算所有的规则和最终的样式。
比如,如果我来实现引擎的话,可能会让每个cssrule对象内部保持着所有适用rule的selector的元素的引用数组,然后如果rule的cssdeclaration发生变化,就通知每个元素重新计算cascade后的样式。按照我之前写的selector api,也许代码类似这样(用JS表示):
rule.selector.getAll().forEach(function(e){e.recalcStyle()});
而recalcStyle肯定也可以做优化,而不必重新计算所有该元素适用的rule。比如只需要计算原来的cssdeclaration和现在的cssdeclaration中有不同的css properties。计算完成之后,再把变更部分通知到render引擎,render引擎进行页面的重绘。注意,这里recalcStyle的计算过程,以及页面重绘过程都可以是异步的。
假如selector部分发生变化,就复杂一点,因为要重新匹配。然而,考虑到这件事情JS也能做,比如所有的JS类库的querySelector功能干的都是这个事情,他们的算法在不断优化性能不断提高,那native的实现不用说干起来肯定快上不知多少!比如说,有些优化,JS做不到或者很难办的,对于native来说却轻而易举,例如,你可以给所有的class做索引,从一个hashmap里根据className反查,这样一个带有class的selector匹配起来根本不用遍历所有元素。总之,这个selector查询问题,就跟sql查询一样,有很多优化可以做。
相比较而言,最困难的一点,大概是我所说的问题,修改了body上的一个class,也就是DOM元素或属性的结构变化,也就是我前面说的selector match/unmatch的监听问题。因为理论上,一个元素发生某种结构变化时,它本身,它的所有子节点,它的sibling节点(主要是后续的兄弟节点)及其子节点,所有这些节点的匹配都可能发生变化。所有这些节点的所有selector匹配都要重新计算。当然也可能存在某种优化方式,例如如果只是一个class变更,那么只需要计算所有selector中包含这个class条件的那些selector,但是窃以为这种优化如果超出class之外就实在非常的困难,也许反而不美。
然而这样困难的问题,在现在所有浏览器中都得到了解决,而且我们日常所最常用的方式,恰恰是修改class这样的操作。所以其他问题跟这个比起来,也许不值一提了。
顺便说一句,至少IE中,class确实是受到特殊待遇的。比如通过CSS绑定的htc,当selector匹配生效或失效的时候,样式虽然会立即生效或失效(实际是异步的),但是htc并不会被自动attach和detach,这一点有些奇怪,也许是出于性能考虑,也许根本就是一个bug。为了强制进行重新计算,你可以这样:
var all = document.getElementsByTagName('*'); for (var n=all.length, i=0; i<n; i++) {all[i].className+=''}
也就是,className的变更,会触发元素对于其本身适用的样式进行刷新。
11 楼
hax
2008-02-25
i_love_sc 写道
col 只有ie才支持。
FF早就支持了。但是正如我之前所说的,它对于col/colgroup上的css prop的支持有限,比如它不支持col/colgroup上的text-align。它也不支持html规范中所列出的align属性,因为本质上,FF是一个CSS浏览器而不是一个HTML浏览器,所以如果一个属性的格式化要求无法被转化为CSS,则就不可能得到支持。也许因此造成你有印象FF不支持col。
但是这是有原因的,我一直想写一篇blog来分析一下这个问题,不过一直没写。各位可直接看https://bugzilla.mozilla.org/show_bug.cgi?id=915,你可以注意到这个bug的编号是915,也就是很老很老很老很老的一个问题,实际上日期是1998-09-26,也就是说,至少10年以前那个时候(那时候我还在用386混DOS,根本上不了网,要用浏览器还得钻学校机房2块钱1小时啊),Mozilla已经支持col,否则就没有这个bug了。简单的原因可以看CSS21作者hixie的解说。各位不喜看英文的朋友,可暂时看看这个:http://forum.moztw.org/viewtopic.php?t=3905。
10 楼
fins
2008-02-25
问题再次延伸!
当 styleSheet 里的 class的内容变化时
浏览器内部是怎么刷新响应的页面元素的?
会不会是 遍历所有的 页面元素, 如果元素的class含有被改变的class那么就刷新?
如果是这样 那页面元素非常多非常多的时候 会不会出现比 js调用更慢的情况呢?
毕竟js调用是有目的的, 例如一个列表1000行 那么js遍历的就是1000个td
而native调用是遍历所有的页面元素.
也就是说 当页面复杂到一定程度 会不会出现native调用比js调用更慢的情况呢?
hax 写道
同等条件下,性能应该是改样式表要快。因为这个变更分发是由浏览器做的,肯定是native调用,比JS调用要快。
当 styleSheet 里的 class的内容变化时
浏览器内部是怎么刷新响应的页面元素的?
会不会是 遍历所有的 页面元素, 如果元素的class含有被改变的class那么就刷新?
如果是这样 那页面元素非常多非常多的时候 会不会出现比 js调用更慢的情况呢?
毕竟js调用是有目的的, 例如一个列表1000行 那么js遍历的就是1000个td
而native调用是遍历所有的页面元素.
也就是说 当页面复杂到一定程度 会不会出现native调用比js调用更慢的情况呢?
9 楼
fins
2008-02-24
我印象中也是
但是 按hax的说法似乎都支持
我记得以前我在ff1.5下试过 不支持 于是之后我就不再用了
不知道现在怎么样
但是 按hax的说法似乎都支持
我记得以前我在ff1.5下试过 不支持 于是之后我就不再用了
不知道现在怎么样
8 楼
i_love_sc
2008-02-24
col 只有ie才支持。
7 楼
fins
2008-02-24
唉 我的英语
四级30多分的水平 ...
而且现在又退步了 tears...
四级30多分的水平 ...
而且现在又退步了 tears...
6 楼
hax
2008-02-24
有关ext的问题,我也回答不了啊。我对ext也不了解,也没有读过它的源码。我只能给出我所知的一些考量因素。但是ext为什么这样做,那还得问ext的作者啦。
否则我们只能猜测。比如如果ext只对ie和safari用fixed,那可能是他认为FF和Opera的性能足够好,不需要用fixed。
不用col,也许是他认为用td就可以了,没有必要多引入一个元素,或者担心col存在某种未知的问题。
还有,虽然修改stylesheet快,但是这个性能快一点可能在ext作者看来关系不大。况且如果他是从ext1到ext2做了改变,可能有一些其他的考虑。
总之,这些只有作者自己才能回答。我不过是瞎猜啦。你真的好奇,就应该直接去问jack。
否则我们只能猜测。比如如果ext只对ie和safari用fixed,那可能是他认为FF和Opera的性能足够好,不需要用fixed。
不用col,也许是他认为用td就可以了,没有必要多引入一个元素,或者担心col存在某种未知的问题。
还有,虽然修改stylesheet快,但是这个性能快一点可能在ext作者看来关系不大。况且如果他是从ext1到ext2做了改变,可能有一些其他的考虑。
总之,这些只有作者自己才能回答。我不过是瞎猜啦。你真的好奇,就应该直接去问jack。
5 楼
fins
2008-02-24
再次感谢. 引出另外一个问题.
您说:"
对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。"
在EXT中 作者始终坚持只对 ie和 safari下的table使用table-layout:fixed.
.ext-ie .x-grid3 table,.ext-safari .x-grid3 table {
table-layout:fixed;
}
您能帮忙分析分析这事为什么吗? table-layout:fixed是不是在 这两个浏览器下和在其他浏览器下有什么不同呢?
另外 为什么 ext的作者坚持不用 <col> 呢
还有 既然修改 styleSheet更快 那为什么ext的作者一定要便利每个单元格呢?
请原谅我总是拿EXT做例子 毕竟在EXT面前 我这样的半吊子只有资格去崇拜和学习 还没有资格去做理性的分析和批判
所以还请楼主能再帮 我 分析一下这两个问题 谢谢了
您说:"
对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。"
在EXT中 作者始终坚持只对 ie和 safari下的table使用table-layout:fixed.
.ext-ie .x-grid3 table,.ext-safari .x-grid3 table {
table-layout:fixed;
}
您能帮忙分析分析这事为什么吗? table-layout:fixed是不是在 这两个浏览器下和在其他浏览器下有什么不同呢?
另外 为什么 ext的作者坚持不用 <col> 呢
还有 既然修改 styleSheet更快 那为什么ext的作者一定要便利每个单元格呢?
请原谅我总是拿EXT做例子 毕竟在EXT面前 我这样的半吊子只有资格去崇拜和学习 还没有资格去做理性的分析和批判
所以还请楼主能再帮 我 分析一下这两个问题 谢谢了
4 楼
hax
2008-02-24
3 楼
hax
2008-02-24
同等条件下,性能应该是改样式表要快。因为这个变更分发是由浏览器做的,肯定是native调用,比JS调用要快。
还有你说的div宽度不会变,应该只有在IE中该td被设了width的情况时发生。如果该td的width保持为auto(默认就是这样),应该不会出现这样的情况吧。
还有你说的div宽度不会变,应该只有在IE中该td被设了width的情况时发生。如果该td的width保持为auto(默认就是这样),应该不会出现这样的情况吧。
2 楼
fins
2008-02-24
非常感谢你的回答, 值得我好好学习一下
再多问一句 不从设计等角度考虑 只是从性能上讲 哪个方法更快呢???
眼前还有一个相对具体点的问题 关于 <col><colgroup>的问题
ext确实没有用 而且我研究过一些其他的表格组件 也都没有用
col是不是有什么潜在的兼容性问题呢?
另外关于
"对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。所以,可以把width设在第一行对应的td上"
我以前也是这么做的 但是有个很头痛的问题.
改变第一个单元格的宽度后 下面的宽度会变化,
但是如果单元格内部的 div宽度是 100% 那么他们不会跟着变
这个怎么解决呢?
谢谢了
再多问一句 不从设计等角度考虑 只是从性能上讲 哪个方法更快呢???
眼前还有一个相对具体点的问题 关于 <col><colgroup>的问题
ext确实没有用 而且我研究过一些其他的表格组件 也都没有用
col是不是有什么潜在的兼容性问题呢?
另外关于
"对于table-layout:fixed的表格来说(注意:对于大表格来说,应尽可能使用fixed),其td宽度只取决于第一行上的td的宽度。所以,可以把width设在第一行对应的td上"
我以前也是这么做的 但是有个很头痛的问题.
改变第一个单元格的宽度后 下面的宽度会变化,
但是如果单元格内部的 div宽度是 100% 那么他们不会跟着变
这个怎么解决呢?
谢谢了
1 楼
Lunatic Sun
2008-02-24
绝对是一篇研究型的大作,收藏了。
另外我觉得,在能够用不需要使用javascript解决的问题尽量不要用javascript解决,毕竟javascript在无障碍性和安全性方面还不是非常完美。
另外我觉得,在能够用不需要使用javascript解决的问题尽量不要用javascript解决,毕竟javascript在无障碍性和安全性方面还不是非常完美。
发表评论
-
对于React体系的一点想法
2015-06-12 01:53 5797这一年来react和react native火得不行。 我对 ... -
图片lazyload兼容无脚本的小改进
2012-12-04 19:09 5732刚刚改进了一下某个页 ... -
tagName的大小写问题(QWrap选择器的一个bug)
2011-07-16 23:33 6524今儿写程序。 对于现 ... -
document.enableStyleSheetsForSet() 的兼容
2011-06-17 16:27 3506可能有不少同学已经了 ... -
IE神奇小bug一则
2010-12-03 18:05 2771<input type="text&quo ... -
前端优化新得一则
2010-02-22 15:05 2848因为把公司的电脑搞坏两台,这两天没有工作电脑可用了,所以就不干 ... -
一个史上最快的Web语法高亮引擎即将诞生
2009-05-02 03:33 6234对比对象是目前最有名,也是JavaEye所使用的highlig ... -
getUsedValue 0.4发布
2009-04-28 18:46 2063关于used value的基本解释,请看getUsedValu ... -
getUsedValue 0.1
2009-04-06 03:26 3670前不久写了一个小脚本,用来获取页面中CSS样式的 used v ... -
表单数据提交时的字符编码问题
2009-01-18 02:28 6214人老了,以前研究过的东西都忘记了。所以还是记录下来比较好。 ... -
再贴一次form的属性和控件name冲突的老问题
2008-11-07 18:59 3188更新: John Resig也谈到了这个问题。 而这里是一个非 ... -
一个嵌入式HTML引擎
2008-05-10 18:28 4132http://www.terrainformatica.com ... -
西方人通常发现不了的一个IE的bug
2008-05-09 20:00 8846这个问题我大概在一年 ... -
IE memory leak 备忘
2008-03-03 01:07 5164本篇只记录一下工具,有空再做研究。 Drip: http:/ ... -
批量修改style采取哪种方式好(续篇)
2008-02-24 19:20 3967前篇见批量修改style采取哪种方式好,主要是回答fins的提 ... -
XBL2的实现
2008-02-24 02:35 2347今天发现几种XBL2的实现。浏览器实现XBL2还要等上一段时间 ... -
使用捕获事件监听器(useCapture=true)的陷阱及其对策
2008-02-17 07:02 9729DOM event flow有三个phase,capture、 ... -
写了一个XML Base的JS实现(简介篇)
2008-01-23 01:08 3162最近想在一个小应用中采用浏览器端的xinclude。找了一下, ... -
MSXML默认解析外部DTD
2007-11-07 18:17 3594昨日aimingoo说它测试xmldom的速度,发现载入一个w ... -
基于Ajax技术的VNC
2007-09-19 10:44 2997http://sourceforge.net/projects ...
相关推荐
在IT行业中,FINS(Fieldbus Network System)是欧姆龙(Omron)公司开发的一种通信协议,主要用于其PLC(可编程逻辑控制器)产品线。FINS协议提供了多种通信方式,包括TCP/IP、RS-232/485以及我们这里关注的UDP...
总结,LABVIEW与OMRON PLC通过FINS协议进行通信是一种高效且灵活的方式,能够满足工业环境中复杂的数据交互需求。通过理解FINS协议的原理,结合LABVIEW提供的强大编程工具,我们可以构建出定制化的PLC控制系统,实现...
FINS协议支持多种通信方式,包括TCP/IP、UDP以及串行通信,为工业环境中的设备联网提供了便利。 **FINS TCP/UDP协议详解:** FINS TCP/UDP是FINS协议在网络层面上的应用,它利用了互联网上广泛使用的传输控制协议...
总的来说,欧姆龙以太网FINS协议通讯测试工具为开发者提供了一种高效的方式来控制和支持欧姆龙PLC,使得在工业自动化系统的设计和维护过程中,能够更加灵活和便捷地进行设备间的通信和数据交换。通过深入理解FINS...
《Node.js连接欧姆龙PLC设备:FINS协议详解及应用》 在现代工业自动化领域,欧姆龙(Omron)的可编程逻辑控制器(PLC)因其稳定性与灵活性而广泛应用。为了实现远程监控与控制,开发者通常需要通过编程接口与PLC...
FINS(Fieldbus Network System)是欧姆龙开发的一种网络通信协议,旨在提供设备间高效、可靠的通信方式。下面我们将深入探讨FINS通讯协议及其在实际应用中的关键知识点。 首先,FINS通讯协议是基于TCP/IP或串行...
FINS UDP基于用户数据报协议(UDP/IP),这是一种无连接的通信方式,速度快但数据可靠性较低。在FINS UDP通信中,你需要设置本地IP和端口号(如192.168.250.111:10000)以及控制器IP和端口号(如192.168.250.1:9600...
总的来说,FINS UDP协议为欧姆龙PLC的通信提供了一种高效且灵活的方式,尤其适用于实时性要求高的应用。在实际工程中,通过熟悉并掌握FINS UDP通信的原理和实现方法,能够有效提升系统运行效率,实现对欧姆龙PLC的...
欧姆龙FINS(Factory Interface Network System)协议是欧姆龙公司开发的一种通信协议,用于其PLC(可编程逻辑控制器)与上位机、其他PLC或设备之间的通信。这个协议提供了简单、高效的数据交换方式,使得用户可以...
FINS是欧姆龙开发的一种网络通信协议,主要用于实现其PLC设备与其他设备之间的数据交换和控制指令的传递。 手册首先列出了支持FINS通信的欧姆龙PLC型号,如CS1G/H-CPU、CJ2H-CPU6、CP1H-X等,以及针对不同系列的CPU...
FINS(Fieldbus Network System)协议是欧姆龙公司为其工业自动化设备,尤其是PLC(可编程逻辑控制器)设计的一种通信协议。FINS协议框架主要用于实现设备间的网络通信,确保数据交换的高效和准确。这个框架允许用户...
FINS是欧姆龙专为实现其自动化设备之间的网络通信设计的一种通信协议。在“SocketClient_FINS_欧姆龙NJPLC基于FINS通信示例”中,我们重点关注的是通过Socket客户端实现FINS通信的C#代码示例。 1. FINS协议详解: ...
QT+PLC 通过FinsTcp通信是一种在嵌入式系统或者工业自动化环境中常见的实践,它允许编程者使用QT框架来实现与可编程逻辑控制器(PLC)的远程交互。以下是对这一技术的详细说明: 首先,QT是一个跨平台的应用程序...
FINS是欧姆龙为实现设备间的网络通信而设计的一种通信协议,而PLCC则是指PLC编程和控制相关的技术。了解如何利用FINS协议和C#进行PLC通信对于自动化系统开发者至关重要。 首先,理解FINS协议是基础。FINS协议基于...
FINS是欧姆龙专为工业设备通信设计的一种网络协议,它允许设备间进行数据交换,包括读取和写入PLC中的寄存器、输入/输出等。在C#中实现FINS通信,通常需要借助一些库或者自定义的通信类来封装FINS协议的细节。 首先...
在本资料中,我们将重点关注“FINS”(Factory Integrated Network System)TCP通信,这是一种专为欧姆龙设备设计的网络协议,使得PLC与其他设备之间的数据交换变得简单高效。 标题中的"自整理欧姆龙PLC以太网FINS...
RC+7.0是爱普生机器人的控制系统,提供了高级编程和控制功能,而FINS TCP/IP是OMRON设备之间通信的一种方式,它允许远程操作、监控和配置PLC。 在IT知识方面,以下是一些关键点: 1. **FINS协议**:FINS是OMRON专...
FINS(Fieldbus Network Integrated System)是欧姆龙公司开发的一种通信协议,主要用于其自动化设备之间的通信,包括PLC、HMI、传感器和其他周边设备。FINS协议能够实现网络上的数据交换,便于实现远程监控、程序...
### Fins驱动使用详解 #### 一、概述 在工业自动化领域中,PLC(可编程逻辑控制器)作为核心控制单元发挥着至关重要的作用。为了实现PLC与上位机或其他...希望本文能够帮助读者更好地理解和掌握FINS驱动的使用方法。
欧姆龙FINS(Factory Integrated Network System)通讯指令是用于欧姆龙自动化设备间通信的一种标准协议,尤其在PLC(可编程逻辑控制器)和HMI(人机界面)之间广泛应用。FINS协议构建在TCP/IP、Ethernet/IP、RS-485...