Skip to content

vuejs和angularJS数据绑定的异同 #1

@front-thinking

Description

@front-thinking

经常有人问起vuejs和angularjs两个框架在实现数据绑定方面的异同点,这也是在面试当中经常问到的一个问题。虽然两个框架都用了很久,但能把这个问题讲清楚其实还是比较困难。虽然曾经仔细研究过框架实现数据绑定的底层代码和机制,但由于缺乏总结,仍然难以讲清楚。


vuejs

先来看一下vuejs是怎么实现的。用一个简单的词就是“数据劫持”。初看这个词,感觉好高深。其实其本质就是通过Object.defineProperty()来实现其具体的getter和setter方法,以达到劫持数据的模式来实现数据的响应式。这么说看起来又掉绕口,下面我们通过一个简单的例子来看看如何实现数据的响应式更新:

// html
<h2></h2>

// js
var obj = {};
var text = '';
var h2 = document.getElementsByTagName('h2')[0];
Object.defineProperty(obj, 'text', {
    get: function () {
        return text;
    },
    set: function (newVal) {
        text = newVal;
        h2.innerHTML = text;
    }
});

上面的代码很简单,我们先在html中创建了h2标签,然后在js中对对象obj的text属性设定了它的修饰符,实现了它的getter和setter。此时,我们在代码里或者console里修改obj.text的值,那么h2标签里的值也会一起跟着改变。

是不是很简单?响应式的数据绑定就这么实现了。而事实上,vuejs就是这么实现的。当然,vuejs中并不是这么简单,它还做了其它一些事情。Vue在初始化执行_init方法的时候会对数据进行reactive化,简单的讲就是对data进行数据依赖收集,通过我们熟知的pub/sub模式来形成一个个watcher,这些watcher有些来自于function,也有来自于视图。

angularjs

下面我们再来看一下angularjs中如何实现数据绑定的。在介绍之前,同样我们用一个词来总结它在angularjs中的实现,即“脏检查”机制。

我们都知道,在angularjs底层代码实现上,定义在$scope上的属性都会定义一个$watcher放到$watchers的数组当中,每一次修改该属性的时候,$watcher都会执行一遍$digest,然后把数据变化更新到视图当中。watch的属性会被封装为一个函数,每次digest的时候都会执行这个函数,然后对比与前一次执行的结果来判断是否dirty,进而执行对应的回调。这是angularjs实现数据绑定的基础。抛开这些容易把人搞晕的高深词汇,angularjs底层实现就是基于pub/sub这个设计模式来的。

前面的一段我们大致介绍了angularjs实现的基础,其中提到了很核心的dirty checking机制。那么都是在什么时候会启用dirty checking呢?

  • DOM事件,譬如用户输入文本,点击按钮等。( ng-click )

  • XHR响应事件( $http )

  • 浏览器Location变更事件 ( $location )

  • Timer事件( $timeout , $interval )

  • 执行 $digest() 或 $apply()

这里angularjs有一个令人诟病的性能问题。如果scope上watcher数组特别长,那么每一次进入digest cycle,都要执行一遍,那么将引起严重的性能问题。其实,个人觉得在这方面大家是多虑了。angularjs团队没那么傻,在框架底层源码其实做了很大的优化,对于数组、对象等复杂数据的watcher方面,代码都做了最大的优化,以保证不会执行不必要的digest cycle. 对于这一点,并不是本文的重点,不再赘述。以后有时间可以单独讲一下。

结论

到此,vuejs和angularjs数据绑定的实现原理基本讲完,归结一下就是分别利用了“数据劫持”和“发布订阅者模式”。文章若有错误的地方,欢迎指正!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions