现在的前端框架主流都是用的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里面的双向绑定,原理其实就这么简单!