vue的双向数据绑定

MVVM

说到 Vue 的双向绑定首先联系到的就是 MVVM(Model-View-ViewModel)模式了,当视图发生改变的时候传递给 VM,再让数据得到更新,当数据发生改变的时候传给 VM,使得视图发生改变。

MVVM 模式是通过以下三个核心组件组成:

  • M: Model - 包含了业务和验证逻辑的数据模型;
  • V: View - 定义屏幕中 View 的结构,布局和外观;
  • VM: ViewModel - 扮演“View”和“Model”之间的使者,帮忙处理 View 的全部业务逻辑。

优点

  • 低耦合  

               视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的 View 上,当 View 变化的时候Model 可以不变,当 Model 变化的时候 View 也可以不变

  • 可重用性

    你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 View 重用这段视图逻辑

  • 独立开发

    开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码

  • 可测试

    界面素来是比较难于测试的,而现在测试可以针对ViewModel来写

缺点:

  • 数据绑定使得 Bug 很难被调试
  • 一个大的模块中model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存就造成了花费更多的内存
  • 数据双向绑定不利于代码重用

vue2使用的是“数据劫持”结合“发布者订阅”模式的方式来实现的。

        那么什么是发布者订阅模式?什么是数据劫持?

        布者订阅模式

        发布者订阅模式分两类:Dep类与watcher类

        Dep类:

  • 负责进行依赖收集  
  • 首先,要有一个数组,专门进行存储所有的订阅信息
  • 其次,要提供一个向数组中可以追加订阅信息的方法
  • 然后还要提供一个循环,循环触发数组中的每一个订阅信息

       watcher类:

  • 负责订阅一些事件

   用js写一个简单的发布订阅:

class Dep {

	constructor() { //创建一个实例

		this.subs = [] //这个数组用于存储所有的发布者信息

	}

	//向subs数组中添加订阅者的信息

	addSubs(watcher) {
		this.subs.push(watcher)

	}

	//通知的方法
	notify() {

		//循环收藏的订阅者,触发其回调函数
		this.subs.forEach((watcher) => watcher.upData())

	}
}
//订阅者的类

class Watcher {

	constructor(cb) { //cb回调传一个函数(根据最新的数据,更新自己)

		this.cb = cb //将cb挂载在自己身上

	}
	//提供了一个触发回调的方法
	upData() {

		this.cb() //当数据更新时,调用cb更新数据

	}
}

//第一个订阅者
const w1 = new Watcher(() => {

	console.log('第一个订阅者')

})

//第二个订阅者
const w2 = new Watcher(() => {

	console.log('第二个订阅者')

})
//创建一个Dep

const dep = new Dep();

// 向dep中的subs数组中存储订阅者

dep.addSubs(w1) //添加第一个订阅者

dep.addSubs(w2) //添加第二个订阅者

dep.notify() //发布通知

 如何进行的监听数据的改变?

---答:数据劫持Object.defineProperty

Object.defineProperty 对传入的数据进行相应的数据拦截,为其动态添加 get 与 set 方法。当数据变化的时候,就会触发对应的 set 方法,当 set 方法执行完成时,内部会进一步触发订阅者 watcher,当数据改变,进行虚拟 Dom 对比(diff 算法),执行 render 函数,进行视图更新。

缺点
1、不能监听数组的变化
2、只能监听已存在的属性,对于新增或删除的属性不能监听

 

 如何使用Object.defineProperty:

const obj={
   name:"2z",
   age:20
}

//赋值操作
 obj.name="ls"
//取值操作
console.log(obj.name);

//如何监听数据?
Object.defineProperty(obj,'name',{

    enumerable:true,//当前属性是否允许被循环
    configurable:true,//当前属性是否允许被配置,例:delete删除,如果当前为false,
                      //当前这个属性无法删除
   
     get(){//监听获取
    
    //当有人获取obj.name时,将触发get,可以拦截别人对obj.name的获取
    return '有人获取了obj.name'
    
    },
    set(newVal){//监听更改

    //当有人想要对obj.name重新赋值的时候,将会触发
    console.log('赋值'+newVal+'失败')    

    },
})

vue在监听数据更新变化的时候是在哪里通知订阅者的? 

--答:在set中!

//只要给obj,name进行赋值时,就会触发name属性中的set,然后可以在set中拿到新值,
//所以在拿到新值的时候,就需要通知订阅者,要更新数据了,所以我们应该在set中调用
//notify()

set(newVal){//监听更改

    //当有人想要对obj.name重新赋值的时候,将会触发
    console.log('赋值'+newVal+'失败')    
    dep.notify()//通知每个订阅者,数据变了,更新自身数据
    },

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值