Vue3 进阶核心:高级响应式工具 + 特殊内置组件核心解析

目录

[1 shallowRef(浅响应)](#1 shallowRef(浅响应))

[2 shallowReactive(浅响应)](#2 shallowReactive(浅响应))

[3 readonly(只读)](#3 readonly(只读))

[4 shallowReadonly(浅只读)](#4 shallowReadonly(浅只读))

[5 toRaw(还原初始对象)](#5 toRaw(还原初始对象))

[6 markRaw(永不响应)](#6 markRaw(永不响应))

[7 customRef(自定义ref)](#7 customRef(自定义ref))

[8 Teleport(传送门)](#8 Teleport(传送门))

[9 Suspenmse(等待一下)](#9 Suspenmse(等待一下))

[10 补充](#10 补充)


1 shallowRef(浅响应)

基础概念:只监听.vlue的引用变化,如果是数据类型就是这个值,但是如果是对象,就只监控这个对象的引用,对.value内部的对象或者数据类型不做监控。

代码示例:

TypeScript 复制代码
const state = shallowRef({ count: 1 })

state.value.count++ // 视图不更新 (层级太深)
state.value = { count: 2 } // 视图更新 (替换了整个 .value)

2 shallowReactive(浅响应)

基础概念:只把对象的第一层做响应式的管理,也是监控引用,内部值切换无法监控到,与shallowRef的区别就是他多了一层盒子RefImpl,原理类似。

代码示例:

TypeScript 复制代码
const state = shallowReactive({ foo: { bar: 1 } })
state.foo = { bar: 2 } //  更新 (第一层)
state.foo.bar++ // 不更新 (第二层)

3 readonly(只读)

基础概念:只读不写,传递的参数都是响应式的,可以防止别人的错误修改。

TypeScript 复制代码
const original = ref(0)
const copy = readonly(original)

original.value++ //  改原值可以
copy.value++     //  改副本报错:Set operation failed

4 shallowReadonly(浅只读)

基础概念:浅只读,只有第一层不能进行修改,允许深层次的修改。

TypeScript 复制代码
const state = shallowReadonly({ n: 1, nested: { n: 2 } })

state.n++ //  拦截 (第一层)
state.nested.n++ //  Pass (深层未被冻结)

5 toRaw(还原初始对象)

基础概念:toRaw用于获取一个响应式对象的原始对象,相当于是将响应式的代理对象进行拆箱,拆箱成原先的非响应式的对象,一般场景为将响应式对象传递给后端或者外部系统,可以确保他们接收的是普通对象。

TypeScript 复制代码
const state = reactive({ n: 1 })
const raw = toRaw(state) // 拿到普通对象 { n: 1 }

console.log(raw === state) // false (一个是对象,一个是代理)

6 markRaw(永不响应)

基础概念:给一个对象打上"永不响应"的标记。Vue 见到它就会绕道走,绝不把它变成 Proxy(响应式)。

TypeScript 复制代码
const foo = markRaw({ complexObj: '地图实例...' })
const state = reactive({ foo })

console.log(isReactive(state.foo)) // false (虽然在 reactive 里,但它免疫)

7 customRef(自定义ref)

  • shallowRef ≈ 一个去掉了递归逻辑的 customRef。

  • readonly ≈ 一个 set 函数只会报错的 customRef。

  • customRef ≈ 万能钥匙 。理论上,你可以用 customRef 手写出 ref、shallowRef 甚至带防抖功能的 ref,因为它们底层的拦截机制是同源的。

基础概念:创建一个自定义的ref,并对其依赖项追踪赫更新触发进行逻辑控制。

防抖节流:

  • track():监控,告诉数据很重要,一旦变化就去更新
  • trigger():触发,通知数据发生变化。

代码:延迟一秒更新的hooks代码(自定义ref)

TypeScript 复制代码
import { customRef } from 'vue'

export function useDelayRef<T>(initialValue: T, delay = 1000) {
  let value = initialValue
  let timer: number | null = null

  return customRef<T>((track, trigger) => {
    return {
      get() {
        track() // 收集依赖
        return value
      },
      set(newValue: T) {
        if (timer) clearTimeout(timer)

        timer = window.setTimeout(() => {
          value = newValue
          trigger() // 延迟触发更新
        }, delay)
      },
    }
  })
}

8 Teleport(传送门)

基础概念:在逻辑上,组件是父子关系;但在 DOM 渲染 上,将组件的 HTML 结构"传送"到页面的其他位置(如 <body> 下(比如一些弹框))。

代码示例:

父组件

TypeScript 复制代码
<template>
  <div>
    <h1>父组件</h1>
    <button @click="show = true">打开弹窗</button>

    <Modal :isOpen="show" @close="show = false" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Modal from './Modal.vue'

const show = ref(false)
</script>

子组件: 用 <Teleport to="body"> 把这块 HTML 扔到 body 标签底部。

TypeScript 复制代码
<template>
  <Teleport to="body">
    <div v-if="isOpen">
      <p>我是弹窗内容</p>
      <button @click="$emit('close')">关闭</button>
    </div>
  </Teleport>
</template>

<script setup>
// 接收状态
defineProps(['isOpen'])
// 声明事件
defineEmits(['close'])
</script>

9 Suspenmse(等待一下)

基础概念:在组件树中协调异步依赖。如果子组件中有 async setup() 或异步组件,它可以显示一个"加载中"的状态(#fallback),等数据都到了再显示真正内容(#default)。

作用:因为子组件有顶层 await,父组件必须使用 <Suspense> 包裹它,否则子组件无法渲染。

TypeScript 复制代码
<template>
  <h3>{{ data }}</h3>
</template>

<script setup>
// 模拟请求延迟 2秒
await new Promise(r => setTimeout(r, 2000))
const data = '✅ 数据请求完成'
</script>
TypeScript 复制代码
<template>
  <h3>{{ data }}</h3>
</template>

<script setup>
// 模拟请求延迟 2秒
await new Promise(r => setTimeout(r, 2000))
const data = '✅ 数据请求完成'
</script>

10 补充

https://v3-migration.vuejs.org/

相关推荐
兰亭妙微UI设计公司几秒前
兰亭妙微软件界面设计公司的解锁按钮设计10大密码
开发语言·前端·javascript
迪幻24 分钟前
封装自己的 npm 依赖并存储到个人 GitHub
前端·npm·github
u0111026751 小时前
WebP 转成 PNG 后为什么更大?图片格式转换不等于压缩
前端·javascript·vue.js
万少1 小时前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法
seconp1 小时前
基于Spring Boot和Vue 3的智慧旅游网站:住宿预订、行程规划与千问接入
vue.js·spring boot·毕业设计·软件工程·课程设计·旅游·毕设
java1234_小锋1 小时前
【技术专题】HTML5 网页技术 - HTML5 列表标签
前端·html·html5
强二小哥帅1 小时前
Kotlin 协程复习笔记
前端
不可能片场1 小时前
工程实践 原子替换改了 ctime 怎么修
前端·electron
暧暧内含光1 小时前
HTTP 文件传输体系全解:从协议标头、OSS 架构到流媒体分片
前端
静默回滚1 小时前
浏览器能显示AVIF,却导不出一张AVIF
前端