目标:$div({id:'id',name:'name'},Dom1,Dom2...) 这么就能创建出结构化的dom,其中参数一,是一个对象,包含着div所需要的属性,dom1,
dom2是div中包含的对象。
实现方式:代码及相关文字解释。
先看例子:比如我们想创建一个div,id为dv,内容为hello的dom结构如下:
<div id="dv">hello</div>
用这个类只需要这么写一句代码:
$div({"id":"dv"},'hello');
//再将这个dom用appendChild添加到body里面就可以了
再比如列表,如:
<ul id="article">
<li>第一节</li>
<li>第二节</li>
<li>第三节</li>
</ul>
我们也只需要一句代码得到都dom结构:
$ul({"id":"article"},$li('第一章'),$li('第二章'),$li('第三章'));
调用很简单吧,比以前一堆的创建赋值来说,这个是不是更加的优雅呢?代码不止可以简洁也能更加诗情画意。
废话不多说先上代码:
<!DOCTYPE html>
<html>
<head>
<title>dom bulider</title>
</head>
<script type="text/javascript">
window.DomBuilder = {
initTag : function(tag){
return function(){
var attrs={},children=[];
if(arguments.length>0){
if(arguments[0].nodeName || typeof arguments[0] =='string'){
children = arguments;
}else{
attrs = arguments[0];
children = Array.prototype.slice.call(arguments,1);
}
}
return window.DomBuilder.create(tag,attrs,children);
}
},
create : function(tag,attrs,children){
var attr = attr ? attr : {};
var children = children ? children : [];
var dom = document.createElement(tag);
for(var attr in attrs){
if(attr == 'class'){
dom.className = attrs[attr];//由于class属性石javascript保留字,所以我们需要加这样的判断,其他属性还有需要大家扩展了
}else{
dom.setAttribute(attr,attrs[attr]);
}
}
for(var i=0; i<children.length; i++){
if(typeof children[i] == 'string'){
children[i] = document.createTextNode(children[i]);
}
dom.appendChild(children[i]);
}
return dom;
}
}
window.onload = function(){
(function(){
var tags = 'div|ul|li'.split('|');
var tag,i=0;
while(tag = tags[i++]){
window['$'+tag] = DomBuilder.initTag(tag);
}
})();
var body = document.getElementsByTagName("body")[0];
body.appendChild($div({"id":"dv","class":"class"},'hello world'));
body.appendChild($ul({"id":"dv"},$li('list1'),$li('list3'),$li('list3')));
}
</script>
<body>
</body>
</html>
也许代码贴出来一头雾水,我现在介绍两种学习方法:
第一种,直接拿来用就好了,代码不多,用着改着就会熟悉流程了,
第二种也就是接下来我们做的事,就是从头推一遍,为什么是这样的:
我们想得到$div({id:'id',name:'name'},Dom1,Dom2...),的用法。当我们发现$div(),我们会想到是不是还有,$span(),$ul{}等,如此一来不是要构建很多函数?既然这样我们就想到了能不能自动构建函数呢?于是有了这一段。
(function(){
var tags = 'div|ul|li'.split('|');
var tag,i=0;
while(tag = tags[i++]){
window['$'+tag] = DomBuilder.initTag(tag);
}
})();
我们的tags是一个包含标签的数组,我门循环这个数组来自创建函数。因为调用方法为$+tag,所以我们需要function $tag(){};这样的方法并且还需要传一个tag的参数,这些事能确定的,每个函数必须是这样的function $tag(tag){};
下面我们来看这段代码:
window.DomBuilder = {
initTag : function(tag){
return function(){
var attrs={},children=[];
if(arguments.length>0){
if(arguments[0].nodeName || typeof arguments[0] =='string'){
children = arguments;
}else{
attrs = arguments[0];
children = Array.prototype.slice.call(arguments,1);
}
}
return window.DomBuilder.create(tag,attrs,children);
}
},
create : function(tag,attrs,children){
var attr = attr ? attr : {};
var children = children ? children : [];
var dom = document.createElement(tag);
for(var attr in attrs){
if(attr == 'class'){
dom.className = attrs[attr];//由于class属性石javascript保留字,所以我们需要加这样的判断,其他属性还有需要大家扩展了
}else{
dom.setAttribute(attr,attrs[attr]);
}
}
for(var i=0; i<children.length; i++){
if(typeof children[i] == 'string'){
children[i] = document.createTextNode(children[i]);
}
dom.appendChild(children[i]);
}
return dom;
}
}
我们用了一个DomBuilder对象,里面有两个方法initTag和create 这两个方法分工明确,因为我们需要的是这样的$div([attrs],[children]);里面的参数是不确定的,可能有一个可能有多个,可能什么都没有,也可能只有文字,所以initTag方法是整理参数。然后调用create创建和赋属性,至于里面到底是怎么回事我就不详细解释了,多看两遍就很清楚,有一点我需要讲一下:children = Array.prototype.slice.call(arguments,1); 这句其实是把类似的数组调用数组的方法,也可以写成[].slice.call(arguments,1)或者[].slice.apply(arguments,[1])等,大家可以研究一下。
这个函数我是从javascript编程艺术上看到的,我稍作修改并加入更详细的解释,如果大家有好的想法或者意见欢迎来讨论。