vue2 数据响应式Object.defineProperty
Posted 奥特曼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue2 数据响应式Object.defineProperty相关的知识,希望对你有一定的参考价值。
我们通常可以对进行输入框进行数据的监听,只需要用到了input 事件或 change事件,就可以实时监听到数据的改变,但是如果只是一个单独的数据呢?怎么去做监听,watch吗??哈哈。
所以 vue响应式就用到了object.defineProperty 中的 get 和 set 方法 ,如果对方法不了解可访问蓝色文字。简单来说 只要一访问就会触发get,设置就会触发set。
基本语法:
Object.defineProperty(对象,键,
get ( ) ,
set (val)
)
let data =
name:'奥特曼'
Object.defineProperty(data,'name',
get()
console.log('访问了')
,
set(val)
console.log('设置了,值是:',val)
)
1. 单个数据实现响应
实现效果:
为了和vue保持格式一致 我们先定义初始变量data ,并且一开始把值赋给类名为name的内容数据
<div class="name"></div>
<script>
let data =
name:'奥特曼'
function setName()
document.querySelector('.name').innerhtml = username
setName()
</script>
接下来要对data.name进行实时的监听,就要用到了obj.defineProperty
let username = "奥特曼";
Object.defineProperty(data, "name",
get()
console.log("访问了");
return username;
,
set(val)
console.log("设置了,值是:", val);
username = val;
setName();
,
);
这里注意 特意用了一个中间变量 username,如果不这么用你可能会想到,错误写法别抄哦
get()
console.log('访问了');
return data.name
,
为什么不直接把data.username给返回出去,为什么要返回一个值一样的username?原因就是 我们返回着data.name 其实也是在访问他,然后呢每次访问每次进入get函数 就会进入一个死循环。
2.多个数据实现响应式
这里就不过多解释了 只需要把对象循环一下 利用Object.defineProperty监听每个属性,我相信你可以看懂的
<script>
let data =
username:'奥特曼',
age:18,
function setData()
username.innerHTML = data.username
age.innerHTML = data.age
function observe(data)
for (const key in data)
let value = data[key]
Object.defineProperty(data,key,
get()
return value
,
set(val)
value = val
setData()
)
observe(data)
setData()
</script>
3. 监听复杂数据类型响应式
我们只需要判断当前的参数是否是对象 如果是对象利用一下递归。
<script>
let data =
username:'奥特曼',
age:18,
student:
name :'怪兽'
function setData()
username.innerHTML = data.username
age.innerHTML = data.age
monster.innerHTML = data.student.name
function observe(data)
for (const key in data)
if(typeof data[key] == 'object')
observe(data[key])
let value = data[key]
Object.defineProperty(data,key,
get()
return value
,
set(val)
value = val
setData()
)
observe(data)
setData()
</script>
4.新增对象属性和数组下标修改
在vue中,我们是检测不到一个对象新增属性和直接修改数组某一项的变化,但是上面的代码中是能够对数组下标进行修改的,那为什么vue不可以呢?
尤大大也说考虑到了性能和用户体验的问题 如果一个数组10000条数据 监听这每一项的数据变化 确实也有很大的性能问题,但vue也提供了解决方案 $set
贴一下 修改数组下标 及 修改不了新增的对象属性代码
<script>
let data =
username:'奥特曼',
age:18,
student:
name :'怪兽'
,
arr:[0,1,2,3]
function setData()
username.innerHTML = data.username
age.innerHTML = data.age
monster.innerHTML = data.student.name
// 无法对新增的属性进行监听 原因就是observe 一开始就对原数据进行数据的监听 这也是object.defineproperty的本身缺陷
monsterAge.innerHTML = data.student.age
number.innerHTML = data.arr[0]
function observe(data)
for (const key in data)
if(typeof data[key] == 'object')
observe(data[key])
let value = data[key]
Object.defineProperty(data,key,
get()
return value
,
set(val)
value = val
setData()
)
observe(data)
setData()
</script>
补充:但是有一点哈,有时候呢 你是可以修改数组某一项实现响应式的,什么时候呢看下面的例子
<div>
<div> arr[0]</div>
obj.a
<button @click="editNumber">要修改了</button>
</div>
<script>
export default
data ()
return
arr: [0, 1, 2, 3, 4, 5],
obj: a: 1
,
methods:
editNumber ()
this.arr[0] = 999
// 如果不加下面这一行代码,视图就不会更新
// 更新的原因:下面的数据是响应式的数据他会去更新视图,一旦更新视图 数据是对整个组件进行更新的,所以arr[0] 会更新
// 其实底层的object.defineProperty 可以对数组进行更新 但是尤大考虑到数组 的性能与用户体验不成正比 去掉了对数组的响应式 (获取涉及几万条数组非常的大)
this.obj.a = 2
</script>
以上是关于vue2 数据响应式Object.defineProperty的主要内容,如果未能解决你的问题,请参考以下文章