MVVM双向绑定之Object.defineProperty

170 阅读2分钟

现在的前端框架主流都是用的mvvm双向绑定的设计思想,vue.js react.js angular.js都是这种思想,通过viewmodel分别去和model,view层进行双向绑定,这种思想使我们的前端框架使用起来更加方便。而这种双向绑定的思想背后的原理主要是ES5的Object.defineProperty属性。

Object.defineProperty

通过下面一段代码实例,我们来简单看下Object.defineProperty属性有哪些功能:

let obj = {a:'1'}
// 数据描述(bool值默认true)
Object.defineProperty(obj,'b',{
	value:'2',
	configuarble:  false,	// 是否可以删除属性delete 是否可以再次设置特性
	enumerable: false,	// 是否可以被枚举 for..in Object.keys() 使用
	writable: false	// 是否可以被重写 false 时obj.a不能改变值
})
obj.b = '3'
console.log(obj.b)	// 2
delete obj.b
console.log(obj.b)	// 2
console.log(Object.keys(obj))	// ["a"]

// 存储器描述
//(当使用了getter或setter方法,不允许使用writable和value属性)
Object.defineProperty(obj,'c',{
	// configuarble: true | false,	// 是否可以删除属性delete 是否可以再次设置特性
	// enumerable: true | false,	// 是否可以被枚举 for..in Object.keys() 使用
	get: function(){
	  // 当获取值的时候触发的函数
	  console.log('this get on')
	  return 'this get on1'
	},
	
	set: function(value){
	  // 当设置值的时候触发的函数
	  console.log('this set on' + value)
	}
})
obj.c 	// this get on
console.log(obj.c)	// this get on  this get on1
obj.c = 5 // this set on5

这其中存储器属性里的get set属性就是我们mvvm核心思想里所用到的。

Object.defineProperty模拟双向绑定

我们来看看下面这一段代码

<input type="text" ><span></span>

<script>
let obj = {}
Object.defineProperty(obj, 'hello', {
  set: function(newValue) {
    document.querySelector('input').value = newValue
    document.querySelector('span').innerHTML = newValue
  }
})
document.addEventListener('keyup', function(e){
  obj.hello = e.target.value
})
</script>

达到的效果是

在input 输入什么右边的span内容也会响应式的跟着去改变

给obj.hello赋值修改input输入框和span里面的内容也会跟着变化

这是不是很像vue.js里面的双向绑定,原理其实就这么简单!