组内同时总结的关于javascript性能优化注意些节。记录一下。
1.
批量增加
Dom
尽量使用修改
innerHTML
的方式而不是用
appendChild
的方式
;
因为使用
innerHTML
开销更小
,
速度更快
,
同时也更加内存安全
.
有一点需要注意的是
,
用
innerHTML
方式添加时
,
一定不要在循环中使用
innerHTML +=
的方式添加
,
这样反而会使速度减慢
;
而是应该中间用
array
缓存起来
,
循环结束后调用
xx.innerHTML = array.join(‘’);
的方式
,
或者至少保存到
string
中再插到
innerHTML
中
.
针对用户列表一块采用这种方式优化后
,
加载速度提升一倍
.
2.
单个增加
Dom
这里是指要将新节点加载到一个内容不断变化的节点的情形
,
对于内容稳定的节点来说
,
随便怎么加都没有问题
.
但是对于有动态内容的节点来说
,
为其添加子节点尽量使用
dom append
的方式
.
这是因为
,dom append
不会影响到其他的节点
;
而如果修改
innerHTML
属性的话
,
该父节点的所有子节点都会从
dom
树中剥离
,
再根据新的
innerHTML
值来重绘子节点
dom
树
;
所有注册到原来子节点的事件也会失效
.
综上
,
如果在一个有动态内容的节点上
出现了
innerHTML +=
的代码
,
就该考虑是否有问题了
.
3.
创建
Dom
节点
用
createElement
方式创建一个
dom
节点
,
有一个很重要的细节
:
在执行完
createElement
代码之后
,
应该马上
append
到
dom
树中
;
否则
,
如果在将这个孤立节点加载到
dom
树之前所做的赋值它的属性和
innerHTML
的操作都会引发该
dom
片段内存无法回收的问题
.
这个不起眼细节
,
一旦遇到大量
dom
增删操作
,
就会引发内存的灾难
.
4.
删除
Dom
节点
删除
dom
节点之前
,
一定要删除注册在该节点上的事件
,
不管是用
observe
方式还是用
attachEvent
方式注册的事件
,
否则将会产生无法回收的内存
.
另
,
在
removeChild
和
innerHTML=’’
二者之间
,
尽量选择后者
.
因为在
sIEve(
内存泄露监测工具
)
中监测的结果是用
removeChild
无法有效地释放
dom
节点
.
5.
创建事件监听
现有的
js
库都采用
observe
方式来创建事件监听
,
其实现上隔离了
dom
对象和事件处理函数之间的循环引用
,
所以应该尽量采用这种方式来创建事件监听
.
6.
监听动态元素
Dom
事件默认是向上冒泡的
,
发生在子节点中的事件
,
可以由父节点来处理
. Event
的
target/srcElement
仍是产生事件的最深层子节点
.
这样
,
对于内容动态增加并且子节点都需要相同的事件处理函数的情况
,
可以把事件注册上提到父节点上
,
这样就不需要为每个子节点注册事件监听了
.
同时
,
这样做也避免了产生无法回收的内存
.
即使是用
Prototype
的
observe
方式注册事件并在删除节点前调用
stopObserving,
也会产生出少量无法回收的内存
,
所以应该尽量少的为
dom
节点注册事件监听
.
所以
,
当代码中出现在循环里注册事件时
,
也是我们该考虑事件上提机制的时候了
.
7.
HTML
提纯
HTML
提纯体现的是一种各负其责的思想
. HTML
只用来显示
,
尽量不出现和显示无关的属性
.
比如
onclick
事件
,
比如自定义的对象属性
.
事件可以用前面的方法避免
,
对象属性指的是这样的一种情景
:
通常情况下
,
动态增加的内容都是有个对象和它对应
,
比如聊天室的用户列表
,
每个显示用户的
dom
节点都有一个
user
对象和它对应
,
这样在
html
中
,
应该仅保留一个
id
属性和
user
对象对应
,
而其他的信息
,
则应通过
user
对象去获取
.
基于
PrototypeJS
,写了一个
Dom
生成器,以提供简单高效的
HTML
操作接口的语法和语义优化
:
1.
使用类似
JSONML
的格式
(HTML in JSON)
描述
DOM
结构,以补充
HTML
转义字符串的表达形式,规范格式中可支持以下
HTML
语义:
l
标签名
l
属性
(
标识符
,
类名
,
事件名
,
内联样式等
)
注:事件名上注册的侦听函数将自动通过
Event.observe
方式添加
l
嵌套标签
格式规范可简单描述为:
{
tag:string,
//
元素的标记名,如果没有,默认为
div
children|cn: string|Array|json,
//
子结点对应的
json
数组或字节点的
html
或单个
json
html:string,
//
对应的
html
,如果有
cn
或
children
属性就忽略
style:function|string|json,
//
元素的样式,可以是函数,字符串,
json
对象
cls:string,
//
元素的
class
属性的值
x:y
// x
表示其他名字,
y
表示变量值、非空字符串
onXXX: function
//
以
on
为首的属性是事件侦听器
}
一个具体的例子为:
var
list = DomBuilder.append(
'my-div'
, {
tag :
'ul'
,
cls :
'my-list'
,
children : [
{
tag :
'li'
,
id :
'item1'
,
html :
'List Item 1'
,
onclick :
function
() {
alert(
'List Item1 Clicked'
)
}
},
{
tag :
'li'
,
id :
'item2'
,
html :
'List Item 2'
,
customattr :
'customValue'
}]
});
2.
在实际修改
DOM
结构时,提供两种方式可供调用者选择,以便应需使用:
l
W3C
标准
DOM
操作
(appendChild, removeChild)
方式
l
使用
innerHTML,insertAdjacentHTML
等的实效模式
一个具体例子为:
DomBuilder.useDom =
true
;
//
显示申明使用
W3C Dom
操作方式
3.
另外提供
DOM
节点的有效回收方法
var
abandoned = DomBuilder.destroy(list); //
将
DOM
节点从文档中移除