Vue3中的ref和reactive响应式原理解析

Vue3中的ref和reactive响应式原理解析

目录

1 ref

2 isref判断是不是一个ref对象

3 shallowref创建一个跟踪自身.value变化的 ref,但不会使其值也变成响应式的

4 triggerRef

5 customRef

6 reactive用来绑定复杂的数据类型

7 readonly

8 shallowReactive

9toRef

10toRefs

11toRaw

Vue3系列4--ref和reactive响应式

本节主要介绍了响应式变量和对象,以及变量和对象在响应式和非响应式之间的转换。

1 ref

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个.valueproperty,指向该内部值。

案例

<template> <div> <button @click="changeMsg">change</button> <div>{{ message }}</div> </div> </template> <script setup lang="ts"> let message: string = "我是message" const changeMsg = () => { message = "change msg" } </script> <style> </style>

我们这样操作是无法改变message 的值 应为message 不是响应式的无法被vue 跟踪要改成ref。响应式就是在页面上实时显示修改的值。

Ref TS对应的接口:

interface Ref<T> { value: T } // 对于接口问题,是TS语法,如果不清楚,直接看TS

但是被ref包裹后需要使用value来进行赋值。

<template> <div> <button @click="changeMsg">change</button> <div>{{ message }}</div> </div> </template> <script setup lang="ts"> import {ref,Ref} from 'vue' let message:Ref<string> = ref("我是message")let message= ref<string>("我是message") // 第二种方式const changeMsg = () => { message.value = "change msg" } </script> <style> </style> 2 isref判断是不是一个ref对象 import { ref, Ref,isRef } from 'vue' let message: Ref<string | number> = ref("我是message") let notRef:number = 123 const changeMsg = () => { message.value = "change msg" console.log(isRef(message)); //true console.log(isRef(notRef)); //false } 3 shallowref创建一个跟踪自身.value变化的 ref,但不会使其值也变成响应式的

例子1

修改其属性是非响应式的这样是不会改变的

<template> <div> <button @click="changeMsg">change</button> <div>{{ message }}</div> </div> </template> <script setup lang="ts"> import { Ref, shallowRef } from 'vue' type Obj = { name: string } let message: Ref<Obj> = shallowRef({ name: "唐少" }) const changeMsg = () => { message.value.name = '唐少2' } </script> <style> </style>

例子2

这样是可以被监听到的修改value,必须要修改整个对象才行

import { Ref, shallowRef } from 'vue' type Obj = { name: string } let message: Ref<Obj> = shallowRef({ name: "唐少" }) const changeMsg = () => { message.value = { name: "唐少2" } } 4 triggerRef

为了解决shallowRef的问题,我们强制更新页面DOM,这样也是可以改变值的

<template> <div> <button @click="changeMsg">change</button> <div>{{ message }}</div> </div> </template> <script setup lang="ts"> import { Ref, shallowRef,triggerRef } from 'vue' type Obj = { name: string } let message: Ref<Obj> = shallowRef({ name: "唐少" }) const changeMsg = () => { message.value.name = '唐2' triggerRef(message) } </script> <style> </style> 5 customRef

自定义ref ,customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set

<script setup lang="ts"> import { Ref, shallowRef, triggerRef, customRef } from 'vue' function Myref<T>(value: T) { return customRef((track, trigger) => { return { get() { track() return value }, set(newVal: T) { console.log('set'); value = newVal trigger() } } }) } let message = Myref('唐少') const changeMsg = () => { message.value = '唐少2' // triggerRef(message) } </script> 6 reactive用来绑定复杂的数据类型

例如 对象 数组

reactive源码约束了我们的类型,类型必须是object,不能绑定普通的类型,会报错。你如果用ref去绑定对象 或者数组等复杂的数据类型 我们看源码里面其实也是 去调用reactive,但使用reactive 去修改值无须.value

reactive 基础用法

import { reactive } from 'vue' let person = reactive({ name:"唐少" }) person.name = "唐少2"

数组异步赋值问题

// 这样赋值页面是不会变化的因为会脱离响应式<br data-filtered="filtered">let person = reactive<number[]>([]) setTimeout(() => { person = [1, 2, 3] console.log(person); },1000)

解决方案1:push

import { reactive } from 'vue' let person = reactive<number[]>([]) setTimeout(() => { const arr = [1, 2, 3] person.push(...arr) console.log(person); },1000)

解决方案2:包裹一层对象

type Person = { list?:Array<number> } let person = reactive<Person>({ list:[] }) setTimeout(() => { const arr = [1, 2, 3] person.list = arr; console.log(person); },1000) 7 readonly

拷贝一份proxy对象将其设置为只读

import { reactive ,readonly} from 'vue' const person = reactive({count:1}) const copy = readonly(person) //person.count++ copy.count++ 8 shallowReactive

只能对浅层的数据 如果是深层的数据只会改变值 不会改变视图

<template> <div> <div>{{ state }}</div> <button @click="change1">test1</button> <button @click="change2">test2</button> </div> </template> <script setup lang="ts"> import { shallowReactive } from 'vue' const obj = { a: 1, first: { b: 2, second: { c: 3 } } } const state = shallowReactive(obj) function change1() { state.a = 7 } function change2() { state.first.b = 8 state.first.second.c = 9 console.log(state); } </script> <style> </style>  9toRef

如果原始对象是非响应式的就不会更新视图 数据是会变的,如果原始对象是响应式的是会更新视图并且改变数据的

<template> <div> <button @click="change">按钮</button> {{state}} </div> </template> <script setup lang="ts"> import { reactive, toRef } from 'vue' const obj = { foo: 1, bar: 1 } const state = toRef(obj, 'bar') // bar 转化为响应式对象 const change = () => { state.value++ console.log(obj, state); } </script> 10toRefs

可以帮我们批量创建ref对象主要是方便我们解构使用

import { reactive, toRefs } from 'vue' const obj = reactive({ foo: 1, bar: 1 }) let { foo, bar } = toRefs(obj) foo.value++ console.log(foo, bar); 11toRaw

将响应式对象转化为普通对象

import { reactive, toRaw } from 'vue' const obj = reactive({ foo: 1, bar: 1 }) const state = toRaw(obj) // 响应式对象转化为普通对象 const change = () => { console.log(obj, state); }

到此这篇关于Vue3中的ref和reactive响应式的文章就介绍到这了,更多相关Vue3 ref和reactive响应式内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    vue项目一些常见问题

    vue项目一些常见问题,组件,样式,**样式污染问题**同样的样式不需要在每个组件都复制组件内单独的样式加外层class包裹。加scope。否则只是

    01-Vue项目实战-网易云音乐-准备工作

    01-Vue项目实战-网易云音乐-准备工作,网易,项目,前言在接下来的一段时间,我会仿照网易云音乐,利用Vue开发一个移动端的网易云音乐项目。在做

    01- 第一天 spring boot2.3.1 +vue3.0 后台管理系统的研发

    01- 第一天 spring boot2.3.1 +vue3.0 后台管理系统的研发,自己的,后台,后台框架一直想开发一套完全属于自己的后台,但是18年的时候,曾经答

    Vue项目中 App.vue文件

    Vue项目中 App.vue文件,文件,内容, 在App.vue文件中,定义了一个id为app的div,在这个div板块中放置Helloworld组件,文件内容如下图所示:在

    Firefox和Opera浏览器哪个好

    Firefox和Opera浏览器哪个好,火狐浏览器,浏览器,操作系统,插件,授权,支持,火狐浏览器火狐浏览器(Mozilla Firefox)是由Mozilla开发的网页浏览器

    1-Vue构造函数的生成

    1-Vue构造函数的生成,函数,属性,版本:@2.6.10环境:web ;思维图:www.processon.com/view/link/5…我们使用的Vue是一个经过层层加强的构造函数

    Firefox和Safari浏览器哪个好

    Firefox和Safari浏览器哪个好,浏览器,火狐浏览器,内核,授权,火狐,插件,火狐浏览器火狐浏览器(Mozilla Firefox)是由Mozilla开发的网页浏览器,采

    prefix是什么词性

    prefix是什么词性,前缀,词根,本文目录prefix是什么词性prefix有哪些Prefix是什么意思linux, configure --prefix=/有什么用CentOS操作系统

    Prefetch文件夹是什么 Prefetch介绍

    Prefetch文件夹是什么 Prefetch介绍,文件,读取,启动,系统,应用程序,索引,Prefetch简介这是预读取文件夹,用来存放系统已访问过的文件的预读信息(