数据驱动
Vue的数据驱动
便是不同以往的js需要通过事件来触发更新DOM,而是直接当数据发生变化
,页面就会随之更新
,不需要手动去更新DOM,更加便捷简单,而Vue的数据驱动就要依赖虚拟DOM
以及双向数据绑定
。
双向数据绑定
Vue的双向数据绑定依赖的是 数据劫持 + 发布者订阅者模式
。
数据劫持——属性的get和set
Vue是通过Object.defineProperty()
来实现数据劫持
的,当我们打印一个对象的时候,会看到对象的属性都绑定着两个函数:get 和 set 。
Vue页面组件的数据初始化都是在data
对象里面进行声明,Vue会遍历data里面所有声明的对象的属性property
,之后Vue会利用Object.defineProperty()
劫持这些属性然后生成get/set
函数 。
顾名思义:get,显示属性值;set,设置属性值。 get/set 对用户来说是不可见的,但是在内部 Vue 能够追踪依赖,在 property 被访问和修改时Object.defineProperty()就会知道。
发布-订阅模式
Object.defineProperty()通过数据劫持可以获知对象属性的更改,但是页面怎么知道数据更改了呢???????????????
JS的页面更新依赖于事件的触发,简单来讲,就是触发事件来通知页面数据更改了,但是Vue不是依靠事件的,依靠的是发布-订阅模式
。
举个🌰:
有人来买报纸,但是报纸还没有出来,此时就把watcher登记一下,然后报纸出来之后,一次性通知所有登记了的watcher,这就是Obsever的发布环节。
1、所谓Obsever,便是当属性更改后,需要将更改信息告知Watcher,他的核心就是Object.defineProperty(),因为数据更改会触发set函数,然后set函数就会进行发布操作
2、所谓Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图
那么了解一下,watcher是怎么知道更新的呢,简单理解,就是 get 函数里面会注册watcher,注册的时候是在一个Dep对象里面进行添加注册watcher;当属性更改,触发set,set 函数通过Dep.notify向所有watcher发送更改通知,watcher就会知道数据更改了。
Obsever{ getter注册 / setter发布 } <---------> watcher <--------------> View
虚拟DOM
当数据发生改变时,set方法会让调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁,进行页面的真正更新。
对象属性添加、移除响应
这里需要提到,属性在data对象里面进行声明后才会有响应数据操作,但是肯定有一些声明的对象,之后会添加一些property,但是这样watcher就根本不知道更新变化。
Vue是没有办法监测到一个对象里面property添加和移除的
,此时就必须要解决上面的问题,Vue提供了一下方法 set
:
Vue.set(Object, propertyName, value);
this.$set(Object, propertyName, value);
// 上面两句是一样的
有时我们需要在一个对象里面添加多个属性,我们可以使用Object.assign()
。但是注意,通过这种方式添加的属性是没有和watcher关联的,也就是说:不能更新
,这个问题也是需要解决的,因此Vue提出了将原对象里面的属性与新属性整合在一起创建一个新的对象。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
数组响应
创建数组时,你会发现数组里面的数据没有get和set函数,因此数组里面的数据变化也是没有办法响应的,Vue 不能检测以下数组的变动:
当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:
vm.items.length = newLength
为了解决第一类问题,以下方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue);
为了解决第二类问题,你可以使用 splice:
vm.items.splice(newLength)
MVVM
MVVM,Model-View-ViewModel,顾名思义,就是Model 模型(连接到服务器的数据库数据)、View 视图(页面展示)、ViewModel视图模型(帮助链接model与view的桥梁)。
正如下面图片所示,ViewModel与View利用的Vue框架实现了双向数据绑定,同时ViewModel和Model主要是进行服务器请求获取服务器端数据,而View用来展示给用户,通过双向数据绑定,无论是View页面操作数据还是Model服务器端数据传递,都可以同步更新到彼此,不需要手动的操作DOM,也就是说,通过MVVM模型以及双向数据绑定,Vue实现了数据驱动,不需要通过事件触发更新页面。