关于数据劫持原理(vue2和vue3)

数据劫持,指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。

Object.defineProperty

const user = {
    username: 'xiaoming',
    age: 10
}
let username = user.username
Object.defineProperty(user, 'username', {
    get() {
        return username
    },
    set(val) {
        console.log('修改了属性', val);
    }
})
console.log(user.username); //xiaoming
user.username = 'zhangsan' // 修改了属性 zhangsan

第一个参数是劫持的对象,第二个参数是劫持的对象属性,第三个参数是执行对象,包括get set方法,此时只能针对一个属性进行劫持,那么我们可以封装一下。

const user = {
    username: 'xiaoming',
    age: 10
}

function defineProperty(data,key,value){
    Object.defineProperty(data, key ,{
        get() {
            console.log(`使用了${key}这个属性`);
            return value
        },
        set(val) {
            console.log(`修改了${key}属性`, val);
            value=val
        }
    })
}
Object.keys(user).forEach(el=>{
    defineProperty(user,el,user[el])
})

console.log(user.username);
console.log(user.age);

当使用Object.defineProperty监听的对象属性是数组时,使用push、unshift、pop、shift、splice, ‘sort’, reverse监听是触发不了set的。只要不是重新赋值一个新的数组对象,任何对数组内部的修改都不会触发set方法的执行。

不能监听属性新增和删除操作,由于js的动态性,可以为对象追加新的属性或者删除其中某个属性,这点对经过Object.defineProperty方法建立的响应式对象来说,只能追踪对象已有数据是否被修改,无法追踪新增属性和删除属性。

Proxy

可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。

参数:

target:为所要代理的目标对象(target 为一个对象)

handler :对代理对象的拦截时进行的操作

let obj={
    a:1,
    b:2
}
const p = new Proxy(obj,{
    //target就是person本身

    //以下两种方式都可以,vue3主要采用Reflect的方式
    get(target,propName){
      // return target[propName]
      console.log(`读取数据`);
      return Reflect.get(target,propName)
    },
    //读取和新增属性,都会调用这个方法
    set(target,propName,value){
      // target[propName] = value
      console.log(`修改或添加数据`);
      Reflect.set(target,propName,value)
    },
    deleteProperty(target,propName){
      // return delete target[propName]
      console.log(`删除数据`);
      return Reflect.deleteProperty(target,propName)
    }
})
console.log(p.a);
p.b=1
delete p.b

Proxy性能优于Object.defineProperty。 Proxy代理的是整个对象Object.defineProperty只代理对象上的某个属性,如果是多层嵌套的数据需要循环递归绑定;

对象上定义新属性时,Proxy可以监听到,Object.defineProperty监听不到,需要借助$set方法;

数组的某些方法(push、unshift和splice)Object.defineProperty监听不到,Proxy可以监听到;

vue2的数据劫持和vue3数据劫持的区别就在这里:

通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写,属性的添加,属性的删除等,比起vue2多出了增加和删除属性的监听。

通过Reflect(反射):对源对象的属性进行操作。类似于objec的操作方法。

相关推荐

  1. 关于数据劫持原理vue2vue3

    2023-12-07 02:12:04       55 阅读
  2. Vue2 Vue3 双向数据绑定的区别原理

    2023-12-07 02:12:04       41 阅读
  3. vue2vue 3 的响应式原理

    2023-12-07 02:12:04       31 阅读
  4. vue2vue3

    2023-12-07 02:12:04       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 02:12:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 02:12:04       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 02:12:04       82 阅读
  4. Python语言-面向对象

    2023-12-07 02:12:04       91 阅读

热门阅读

  1. Docker在实际应用开发中的应用-AI生成

    2023-12-07 02:12:04       53 阅读
  2. mysql-binlog,redolog 和 undolog区别

    2023-12-07 02:12:04       55 阅读
  3. 深度学习常用指令(Anaconda、Python)

    2023-12-07 02:12:04       67 阅读
  4. 力扣 572. 另一棵树的子树

    2023-12-07 02:12:04       58 阅读
  5. rabbitmq技术

    2023-12-07 02:12:04       65 阅读
  6. React自定义Hook之useModel hook

    2023-12-07 02:12:04       68 阅读
  7. C++EasyX之跟随鼠标移动的小球

    2023-12-07 02:12:04       72 阅读
  8. Vue2 模版编译及生命周期钩子 总结归纳

    2023-12-07 02:12:04       61 阅读