【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()效果图

相关推荐
PedroQue9911 小时前
0.8.2 新增 backFallback 配置,无 tabbar 页返回无忧
前端·uni-app
淡漠的蓝精灵11 小时前
web.py:一个简单到极致的 Python Web 框架
开发语言·前端·python·其他
开开心心就好11 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
起个名字费劲死了12 小时前
Halcon学习一:骰子识别
前端·python·学习
大江东去浪淘尽千古风流人物12 小时前
【HexVIO】DSP卸载双目惯性VIO:Hexagon向量化前端与单帧融合调度深度解析
前端·状态模式·slam·dsp·vio·hexagon·移动端加速
এ慕ོ冬℘゜12 小时前
JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序
开发语言·javascript·ecmascript
其实防守也摸鱼12 小时前
Chrome 扩展安全攻防实录:从攻击面到防御实践
开发语言·前端·网络·chrome·安全·web安全·php
web打印社区12 小时前
Lodop排障总纲-常见报错一张表
开发语言·前端·javascript·chrome·websocket
李剑一12 小时前
为什么几乎所有的知名开源项目都是外国人写的?
前端·ai编程·deepseek
小郎君65812 小时前
(一)为什么表单需要第三种状态:disabled、readonly 与纯文本展示
前端·vue.js