用过vue的都知道,vue中data中定义的数据会随着我们通过方法改变该数据的同时,页面上相关此数据的也会相应的刷新,实现响应式数据。它是如何实现这一功能的?
Vue2.xx版本中用Object.defineProperty(obj, prop, descriptor)
可传入三个值,其作用是该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
第一个值传入要修改的对象
第二个值传入该对象中要修改的key
第三个值是一个对象,里面有set 和get两种方法 set为值发生修改是所做的操作 get为读取改值时的操作。
简单实现的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
</head>
<body>
<input type="text">
<p></p>
<script>
var obj = {}
var temp = null
document.querySelector('input').oninput =function(){
//当我们设置obj中的a属性的值时,会触发set方法,接收到新的值,我们将文本框中的值赋给a属性
obj.a = this.value
//当我们获取obj中的a属性的值时,会触发get方法,返回新的值,我们将获取到的新值显示在网页的p标签中
document.querySelector('p).innerHTML = obj.a
}
Object.defineProperty(obj,'a',{
get:function(){
console.log('获取到新值在p标签中显示')
return temp
},
set:function(val){
temp = val
console.log('监听到了a属性的值在改变')
}
})
</script>
</body>
</html>
Vue3.xx版本利用ES6中的Proxy
Vue2.xx版本中的数据双向绑定有如下缺点:
1. 监听数组的方法不能触发Object.defineProperty方法中的set操作(如果要监听的到话,需要重新编写数组的方法)。
2. 必须遍历每个对象的每个属性,如果对象嵌套很深的话,需要使用递归调用。Proxy更好的解决如上面的问题。
当外界每次对obj进行操作时,就会执行handler对象上的一些方法。
handler中常用的对象方法如下:
1. get(target, propKey, receiver)
该方法的含义是:用于拦截某个属性的读取操作。它有三个参数,如下解析:
target: 目标对象
propKey: 目标对象的属性
receiver: (可选),该参数为上下文this对象
2. set(target, propKey, value, receiver)
该方法是用来拦截某个属性的赋值操作,它可以接受四个参数,参数解析分别如下:
target: 目标对象
propKey: 目标对象的属性名
value: 属性值
receiver(可选): 一般情况下是Proxy实列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text">
<p></p>
</body>
<script>
var target={
msg:null
}
document.querySelector('input').oninput=function(){
obj.msg=this.value
document.querySelector('p').innerHTML=obj.msg
}
var handler={
get:function(target,property){
return target[property];
},
set:function(target,property,value){
target[property]= value
}
}
var obj=new Proxy(target,handler)
</script>
</html>