如何在Vue/Pinia中强制实现状态修改时的校验?
在Pinia中实现强制状态校验与类似Setter的约束
方案一:用ES6代理(Proxy)拦截所有状态修改
通过将初始状态包裹在Proxy中,拦截所有属性的赋值操作,强制触发校验逻辑。无论使用者是直接修改状态还是通过Action修改,都会被拦截,从根源上阻止非法值写入。
示例代码:
import { defineStore } from 'pinia' function createValidatedState(initialState, validators) { return new Proxy(initialState, { set(target, prop, value) { // 执行对应属性的校验规则 if (validators[prop]) { const isValid = validators[prop](value) if (!isValid) { throw new Error(`属性 ${prop} 不符合规则:传入值为 ${value}`) } } target[prop] = value return true } }) } export const useCounterStore = defineStore('counter', { state: () => { const initialState = { count: 0 } // 定义校验规则:count必须是数值类型 const validators = { count: (value) => typeof value === 'number' } return createValidatedState(initialState, validators) }, // 可选:提供规范的Action方法,Proxy已保证所有修改都走校验 actions: { increment() { this.count++ }, setCount(value) { this.count = value } } })
方案二:TypeScript类型约束+运行时校验(TS项目首选)
先通过TS类型定义约束状态属性的类型,在开发阶段给使用者明确的类型提示,再在Action中添加运行时校验,防止JS环境下的类型绕过。
示例代码:
import { defineStore } from 'pinia' // 定义状态类型,约束属性类型 interface CounterState { count: number } export const useCounterStore = defineStore('counter', { state: (): CounterState => ({ count: 0 }), actions: { setCount(value: number) { // 运行时二次校验 if (typeof value !== 'number') { throw new Error('count必须是数值类型') } this.count = value }, increment() { this.count++ } } })
如果要彻底阻止直接修改,可以结合上面的Proxy方案,实现类型提示+强制校验的双重保障。
方案三:watch监听+状态回滚(兜底方案)
开启Vue严格模式,结合watch监听状态变化,发现非法值时抛出错误并恢复原状态。这种方式属于事后校验,适合不想引入Proxy的场景。
示例代码:
import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { setCount(value) { if (typeof value !== 'number') { throw new Error('count必须是数值类型') } this.count = value } }, created() { this.$watch('count', (newVal, oldVal) => { if (typeof newVal !== 'number') { console.error('count必须是数值类型') // 回滚到合法状态 this.count = oldVal throw new Error('count必须是数值类型') } }, { deep: true }) } })
内容的提问来源于stack exchange,提问作者Oidipous_REXX
相关产品推荐
相关产品推荐

