• vue3 第二天vue响应式原理以及ref和reactive区别


    前言:

    前天我们学了 ref 和 reactive ,提到了响应式数据和 Proxy ,那我们今天就来了解一下,vue3 的响应式

    在了解之前,先复习一下之前 vue2 的响应式原理

    vue2 的响应式:

    原理:

    对象类型:通过 Object.defineProperty() 对象的读取,修改进行拦截,也就是数据劫持,响应式的根基

    缺点:因为只有 读取和修改(get,set)所以新增属性,和删除属性,页面是不会刷新的

    数组类型:通过重写,更新数组的一系列方法来实现拦截,假如你调了一个数组的 push 方法,其实 push 是被二次重写封装的(对数组的变更方法进行了重写)

    缺点:直接通过下标修改数组,页面不会更新

     

    解决方法:用 this.setthis.delete(数据,删除的数据名)

    vue3 的响应式:

    通过 Proxy 代理 :拦截对象中任意属性的变化,包括增,删,改,查

    通过 Reflect 反射 : 对被代理对象(源对象)的属性进行操作

    复制代码

    new Proxy(data,{

    //拦截读取的属性值

    get(target,prop){

    return Reflect.get(targert,prop)

    }

    //拦截设置和添加

    set(target,prop,value){

    return Reflect.set(targert,prop,value)

    }

    // 拦截删除

    deleteProperty(target,prop){

    return Reflect.deleteProperty(targert,prop)

    }

    })

    复制代码

    这差不多就是 vue3 响应式的简单原理,Proxy 比较之前的 Object.defineProperty 功能更详细,和强壮

    reactive 与 ref 的区别:

    定义:

    ref:用来定义基本数据类型

    reactive:用来定义对象(数组)类型数据

    ps:ref 也可以用来定义对象(或数组)类型数据,内部求助了 reactive 

    原理:

    ref: 通过 Object.defineProperty()的 get 与 set 来实现响应式也就是数据劫持

    reactive:通过使用 Proxy 来实现响应式,并用 Reflect 操作源对象内部数据

    使用:

    ref:用 ref 定义的数据,操作需要 .value 

    reactive ; 定义的数据,操作不需要

    setup 的注意:

    setup 的执行时机是在 beforeCreate 之前执行,this 是 undefined

    setup的参数

    props :值为对象,包含:组件外部传递过来,并且组件内部声明接收了的属性

    context:上下文对象,有三个值分别是 attrs,slots,emit

    attrs :对象,没有在 props 声明配置的属性,相当于 vue2 的 this.$attrs 

    slots :插槽,相当于 this. $slots 

    emit :分发自定义事件的函数,相当于 this.$emit 

    计算属性,computed函数

    与 vue2 中的 computed 配置功能一致

     watch 函数监听:

      与 vue2 中的 watch 配置功能一致

    watch 监视 ref 基本数据:

     情况一 :监视 ref 定义的一个响应式数据

    复制代码

     

    let sum = ref(0)

    watch(sum,(newValue,oldValue)=>{

    console.log('监听sum变了',newValue,oldValue)

    })

    复制代码

    情况二:监视 ref 定义的多个响应式数据

    复制代码

     

    let msg = ref('你好啊')

    let sum = ref(0)

    watch([sum,msg],(newValue,oldValue)=>{

    console.log('监听sum变了',newValue,oldValue)

    },{immediate:true})

    复制代码

    ps:watch 一共可以传递三个值,第一个 监视的数据,监视的行为,watch 的配置

    watch 监视 reactive 对象:

     情况三:监视 reactive  所定义数据中的全部属性

    复制代码

     

    let preson = reactive({

    name:'六扇老师',

    age:18

    })

    watch(preson,(newValue,oldValue)=>{

    console.log('监听preson变了',newValue,oldValue)

    },{deep:false}) // 此处的 deep 配置无效

    复制代码

    ps:此处无法正确的获得 oldValue,是 reactive 的问题无法解决

    强制开启深度监视(deep配置无效)

    情况四:监视 reactive 所定义数据中的某一个属性

    watch(()=>preson.name,(newValue,oldValue)=>{

    console.log('监听preson.name变了',newValue,oldValue)

    })

    情况五:监视 reactive 所定义数据中的某些属性

    watch([()=>preson.name,()=>preson.age],(newValue,oldValue)=>{

    console.log('监听preson.name/preson.age变了',newValue,oldValue)

    })

    特殊情况:

    复制代码

    let preson = reactive({

    name:'六扇老师',

    age:18,

    job:{

    j1:{ salary:30 }

    }

    })

    watch(()=>preson.job,(newValue,oldValue)=>{

    console.log('监听preson.job变了',newValue,oldValue)

    },{deep:true})

    复制代码

    ps:如果单独监视 reactive 对象里面的对象的数据,则必须开启 deep:true 深度监视,否则监视无效

    watchEffect 函数:

    watchEffect 函数是 vue3 新增的一个函数

    和 watch 区别:

    watch:既要指明监视属性,也要指明监视的回调

    watchEffect :不用指明监视属性,监视的回调中使用了那个属性,就默认监视那几个属性

    watchEffect 和 computed 有点像似

    不一样的是,computed 注重计算出来的值,回调函数的返回值,所以必须要写返回值

    watchEffect 更注重过程,回调函数的函数体,所以不用写返回值

    复制代码

    let sum = ref(0)

    let preson = reactive({

    name:'六扇老师',

    age:18,

    job:{

    j1:{ salary:30 }

    }

    })

    // watchEffect vue3 新增

    // 默认开启 immediate,也有 deep

    watchEffect(()=>{

    const x1 = sum.value const

    x2 = preson.job.j1.salary

    console.log('所指定的 watchEffect 的回调执行了')

    })

    复制代码

    这就是今天的全部内容,我们明天见!这里是六扇有伊人

     

     

     

     

     

  • 相关阅读:
    2023国赛数学建模C题思路分析 - 蔬菜类商品的自动定价与补货决策
    学习VGG笔记
    Excel怎么转换成PDF?这两招轻松解决
    第n个程序员节
    【Hadoop】学习笔记(六)
    PHP如何切割excel大文件,使用 PHP_XLSXWriter 代替 PHPExcel 10W+ 数据秒级导出
    golang中的信号量的实现原理
    诊断DLL——CAPL_DLL集成安全访问算法
    Apache的配置详解
    DTS搭载全新自研内核,突破两地三中心架构的关键技术|腾讯云数据库
  • 原文地址:https://www.cnblogs.com/LiuSan/p/16932268.html