【vue3】实现数据响应式(ref、shallowRef、trigger、reactive、shallowReactive、toRef、toRefs)

一、ref、shallowRef、trigger

ref支持所有类型

可以粗略理解为 ref = shallowRef + triggerRef

1、通过ref获取dom元素

javascript 复制代码
	<p ref="_ref">这是ref获取dom元素</p>
	
	 import {ref,shallowRef, triggerRef} from 'vue'
	 const _ref = ref()
	 console.log(_ref.value?.innerText)

2、实现数据响应

javascript 复制代码
  import {ref,shallowRef, triggerRef} from 'vue'
  //ref
  type M = {
    name:string,
    age:number
  }
  const personObj= ref<M>(
    {
      name:'孙悟空',
      age:90
    }
  )
  const fn1= ()=>{
    personObj.value.name = '白骨精' //视图也会更新
    console.log(personObj)
  }

  //shallowRef
  const man = shallowRef ({name:'张三'})
  const fn1= ()=>{
    /**
     * man是shallowRef对象,直接更改value值不会更新视图,调用triggerRef强制更新
     * 并且会受ref变量personObj更改值的影响(personObj.value.name = '白骨精')
     * 所以ref和shallowRef不要写在一起
     * 可以粗略理解为 ref = shallowRef + triggerRef
     */
    man.value.name = '李四'  
    triggerRef(man)
    console.log(man) //视图会更新

  }

二、reactive、shallowReactive

reactive只接收引用类型 array、object、map

shallowReactive与shallowRef的问题一样,shallowReactive只能响应第一层

javascript 复制代码
//对象场景
  type M2 = {
    name:string,
    age:number
  }
  let from = reactive<M2>({
    name:'yyx',
    age:18
  })
  from.age = 90 //不需要.value  和ref不一样,ref取值/赋值都需要.value
  
//数组场景
  let list = reactive<string[]>([])
  list = ['aaa','bbb','ccc']

//数据异步场景(从接口请求回来)
  /**
   * 异步数据不能直接 = 赋值
   * 通过push
   * 或者定义为对象,包裹起来
   */
   
  let list = reactive<string[]>([])
  setTimeout(() => {
    const res = ['aaa','bbb','ccc']
    list.push(...res)  //通过push注入值,不能直接 = 赋值
  }, 3000);

	/**或者*/
	
  let data = reactive<any>({
    list:[]
  })

  setTimeout(() => {
    const res = ['aaa','bbb','ccc']
    data.list = res
  }, 3000);

三、toRef、toRefs、toRaw

只能对响应式的对象有用,非响应式的 视图毫无变化;

reactive的值被解构出来丢失了响应式,这个时候就要用toRef、toRefs;

为了单独提取对象中的一个,然后变成响应式,可以把toRef、toRefs理解为解构操作;

javascript 复制代码
  import {reactive,toRef, toRefs,toRaw} from 'vue'

   /**
   * toRef
   * 一次性解构一个
  */
  const toRef_Obj = reactive({
    name:'游芸霞',
    nickname:'fenyin'
  })
  
  /**只更新视图,但是toRef_Obj内的数据并未变化 */
  let {name,nickname} = toRef_Obj
  name = 'youyunxia' //这样写toRef_Obj的name还是'游芸霞"

  /**双向响应式,视图、数据都发生变化 */
  let _toRef_name = toRef(toRef_Obj,'name')
  _toRef_name.value = 'youyunxia' //这样写toRef_Obj的name就会变成'youyunxia"


  /**
   * toRefs
   * 和toRef一样,只是toRefs一次性解构多个
  */
  let {name,nickname} = toRefs(toRef_Obj)
  name.value = '张三'
  console.log('toRefs========',name,nickname)
  
  /**
   * toRaw
   * 不想要响应式的proxy时,可以用toRaw转化
   */
  console.log('响应式=============',toRef_Obj)
  console.log('非响应式===========',toRaw(toRef_Obj))

toRaw()效果图

相关推荐
web小白成长日记2 小时前
企业级 Vue3 + Element Plus 主题定制架构:从“能用”到“好用”的进阶之路
前端·架构
APIshop2 小时前
Python 爬虫获取 item_get_web —— 淘宝商品 SKU、详情图、券后价全流程解析
前端·爬虫·python
风送雨2 小时前
FastMCP 2.0 服务端开发教学文档(下)
服务器·前端·网络·人工智能·python·ai
XTTX1102 小时前
Vue3+Cesium教程(36)--动态设置降雨效果
前端·javascript·vue.js
LYFlied3 小时前
WebGPU与浏览器边缘智能:开启去中心化AI新纪元
前端·人工智能·大模型·去中心化·区块链
Setsuna_F_Seiei3 小时前
2025 年度总结:人生重要阶段的一年
前端·程序员·年终总结
model20053 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
han_4 小时前
从一道前端面试题,谈 JS 对象存储特点和运算符执行顺序
前端·javascript·面试
aPurpleBerry4 小时前
React 01 目录结构、tsx 语法
前端·react.js
jayaccc5 小时前
微前端架构实战全解析
前端·架构