HTML ツリービルダー (Pure DOM)
function h (str) {
var t, cur, stack = [cur = document.createElement("div")];
while (str.length) {
if (str.indexOf("<") == 0) {
if (t = str.match(/^\s*<(\/?[^\s>\/]+)([^>]+?)?(\/)?>/)) {
var tag = t[1], attrs = t[2], isempty = !!t[3];
if (tag.indexOf("/") == -1) {
child = document.createElement(tag);
if (attrs) attrs.replace(/([a-z]+)=(?:'([^']+)'|"([^"]+)")/gi,
function (m, name, v1, v2) {
child.setAttribute(name, v1 || v2);
}
);
cur.appendChild(child);
if (!isempty) {
stack.push(cur);
cur = child;
}
} else cur = stack.pop();
} else throw("Parse Error: " + str);
} else {
if (t = str.match(/^([^<]+)/)) cur.appendChild(document.createTextNode(t[0]));
}
str = str.substring(t[0].length);
}
return stack.pop().firstChild;
}window.onload = function () {
var t = [
h("<div><img src='http://mixi.jp/favicon.ico'/>hello<span style='color:red'>!</span></div>"),
h("<div class='test'/>"),
h("<div class='test'><ul><li>aa</li></ul></div>"),
h("<div class='test' style='background: #f00'>hogehoe aaa</div>")
];
for (var i = 0; i < t.length; i++) {
var e = t[i];
document.body.appendChild(e);
}
};jQuery でふつうに HTML かいて要素生成しはじめると、$N("div", {attr}, [childs]) みたいなのがめんどくさくてしかたないので簡単なパーサ書いて生成するようにした。innerHTML 使えよって感じですね。なんで innerHTML つかわないで書いたんだっけ……
- 実体参照もどしてない。
たぶんおれはパーサーがかきたかったんだ。よくわかんないけど
innerHTML より遅いんだろうなぁとおもってベンチマークとってみた。http://d.hatena.ne.jp/amachang/20060906/1157571938 amachang+=100
まず innerHTML バージョンを定義 (テーブルとかいろいろ考慮してないけど)
function hi (str) {
var t = document.createElement("div");
t.innerHTML = str;
return t.firstChild;
}benchmark({
"pure dom" : function () {
for (var i = 0; i < 1000; i++) {
h("<div><img src='http://mixi.jp/favicon.ico'/>hello<span style='color:red'>!</span></div>");
h("<div class='test'/>");
h("<div class='test'><ul><li>aa</li><li>bb</li></ul></div>");
h("<div class='test' style='background: #f00'>hogehoe aaa</div>");
}
},
"innerHTML" : function () {
for (var i = 0; i < 1000; i++) {
hi("<div><img src='http://mixi.jp/favicon.ico'/>hello<span style='color:red'>!</span></div>");
hi("<div class='test'/>");
hi("<div class='test'><ul><li>aa</li><li>bb</li></ul></div>");
hi("<div class='test' style='background: #f00'>hogehoe aaa</div>");
}
}
});# GranParadiso A8 preparing ... let's go! . *** pure dom *** result : 2213.987429[ms] . *** innerHTML *** result : 829.987429[ms] . finish! # Safari 3 preparing ... let's go! . *** pure dom *** result : 1005.991463[ms] . *** innerHTML *** result : 200.991463[ms] . finish # IE 6 preparing ... let's go! . *** pure dom *** result : 1921.985521[ms] . *** innerHTML *** result : 1342.985521[ms] . finish! # IE 7 preparing ... let's go! . *** pure dom *** result : 1890.984139[ms] . *** innerHTML *** result : 1312.984139[ms] . finish! # Opera 9.24 preparing ... let's go! . *** pure dom *** result : 2353.990287[ms] . *** innerHTML *** result : 474.990287[ms] . finish!
かなしいですが現実はこんなもんですね。