Vue3响应式系统基于Proxy实现,替代了Vue2的Object.defineProperty。理解ref与reactive的内部机制,才能写出高性能组件,避开常见的更新丢失和性能陷阱。本文从源码角度拆解Vue3响应式原理,给出可直接验证的代码示例与性能优化方案。
Vue3响应式原理:Proxy与副作用收集
Vue3的reactive用Proxy拦截对象的get、set、has、deleteProperty操作。get时把当前正在执行的副作用函数收集进依赖表,set时触发收集到的副作用重新执行。依赖表结构是target → key → Set(副作用函数)的三层映射。
import { ref, effect } from 'vue'
const count = ref(0)
// effect中访问count会触发依赖收集
effect(() => {
console.log('副作用执行:', count.value)
})
count.value++ // 触发副作用重新执行
ref本质是{ value: … }结构,对象类型的value会转成reactive(reactive对象),基本类型直接保存。这是ref既能包装对象又能包装基本类型的原因。
reactive与ref的区别和选择
reactive直接代理对象,适合对象/数组,访问属性不用.value;ref适合基本类型或需要跨组件传递的响应式值,模板中自动解包,JS中要.value。选型标准:对象内部属性操作频繁用reactive,单个值或需要替换整个引用时用ref。
import { reactive, ref } from 'vue'
// reactive 适合对象
const state = reactive({ user: { name: 'zhang' }, list: [] })
state.user.name = 'li' // 直接访问
// ref 适合基本类型
const loading = ref(false)
loading.value = true
// 模板中ref自动解包,reactive保持不变
// {{ loading }} 直接显示,{{ state.user.name }}
响应式更新优化:readonly、shallow与markRaw
Vue3响应式的开销来自依赖收集和触发更新。对不需要响应式的数据用markRaw跳过代理,对大列表用shallowRef避免深度响应,性能提升立竿见影。常见陷阱是给状态绑定的外部库对象整体转响应式,导致每次改动触发大量无关更新。
import { shallowRef, markRaw } from 'vue'
// 大列表数据不需要深度响应
const bigList = shallowRef(rawList)
bigList.value = newItems // 整体替换才触发更新
// 第三方对象禁止深度响应
const chartInstance = markRaw(new Chart())
state.chart = chartInstance // 只存引用,不代理
组合式API逻辑复用与组件性能优化
组合式API把响应式状态和逻辑抽成自定义hook,多个组件复用同一份逻辑。配合computed缓存派生数据,避免每次渲染重复计算。
import { ref, computed } from 'vue'
function useSearch(list) {
const keyword = ref('')
const results = computed(() =>
list.value.filter(item => item.name.includes(keyword.value))
)
return { keyword, results }
}
// 组件中使用
const { keyword, results } = useSearch(userList)
列表渲染加key、v-for与v-if分离、长列表用虚拟滚动,是组件层最常见的三个性能瓶颈。配合defineProps与defineEmits,响应式代码在TS下也能获得完整类型推导。
Vue3响应式常见问题与排查方法
遇到页面不更新的情况,先确认三件事:对象属性是否为新增属性(Proxy能监听新增,但reactive与set的边界还是要靠ref/defineProperty);数组索引修改(要用splice或整体替换);嵌套层级过深导致收集不到(改用shallowRef管理)。用Vue Devtools的响应式面板能直观看到依赖链,多数问题一眼定位。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vue3-xiang-ying-shi-yuan-li-shi-zhan-ref-yu-reactive-yuan/