COMP交易所最新版本V1.0.463728 安卓版
96.3MB · 2025-09-15
ref
和reactive
是Vue3
的Composition API
里最常用的两个核心成员,专门用来创建响应式数据的。
啥叫响应式呢?就是数据一变,页面自动跟着更新,不用你手动刷新。
其实它们干的是一件事就是:让Vue能监听到你的数据变化。
但它们用起来不一样,适合的场景也不一样。很多人在用的时候都是凭感觉选,到底该用哪个?一直都觉得很模糊。
先简单认识一下:
ref:可以包装任何类型的值,包括基本类型(数字、字符串等)和对象类型。使用时需要通过.value
来访问和修改值。
reactive:只能包装对象类型(包括数组)。使用时直接访问属性即可,不需要.value
。
下面咱们通过实际例子来看一下。
// ref 啥都能包
const count = ref(0) // 数字
const name = ref('小明') // 字符串
const isActive = ref(false) // 布尔值
const user = ref({ age: 18 }) // 对象
const list = ref([1, 2, 3]) // 数组
// reactive 只接对象/数组
const user = reactive({ age: 18 }) // 对象
const list = reactive([1, 2, 3]) // 数组
const count = reactive(0) // 报错
ref
xxx.value = newValue
TypeScript
支持完美reactive
Vue2
的data
这里是最容易踩坑的地方!
const count = ref(0)
const user = ref({ name: '小明', age: 18 })
// 监听基本类型 ref
watch(count, (newVal, oldVal) => {
console.log('count变化:', newVal, oldVal)
})
// 监听对象 ref - 需要深度监听
watch(user, (newVal, oldVal) => {
console.log('user变化:', newVal, oldVal)
}, { deep: true }) // 必须加 deep!
// 监听对象 ref 的特定属性
watch(() => user.value.name, (newVal, oldVal) => {
console.log('name变化:', newVal, oldVal)
})
const state = reactive({
count: 0,
user: { name: '小明', age: 18 }
})
// 自动深度监听,不需要 deep: true
watch(state, (newVal, oldVal) => {
console.log('state变化:', newVal, oldVal)
})
// 推荐:监听特定属性
watch(() => state.count, (newVal) => {
console.log('count变了', newVal)
})
// 监听嵌套属性
watch(() => state.user.name, (newVal) => {
console.log('名字变了', newVal)
})
// 监听多个属性
watch([() => state.count, () => state.user.name], ([newCount, newName]) => {
console.log('count或name变了', newCount, newName)
})
1.深度监听:
ref
对象需要手动{ deep: true }
reactive
自动深度监听2.旧值获取:
reactive
的旧值和新值相同(Proxy
特性)ref
的旧值正常3.性能影响:
reactive
自动深度监听,可能影响性能ref
可以精确控制监听深度reactive
// 相关联的表单数据,用 reactive 更合适
const form = reactive({
username: '',
password: '',
remember: false,
errors: {}
})
// 验证函数
const validateForm = () => {
form.errors = {}
if (!form.username) {
form.errors.username = '用户名不能为空'
}
// ...其他验证
}
ref
// API 返回的数据,经常需要重新赋值,用 ref
const data = ref(null)
const loading = ref(false)
const error = ref(null)
const fetchData = async () => {
loading.value = true
try {
const response = await fetch('/api/data')
data.value = await response.json() // 直接赋值,美滋滋
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
// 方案1:用 reactive(状态相关联)
const modal = reactive({
isOpen: false,
title: '',
content: '',
loading: false
})
// 方案2:用多个 ref(状态相对独立)
const isModalOpen = ref(false)
const modalTitle = ref('')
const modalContent = ref('')
const modalLoading = ref(false)
const list = ref([])
// 添加项目
const addItem = (item) => {
list.value = [...list.value, item] // 重新赋值,安全
}
// 删除项目
const removeItem = (id) => {
list.value = list.value.filter(item => item.id !== id)
}
// 清空列表
const clearList = () => {
list.value = [] // 直接赋值,不会丢失响应式
}
如果用reactive
来做列表:
const list = reactive([])
// 添加项目 - 只能用 push
const addItem = (item) => {
list.push(item) // 可以,但不够直观
}
// 删除项目 - 需要找到索引
const removeItem = (id) => {
const index = list.findIndex(item => item.id === id)
if (index !== -1) {
list.splice(index, 1) // 有点麻烦
}
}
// 清空列表 - 只能修改长度
const clearList = () => {
list.length = 0 // 能工作,但有点 hack
}
这是决定用哪个的关键场景!
function useCounter(initialValue = 0) {
const count = ref(initialValue)
const double = computed(() => count.value * 2)
const increment = () => count.value++
return { count, double, increment }
}
// 使用时:
const { count, double, increment } = useCounter()
function useUser() {
const state = reactive({
user: null,
loading: false,
error: null
})
const fetchUser = async (id) => {
state.loading = true
try {
state.user = await fetchUserById(id)
} catch (err) {
state.error = err.message
} finally {
state.loading = false
}
}
return { ...toRefs(state), fetchUser } // 必须用 toRefs!
}
// 使用时:
const { user, loading, error, fetchUser } = useUser()
明显看到,返回多个ref
更简单直接。
// 基本类型和需要重新赋值的用 ref
const loading = ref(false)
const error = ref(null)
const data = ref(null)
// 相关联的数据用 reactive
const form = reactive({
username: '',
password: '',
remember: false
})
// 这样写,既清晰又安全
其实在大多数情况下,性能差异可以忽略不计,推荐如下:
ref
,因为reactive
需要创建Proxy
对象ref
,避免不必要的深度监听ref
,reactive
不能直接重新赋值优先使用ref
的场景:
-基本类型(数字、字符串、布尔值)
-DOM 引用和组件引用
-需要频繁重新赋值的变量
-API 返回的数据
-组合式函数的返回值
-列表数据
考虑使用reactive
的场景:
-相关联的表单数据
-复杂的组件状态
-配置对象
-不需要重新赋值的对象
希望这篇分析对你有帮助。如果有不同意见,欢迎在评论区理性讨论!
《工作 5 年没碰过分布式锁,是我太菜还是公司太稳?网友:太真实了!》
《Java 订单超时未支付,如何自动关闭?掌握这 3 种方案,轻松拿 offer!》
《写给小公司前端的 UI 规范:别让页面丑得自己都看不下去》
《终于找到 Axios 最优雅的封装方式了,再也不用写重复代码了》
96.3MB · 2025-09-15
63.0MB · 2025-09-15
23.6MB · 2025-09-15