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

相关推荐
超哥--3 小时前
B站视频内容智能分析系统(九):React 前端与管理面板
前端·react.js·前端框架
Cutecat_6 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
dsyyyyy11016 小时前
JavaScript变量
开发语言·javascript·ecmascript
qq_422152576 小时前
PDF 加水印工具怎么选?2026 年文档版权保护方案对比
前端·pdf·github
kyriewen6 小时前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
brucelee1867 小时前
OpenClaw 浏览器控制(Chrome MCP)完整教程
前端·chrome
ct9787 小时前
React 状态管理方案深度对比
开发语言·前端·react
胡志辉的博客7 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖8 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty8 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js