2

引子

在前端开发中,常常有这样的naive的代码,先是在HTML中定义了页面结构:

<div class="order-total">100</div>

在有交互时,用js通过其class来取到节点,然后将数据写进去,如$('.order-total').html(300)

大约在三年前,这种做法在业界还颇为流行,几乎所有的书里,网上教义,都在鼓吹这种分离JS和HTML的行为,认为这么做就是天经地义。

但是当代码量多了之后,当页面交互复杂了之后,我们的代码常常就成了:

if (exist($('.selector'))) {
   // do something
}

整个文件中,充斥着这样或那样的if,因为没人能确定这个节点是否存在。还充斥着另一种东西:

/* note: 这不是标准的jquery代码 */
var quantity = $(this).parent().parent().find('.quantity-value');

这种连扔垃圾桶都不配的代码真是写的时候爽,后面维护者遭殃的典型范例,你必须不断地切换js/html来审视其强依赖的结构。

那么问题来了,为什么会写出这样的代码呢?

因为这种代码是最符合直觉的书写方式,一个初级程序员未经任何训练,就能写出这样的代码。它的名字叫:命令式编程。

存在的问题

命令式编程存在的问题就是,写的人在写的时候知道是怎么回事,试图掌控一切,后果是:
- 不知道代码中的一系例选择器对应着什么节点
- 可维护性差,你不敢轻易改动类名或删除节点,也不清楚节点的内容究竟对应着什么数据
- 代码量多

控制反转

上面说道,命令式编程试图控制一切,而解决的办法就是,交出控制权,将控制权反转,即:

不要来找我,我会去找你。

原来的工作流:

  • 用户输入/点击/Ajax请求
  • 数据变化 => order = 100
  • 取节点,将内容设到页面 => $('.order-div').html(order) #JS主动来找DOM#

如果页面已经不需要这个信息了,将.order-div从html中删掉,重复上面的流程,执行到第三步时,JS将抛出异常,因为节点找不到。

控制反转的工作流:

  • 元素监听数据变化<div class='order-dv' ng-bind='order'></div>,即#我会去找你#
  • 用户输入/点击/Ajax请求
  • 数据变化 => order = 100
  • 元素的innerHTML将被自动设上100

如果页面已经不需要这个信息了,将.order-div从html中删掉,重复上面的流程,对程序没有任何影响,因为是节点自己去取数据,而不是JS主动去取节点,而这种方式就做:声明式编程。

小结

双向绑定本质上是一种IoC的思想,通过让:

  • 页面元素声明自己依赖的model
  • JS逻辑不依赖具体dom

达到了解耦合的目的。


ssnau
1.5k 声望98 粉丝

负能量职业打码师