摘要:組織大表單應用中代碼的一種方法問題,動機,目的超過一屏,屬性復雜到一定程度的錄入界面系統(tǒng)中,缺乏良好架構(gòu)的代碼往往容易失控。改變樹結(jié)構(gòu)更換表單控件等改變展現(xiàn)方式的需求不應當對產(chǎn)生毀滅性打擊。
組織大表單應用中javascript代碼的一種方法 問題,動機,目的
超過一屏,屬性復雜到一定程度的錄入界面/系統(tǒng)中,缺乏良好架構(gòu)的javascript代碼往往容易失控。尤其是當規(guī)模從小型表單開始逐漸變大時,javascript代碼很容易演變成已DOM為核心的、缺乏結(jié)構(gòu)、滿是hack且難以維護的狀態(tài)。
我認為良好可維護的JS代碼應該具有以下的特性
單個文件應該控制在一千行以內(nèi)
依賴管理和合并,開發(fā)應該單看一個JS文件就知道它依賴別的哪些代碼,而不是在HTML中直接列舉所有依賴,或者更糟,把所有超過2個頁面要用的JS全寫一起。
良好的代碼復用,清晰的模塊劃分
改變字段的表現(xiàn)形式或邏輯時,不應該需要修改/考慮/知道其他字段的邏輯和展現(xiàn)形式。改變DOM樹結(jié)構(gòu)、更換表單控件等改變展現(xiàn)方式的需求不應當對JS產(chǎn)生毀滅性打擊。
前三個問題基本可以歸結(jié)為,超過一千行的或是需要復用的JS代碼使用RequireJS / SeaJS 等方案進行分解和管理。由于這是復雜JS工程的共性,這里不多做展開討論。本文主要關注最后一點,也就是如何解除字段邏輯和展示之間的耦合,如何解除字段和其他字段的耦合。
解耦,協(xié)議,模板化解除耦合的做法不外乎將抽象出最小化的接口(協(xié)議)。字段可以有千奇百怪的各種邏輯,但抽象后發(fā)現(xiàn)其實針對單個字段來說,需要的最小接口非常小——簡直太適合解耦、正交化了
val 方法,傳值則寫入,不傳則讀?。╦Query風格)
setReadonly 方法 設置只讀
setWritable 方法 設為可寫(當然設計成setReadonly(false)也不壞)
change 事件 值被改變時觸發(fā)
error 事件 需要提示用戶這個字段有問題時觸發(fā)
訂好接口以后,每個字段只需要自己都實現(xiàn)接口,除了每個字段自己的實現(xiàn)代碼之外,外部一律通過接口來和字段交互。這樣代碼就整體可控可維護,擴展性和可讀性都能令人滿意。
有了這樣的接口,我們的邏輯實現(xiàn)就可以非常語義化,比如折扣鎖定為=現(xiàn)價/原價
good.discount.setReadonly(); var discountUpdate = function() { good.discount.val(good.price.val() / good.originalPrice.val()); }; good.price.addListener("change", discountUpdate); //注意:這不是DOM事件 good.originalPrice.addListener("change", discountUpdate);
這樣一段代碼完全不涉及dom交互,所以無論價格如何輸入展示,折扣如何展示都沒有問題。而實現(xiàn)dom交互的代碼也完全不必關心這個字段的邏輯如何,只需要實現(xiàn)前述接口,將輸入輸出、只讀、提示信息這些行為和DOM綁定即可。
最常用也是最多的綁定就是一個字段對應一個DOM控件,這種綁定只需要簡單地將DOM事件轉(zhuǎn)發(fā)成自定義事件,將讀寫轉(zhuǎn)換成DOM控件讀寫即可;稍微復雜一些的交互涉及富文本編輯、日歷控件等輸入形式,由于我們的接口非常小,所以一般也無需太多的代碼。
問題往往來源于更復雜的一些字段,他們在持久化時往往體現(xiàn)成JSON/XML格式字符串,或者是額外的擴展表。這些字段往往無法輕易地用一個標準DOM控件來表現(xiàn),也往往是混亂的來源。
DOM操作難以維護的主要原因是插入、刪除元素的同時還要維護事件,在同一個頁面反復進行各種操作的時候,邏輯容易有問題,所以我的做法是
事件用委托僅在初始化的時候綁在容器上一次
不多帶帶插入、刪除dom元素,而是以模板和數(shù)據(jù)渲染出所有元素
在內(nèi)存里維護一個變量存儲當前的數(shù)據(jù),dom里面的數(shù)據(jù)并不具權威性
render渲染例程:
觸發(fā)點:由change事件觸發(fā)
行為:從內(nèi)存讀取數(shù)據(jù)后(用模板)渲染出所有的DOM元素的HTML代碼,一次性吐在容器中
normalize規(guī)范化例程:
觸發(fā)點:dom事件/val賦值 寫入數(shù)據(jù)時
行為:將輸入數(shù)據(jù)進行規(guī)范化,然后寫入內(nèi)存并觸發(fā)change事件
校驗,提交由于復雜表單往往涉及同樣復雜的驗證邏輯,建議盡可能將邏輯集中在后臺CGI,JS少做邏輯(否則同時維護兩套不同語言的等價的邏輯成本較大)
無論錯誤是從CGI拿到,還是JS自己驗出來,顯示錯誤提示都一樣通過字段上的error事件來傳遞,校驗代碼負責觸發(fā)事件,字段本身的實現(xiàn)代碼監(jiān)聽事件來在界面上顯示相應的提示。
提交數(shù)據(jù)時,只需要遍歷所有字段的集合,將他們的字段名和val()結(jié)果拼裝
DSL總而言之,解決混亂代碼的思路之一是將“需求/規(guī)則”和“表現(xiàn)/操作”分離,將前者抽象成某種形態(tài)的DSL,使之盡量貼近產(chǎn)品的需求,然后將后者作為這種DSL的解釋器來寫。代碼寫到像自然語言就贏了。如果做不到,不妨針對一個領域?qū)懡忉屍鱽斫忉尀槭裁催@些自然語言能工作。這是符合計算機科學發(fā)展大規(guī)律的,道法自然。
--EOF--
原文鏈接 http://mcfog.github.io/2013/06/dsl-style-javascript/
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78076.html
摘要:因為用戶不用在第一次進入應用時下載所有代碼,用戶能更快的看到頁面并與之交互。譯高階函數(shù)利用和來編寫更易維護的代碼高階函數(shù)可以幫助你增強你的,讓你的代碼更具有聲明性。知道什么時候和怎樣使用高階函數(shù)是至關重要的。 Vue 折騰記 - (10) 給axios做個挺靠譜的封裝(報錯,鑒權,跳轉(zhuǎn),攔截,提示) 稍微改改都能直接拿來用~~~喲吼吼,喲吼吼..... 如何無痛降低 if else 面...
摘要:設計模式是一套可復用的,被眾人知曉,經(jīng)過編目分明的,經(jīng)驗的總結(jié)。創(chuàng)建類安全工廠判斷是否調(diào)用關鍵字設計模式設計模式運算符可以用來判斷某個構(gòu)造函數(shù)的屬性所指向的對象是否存在于另外一個要檢測對象的原型鏈上。 設計模式 是一套可復用的,被眾人知曉,經(jīng)過編目分明的,經(jīng)驗的總結(jié)。作用:使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性 模式類型 創(chuàng)建型設計模式:解決對象在創(chuàng)建時產(chǎn)...
摘要:該區(qū)域代表可以被所控制的畫布。那么現(xiàn)在第二個問題,識別該文檔,這或許不是大部分用戶的需求,但小部分用戶并不意味著人數(shù)少。因此一個基于的請求于標準內(nèi)提出。 前言 作為程序員,技術的落實與鞏固是必要的,因此想到寫個系列,名為 why what or how 每篇文章試圖解釋清楚一個問題。 這次的 why what or how 主題:現(xiàn)在幾乎所有人都知道了 HTML5 ,那么 H5 到底相...
摘要:,微軟發(fā)布,同時發(fā)布了,該語言模仿同年發(fā)布的。,公司在瀏覽器對抗中沒落,將提交給國際標準化組織,希望能夠成為國際標準,以此抵抗微軟。同時將標準的設想定名為和兩類。,尤雨溪發(fā)布項目。,正式發(fā)布,并且更名為。,發(fā)布,模塊系統(tǒng)得到廣泛的使用。 前言 作為程序員,技術的落實與鞏固是必要的,因此想到寫個系列,名為 why what or how 每篇文章試圖解釋清楚一個問題。 這次的 why w...
閱讀 740·2021-11-24 10:19
閱讀 1126·2021-09-13 10:23
閱讀 3445·2021-09-06 15:15
閱讀 1788·2019-08-30 14:09
閱讀 1702·2019-08-30 11:15
閱讀 1850·2019-08-29 18:44
閱讀 948·2019-08-29 16:34
閱讀 2470·2019-08-29 12:46