組織大表單應用中javascript代碼的一種方法

組織大表單應用中javascript代碼的一種方法

問題,動機,目的

超過一屏,屬性複雜到必定程度的錄入界面/系統中,缺少良好架構的javascript代碼每每容易失控。尤爲是當規模從小型表單開始逐漸變大時,javascript代碼很容易演變成已DOM爲核心的、缺少結構、盡是hack且難以維護的狀態。javascript

我認爲良好可維護的JS代碼應該具備如下的特性java

  • 單個文件應該控制在一千行之內
  • 依賴管理和合並,開發應該單看一個JS文件就知道它依賴別的哪些代碼,而不是在HTML中直接列舉全部依賴,或者更糟,把全部超過2個頁面要用的JS全寫一塊兒。
  • 良好的代碼複用,清晰的模塊劃分
  • 改變字段的表現形式或邏輯時,不該該須要修改/考慮/知道其餘字段的邏輯和展示形式。改變DOM樹結構、更換表單控件等改變展示方式的需求不該當對JS產生毀滅性打擊。

前三個問題基本能夠歸結爲,超過一千行的或是須要複用的JS代碼使用RequireJS / SeaJS 等方案進行分解和管理。因爲這是複雜JS工程的共性,這裏很少作展開討論。本文主要關注最後一點,也就是如何解除字段邏輯和展現之間的耦合,如何解除字段和其餘字段的耦合。git

解耦,協議,模板化

解除耦合的作法不外乎將抽象出最小化的接口(協議)。字段能夠有千奇百怪的各類邏輯,但抽象後發現其實針對單個字段來講,須要的最小接口很是小——簡直太適合解耦、正交化了github

  • val 方法,傳值則寫入,不傳則讀取(jQuery風格)
  • setReadonly 方法 設置只讀
  • setWritable 方法 設爲可寫(固然設計成setReadonly(false)也不壞)
  • change 事件 值被改變時觸發
  • error 事件 須要提示用戶這個字段有問題時觸發

訂好接口之後,每一個字段只須要本身都實現接口,除了每一個字段本身的實現代碼以外,外部一概經過接口來和字段交互。這樣代碼就總體可控可維護,擴展性和可讀性都能使人滿意。架構

有了這樣的接口,咱們的邏輯實現就能夠很是語義化,好比折扣鎖定爲=現價/原價dom

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交互,因此不管價格如何輸入展現,折扣如何展現都沒有問題。而實現dom交互的代碼也徹底沒必要關心這個字段的邏輯如何,只須要實現前述接口,將輸入輸出、只讀、提示信息這些行爲和DOM綁定便可。ui

最經常使用也是最多的綁定就是一個字段對應一個DOM控件,這種綁定只須要簡單地將DOM事件轉發成自定義事件,將讀寫轉換成DOM控件讀寫便可;稍微複雜一些的交互涉及富文本編輯、日曆控件等輸入形式,因爲咱們的接口很是小,因此通常也無需太多的代碼。spa

問題每每來源於更復雜的一些字段,他們在持久化時每每體現成JSON/XML格式字符串,或者是額外的擴展表。這些字段每每沒法輕易地用一個標準DOM控件來表現,也每每是混亂的來源。設計

DOM操做難以維護的主要緣由是插入、刪除元素的同時還要維護事件,在同一個頁面反覆進行各類操做的時候,邏輯容易有問題,因此個人作法是code

  • 事件用委託僅在初始化的時候綁在容器上一次
  • 不單獨插入、刪除dom元素,而是以模板和數據渲染出全部元素
  • 在內存裏維護一個變量存儲當前的數據,dom裏面的數據並不具權威性

Templated field

  • render渲染例程:

    • 觸發點:由change事件觸發
    • 行爲:從內存讀取數據後(用模板)渲染出全部的DOM元素的HTML代碼,一次性吐在容器中
  • normalize規範化例程:

    • 觸發點:dom事件/val賦值 寫入數據時
    • 行爲:將輸入數據進行規範化,而後寫入內存並觸發change事件

校驗,提交

因爲複雜表單每每涉及一樣複雜的驗證邏輯,建議儘量將邏輯集中在後臺CGI,JS少作邏輯(不然同時維護兩套不一樣語言的等價的邏輯成本較大)

不管錯誤是從CGI拿到,仍是JS本身驗出來,顯示錯誤提示都同樣經過字段上的error事件來傳遞,校驗代碼負責觸發事件,字段自己的實現代碼監聽事件來在界面上顯示相應的提示。

提交數據時,只須要遍歷全部字段的集合,將他們的字段名和val()結果拼裝

DSL

總而言之,解決混亂代碼的思路之一是將「需求/規則」和「表現/操做」分離,將前者抽象成某種形態的DSL,使之儘可能貼近產品的需求,而後將後者做爲這種DSL的解釋器來寫。代碼寫到像天然語言就贏了。若是作不到,不妨針對一個領域寫解釋器來解釋爲何這些天然語言能工做。這是符合計算機科學發展大規律的,道法天然

--EOF--

原文連接 http://mcfog.github.io/2013/06/dsl-style-javascript/

相關文章
相關標籤/搜索