为何父组件更新后,AG Grid才与Vue父组件实现响应式同步?
AG Grid Vue3 响应式异常行为解析
问题背景
使用AG Grid Vue3时遇到响应式异常,以下是最简复现组件:
<script setup> import { reactive, ref } from "vue" import { AgGridVue } from "ag-grid-vue3" const data = reactive({ val: "test" }) const rowData = ref([data]) const colDefs = ref([ { field: "val", headerName: 'View' }, { field: "val", headerName: 'Edit', editable: true }, ]) </script> <template> <main> <ag-grid-vue :rowData="rowData" :columnDefs="colDefs" domLayout="autoHeight" /> <button @click="() => console.log('Val:', data.val)">Dump</button> <div> Val: <pre>{{ data.val }}</pre> <input v-model="data.val" /> </div> </main> </template>
组件中data是reactive声明的响应式对象,既作为行数据传入AG Grid,也在父组件模板中渲染。AG Grid的两列均绑定data.val,其中“Edit”列可编辑。
观察到的现象
- 初始状态下,编辑AG Grid的“Edit”列,值会同步到“View”列,但父组件中
data.val的渲染内容无变化 - 点击“Dump”按钮,控制台能打印出更新后的
data.val(证明数据实际已修改) - 在父组件输入框编辑
data.val后,后续无论通过AG Grid还是输入框修改,都会实现双向同步
通过setTimeout等非setup顶层方式修改值,也会出现相同现象。
已知用v-model:rowData替代:rowData可解决问题,但此处聚焦现象背后的原理,核心疑问:
- 既然
data是reactive响应式对象,为何AG Grid初始编辑无法触发父组件视图更新? - 为何父组件内编辑后,响应式关联会自动建立?
原理解析
1. 初始AG Grid编辑不触发父组件视图更新的原因
Vue 3的reactive基于Proxy实现,只有通过Proxy对象修改属性时,才会触发响应式依赖更新。而AG Grid Vue3组件在初始化处理rowData时,为了避免Vue响应式代理干扰自身内部逻辑,会调用toRaw方法获取原始对象(而非Proxy代理对象)。
当AG Grid编辑单元格时,直接修改的是原始对象的val属性,这个操作绕过了Vue的Proxy拦截:
- 由于
reactive的Proxy会实时读取原始对象的值,所以点击“Dump”按钮能拿到最新的data.val - 但修改操作未经过Proxy的setter,Vue的响应式系统无法检测到变化,因此父组件视图不会更新
- AG Grid自身的视图同步是基于内部的数据更新机制,与Vue响应式无关,所以“View”列会同步变化
2. 父组件编辑后响应式关联建立的原因
通过输入框v-model修改data.val时,操作是通过Vue的Proxy对象完成的:
v-model触发data.val = 新值,调用Proxy的setter,Vue立即通知所有依赖更新,触发父组件重新渲染- 组件重新渲染时,AG Grid会重新接收
rowDataprop,此时传递的是data的Proxy代理对象 - 后续AG Grid编辑单元格时,修改的是Proxy对象的
val属性,会触发Proxy的setter,Vue检测到变化后同步更新父组件视图,实现双向同步
总结
该现象本质是AG Grid Vue3组件对rowData的初始化处理逻辑,导致其初始拿到的是reactive对象的原始版本,绕过了Vue的响应式检测;而父组件的修改触发了组件重新渲染,AG Grid重新获取到Proxy对象,后续修改便会正常触发Vue的响应式更新。
内容的提问来源于stack exchange,提问作者bisgardo
相关产品推荐
相关产品推荐

