前言
白天的時間我們一起學習了bootstrap,雖然是剛開始學習,但是我們還是不得不承認他做得好,其中就我們到底是否使用一些朋友提出了自己的想法,我在討論之中也受益啦!
所以感謝各位的留言,我們不管用不用,還是得學習的,所以后面我們應該還會繼續一起學習bootstrap。
好了,進入今天的正題吧,我這邊前端培訓的時間被再次壓縮了,壓縮到只有6天啦,我是這么想的:
第一天介紹CSS
第二天介紹JS
第三天介紹jquery
第四天介紹jquery easyui
第五天介紹ajax,並逐步將之前的成果形成最后的實例
第六天便直接進行實例講解,也就是今天的內容
因為我們的后端同事是搞.net的,所以我這里搬出了大家都比較熟悉的datalist作為切入點,然后逐步講解我們前后端如何配合以及為什么不使用服務器控件。
我這里是邊學習邊寫的,最后肯定有很多沒考慮到,各位要提出來喲!
Datalist·我是標題黨:)
呵呵,我絕對是一個優秀的標題黨,因為前端怎么會有datalist呢?所以我們這里來模擬一個看看呢(其實我原來也寫過,但是那時候寫的不夠好)。
有一段時間沒有關注過后端開發了,甚至都忘了后端代碼怎么寫了呢,我們看datalist事實上就是:
1 給定一個html片段,里面具有數據表字段標志
2 數據綁定,將html片段中的變量與數據表進行替換
3 結束
於是我們按照這個思路來試試看呢!
DataItem
第一步我們當然是定義DataItem了呢,來來,我這里是這樣寫的:
PS:為了方便與后端同事交流,我這里盡量和服務器控件靠齊,所以寫法會和一般插件寫法有所不一致。
1 var DataItem = function () { 2 this.data = null; 3 this.template = ''; 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 };
PS:一來就發現個問題,那個event是關鍵字,我居然就這么用了,罪過罪過啊!!!
我們簡單看看他的定義,其實沒有多少東西的:
1 首先每個dataitem項需要數據源
2 每個item會依賴於為其設置的html片段生成最后的代碼
3 后面的那些基本可以忽略不計了,我們用到的時候在說
第一步結束了,我們就沿着上面的邏輯寫代碼吧
根據數據表生成item
我們做的第一步就是根據數據表中的數據,注意我們數據表是一行一行的,所以我們每一行都會生成一個html片段:
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); //形成dom 18 //為了避免id重復,這里對id必須進行處理,我們同時不允許為元素設置id 19 el.attr('id', id); 20 if (this.className) 21 this.el.attr("class", this.className); 22 parentEl.append(el); 23 }
我們來看看這些代碼,其實整個代碼不難:
1 index是數據表的行索引,data是那一行形成的json數據
當然,我們現在不知道templateObj是從哪里來的,不要着急嘛,我們馬上就到這一塊了,既然有了dataitem,怎么少得了主角datalist呢?
偽Datalist
根據item我們現在要寫datalist就相對比較輕松了,直接根據我們需要的東東來吧(安裝后端的寫法來喲)
1 var Datalist = function () { 2 this.id = new Date().getTime().toString(); 3 this.items = []; //所具有的dataitem的項目 4 this.dataSource = null; //各位對他熟悉吧 5 this.container = $("body"); //我們的datalist的容器,沒有指定的話就放在body里面 6 this.style = {}; //可以為其設置樣式這里考慮的好像有點多了 7 this.attribute = {}; //為其設置屬性 8 this.className = ''; 9 this.template = ''; //可以在此設置,也可以指定容器id,然后由容器尋找 10 };
初略一看,感覺這個樣子就差不多了,我們現在來做一件很重要的事情!!!格式化模板!
格式化模板htm
所謂格式化模板htm哎,說的不夠給力直接上代碼吧,看demo:
1 var template = '<dl><dt><span class="span2" ></span><a href="#">{%title%}</a><p class="summary">{%summary%}</p></dt></dl>'; 2 var reg = /\{%[\w]*\%}/; 3 var para = reg.exec(template); 4 var html = template; 5 var templateObj = []; 6 while (para && para.length > 0) { 7 var len = para.index; 8 var tmp = {}; 9 tmp.html = html.substr(0, len); 10 tmp.field = para[0].substr(2, para[0].length - 4); 11 templateObj.push(tmp); 12 html = html.substr(len + para[0].length); 13 para = reg.exec(html); 14 } 15 tmp = {}; 16 tmp.html = html; 17 templateObj.push(tmp); 18 var s = '';
我們這個家伙事干什么的大家一下就看出來了,若是不知道怎么實現的同學可以去看看js的正則我這里就不拓寬了,回到我們的代碼。
我們為datalist增加一個方法,用於格式化模板,以便后面數據的遍歷:
1 Datalist.prototype.formatTemplate = function () { 2 var template = this.template; 3 var reg = /\{%[\w]*\%}/; 4 var para = reg.exec(template); 5 var html = template; 6 var templateObj = []; 7 while (para && para.length > 0) { 8 var len = para.index; 9 var tmp = {}; 10 tmp.html = html.substr(0, len); 11 tmp.field = para[0].substr(2, para[0].length - 4); 12 templateObj.push(tmp); 13 html = html.substr(len + para[0].length); 14 para = reg.exec(html); 15 } 16 tmp = {}; 17 tmp.html = html; 18 templateObj.push(tmp); 19 this.templateObj = templateObj;//注意我們的datalist多了一個東西了哦 20 };
接下來,我們上一個重量級方法,databind!
偽databind
我們知道,這個家伙一調用,我們的數據可就出來了哦:
次要代碼:

Datalist.prototype.initElement = function () { var el = $("<div></div>"); this.el = el; this.initAttribute(); this.initStyle(); }; Datalist.prototype.initAttribute = function () { var scope = this; var element = scope.el; $.each(scope.attribute, function (key, value) { if (typeof (value) == "string") if (value && value.length > 0) { element.attr(key, value); } }); }; Datalist.prototype.initStyle = function () { var scope = this; var element = attribute.el; var style = attribute.style; $.each(style, function (key, value) { if (value && value.length > 0) { element.css(key, value); } }); };
主要代碼:
1 Datalist.prototype.bind = function () { 2 //初始化屬性等操作,我們暫時忽略之 3 //............... 4 this.initElement(); //初始化元素 5 var scope = this; 6 var itemIndex = 0; 7 var container = this.container; 8 container.append(this.el); //將datalist裝入容器 9 10 $.each(this.dataSouce, function (k, v) { 11 var item = new DataItem(); //實例化了一個item了哦 12 item.parentObj = scope; 13 item.templateObj = scope.templateObj; 14 item.load(itemIndex, v); 15 scope.items.push(item); 16 itemIndex++; 17 }); 18 };
我們看到,我們會遍歷我們的數據表,然后每一行會實例化一個item並裝入東西,好了我們來試試他行不行了。
初步測試
先看看我們獲取到的數據:
[{"id":1,"title":"電腦"},{"id":2,"title":"書籍"},{"id":3,"title":"手機"},{"id":4,"title":"照相機"},{"id":5,"title":"洗衣機"}]
好了上代碼,注意我這里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 = $('<div></div>'); //形成dom 30 //為了避免id重復,這里對id必須進行處理,我們同時不允許為元素設置id 31 el.attr('id', id); 32 el.html(tmpHtm); 33 if (this.className) 34 this.el.attr("class", this.className); 35 parentEl.append(el); 36 }; 37 38 var Datalist = function () { 39 this.id = new Date().getTime().toString(); 40 this.items = []; //所具有的dataitem的項目 41 this.dataSource = null; //各位對他熟悉吧 42 this.container = $("body"); //我們的datalist的容器,沒有指定的話就放在body里面 43 this.style = {}; //可以為其設置樣式這里考慮的好像有點多了 44 this.attribute = {}; //為其設置屬性 45 this.className = ''; 46 this.itemClass = ''; //子元素的class 47 48 this.template = ''; //可以在此設置,也可以指定容器id,然后由容器尋找 49 }; 50 51 //好了,我們第一步需要 52 Datalist.prototype.formatTemplate = function () { 53 var template = this.template; 54 var reg = /\{%[\w]*\%}/; 55 var para = reg.exec(template); 56 var html = template; 57 var templateObj = []; 58 while (para && para.length > 0) { 59 var len = para.index; 60 var tmp = {}; 61 tmp.html = html.substr(0, len); 62 tmp.field = para[0].substr(2, para[0].length - 4); 63 templateObj.push(tmp); 64 html = html.substr(len + para[0].length); 65 para = reg.exec(html); 66 } 67 tmp = {}; 68 tmp.html = html; 69 templateObj.push(tmp); 70 this.templateObj = templateObj;//注意我們的datalist多了一個東西了哦 71 }; 72 73 Datalist.prototype.bind = function () { 74 //初始化屬性等操作,我們暫時忽略之 75 //............... 76 this.initElement(); //初始化元素 77 this.formatTemplate(); 78 var scope = this; 79 var itemIndex = 0; 80 var container = this.container; 81 container.append(this.el); //將datalist裝入容器 82 83 $.each(this.dataSource, function (k, v) { 84 var item = new DataItem(); //實例化了一個item了哦 85 item.parentObj = scope; 86 item.templateObj = scope.templateObj; 87 item.load(itemIndex, v); 88 scope.items.push(item); 89 itemIndex++; 90 }); 91 }; 92 93 Datalist.prototype.initElement = function () { 94 var el = $('<div id="' + this.id + '"></div>'); 95 this.el = el; 96 this.initAttribute(); 97 this.initStyle(); 98 }; 99 100 Datalist.prototype.initAttribute = function () { 101 var scope = this; 102 var element = scope.el; 103 $.each(scope.attribute, function (key, value) { 104 if (typeof (value) == "string") 105 if (value && value.length > 0) { 106 element.attr(key, value); 107 } 108 }); 109 }; 110 111 Datalist.prototype.initStyle = function () { 112 var scope = this; 113 var element = this.el; 114 var style = this.style; 115 $.each(style, function (key, value) { 116 if (value && value.length > 0) { 117 element.css(key, value); 118 } 119 }); 120 };
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <script src="js/jquery-1.7.1.min.js" type="text/javascript"></script> 5 <script src="js/Datalist.js" type="text/javascript"></script> 6 <script type="text/javascript"> 7 $(document).ready(function () { 8 var _url = 'Ajax.aspx?sql=select * from bigType'; 9 $.getJSON(_url, function (data) { 10 var d = new Datalist(); 11 d.template = 'id:{%id%},title{%title%}'; 12 d.dataSource = data; 13 d.bind(); 14 }); 15 }); 16 </script> 17 </head> 18 <body> 19 </body> 20 </html>
別說,他還真把我們的東西讀了出來呢!一個非常不好的地方就是他多了一個div並且多了一個id!!!現在我們將之拓寬一點:
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <style type="text/css"> 5 .box { margin: 10px; padding: 10px; border: 1px solid gray; display: inline-block; } 6 </style> 7 <script src="js/jquery-1.7.1.min.js" type="text/javascript"></script> 8 <script src="js/Datalist.js" type="text/javascript"></script> 9 <script type="text/javascript"> 10 $(document).ready(function () { 11 var _url = 'Ajax.aspx?sql=select * from bigType'; 12 $.getJSON(_url, function (data) { 13 var d = new Datalist(); 14 d.template = 'tmp'; 15 d.dataSource = data; 16 d.bind(); 17 }); 18 }); 19 </script> 20 </head> 21 <body> 22 <textarea id="tmp"> 23 <div class="box"> 24 <h3> 25 {%title%}</h3> 26 27 <dl> 28 <dt>{%id%}</dt> 29 <dd>{%title%} 30 </dd> 31 </dl> 32 </div> 33 </textarea> 34 </body> 35 </html>
我們看見我們將模板寫在了文本域里面(這樣可以避免id重復神馬的帶來的不方便)
結語
好吧,今天已經很晚啦,我們明天繼續,結束這一章的東西,明天會解決以下問題(或者說嘗試解決。。。)
1 datalist的嵌套
2 datalist的事件綁定
3 嘗試減少多余的div
4 后端配合之拖動排序
5 后端配合之分屏
6 后端配合之移動
......
好啦好啦,我們睡覺吧。