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

相关推荐
别看我只是一直狼15 分钟前
从观察者模式到 RxJS:让复杂的异步逻辑变得优雅又舒服
javascript
花间相见16 分钟前
【终端效率工具01】—— Yazi:Rust 编写的现代化终端文件管理器,告别繁琐操作
前端·ide·git·rust·极限编程
|晴 天|25 分钟前
我如何用Vue 3打造一个现代化个人博客系统(性能提升52%)
前端·javascript·vue.js
风止何安啊33 分钟前
网页都知道要双向握手才加载!从 URL 到页面渲染,单向喜欢连 DNS 都解析不通
前端·javascript·面试
太极OS39 分钟前
给 AI Skill 做 CI/CD:GitHub + ClawHub + Xiaping 同步发布实战
前端
你_好39 分钟前
Chrome 内置了 AI 工具协议?WebMCP 抢先体验 + 开源 DevTools 全解析
前端·mcp
GISer_Jing40 分钟前
LangChain.js + LangGraph.js 前端AI开发实战指南
前端·javascript·langchain
正在发育ing__43 分钟前
从源码看vue的key和状态错乱的patch
前端
木心术11 小时前
TypeScript实战进阶:从基础类型到高级类型编程
javascript·ubuntu·typescript
Hello--_--World1 小时前
浏览器同源策略与跨域问题
javascript