Vue.js响应式API

1. ref, reactive, toRef, toRefs

  • ref - 创建响应式引用
  • reactive - 创建响应式对象
  • toRef - 创建指向响应式对象属性的引用
  • toRefs - 将响应式对象转换为普通对象(包含 ref)

1.1 ref

  • 作用​:创建一个响应式的引用对象,可以包装基本类型或对象类型。
  • ​特点​
    • 返回一个带有 .value属性的对象
    • 在模板中自动解包(无需使用 .value)
    • 适合包装基本类型值(字符串、数字等)
    • 也可以包装对象,但内部会使用 reactive转换
js 复制代码
import { ref } from 'vue'

// 基本类型
const count = ref(0)
console.log(count.value) // 0

// 对象类型
const user = ref({ name: 'John', age: 30 })
console.log(user.value.name) // John

1.2 reactive

  • 作用​ :创建一个深层次的响应式对象(Proxy 代理)。
    • 特点
    • 只能用于对象类型(对象、数组、Map、Set)
    • 不需要 .value访问
    • 嵌套对象也会被自动转换为响应式
    • 不适合解构(会失去响应性)
js 复制代码
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  user: {
    name: 'John',
    age: 30
  }
})

// 直接访问属性
state.count++ // 响应式更新
console.log(state.user.name) // John

1.3 toRef

  • 作用​:为响应式对象的某个属性创建一个 ref,保持与源属性的响应式连接。
  • 特点
    • 保持对源属性的响应式连接
    • 修改 ref 会更新源对象,反之亦然
    • 当需要将 prop 转换为 ref 时特别有用
js 复制代码
import { reactive, toRef } from 'vue'

const state = reactive({
  count: 0
})

// 创建指向 state.count 的 ref
const countRef = toRef(state, 'count')

countRef.value++ // 会更新 state.count
console.log(state.count) // 1

state.count = 10 // 也会更新 countRef.value
console.log(countRef.value) // 10

1.4 toRefs

  • 作用​:将响应式对象的每个属性转换为 ref,保持响应式连接。
  • 特点
    • 解决 reactive 对象解构时失去响应性的问题
    • 返回的对象每个属性都是 ref
    • 在组合函数中返回响应式状态时特别有用
js 复制代码
import { reactive, toRefs } from 'vue'

const state = reactive({
  count: 0,
  name: 'John'
})

// 将响应式对象转换为 ref 对象
const stateRefs = toRefs(state)

// 解构后仍然保持响应性
const { count, name } = toRefs(state)

count.value++ // 会更新 state.count
name.value = 'Alice' // 会更新 state.name

2. computed, watch, watchEffect,

  • computed - 计算属性
  • watch - 侦听器
  • watchEffect - 立即执行侦听器

2.1 computed

  • 作用:创建基于其他响应式数据的派生值,具有缓存机制。
  • 特点
    • 惰性求值:只有依赖变化时才会重新计算
    • 自动追踪依赖
    • 返回一个只读的响应式 ref
    • 适合同步计算
js 复制代码
import { ref, computed } from 'vue'

const count = ref(0)
const doubleCount = computed(() => count.value * 2)

console.log(doubleCount.value) // 0
count.value = 5
console.log(doubleCount.value) // 10

2.2 watch

  • 作用:观察特定数据源的变化,执行回调函数。
  • ​特点​
    • 需要明确指定侦听的数据源
    • 可以获取变化前后的值
    • 支持深度侦听
    • 支持异步操作
    • 可以手动停止侦听
js 复制代码
import { ref, watch } from 'vue'

const count = ref(0)

// 基本用法
watch(count, (newValue, oldValue) => {
  console.log(`count从${oldValue}变为${newValue}`)
})

// 侦听多个源
const name = ref('John')
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  // 处理变化
})

// 深度侦听对象
const user = ref({ name: 'Alice', age: 30 })
watch(user, (newUser) => {
  console.log('用户信息变化', newUser)
}, { deep: true })

// 立即执行
watch(count, callback, { immediate: true })

2.3 watchEffect

  • 作用:立即执行一个函数,并自动追踪其依赖,依赖变化时重新执行。
  • 特点​
    • 立即执行
    • 自动收集依赖
    • 没有新旧值参数
    • 支持异步操作
    • 可以手动停止
js 复制代码
import { ref, watchEffect } from 'vue'

const count = ref(0)
const name = ref('John')

// 基本用法
watchEffect(() => {
  console.log(`count: ${count.value}, name: ${name.value}`)
})

// 停止侦听
const stop = watchEffect(() => { /* ... */ })
stop() // 停止侦听

// 清理副作用
watchEffect((onInvalidate) => {
  const timer = setTimeout(() => {
    console.log('执行操作')
  }, 1000)
  
  onInvalidate(() => {
    clearTimeout(timer) // 清理操作
  })
})
  • 使用场景
    • 需要立即执行的副作用
    • 依赖关系复杂时
    • 不需要知道具体变化的值时
    • 需要自动收集依赖时

3. shallowRef, shallowReactive

  • shallowRef - 创建浅层响应式引用,只对 .value本身进行响应式处理

    js 复制代码
    import { shallowRef } from 'vue'
    
    const largeObject = shallowRef({ 
      nested: { data: 'value' } // 嵌套对象不会被响应式处理
    })
    
    // 改变顶层属性会触发响应
    largeObject.value = { ... } 
    
    // 改变嵌套属性不会触发响应
    largeObject.value.nested.data = 'new value' // 不会触发更新
  • shallowReactive - 创建浅层响应式对象,只对顶层属性进行响应式处理

    js 复制代码
    import { shallowReactive } from 'vue'
    
    const state = shallowReactive({
      topLevel: 'value',
      nested: { data: 'value' } // 嵌套对象不会被响应式处理
    })
    
    // 改变顶层属性会触发响应
    state.topLevel = 'new value'
    
    // 改变嵌套属性不会触发响应
    state.nested.data = 'new value' // 不会触发更新

4. readonly, shallowReadonly

  • readonly - 创建只读的响应式代理

    • 任何修改尝试都会失败并产生警告
    • 深度只读(所有嵌套属性都是只读的)
    js 复制代码
    import { reactive, readonly } from 'vue'
    
    const original = reactive({ count: 0 })
    const copy = readonly(original)
    
    copy.count++ // 警告:Set operation on key "count" failed
  • shallowReadonly - 创建浅层只读的响应式代理

    • 顶层属性只读
    • 嵌套属性可修改(非只读)
    js 复制代码
    import { shallowReadonly } from 'vue'
    
    const state = shallowReadonly({
      topLevel: 'value',
      nested: { data: 'value' }
    })
    
    state.topLevel = 'new' // 警告:Set operation failed
    state.nested.data = 'new' // 允许修改

5. customRef

  • customRef - 创建自定义的 ref,显式控制依赖追踪和更新触发

    • 提供 track和 trigger函数手动控制
    • 适合实现防抖、节流等高级功能
    js 复制代码
    import { customRef } from 'vue'
    
    function useDebouncedRef(value, delay = 200) {
      let timeout
      return customRef((track, trigger) => {
        return {
          get() {
            track() // 追踪依赖
            return value
          },
          set(newValue) {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
              value = newValue
              trigger() // 触发更新
            }, delay)
          }
        }
      })
    }
    
    // 使用示例
    const text = useDebouncedRef('', 500)

6. effectScope

  • effectScope - 创建一个作用域,可以捕获其中创建的所有响应式 effect

    • 可以统一停止所有 effect
    • 适合在组件作用域外管理 effect
    js 复制代码
    import { effectScope, ref, watch } from 'vue'
    
    const scope = effectScope()
    
    scope.run(() => {
      const count = ref(0)
      
      watch(count, () => {
        console.log('count changed')
      })
      
      // 其他 effect...
    })
    
    // 停止所有 effect
    scope.stop()

7. getCurrentScope, onScopeDispose

  • getCurrentScope - 获取当前活动的 effect 作用域
  • onScopeDispose - 在当前作用域销毁时注册回调函数(在组合式函数中清理资源)
js 复制代码
import { getCurrentScope, onScopeDispose } from 'vue'

function useEventListener(target, event, callback) {
  target.addEventListener(event, callback)
  
  // 如果有当前作用域,注册清理函数
  if (getCurrentScope()) {
    onScopeDispose(() => {
      target.removeEventListener(event, callback)
    })
  }
}

8. provide, inject

依赖注入

9. nextTick

等待下一次 DOM 更新刷新(等DOM更新完成之后,再执行的回调函数)

10. useAttrs, useSlots

  • useAttrs - 访问组件接收的非 props 属性
  • useSlots - 访问组件的插槽内容
js 复制代码
import { useAttrs, useSlots } from 'vue'

const attrs = useAttrs()
const slots = useSlots()

console.log(attrs.class) // 获取 class 属性
console.log(slots.default) // 获取默认插槽

11. defineModel

  • defineModel - 简化自定义组件的双向绑定(v3.4新增)
    • 自动处理 modelValue和 update:modelValue
    • 支持修饰符
js 复制代码
// 子组件
const model = defineModel()

// 父组件
<ChildComponent v-model="value" />

12. withDirectives

  • withDirectives - 在渲染函数中应用自定义指令
js 复制代码
import { withDirectives, h } from 'vue'
import { vTooltip } from './directives/tooltip'

export default {
  render() {
    return withDirectives(h('div'), [
      [vTooltip, 'This is a tooltip']
    ])
  }
}

13. renderList

  • renderList - 高效渲染列表(优化列表渲染性能)
js 复制代码
import { renderList } from 'vue'

export default {
  render() {
    return renderList(items, (item, index) => {
      return h('div', { key: item.id }, item.text)
    })
  }
}

14. resolveComponent, resolveDirective ​调试工具​

  • resolveComponent - 按名称解析已注册的组件
  • resolveDirective - 按名称解析已注册的指令
js 复制代码
import { resolveComponent, h } from 'vue'

export default {
  render() {
    const ButtonComponent = resolveComponent('MyButton')
    return h(ButtonComponent, { onClick: handleClick }, 'Click me')
  }
}

15. onRenderTracked, onRenderTriggered 样式处理​

  • 调试钩子,用于追踪组件的渲染依赖和触发重新渲染的原因(性能分析和调试)
js 复制代码
import { onRenderTracked, onRenderTriggered } from 'vue'

onRenderTracked((event) => {
  console.log('依赖被追踪', event)
})

onRenderTriggered((event) => {
  console.log('重新渲染被触发', event)
})

16. useCssModule, useCssVars

  • useCssModule - 在 <script setup> 中访问 CSS 模块(在组合式 API 中使用作用域 CSS)

    js 复制代码
    import { useCssModule } from 'vue'
    
    const $style = useCssModule()
    
    // 在模板中使用
    <template>
      <div :class="$style.container"></div>
    </template>
  • useCssVars - 在组合式 API 中动态设置 CSS 变量(主题切换和动态样式)

    js 复制代码
    import { useCssVars } from 'vue'
    
    useCssVars((_ctx) => ({
      '--primary-color': theme.value.primary,
      '--secondary-color': theme.value.secondary
    }))
相关推荐
Coder_R2 小时前
如何 把 Mac 上的 APK(app) 安装到安卓手机上?
前端·面试
前端小灰狼2 小时前
Ant Design Vue Vue3 table 表头筛选重置不清空Bug
前端·javascript·vue.js·bug
前端付豪2 小时前
11、JavaScript 语法:到底要不要写分号?一文吃透 ASI 与坑点清单
前端·javascript
Copper peas2 小时前
Vue 中的 v-model 指令详解
前端·javascript·vue.js
前端小书生2 小时前
NestJs
前端·nestjs
万少2 小时前
十行代码 带你极速接入鸿蒙6新特性 - 应用内打分评价
前端·harmonyos
一写代码就开心2 小时前
VUE 里面 Object.prototype 是什么,如何使用他
前端
GHOME2 小时前
vue3中setup语法糖和setup函数的区别?
前端·vue.js·面试
lecepin2 小时前
AI Coding 资讯 2025-09-25
前端·javascript·后端