vue2的实现(4)之对象劫持的一些细节处理一

161 阅读2分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

vue2的实现(4)之对象劫持的一些细节处理

回顾

  • 上次内容我们介绍了observe模块,rewrite-vue/src/observe/index.js逻辑代码主要存放在这个文件中。主要做的是对数据data的观测劫持,下面是这个文件中的代码。
  • rewrite-vue/src/observe/index.js
    class Observe {
      consturctor(data){
        this.walk(data)
      }
    
      walk(data){
        Object.keys(data).forEach(key => defineReactive(data, key, data[key]))
      }
    }
    
    export function defineReactive(target, key, value){
      Object.defineProperty(target, key, {
        get(){
          console.log('劫持用户的取值操作,get');
          return value
        },
        set(newValue){
          if(newValue !== value){
            console.log('劫持用户的设置操作,set');
            value = newValue
          }
        }
      })
    }
    
    
    export function observe(data){
      if(typeof data !== 'object' || data === null){
        return 
      }
      return new Observe(data)
    }
    

给对象的属性赋值为一个新对象能否劫持到?

  • 我们用下面的代码测试一下,在浏览器打开rewrite-vue/dist/index.html

  • rewrite-vue/dist/index.html

      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Vue2</title>
      </head>
      <body>
      <script src="./vue.js"></script>
      <script>
          const vm = new Vue({
          data:{
              name:'vue2',
              age:3
          }
          })
    
          vm._data.age = {
          num:666,
          key:'age'
          }
    
          console.log(vm._data.age.key);
          console.log(vm._data.name);
    
      </script>
      </body>
      </html>
    
  • 下面的图片是输出结果,我们可以看到第一次打印的是我们设置vm._data.age时输出的set。我们可以看到在访问vm._data.age.key时,只打印了一次get的输出,最后一次输出的是访问vm._data.name时,打印的get

  • 按理说,我们访问了vm._data.age.key,在访问age时打印一次get,在访问key的时候也打印一次get,这样才对。

    2022-01-28-1.png

  • 所以说,我们还需要对用户设置值时的值,进行劫持。我们来改造一下,我们只需要在set方法中,重新observe一下newValue即可。

  • rewrite-vue/src/observe/index.js

    class Observe {
      consturctor(data){
        this.walk(data)
      }
    
      walk(data){
        Object.keys(data).forEach(key => defineReactive(data, key, data[key]))
      }
    }
    
    export function defineReactive(target, key, value){
      Object.defineProperty(target, key, {
        get(){
          console.log('劫持用户的取值操作,get');
          return value
        },
        set(newValue){
          if(newValue !== value){
            console.log('劫持用户的设置操作,set');
            observe(newValue)
            value = newValue
          }
        }
      })
    }
    
    
    export function observe(data){
      if(typeof data !== 'object' || data === null){
        return 
      }
      return new Observe(data)
    }
    
  • 这样observe方法就会对我们设置的值,进行劫持。

测试

  • rewrite-vue/dist/index.html里面的代码还是上面的测试用例,我们再次在浏览器中打开rewrite-vue/dist/index.html可以看到。

  • 从下面的图可以看出我们的打印已经生效了,证明我们已经拦截到了用户设置值时的操作。在访问vm._data.age.key时打印了两次get

    2022-01-28-2.png 今天是更文第十一天加油~ 看到这里兄弟帮忙点个赞吧

往期精彩

vue2的实现(3)之初始化数据data

vue2的实现(2)之初始化数据data

vue2的实现(1)之搭建rollup打包环境

手撕koa,从零掌握koa的实现原理(1)

手撕koa,从零掌握koa的实现原理(2)

手撕koa,从零掌握koa的实现原理(3)

手撕koa,从零掌握koa的实现原理(4)

手撕koa,从零掌握koa的实现原理(5)

手撕koa,从零掌握koa的实现原理(6)

手撕koa,从零掌握koa的实现原理(7)