reactive适合管理考试系统的结构化状态(如题目集合、答题数据),但单个基础值(如填空答案)应使用ref;需用toRefs保持解构响应性,并注意reactive的惰性代理特性。

在考试答题系统中,reactive 适合管理题目集合、答题状态、用户作答数据等结构化对象,但它不是直接“处理”题目的工具,而是为整个动态表单提供响应式基础支撑。关键在于:用 reactive 组织好数据结构,再配合 JSON Schema 配置、组件工厂和依赖追踪,实现题目渲染、联动、校验与提交闭环。
reactive 管理答题核心状态
考试过程中需要实时响应的数据,比如:
- 当前题目索引、总题数、剩余时间
- 所有题目的作答值(如
{ q1: "Proxy", q3: true, q5: ["A", "C"] }) - 题目显示状态(受条件控制,如“q2 只在 q1 选了 B 时出现”)
- 错误提示、提交状态、阅卷结果
这些都建议用 reactive 包裹成一个统一状态对象:
const examState = reactive({
currentQIndex: 0,
answers: {} as Record<string any>,
visibleQuestions: [] as QuestionSchema[],
errors: {} as Record<string string>,
isSubmitting: false
})</string></string>
这样修改 examState.answers.q7 = "const" 或 examState.currentQIndex++ 会自动触发视图更新,无需 .value,写法更贴近原生对象操作。
reactive 不适合单独存单个基础答案
比如不能写 reactive("const") —— 这会报警告且无响应。
填空题的单个字符串答案、判断题的布尔值,应统一用 ref:
const q2Answer = ref<string>('')
const q4Judgement = ref<boolean null>(null)</boolean></string>
理由很实际:
- 模板里可直接
v-model="q2Answer",不用.value - 类型推断清晰,TS 支持好
- 多个独立基础值混在 reactive 对象里反而破坏语义,也容易因解构丢失响应性
配合 toRefs 解构保持响应性
当从组合式函数返回一个 reactive 状态对象供组件使用时,直接解构会切断响应:
// ❌ 错误:解构后失去响应
const { answers, currentQIndex } = examState
answers.q1 = "X" // 页面不更新
// ✅ 正确:用 toRefs
const { answers, currentQIndex } = toRefs(examState)
// 此时 answers 是 Ref<record any>>,赋值仍需 .value,但保持响应
answers.value.q1 = "X"</record>
更推荐的做法是:在模板中直接访问 examState.answers.q1,避免过早解构;或只对需要传给子组件的字段用 toRef 单独提取。
reactive 支持嵌套联动,但需注意“惰性代理”
Vue 3 的 reactive 是懒代理:只有被访问过的属性才会递归转为响应式。
例如配置中某题的选项来自接口:
{
type: "radio",
options: ref([]), // ✅ 用 ref 包裹异步数组,确保响应
// 或
options: reactive([]) // ✅ 也可,但需确保初始化就存在
}
如果 options 是后端返回的深层嵌套对象(如 question.config.rules[0].message),只要你在模板或逻辑中访问过它,就会自动变成响应式——这对动态校验提示(如正则不匹配时显示 message)非常友好。
和 ref 协同工作的典型流程
- 用
reactive管理整体答题上下文(examState) - 用
ref存单个原子值(每道题的输入框值、开关状态、富文本内容) - 提交前遍历
examState.visibleQuestions,逐题调用其validate()方法(该方法读取对应 ref 值或 reactive 中的字段) - 校验错误写入
examState.errors,触发 UI 更新
这样分工清晰:reactive 负责“结构”,ref 负责“叶子”,既发挥 Proxy 懒代理优势,又规避基础类型限制。
不复杂但容易忽略
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











