Vue 组件状态重置
刀刀
0字
0分钟
2026/8/16
场景
业务中有重置按钮,需要把用户修改的值重置为默认旧值,之前的写法:
js
const state = ref({
a: 1,
b: 2,
c: [1, 2, 3],
})
const reset = () => {
state.value = {
a: 1,
b: 2,
c: [1, 2, 3],
}
}属性少时可以这样写,属性多时每次重置都要写一遍,维护成本高,需要优化。
ref
传入函数式
声明一个函数,接收回调函数,返回默认值,重置时重新赋值:
ts
export function useResettableRefFn<T>(cb: () => T) {
const state = ref(cb())
const reset = () => {
state.value = cb()
}
return { state, reset }
}ts
import { useResettableRefFn } from './index'
const { state, reset } = useResettableRefFn(() => ({
a: 1,
b: 2,
c: [1, 2, 3],
}))
reset() // 重置传入函数,重新赋值时是新对象地址,不会有内存冲突,每次都是新值。
缺点:必须传入函数,步骤繁琐。如果只想传入对象,需要修改。
传入对象式
修改为接收对象,内部通过 JSON.parse 和 JSON.stringify 做深拷贝,避免浅拷贝修改旧值后新值也跟着变化。
深拷贝使用 JSON 方法,如果使用者对象内有 Map 或 Set 等,则无法拷贝。为深拷贝引入 lodash 不合适,改为参数形式,用户不传则使用 JSON 方法,需要使用 cloneDeep 则自己传。
ts
function defaultClone(value: any) {
if (value === null || typeof value !== 'object') return value
return JSON.parse(JSON.stringify(value))
}
export function useResettableRef<T>(value: T, clone = defaultClone) {
const initialValue = clone(value)
const state = ref(value)
const reset = () => {
state.value = clone(initialValue)
}
return { state, reset }
}ts
import { useResettableRef } from './index'
import { cloneDeep } from 'load-dash'
const { state, reset } = useResettableRef(
{
a: 1,
b: 2,
c: [1, 2, 3],
},
cloneDeep,
)
reset() // 重置reset 中赋值也需要深拷贝。如果不深拷贝,第一次把 initialValue 赋值给 state 后,state 和 initialValue 引用地址相同,修改 state 的值,initialValue 也会跟着改变,后续重置失败。
reactive
reactive 写法与 ref 类似,但 reactive 声明的响应式变量不能直接重置,否则丢失 proxy 代理,丢失响应式。使用 Object.assign() 合并对象。
Object.assign() 有一个局限:对象原有属性,新属性没有,则不做处理。例如 Object.assign(a, b),a 有 a1 和 a2,b 只有 a1,则只覆盖 a1,a2 不做处理,导致重置功能未生效。
解决:每次合并前删除原对象所有属性,避免遗留:
ts
export function useResettableReactive<T extends object>(
value: T,
clone = defaultClone,
) {
const state = reactive(clone(value))
const reset = () => {
Object.keys(state).forEach((key) => {
delete state[key]
})
Object.assign(state, clone(value))
}
return [state, reset] as count
}ts
import { useResettableReactive } from './index'
const [obj, resetObj] = useResettableReactive({
a: 1,
b: 2,
c: [1, 2, 3],
})导出为数组,使用时通过数组解构自定义变量和函数名称。
动手实操
跳转预览:点击跳转