D2JS 将数据绑定视为“对象-路径-渲染/收集 ”组成。主要 DOM 元素和对象绑定,称为 d2js.root,非主要元素指定数据路径,通过路径定位到值,根据值可进行渲染或收集。
为何要设计路径概念?页面域中的对象,其成员值对象经常在变化,如果每个DOM元素都直接绑定到对象,下次渲染时可能成员对象已经被新的成员值对象取代了。如图中,当执行下面代码后
Linda 成为顺序为 0 的朋友。由于 td 使用的是 “0,name”这样的形式说明的字符串,而不是 {name:”Tim”,tel:”…”} 对象,因此可以再次从 person 对象展开得到新的索引为 0 的 friend 对象 Linda。
d2js 使用 data 说明数据路径。带有数据路径的元素在渲染或收集时,从最近的(closest)含有 d2js.root 的元素所绑定的对象开始,按数据路径层层展开。
该设计动静结合,相对稳定的对象,通过 bindRoot 绑定后基本不再活动,相对不稳定的对象,通过数据路径约定,每次渲染重新定位值。
此外,d2js 还有一个单根的全局数据对象,d2js.root,其又是 d2js.dataset 的别名。html 元素也可以使用 <element d2js.root="member"> 方式(而不是 bindRoot)说明数据对象。关于该方式可详见 d2js 示例。
d2js 框架不是一个灵敏绑定框架,也不是双向绑定框架。许多使用灵敏框架的人都在找怎么避免文本框一敲界面就乱动——加 onchange/oninput 容易,禁止 onchange/oninput 难。
实际业务开发中,收集行为极少发生,界面与对象并不需要实时同步。有时界面以 24fps 速率刷新,有时在用户强制行为后刷新,这些行为各有特色,实时同步实现繁琐且又无实际价值,只对初学者有“哇,全自动化什么都不用干了”的快感。
取消灵敏绑定,渲染收集可以局部进行,程序员可根据业务情景决定刷新哪部分界面,页面开发变得更直接灵活。而灵敏绑定方案里,程序员面对的是一个强大的黑匣子,很难识别数据与界面是如何发生关系的,难以跟踪运行过程,难以排查错误。