【web前端培训之前后端的配合(中)】继续昨日的故事
前言
接着昨天的写:【web前端培训之前后端的配合(上)】以我们熟悉的Datalist说明问题吧
经过昨天晚上的学习,我们形成了一个伪datalist,但是他没有事件绑定,甚至每个datait还多出了一个无意义的div!!!
其实datalist多出一个div我是可以接受的,但是dataitem多出一个我这里就不太能接受了,所以里面还有很多东西可以继续深入。
昨天说了那么久也没有扯到和后端的配合,今天需要补足,于是进入今天的学习吧。
题外话
今天碰到一个有趣的东西,也许各位已经知道了,但是我这里还是提出来,老夫脸皮厚是不怕人笑话的哟。
- 解析HTML结构。
- 加载外部脚本和样式表文件。
- 解析并执行脚本代码。
- 构造HTML DOM模型。
- 加载图片等外部文件。
- 页面加载完毕。
其中图片会最后加载,无论如何都会最后加载,我当时想最开始就加载我一个广告(这个广告是个卷轴,会慢慢展开,会有黑色的层遮盖)。
我当时虽然将它放到了最前面,却给他的display设置为none了,于是我满以为他会最先加载的,结果却是最后加载(因为我js在最后控制的显示)。
我这里就犯了一个错误,因为在display为none的情况下,图片是不会加载的。
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 4 <title>测试页面</title> 5 </head> 6 <body> 7 <div style=" background-image: url(http://pic002.cnblogs.com/images/2012/294743/2012032201481631.png); display: none;"></div> 8 </body> 9 </html>
PS:注意,我这里的说的都是背景,不是img标签,img标签都会加载的。
以上代码开始不会加载背景图片,但是当显示时候起图片便会加载了。所以我们若是有些隐藏的dom元素需要加载而且里面含有大量背景图片。而我们加载时候又不想其感觉加载很慢,就需要做特殊处理啦。
完了,这里还有其它问题:
在动画执行过程中因为下面还有几个js文件需要加载,加载时候动画效果会偶尔出现一点点卡的现象,这块需要处理,我想的是采用异步加载余下js的方法,但是感觉为一个广告又不太划算,不知道各位有什么看法没有。
好了进入今日的正题。
剔除多余的div
首先上一章昨天的图:
最外层div为datalist的,我这里可以接受,但是内层的div,我这里真不能接受了!所以我们想法改变一下,这里也需要考虑到这种场景:
若是外层datalist使用的不是div,而是ul或者dl我们也是必须支持的,因为里面的item是可能出现li的
我们这里做一点简单的处理,若是模板不能形成dom,我们便为之添加div,若是能的话就不需要div了:
1 DataItem.prototype.load = function (index, data) { 2 this.data = data; 3 var parentEl = this.parentObj.el; //注意此处是parent已经赋值 4 var parentId = this.parentObj.id 5 var id = parentId + this.idPrefix + index; //生成唯一id 6 this.id = id; 7 //注意啦,这里根据html片段开始生成最终数据了哦 8 var templateObj = this.templateObj; //此处的膜拜已经过处理 9 var tmpHtm = ''; 10 $.each(templateObj, function (i, item) { 11 if (item.field) { 12 tmpHtm = tmpHtm + item.html + data[item.field] 13 } else { 14 tmpHtm = tmpHtm + item.html; 15 } 16 }); 17 var el = $(tmpHtm); 18 // var el = $('<div></div>'); //形成dom 19 //为了避免id重复,这里对id必须进行处理,我们同时不允许为元素设置id 20 if (!el[0]) { 21 el = $('<div/>'); 22 el.html(tmpHtm); 23 } 24 el.attr('id', id); 25 if (this.className) 26 this.el.attr("class", this.className); 27 parentEl.append(el); 28 };
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <style type="text/css"> .box { margin: 10px; padding: 10px; border: 1px solid gray; display: inline-block; } </style> <script src="js/jquery-1.7.1.min.js" type="text/javascript"></script> <script src="js/Datalist.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { var _url = 'Ajax.aspx?sql=select * from bigType'; $.getJSON(_url, function (data) { var d = new Datalist(); d.tag = '<ul/>' d.template = 'tmp'; d.dataSource = data; d.bind(); }); }); </script> </head> <body> <textarea id="tmp"> <li class="box"> <h3> {%title%}</h3> <dl> <dt>{%id%}</dt> <dd>{%title%} </dd> </dl> </li> </textarea> </body> </html>
现在这种结构式可以接受的。。。好啦,我们现在来为我们里面的元素绑定事件吧:
事件绑定
无论是我们的datalist还是我们的dataitem,他们都是拥有事件的,我们应该可以像.net那样可以找到各自里面的某个标签,并且操作他呢,我们并且也可以datalist嵌套的。
首先我们为datalist添加两个参数,一个用于自己的事件,一个用于定义其item的事件,因为他的item事件应该大致相同:
var Datalist = function () { this.id = new Date().getTime().toString(); this.items = []; //所具有的dataitem的项目 this.dataSource = null; //各位对他熟悉吧 this.container = $("body"); //我们的datalist的容器,没有指定的话就放在body里面 this.style = {}; //可以为其设置样式这里考虑的好像有点多了 this.attribute = {}; //为其设置属性 this.className = ''; this.itemClass = ''; //子元素的class this.tag = '<div></div>'; this.template = ''; //可以在此设置,也可以指定容器id,然后由容器寻找 this.itemEvent = {}; this.itemElementEvent = {}; };
注意最后我们新增加的方法哦,itemEvent用于datalist的item的,比如上面的li标签,后面的用于其中item里面的元素,比如h3标签。
我们在.net中定义事件好像也是放出来的呢,我们这先看看怎么使用吧:
1 $(document).ready(function () { 2 var _url = 'Ajax.aspx?sql=select * from bigType'; 3 $.getJSON(_url, function (data) { 4 var d = new Datalist(); 5 d.tag = '<ul/>' 6 d.template = 'tmp'; 7 d.dataSource = data; 8 d.itemEvent.clickLi = { 9 eventType: 'click', 10 funcName: function (data, e, sender) { 11 12 var s = ''; 13 } 14 }; 15 d.bind(); 16 }); 17 });
1 DataItem.prototype.bindEvent = function () { 2 var scope = this; 3 var el = scope.el; //获取当前元素 4 var data = scope.data; //当前行数据 5 var events = scope.event; 6 $.each(events, function (k, v) { 7 var type = v.eventType; 8 var func = v.funcName; 9 var sender = v.sender; //最初调用对象 10 if (func && typeof func == 'function') { 11 if (type == 'ready') { 12 func.call(scope, params, e, original); 13 } else { 14 el.unbind(type).bind(type, function (e) { 15 func.call(scope, data, e, sender); 16 }); 17 } 18 } 19 }); 20 };
我们看到这里基本上达到了我们的要求了,而且传了很多有意义的参数回来,接下来我们再加一点东西便来试试吧:
这里贴上完整代码啦:
js:
1 /// <reference path="jquery-1.7.1.min.js" /> 2 var DataItem = function () { 3 this.data = null; 4 this.el = null; 5 this.id = ''; 6 this.parentObj = null; 7 this.idPrefix = '_item_'; //id前缀 8 this.className = ''; 9 this.event = {}; 10 this.elementEvent = {}; 11 }; 12 13 DataItem.prototype.load = function (index, data) { 14 this.data = data; 15 var parentEl = this.parentObj.el; //注意此处是parent已经赋值 16 var parentId = this.parentObj.id 17 var id = parentId + this.idPrefix + index; //生成唯一id 18 this.id = id; 19 //注意啦,这里根据html片段开始生成最终数据了哦 20 var templateObj = this.templateObj; //此处的膜拜已经过处理 21 var tmpHtm = ''; 22 $.each(templateObj, function (i, item) { 23 if (item.field) { 24 tmpHtm = tmpHtm + item.html + data[item.field] 25 } else { 26 tmpHtm = tmpHtm + item.html; 27 } 28 }); 29 var el = $(tmpHtm); 30 // var el = $('<div></div>'); //形成dom 31 //为了避免id重复,这里对id必须进行处理,我们同时不允许为元素设置id 32 if (!el[0]) { 33 el = $('<div/>'); 34 el.html(tmpHtm); 35 } 36 el.attr('id', id); 37 if (this.className) 38 this.el.attr("class", this.className); 39 parentEl.append(el); 40 this.el = el; 41 //增加相应事件绑定 42 this.bindEvent(); 43 this.bindElementEvent(); 44 }; 45 46 DataItem.prototype.bindEvent = function () { 47 var scope = this; 48 var el = scope.el; //获取当前元素 49 var data = scope.data; //当前行数据 50 var events = scope.event; 51 $.each(events, function (k, v) { 52 var type = v.eventType; 53 var func = v.funcName; 54 var sender = v.sender; //最初调用对象 55 if (func && typeof func == 'function') { 56 if (type == 'ready') { 57 func.call(scope, params, e, original); 58 } else { 59 el.unbind(type).bind(type, function (e) { 60 func.call(scope, data, e, sender); 61 }); 62 } 63 } 64 }); 65 }; 66 //绑定item里面的某一个标签 67 DataItem.prototype.bindElementEvent = function () { 68 var scope = this; 69 var data = scope.data; //当前行数据 70 var events = scope.elementEvent; 71 $.each(events, function (k, v) { 72 var elementkey = v.elementkey; //元素选择器 73 var type = v.eventType; 74 var func = v.funcName; 75 var sender = v.sender; 76 var id = '#' + scope.id + ' ' + elementkey; 77 var el = $(id); 78 if (func && typeof func == 'function') { 79 if (type == 'ready') { 80 func.call(scope, params, e, original); 81 } else { 82 el.unbind(type).bind(type, function (e) { 83 func.call(scope, data, e, sender); 84 }); 85 } 86 } 87 }); 88 }; 89 90 var Datalist = function () { 91 this.id = new Date().getTime().toString(); 92 this.items = []; //所具有的dataitem的项目 93 this.dataSource = null; //各位对他熟悉吧 94 this.container = $("body"); //我们的datalist的容器,没有指定的话就放在body里面 95 this.style = {}; //可以为其设置样式这里考虑的好像有点多了 96 this.attribute = {}; //为其设置属性 97 this.className = ''; 98 this.itemClass = ''; //子元素的class 99 this.tag = '<div></div>'; 100 this.template = ''; //可以在此设置,也可以指定容器id,然后由容器寻找 101 102 this.itemEvent = {}; 103 this.itemElementEvent = {}; 104 }; 105 106 //好了,我们第一步需要 107 Datalist.prototype.formatTemplate = function () { 108 var template = this.template; 109 if (template.length < 10) { 110 template = $('#' + template); 111 if (template[0]) template = template.val(); 112 } 113 var reg = /\{%[\w]*\%}/; 114 var para = reg.exec(template); 115 var html = template; 116 var templateObj = []; 117 while (para && para.length > 0) { 118 var len = para.index; 119 var tmp = {}; 120 tmp.html = html.substr(0, len); 121 tmp.field = para[0].substr(2, para[0].length - 4); 122 templateObj.push(tmp); 123 html = html.substr(len + para[0].length); 124 para = reg.exec(html); 125 } 126 tmp = {}; 127 tmp.html = html; 128 templateObj.push(tmp); 129 this.templateObj = templateObj; //注意我们的datalist多了一个东西了哦 130 }; 131 132 Datalist.prototype.bind = function () { 133 //初始化属性等操作,我们暂时忽略之 134 //............... 135 this.initElement(); //初始化元素 136 this.formatTemplate(); 137 var scope = this; 138 var itemIndex = 0; 139 var container = this.container; 140 container.append(this.el); //将datalist装入容器 141 142 $.each(this.dataSource, function (k, v) { 143 var item = new DataItem(); //实例化了一个item了哦 144 item.parentObj = scope; 145 item.templateObj = scope.templateObj; 146 item.event = scope.itemEvent; 147 item.elementEvent = scope.itemElementEvent; 148 item.load(itemIndex, v); 149 scope.items.push(item); 150 itemIndex++; 151 }); 152 }; 153 154 Datalist.prototype.initElement = function () { 155 var el = $(this.tag); 156 el.attr('id', this.id); 157 this.el = el; 158 this.initAttribute(); 159 this.initStyle(); 160 }; 161 162 Datalist.prototype.initAttribute = function () { 163 var scope = this; 164 var element = scope.el; 165 $.each(scope.attribute, function (key, value) { 166 if (typeof (value) == "string") 167 if (value && value.length > 0) { 168 element.attr(key, value); 169 } 170 }); 171 }; 172 173 Datalist.prototype.initStyle = function () { 174 var scope = this; 175 var element = this.el; 176 var style = this.style; 177 $.each(style, function (key, value) { 178 if (value && value.length > 0) { 179 element.css(key, value); 180 } 181 }); 182 };
html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <style type="text/css"> .box { margin: 10px; padding: 10px; border: 1px solid gray; display: inline-block; } </style> <script src="js/jquery-1.7.1.min.js" type="text/javascript"></script> <script src="js/Datalist.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { var _url = 'Ajax.aspx?sql=select * from bigType'; $.getJSON(_url, function (data) { var d = new Datalist(); d.tag = '<ul/>' d.template = 'tmp'; d.dataSource = data; d.itemEvent.clickLi = { eventType: 'click', funcName: function (data, e, sender) { var s = ''; } }; d.itemElementEvent.clickH = { elementkey: 'h3', eventType: 'click', funcName: function (data, e, sender) { var s = ''; } }; d.bind(); }); }); </script> </head> <body> <textarea id="tmp"> <li class="box"> <h3> {%title%}</h3> <dl> <dt>{%id%}</dt> <dd>{%title%} </dd> </dl> </li> </textarea> </body> </html>
好了,我们来检测下今天的学习成果吧。
嵌套的datalist
我们这里搞一个datalist嵌套的实验,并点击每个h3便alert名字:
完整代码:
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 .box { margin: 10px; padding: 10px; border: 1px solid gray; display: inline-block; } 7 </style> 8 <script src="js/jquery-1.7.1.min.js" type="text/javascript"></script> 9 <script src="js/Datalist.js" type="text/javascript"></script> 10 <script type="text/javascript"> 11 $(document).ready(function () { 12 var _url = 'Ajax.aspx?sql=select * from bigType'; 13 $.getJSON(_url, function (data) { 14 var d = new Datalist(); 15 d.template = 'datalist'; 16 d.dataSource = data; 17 d.itemElementEvent.clickH3 = { 18 elementkey: 'h3', 19 eventType: 'click', 20 funcName: function (data, el, e) { 21 alert(el.html()); 22 } 23 }; 24 d.itemElementEvent.loadItem = { 25 elementkey: '.wrapper', 26 eventType: 'ready', 27 funcName: function (data, el) { 28 var bigTypeId = data.id; 29 var url = 'Ajax.aspx?sql=select * from smallType where bigTypeId=' + bigTypeId; 30 var scope = this; 31 $.getJSON(url, function (_data) { 32 var tmp = new Datalist(); 33 tmp.container = el; 34 tmp.template = 'dataItem'; 35 tmp.tag = '<ul/>' 36 tmp.dataSource = _data; 37 tmp.bind(); 38 var s = ''; 39 40 }); 41 } 42 }; 43 d.bind(); 44 }); 45 }); 46 </script> 47 </head> 48 <body> 49 50 <textarea id="datalist"> 51 <div class="box"> 52 <h3> 53 {%title%}</h3> 54 <div class="wrapper"></div> 55 </div> 56 </textarea> 57 58 <textarea id="dataItem"> 59 <li class="box"> 60 <dl> 61 <dt>{%id%}</dt> 62 <dd> 63 {%title%}</dd> 64 </dl> 65 </li> 66 </textarea> 67 </body> 68 </html>
1 /// <reference path="jquery-1.7.1.min.js" /> 2 var DataItem = function () { 3 this.data = null; 4 this.el = null; 5 this.id = ''; 6 this.parentObj = null; 7 this.idPrefix = '_item_'; //id前缀 8 this.className = ''; 9 this.event = {}; 10 this.elementEvent = {}; 11 }; 12 13 DataItem.prototype.load = function (index, data) { 14 this.data = data; 15 var parentEl = this.parentObj.el; //注意此处是parent已经赋值 16 var parentId = this.parentObj.id 17 var id = parentId + this.idPrefix + index; //生成唯一id 18 this.id = id; 19 //注意啦,这里根据html片段开始生成最终数据了哦 20 var templateObj = this.templateObj; //此处的膜拜已经过处理 21 var tmpHtm = ''; 22 $.each(templateObj, function (i, item) { 23 if (item.field) { 24 tmpHtm = tmpHtm + item.html + data[item.field] 25 } else { 26 tmpHtm = tmpHtm + item.html; 27 } 28 }); 29 var el = $(tmpHtm); 30 // var el = $('<div></div>'); //形成dom 31 //为了避免id重复,这里对id必须进行处理,我们同时不允许为元素设置id 32 if (!el[0]) { 33 el = $('<div/>'); 34 el.html(tmpHtm); 35 } 36 el.attr('id', id); 37 if (this.className) 38 this.el.attr("class", this.className); 39 parentEl.append(el); 40 this.el = el; 41 //增加相应事件绑定 42 this.bindEvent(); 43 this.bindElementEvent(); 44 }; 45 46 DataItem.prototype.bindEvent = function () { 47 var scope = this; 48 var el = scope.el; //获取当前元素 49 var data = scope.data; //当前行数据 50 var events = scope.event; 51 $.each(events, function (k, v) { 52 var type = v.eventType; 53 var func = v.funcName; 54 var sender = v.sender; //最初调用对象 55 if (func && typeof func == 'function') { 56 if (type == 'ready') { 57 func.call(scope, data, sender); 58 59 } else { 60 el.unbind(type).bind(type, function (e) { 61 func.call(scope, data, e, sender); 62 }); 63 } 64 } 65 }); 66 }; 67 //绑定item里面的某一个标签 68 DataItem.prototype.bindElementEvent = function () { 69 var scope = this; 70 var data = scope.data; //当前行数据 71 var events = scope.elementEvent; 72 $.each(events, function (k, v) { 73 var elementkey = v.elementkey; //元素选择器 74 var type = v.eventType; 75 var func = v.funcName; 76 var sender = v.sender; 77 var id = '#' + scope.id + ' ' + elementkey; 78 var el = $(id); 79 if (func && typeof func == 'function') { 80 if (type == 'ready') { 81 func.call(scope, data, el, sender); 82 } else { 83 el.unbind(type).bind(type, function (e) { 84 func.call(scope, data, el, e, sender); 85 }); 86 } 87 } 88 }); 89 }; 90 91 var Datalist = function () { 92 this.id = new Date().getTime().toString(); 93 this.items = []; //所具有的dataitem的项目 94 this.dataSource = null; //各位对他熟悉吧 95 this.container = $("body"); //我们的datalist的容器,没有指定的话就放在body里面 96 this.style = {}; //可以为其设置样式这里考虑的好像有点多了 97 this.attribute = {}; //为其设置属性 98 this.className = ''; 99 this.itemClass = ''; //子元素的class 100 this.tag = '<div></div>'; 101 this.template = ''; //可以在此设置,也可以指定容器id,然后由容器寻找 102 103 this.itemEvent = {}; 104 this.itemElementEvent = {}; 105 }; 106 107 //好了,我们第一步需要 108 Datalist.prototype.formatTemplate = function () { 109 var template = this.template; 110 if (template.length < 10) { 111 template = $('#' + template); 112 if (template[0]) template = template.val(); 113 } 114 var reg = /\{%[\w]*\%}/; 115 var para = reg.exec(template); 116 var html = template; 117 var templateObj = []; 118 while (para && para.length > 0) { 119 var len = para.index; 120 var tmp = {}; 121 tmp.html = html.substr(0, len); 122 tmp.field = para[0].substr(2, para[0].length - 4); 123 templateObj.push(tmp); 124 html = html.substr(len + para[0].length); 125 para = reg.exec(html); 126 } 127 tmp = {}; 128 tmp.html = html; 129 templateObj.push(tmp); 130 this.templateObj = templateObj; //注意我们的datalist多了一个东西了哦 131 }; 132 133 Datalist.prototype.bind = function () { 134 //初始化属性等操作,我们暂时忽略之 135 //............... 136 this.initElement(); //初始化元素 137 this.formatTemplate(); 138 var scope = this; 139 var itemIndex = 0; 140 var container = this.container; 141 container.append(this.el); //将datalist装入容器 142 143 $.each(this.dataSource, function (k, v) { 144 var item = new DataItem(); //实例化了一个item了哦 145 item.parentObj = scope; 146 item.templateObj = scope.templateObj; 147 item.event = scope.itemEvent; 148 item.elementEvent = scope.itemElementEvent; 149 item.load(itemIndex, v); 150 scope.items.push(item); 151 itemIndex++; 152 }); 153 }; 154 155 Datalist.prototype.initElement = function () { 156 var el = $(this.tag); 157 el.attr('id', this.id); 158 this.el = el; 159 this.initAttribute(); 160 this.initStyle(); 161 }; 162 163 Datalist.prototype.initAttribute = function () { 164 var scope = this; 165 var element = scope.el; 166 $.each(scope.attribute, function (key, value) { 167 if (typeof (value) == "string") 168 if (value && value.length > 0) { 169 element.attr(key, value); 170 } 171 }); 172 }; 173 174 Datalist.prototype.initStyle = function () { 175 var scope = this; 176 var element = this.el; 177 var style = this.style; 178 $.each(style, function (key, value) { 179 if (value && value.length > 0) { 180 element.css(key, value); 181 } 182 }); 183 };
结语
本来今天想结束的,结果不知不觉时间就没有了,看来的加快点速度啊。。。。