当前位置:   article > 正文

vue2 数据响应式Object.defineProperty_vue2的 object.definedpropery的get里面做了啥

vue2的 object.definedpropery的get里面做了啥

我们通常可以对进行输入框进行数据的监听,只需要用到了input 事件或 change事件,就可以实时监听到数据的改变,但是如果只是一个单独的数据呢?怎么去做监听,watch吗??哈哈。

所以 vue响应式就用到了object.defineProperty 中的 get 和 set 方法 ,如果对方法不了解可访问蓝色文字。简单来说 只要一访问就会触发get,设置就会触发set。

基本语法:

Object.defineProperty(对象,键,{
        get (   )   {   },
        set (val) {   }        
})

  1. let data = {
  2. name:'奥特曼'
  3. }
  4. Object.defineProperty(data,'name',{
  5. get(){
  6. console.log('访问了')
  7. },
  8. set(val){
  9. console.log('设置了,值是:',val)
  10. }
  11. })

1. 单个数据实现响应

实现效果:

为了和vue保持格式一致 我们先定义初始变量data ,并且一开始把值赋给类名为name的内容数据

  1. <div class="name"></div>
  2. <script>
  3. let data = {
  4. name:'奥特曼'
  5. }
  6. function setName() {
  7. document.querySelector('.name').innerHTML = username
  8. }
  9. setName()
  10. </script>

接下来要对data.name进行实时的监听,就要用到了obj.defineProperty

  1. let username = "奥特曼";
  2. Object.defineProperty(data, "name", {
  3. get() {
  4. console.log("访问了");
  5. return username;
  6. },
  7. set(val) {
  8. console.log("设置了,值是:", val);
  9. username = val;
  10. setName();
  11. },
  12. });

这里注意 特意用了一个中间变量 username,如果不这么用你可能会想到,错误写法别抄哦

  1. get(){
  2. console.log('访问了');
  3. return data.name
  4. },

为什么不直接把data.username给返回出去,为什么要返回一个值一样的username?原因就是 我们返回着data.name 其实也是在访问他,然后呢每次访问每次进入get函数 就会进入一个死循环。

2.多个数据实现响应式

这里就不过多解释了 只需要把对象循环一下 利用Object.defineProperty监听每个属性,我相信你可以看懂的

  1. <script>
  2. let data = {
  3. username:'奥特曼',
  4. age:18,
  5. }
  6. function setData() {
  7. username.innerHTML = data.username
  8. age.innerHTML = data.age
  9. }
  10. function observe(data) {
  11. for (const key in data) {
  12. let value = data[key]
  13. Object.defineProperty(data,key,{
  14. get(){
  15. return value
  16. },
  17. set(val){
  18. value = val
  19. setData()
  20. }
  21. })
  22. }
  23. }
  24. observe(data)
  25. setData()
  26. </script>

3. 监听复杂数据类型响应式

我们只需要判断当前的参数是否是对象 如果是对象利用一下递归。

  1. <script>
  2. let data = {
  3. username:'奥特曼',
  4. age:18,
  5. student:{
  6. name :'怪兽'
  7. }
  8. }
  9. function setData() {
  10. username.innerHTML = data.username
  11. age.innerHTML = data.age
  12. monster.innerHTML = data.student.name
  13. }
  14. function observe(data) {
  15. for (const key in data) {
  16. if(typeof data[key] == 'object') {
  17. observe(data[key])
  18. }
  19. let value = data[key]
  20. Object.defineProperty(data,key,{
  21. get(){
  22. return value
  23. },
  24. set(val){
  25. value = val
  26. setData()
  27. }
  28. })
  29. }
  30. }
  31. observe(data)
  32. setData()
  33. </script>

4.新增对象属性和数组下标修改

在vue中,我们是检测不到一个对象新增属性和直接修改数组某一项的变化,但是上面的代码中是能够对数组下标进行修改的,那为什么vue不可以呢?

 尤大大也说考虑到了性能和用户体验的问题 如果一个数组10000条数据 监听这每一项的数据变化 确实也有很大的性能问题,但vue也提供了解决方案 $set

贴一下 修改数组下标 及 修改不了新增的对象属性代码

  1. <script>
  2. let data = {
  3. username:'奥特曼',
  4. age:18,
  5. student:{
  6. name :'怪兽'
  7. },
  8. arr:[0,1,2,3]
  9. }
  10. function setData() {
  11. username.innerHTML = data.username
  12. age.innerHTML = data.age
  13. monster.innerHTML = data.student.name
  14. // 无法对新增的属性进行监听 原因就是observe 一开始就对原数据进行数据的监听 这也是object.defineproperty的本身缺陷
  15. monsterAge.innerHTML = data.student.age
  16. number.innerHTML = data.arr[0]
  17. }
  18. function observe(data) {
  19. for (const key in data) {
  20. if(typeof data[key] == 'object') {
  21. observe(data[key])
  22. }
  23. let value = data[key]
  24. Object.defineProperty(data,key,{
  25. get(){
  26. return value
  27. },
  28. set(val){
  29. value = val
  30. setData()
  31. }
  32. })
  33. }
  34. }
  35. observe(data)
  36. setData()
  37. </script>

补充:但是有一点哈,有时候呢 你是可以修改数组某一项实现响应式的,什么时候呢看下面的例子

  1. <div>
  2. <div> {{arr[0]}}</div>
  3. {{ obj.a }}
  4. <button @click="editNumber">要修改了</button>
  5. </div>
  6. <script>
  7. export default {
  8. data () {
  9. return {
  10. arr: [0, 1, 2, 3, 4, 5],
  11. obj: { a: 1 }
  12. }
  13. },
  14. methods: {
  15. editNumber () {
  16. this.arr[0] = 999
  17. // 如果不加下面这一行代码,视图就不会更新
  18. // 更新的原因:下面的数据是响应式的数据他会去更新视图,一旦更新视图 数据是对整个组件进行更新的,所以arr[0] 会更新
  19. // 其实底层的object.defineProperty 可以对数组进行更新 但是尤大考虑到数组 的性能与用户体验不成正比 去掉了对数组的响应式 (获取涉及几万条数组非常的大)
  20. this.obj.a = 2
  21. }
  22. }
  23. }
  24. </script>

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号