Vue3 ref和reactive的使用和区别以及响应式原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue3 ref和reactive的使用和区别以及响应式原理相关的知识,希望对你有一定的参考价值。

参考技术A

语法:const xxx = ref (initValue)
接受的数据类型:基本类型,引用类型
作用:把参数加工成一个响应式对象,全称为reference对象(我们下面一律简称为ref对象)
核心原理:如果使用的是基本类型响应式依赖Object.defineProperty( )的get( )和set( ),如果ref使用的是引用类型,底层ref会借助reactive的proxy 定义响应式
基本使用:

语法:const xxx = ref (源对象)
接受的数据类型:引用类型
作用:把参数加工成一个代理对象,全称为proxy对象
核心原理:基于Es6的Proxy实现,通过Reflect反射代理操作源对象,相比于reactive定义的浅层次响应式数据对象,reactive定义的是更深层次的响应式数据对象

基本使用:

ref和reactive都可以做响应式

ref:一般用在定义基本类型和引用类型,如果是引用类型底层会借助reactive形成proxy代理对象,可以直接复制整个对象,如table的数据请求回来,需要将数据整体赋值个响应对象这时如果使用的是reactive就无法进行响应。

reactive:一般用在引用类型,如等,不能一次性修改整个对象,如我们后端请求table的数据数据,如果想一次性赋值的整个数组的话,就行不通,此时建议使用ref来定义数组。

第一种写法:除了对象都用ref来定义

第二种写法:都用reactive来定义,然后用toRefs进行导出到页面使用

不习惯的Vue3起步二 の alias别名ref和reactive

在之前的学习中,对vue3和vite做了一下简单的了解。也知道了vue3,相较于vue2,对typescript的支持更加好了。所以直接从ts+vue3一起来吧。(之前我对typescript基础也有过学习,忘记也可以翻看资料《typescript系列笔记》

vue3 + ts项目

创建的还是vite项目,之前没有使用ts,所以创建项目命令: yarn create vite first-vite-demo --template vue。 现在如果要在项目中添加ts,只需要在命令最后加上-ts: yarn create vite demo-name --template vue-ts

这样创建出来的项目,main.js也已经变成了main.ts

项目结构:

然后现在的.vue组件中,<script>上需要添加lang="ts

因为使用命令创建完项目后,会自动生成tsconfig.json。不过这里关于tsconfig.json配置也可以根据自己需求调整,可以参考

TS模块声明

在ts中,有类型声明的特性,在vue3+ts项目中,会看到一个env.d.ts文件,此文件中声明了*.vue

declare module '*.vue' 
  import type  DefineComponent  from 'vue'
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<, , any>
  export default component

如果将其注释掉,会发现main.ts中出现红色波浪线报错:

resolve.alias别名

在引用文件时,可以使用相对路径的方式,但是这样嵌套的页面非常复杂,有可能会造成多个层级../../../这种引用情况,所以有时候可以通过配置resolve.alias别名来进行缓解。

vite.config.ts文件中,引入path中的resolve,然后在defineConfig写入配置的相对路径:

import  defineConfig  from 'vite'
import vue from '@vitejs/plugin-vue'
import  resolve  from 'path';

// https://vitejs.dev/config/
export default defineConfig(
  plugins: [vue()],
  resolve: 
    alias: 
      '@': resolve(__dirname, './src')
    
  
)

这样调用路径时就可以使用@来引入

PS:如果这样在ts项目中还未成功,可以在tsconfig.jsoncompilerOptions进行配置

"baseUrl": ".",
"paths": 
  "@/*":["src/*"]

ref和reactive

ref: 接受一个内部值并返回一个响应式且可变的 ref 对象,ref底层其实还是reactive,所以当运行时系统会自动根据传入的ref转换成reactive

这是为了实现数据响应式,如果单纯对变量定义为一个数据,是不会在template中实现数据响应式变动的。

比如:

<template>
 count 
</template>

<script setup lang="ts">
    import  ref, reactive  from "vue";
    let count = 10

    setInterval(()=>
        count++;
    , 1000)
</script>

最终界面上依旧是10,setInterval产生的变动并没有实时更新。

而如果count做ref的定义,那么界面上数据就会实时更新

<script setup lang="ts">
    import  ref, reactive  from "vue";
    // ref就是某个元素,简单数据类型,reactive对象
    let count = ref(10)

    setInterval(()=>
        count.value++;
    , 1000)
</script>

PS: 在vue中使用ref的值不用通过value获取,在js中使用ref的值必须通过value获取

如果想要像以前Vue2一样,通过refs.refname获取元素,也要稍作改变

<template>
    <div class="box" ref="box"></div>
</template>

<script setup lang="ts">
    import  ref, reactive, onMounted  from "vue";
    // 名称要与节点上ref名称一致
    let box = ref(null)

    onMounted(()=>
        // setup执行时机比mounted早,此时界面dom还没形成
        console.log(box.value)
    )
</script>

reactive是用来定义更复杂的数据类型的,以下是reactive的具体示例

<template>
    <div class="box" ref="box">
         users[0] 
    </div>
</template>

<script setup lang="ts">
    import  ref, reactive, onMounted, toRefs  from "vue";
    
    interface personInfo 
        name: string,
        age: number,
        hobby: ()=>void
    

    let users: personInfo[] = reactive([
        
            name: '张三',
            age: 18,
            hobby: ()=> console.log('打李四') 
        
    ])
    let refUsers = toRefs(users);
    setInterval(()=>
        refUsers[0].value.age++;
    ,1000)
</script>

效果:

以上是使用reactive定义对象,实际上reactive也可以包裹ref,比如:

<template>
    <div class="box" ref="box">
         count 
    </div>
</template>

<script setup lang="ts">
import  ref, reactive, onMounted, toRefs  from "vue";
    let count = ref(10)
    let countRef = reactive(
        count
    )
    console.log(countRef)
    setInterval(()=>
        countRef.count++;
    ,1000)
</script>

以上是关于Vue3 ref和reactive的使用和区别以及响应式原理的主要内容,如果未能解决你的问题,请参考以下文章

vue3的ref和reactive以及toRef和toRefs的区别。

vue3中ref和reactive的区别

初识vue3-setup语法糖,ref和reactive语法,computde计算属性,watch开启监听

2-3-3 Vue3 Reactive的值:Ref和Reactive

Vue3 中有场景是 reactive 能做而 ref 做不了的吗?

Vue3全家桶升级指南二reftoReftoRefs的区别