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 手写出 refshallowRef 甚至带防抖功能的 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/

相关推荐
Roc.Chang2 小时前
Vue 3 setup 语法糖 computed 的深度使用
前端·javascript·vue.js
玄尺_0072 小时前
uniapp h5端使浏览器弹出下载框
前端·javascript·uni-app
军军君012 小时前
Three.js基础功能学习三:纹理与光照
前端·javascript·3d·前端框架·three·三维·三维框架
淡笑沐白2 小时前
Vue3基础语法教程
前端·javascript·vue.js
一 乐2 小时前
景区管理|基于springboot + vue景区管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
Sylus_sui2 小时前
企业级Axios封装实战指南
vue.js
幽络源小助理2 小时前
SpringBoot+Vue大型商场应急预案管理系统源码 | Java安全类项目免费下载 – 幽络源
java·vue.js·spring boot
JIngJaneIL2 小时前
基于java + vue连锁门店管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
Mintopia2 小时前
🧠 从零开始:纯手写一个支持流式 JSON 解析的 React Renderer
前端·数据结构·react.js