组织大表单应用中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/

相关文章
相关标签/搜索