在 Angular, Vue.js等MVVM框架中,都涉及到指令(directive)的概念,directive实际上是一种针对DOM操作的抽象封装,并通过框架处理,将DOM操作逻辑与DOM元素进行自动化绑定,用一个简单的声明式语法简化了DOM操作逻辑中的给元素命名,查询目标元素,进行DOM操作步骤。举个小例子,比如我们有一个header组件,它的HTML片段内容是:html如果我们希望给这里的按钮添加一个高亮的class,用zepto的代码是这样写的:jsvar $ = require('zepto');var $btn = $('.header button')$btn.addClass('highlight')由以上小例子可以看出,我们在写JS交互逻辑的时候,几乎所有的JS交互逻辑都像以下流程一样:初始化/数据变更/事件触发 --> 给目标元素命名(或者使用DOM树结构)--> 用选择器选中目标元素 --> 进行DOM操作为此,封装DOM操作并自动化将DOM操作与元素绑定,可以减少1/2的交互逻辑代码(1个步骤替换3步骤),甚至做到根据DOM操作与元素与及数据进行绑定,那就可以用一个绑定声明减少了全部的手动步骤。根据这一思路,我们先实现DOM操作封装与html组件的HTML中声明了一个click事件,绑定JS模块中的onBtnClick函数,JS模块的代码为:js// 绑定时依赖的数据var data = {isOn: true}// 封装DOM操作function addClassOrRemove (el, clazz, cnd) {var $el = $(el)cnd ? $el.addClass(clazz) : $el.remove(clazz)}// 将DOM操作与元素绑定,返回操作步骤function classBinding () {var tar = document.querySelector('[binding-class]')var dec = $(tar).attr('binding-class')var clazz = desc.split(':')[0]var field = desc.split(':')[1].trim()return function () {addClassOrRemove(tar, clazz, data[field])}}// 进行绑定操作,获取绑定后的操作方法var updateClassAction = classBinding()// 初始化时更新updateClassAction()显然,在完成DOM操作与DOM元素的绑定后,以后的每次更新触发场景中一个步骤就可以完成DOM元素的更新。我们需要更懒惰一点,把手动触发更新的操作也省略了,如何?那么我们需要现实监听数据的变更,在不考虑兼容IE9的情况下,我们可以使用ES5的defineProperty方法来实现:jsvar data = {}var _isOnObject.defineProperty(data, 'isOn', {get: function () {return _isOn},set: function (nextValue) {_isOn = nextValue// 在监听到数据变更后立即触发UI更新updateClassAction()}})这就是MVVM的数据绑定的实现,在框架帮助下完成以上一系列的绑定行为,要完成根据状态给按钮添加/移除高亮的class,我们只需要这样一个属性标志:html个人认为,使用属性声明的方式自动化绑定优于具名选择器的方式操作DOM元素。从开发效率角度,我们省去了给元素命名/查询目标元素/进行DOM操作这3步操作,从维护性角度,我们也省却了知道文档结构/知道选择器标志2个步骤。