直接赋值失效是因为列配置是引用对象,浅拷贝导致多处修改互相影响;正确做法是结构化克隆,兼容方案为JSON.parse(JSON.stringify())并手动处理函数等不可序列化字段。
复制列定义时为什么 field 对象直接赋值会失效
因为多数可视化工具(如 ant design pro 的 protable、echarts 配置、lowcode 平台字段区)里的列配置是引用对象,直接 const newcol = oldcol 只拷贝了引用,后续任意一处修改都会影响所有复用位置。
- 真实场景:你在「用户列表」和「导出预览」两个地方用了同一套列定义,结果改了导出列的
render,用户列表也跟着变了 - 根本原因:列配置中常含函数(
render、valueType)、闭包变量或响应式依赖,浅拷贝无法隔离行为 - 正确做法是结构化克隆——但不是所有环境都支持
structuredClone(比如旧版 Chrome 或某些 Electron 内核)
用 JSON.parse(JSON.stringify()) 复制列定义的边界条件
这是最常用、兼容性最好的“伪深拷贝”方式,但它只适用于纯 JSON 可序列化的字段结构。
- 能安全复制:字符串、数字、布尔、
null、普通对象、数组、嵌套title/dataIndex/width等配置项 - 会丢失:函数(
render、onCell)、正则、Date、undefined、循环引用、Map/Set - 典型报错:
TypeError: Converting circular structure to JSON(遇到带ref或父子引用的列配置时) - 建议搭配判断使用:
if (typeof col.render === 'function') { newCol.render = col.render; }
在 ProTable 里复用列定义的实操要点
ProTable 的列数组本质是 React 组件属性,复用时需注意生命周期和闭包变量绑定问题。
- 别在组件顶层直接导出列数组(如
export const userColumns = [...]),否则所有实例共享同一个render闭包,状态互相污染 - 应该封装为函数:
export const getUserColumns = (extraProps = {}) => [...],每次调用生成新对象 - 如果列中用了
useMemo或useCallback,必须确保依赖数组准确,否则复用后render拿不到最新props - 注意
search相关字段(如hideInSearch):同一套列定义在不同页面可能需要差异化控制,别硬编码
低代码平台中“复制字段结构”按钮背后的逻辑差异
不同平台对“复制列”的理解完全不同,不能假设行为一致。
- 部分平台(如宜搭、简道云)点击“复制字段”仅复制元数据(
dataIndex、类型、校验规则),不复制 UI 层配置(render、宽度、排序) - 另一些平台(如内部搭建的 LowCode 引擎)会把整个
column对象做lodash.cloneDeep,但若字段含自定义组件,则可能因未注册而渲染为空 - 关键检查点:复制后看
console.log(newColumn),确认render是函数还是undefined;再查 DOM 是否出现React.createElement: type is invalid - 稳妥策略:把可复用的部分(
title、dataIndex、valueType、search配置)抽成基础 schema,UI 层单独组合










