vue实现数据驱动视图原理

1、什么是数据驱动

  数据驱动是vuejs最大的特色。在vuejs中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不须要手动的去修改dom。javascript

  好比说咱们点击一个button,须要元素的文本进行是和否的切换。在jquery刀耕火种的年代中,对于页面的修改咱们通常是这样的一个流程,咱们对button绑定事件,而后获取文案对应的元素dom对象,而后根据切换修改该dom对象的文案值。而对于vuejs实现这个功能的流程,只须要在button元素上指明事件,同时声明对应文案的属性,点击事件的时候改变属性的值,对应元素的文本就可以自动的进行切换,咱们不须要像之前那样手动的操做dom。前端

  简而言之,就是vuejs帮咱们封装了数据和dom对象操做的映射,咱们只须要关心数据的逻辑处理,数据的变化就可以天然的通知页面进行页面的从新渲染vue

  这样作的确实给咱们带来的好处,咱们不须要再在代码中频繁地去操做dom了,在实际项目中,咱们有很大部分代码都是在数据修改之后,手动操做从新渲染页面元素,当页面愈来愈复杂的时候,页面代码组织会越来难以维护。同时,js对dom的频繁操做,会使得页面代码的出错几率高,页面的视图展现会融合在js代码中,对于页面视图显示的升级也不友好。java

  那么vuejs是如何实现这种数据驱动的呢?jquery

2、MVVM框架

  Vuejs的数据驱动是经过MVVM这种框架来实现的。MVVM框架主要包含3个部分:model、view和 viewmodel。app

  Model:指的是数据部分,对应到前端就是javascript对象框架

  View:指的是视图部分,对应前端就是domdom

  Viewmodel:就是链接视图与数据的中间件函数

  数据(Model)和视图(View)是不能直接通信的,而是须要经过ViewModel来实现双方的通信。当数据变化的时候,viewModel可以监听到这种变化,并及时的通知view作出修改。一样的,当页面有事件触发时,viewModel也可以监听到事件,并通知model进行响应。spa

  Viewmodel就至关于一个观察者,监控着双方的动做,并及时通知对方进行相应的操做。

3、Vuejs的数据驱动实现

  对于数据驱动的实现,咱们能够简单的经过定时器来实现这个功能,定时器定时监控对象数据,定时器监控数据变化,肯定是否更新界面

var a = 1; function renderDom() { document.getElementById('app').innerHTML = '数据是' + a; } function watcher(method) { var b = a; method.apply(); return setInterval(function() { if (b != a) { method.apply(); b = a; } }, 1000) } watcher(renderDom);

  固然vuejs不多是这样简单暴力的实现方式,vuejs是经过在实现一个观察者来实现的数据驱动。

  首先,vuejs在实例化的过程当中,会遍历传给实例化对象选项中的data 选项,遍历其全部属性并使用 Object.defineProperty 把这些属性所有转为 getter/setter。

  同时每个实例对象都有一个watcher实例对象,他会在模板编译的过程当中,用getter去访问data的属性,watcher此时就会把用到的data属性记为依赖,这样就创建了视图与数据之间的联系。当以后咱们渲染视图的数据依赖发生改变(即数据的setter被调用)的时候,watcher会对比先后两个的数值是否发生变化,而后肯定是否通知视图进行从新渲染。

  这样就实现了所谓的数据对于视图的驱动。通俗地讲,它意味着咱们在普通 HTML 模板中使用特殊的语法将 DOM “绑定”到底层数据。一旦建立了绑定,DOM 将与数据保持同步。每当修改了数据,DOM 便相应地更新。这样咱们应用中的逻辑就几乎都是直接修改数据了,没必要与 DOM 更新搅在一块儿。这让咱们的代码更容易撰写、理解与维护。

  对getter/setter的理解
  当打印出Vue实例下的data对象里的属性,它的每一个属性都有两个相对应的get和set方法。正常状况下,咱们取值和赋值是用obj.prop的方式,可是这样作有一个问题,我如何知道对象的值改变了?因此就轮到set登场了。
  你能够把get和set理解为function,当咱们调用对象的属性时,咱们会进入到get.属性(){...}中,先判断对象是否有这个属性,若是没有,那么就添加一个name属性,并给它赋值;若是有name属性,那就返回name属性。你能够把get当作一个取值的函数,函数的返回值就是它拿到的值。
  感受比较重要的是set属性,当给实例赋值:此时,会进入set name(val){...};形参val就是我赋给name属性的值,在这个函数里,就能够作不少事了,好比双向绑定!由于这个值的每次改变都必须通过set,其余方式是改变不了它的,至关于一个万能的监听器。ES5的对象原型有两个新的属性__defineGetter__和__defineSetter__,专门用来给对象绑定get和set。建议使用下面这种方式,由于是在原型上书写,因此能够继承和重用。
相关文章
相关标签/搜索