vue响应原理是数据劫持结合发布者、订阅者的方式来实现的。通过object.defineProperty来劫持各个属性的setter和getter,在数据发生变化的时候发布消息给订阅者,触发响应的监听回调
------object.defineProperty下面会详细讲解
那什么是MVC和MVVM呢?
MVC:即model-view-controller(模型-视图-控制器),是项目的一种分层架构的思想,它把复杂的项目逻辑,抽离成职能单一的小模块,每个模块看似相互独立,其实也是相互依赖的,好处:保证了模块的职能单一性,方便程序的开发、维护、耦合度低
MVVC:即model-view-viewModel(模型-视图-控制器),它是一种数据双向绑定的模式,用viewModel来建立model数据层和view视图层的连接,数据改变会影响视图,视图改变会影响数据
具体流程:
第一步:数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新的值并通知订阅者
第二步:指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
第三步:Watcher作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和watcher三者,通过Observer监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭建起Observer和Compile之间的通信桥梁达到数据双向绑定效果
Objest.defineProperty:直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
语法:Object.defineProperty (obj , prop , descriptor)
参数:obj:要定义属性的对象
prop:要定义或修改的属性的名称或Symbol
descriptor:要定义或修改的属性描述,也就是配置项(6个)
配置项一:value (默认为undefined)
由图可以看出新添加的属性颜色和上面原有属性颜色不一样(该属性不可枚举)
配置项二:enumerable(默认为false)
created() { Object.defineProperty(this.obj, 'address', { value: '地址', //该属性对应的值 enumerable: true, //是否可枚举 }) console.log(this.obj) },
下面我想去更改添加属性的值
created() { Object.defineProperty(this.obj, 'address', { value: '地址', enumerable: true, }) this.obj.address = 'change地址' //改变address的值 console.log(this.obj) },
发现它并不能被改变,下面用第三个配置项去实现
配置项三:writable(默认为false)
created() { Object.defineProperty(this.obj, 'address', { value: '地址', //该属性对应的值 enumerable: true, //是否可枚举 writable: true, //是否可更改 }) this.obj.address = 'change地址' //改变address值 console.log(this.obj) },
下面我们去删除这个属性
发现这个属性是没有被删除的,下面用第四个配置项去实现
配置项四:configurable(默认为false)
created() { Object.defineProperty(this.obj, 'address', { value: '地址', //该属性对应的值 enumerable: true, //是否可枚举 writable: true, //是否可更改 configurable: true, //是否可删除 }) this.obj.address = 'change地址' //改变address值 delete this.obj.address console.log(this.obj) },
那这样也没实现数据双向绑定啊,下面我们用原生js来讲讲最重要的get和set的配置
配置项五:get(默认值为undefined)
怎么让age与changeAge实现双向绑定呢
Object.defineProperty(obj, 'age', { // get:function(){} 简写为get(){} get() { return 123 }, })
现在将changeAge返回给age
Object.defineProperty(obj, 'age', { get() { return changeAge }, })
此时 age值等于changeAge,但是无法进行修改,它的值会一直为changeAge
配置项六:set(默认值为undefined)
Object.defineProperty(obj, 'age', { //让age值等于changeAge,但是不写set,他会一直为changeAge值,不会发生改变 get() { return changeAge }, //使changeAge等于age的值,让age值可以改变 set(value) { return (changeAge = value) }, })
下面放下测试代码,大家可以运行看看
Document