來源:互聯網
上載者:User
關鍵字
nbsp;
我們
function
name
1 名詞解釋
桐花萬里丹山路,雛鳳清于老鳳聲——唐·李商隱《韓冬郎既席為詩相送因成二絕》
作為一種有別傳統的前端程式設計方法,雛風名之。
面向資料的程式設計方法,避開繁瑣的ui代碼,直接針對前端資料模型程式設計,你的程式就能更加清晰簡單。 清音名之。
2 從實例開始
避免過於枯燥的陳述,我們從實例開始,我們以百度 WebIM分組管理為例。
這裡面,我們需要對使用者群組清單執行:添加、刪除、修改、保存、取消、排序等六種功能。
這算是一個比較常見的需求,那麼,我們通常在前段實現這種功能,一般如何設計? 多少代碼? 多長時間?
考慮時間............................
===================================================
好了現在我們來展示一中簡單的實現方式:
程式碼:
var data = { "list": [ { " id": 1, "name": "我的分組1" }, { "id": 2, "name": "我的分組2" }, { "id": 3, "name": " 我的分組3" }, { "id": 4, "name": "我的分組4" } ]}var action = { sort: function(list, inc) { $("sort").className = inc ? "down": "up"; list.sort(function(a, b) { & nbsp; return (inc ? 1: -1) * a.name.localeCompare(b.name); }); render(data); }, & nbsp; create: function(name) { data.list.push({ id: +new Date(), name: name }); render(data); }, edit: function(id) { each(data.list, function(value, i) { data.list[i].state = value.id == id ? "edit": "normal"; }); render(data); }, del: function(id) { each(data.list, function(value, i) { if (value.id == id) { data.list.splice(i, 1); } }) & nbsp; render(data); }, save: function(id) { each(data.list, function(value, i) { if (value.id == id) { value.name = $("g_" + id).value; value.state = "normal"; } });& nbsp; render(data); }, cancel: function(id) { each(data.list, function(value, i) { data.list[i].state = "normal"; & nbsp;}); render(data); }}function $(id) { return document.getElementById(id);} function each(obj, fn) { for (var i = 0; i & lt; obj.length; i++) { fn.call(obj[i], obj[i], i); }}function render(data) { $("container").innerHTML = teamList(data);}
範本代碼:
<div class="${item.state}"><div class="cell1"><input id="g_${item.id}" value="${item.name}" / ></div><div class="cell2"><button onclick="action.submit(${item.id})">提交</button>< /div><div class="cell3"><button onclick="action.cancel(${item.id})">取消</button></div> <div class="cell1">${item.name}</div><div class="cell2"><img onclick="action.edit(${item.id} )" src="images/edit.gif" alt="" /></div><div class="cell3"><img onclick="action.del(${item.id})" src="images/delete.gif" alt="" /></div></div>
以傳統的程式設計方法不同,我們沒有直接操作html,或者說文件物件模型,而是抽象出一個更加簡單的資料模型–一個JavaScript 陣列物件。
我們所有的操作都是從這個簡單的原始資料開始,資料模型被修改後,調用範本渲染函數,重新前端局部刷新展現UI。 操作即可完成。
我們所有的操作都是從這個簡單的原始資料開始,資料模型被修改後,調用範本渲染函數,重新前端局部刷新展現UI。 操作即可完成。
這種方法能給我們簡化多少代碼呢? 大家可以去翻翻那些比較出名的JavaScript圖書,裡面通常會花一個小節的篇幅去講解一個話題,那就是表格排序。
對照這裡的表格排序,7行代碼,需要一個章節去解釋嗎?
3 核心思想3.1 一切從源頭開始
傳統的程式設計方法有一個問題,那就是他修改的物件是文件物件模型,但是,當您的程式足夠複雜的時候,這種文件物件模型往往不夠簡單,有太多冗余,或者夾雜著太多的靜態展示邏輯,我們控制它非常麻煩。 好了,我們沒有必要遷就文件物件模型,我們要設計更加簡單的沒有冗余的前端模型。
一切從源頭開始,不僅是為了操作上更加簡單,更重要的一點是,避免資料不一致和錯誤累加的危害。
如果是傳統的文檔資料模型,不僅他本身帶有大量冗余。 我們前段操作代碼也容易有大量的冗余。 如上例,傳統的方法中,初次展現的群組清單和後來編輯,添加的分組,可能生成方法都不一樣,分佈在不同的代碼中,一單涉及到展現風格的修改,都得多次同步編輯,這在程式設計上的大忌。 而我們上面介紹的方法中,我們只有一處展現邏輯,那就是完整覆蓋。 仍外,傳統方法是對UI做增量的修改操作,但是加加減減的多了,難免不出點小問題,而且,這種問題只能被累加起來,但是在我們新的程式設計方法中,因為我們每次都是整體覆蓋,這樣就不會有錯誤累加的問題了。
3.2 表現層沒有上下文
既然我們有自己的資料模型,就不要隨便在文件物件模型上保留任何狀態了,任何修改,都反映到資料模型中去吧,狀態改變了,同步資料模型,再從資料模型開始,完全覆蓋前端展示。
4 性能的問題
上例中的連絡人分組管理,能承受多大的資料呢?
我們得先解釋一下我們的統計方法。
人的視覺停留時間是0.1秒,或者說100毫秒。 也就是說,100毫秒間隔人類是無法感知的。 而我們的網頁操作。 是一種延遲,不是間隔,人類能感知的時間延遲有多少呢? 我們沒有權威的資料,一般認為是300毫秒。 300毫秒內的延遲,我們是無法感知的。
那麼300毫秒內,我們能渲染多少資料呢? IE8,FF3(不打開Firebug,打開firebug能渲染400次)上能支援1000條左右,Chrome上能支援3000次左右。
另外,在某些情況下,面向資料的程式設計方法,性能可能還具有一定的優勢。 比如,百度工具列widget清單的設計中,我們一次裝載了較多的widget資料,但是我們每次只展示一小部分,這樣,面向資料邊車呢個方法中DOM節點明顯比傳統方式少一個數量級。 要知道,DOM節點是非常消耗記憶體的。。。。
說點不足
動畫,對,我們不應該採用這種方式做網頁動畫,因為動畫的刷性要求太高,範本這種重頭開始的方式不再適用。
所以,真要使用js動畫效果的時候,你還是應腳本庫去輔助。
同時提一點個人看法,使用者體驗的提高並不是動畫這樣吸引 眼球的效果。 更多考慮應該是讓使用者操作更方便,不要被扣分。
5 如何體驗?
1. 運行JSide調試伺服器:HTTP://www.xidea.org/webstart/JSide.jnlp
一個webstart程式,JSide 啟動之後會在視窗右側出現一個彩色的浮層(無邊框視窗,如果是JAVA6u10+,這個視窗會透明顯示)
2. 下載測試程式並解壓。 HTTP://lite.googlecode.com/files/Example-20091219.zip
下載之後隨便解壓縮到一個目錄裡面吧。
3. 設置調試網站目錄。
測試伺服器就是為了測試方便而設計的,你只要把剛才解壓縮的目標目錄拖放到JSide浮層上,測試伺服器自動切換網站目錄。
4. 查看測試程式。
每次切換網站目錄後,程式會提示您打開網站首頁,你打開就是了。 首頁預設是一個檔案清單。 選擇你看著順眼的檔點擊吧(*.s.js是一種用JavaScript編寫的服務端小程式,可以在JSide測試伺服器上運行)
5.修改程式碼。
在JSide浮層上右鍵,流覽檔,修改吧。
來源:HTTP://www.baiduux.com/blog/2010/01/14/data_oriented_programing_in_web_frontend/