展开运算符仅是浅拷贝工具,不提供平移语义;所谓“平移式浅拷贝”指在保持坐标对象结构不变前提下,精准更新lng/lat等位移字段,复用其余不可变字段以避免无效重渲染。
展开运算符本身不提供“平移”语义,它只是浅拷贝工具;所谓对地图坐标对象的“平移式浅拷贝”,本质是:在保持原始坐标结构不变的前提下,仅对 x、y(或 lng、lat)等位移字段做增量更新,同时避免创建新引用导致不必要的重渲染。关键不在“展开”,而在“怎么展开+怎么改”。
地图坐标常以如下形式存在:
const origin = { lng: 116.4, lat: 39.9, zoom: 12, meta: { source: 'user', id: 'abc' } };
其中 lng/lat 是需平移的字段,meta 是只读元数据。直接 {...origin} 会复制整个对象,但 meta 内部引用未变——这没问题;真正要控制的是:只让 lng/lat 参与计算,其余字段原样复用。
即使你做了 {...origin, lng: ...},若父组件每次 render 都生成新对象,子地图组件(如 <MapMarker />)仍会收到新 props 引用而重绘。
React.memo 包裹接收坐标 props 的子组件,并确保其内部只依赖 lng/lat 值变化触发更新shallowRef,或使用 toRefs 解构后仅响应式追踪关键字段,避免整个对象被 proxy 拦截当需要批量平移多个点时,展开运算符可结合 map 使用,但注意避免双重浅拷贝:
const points = [ { lng: 116.4, lat: 39.9 }, { lng: 116.5, lat: 39.8 } ];
const shiftedPoints = points.map(p => ({ ...p, lng: p.lng + dx, lat: p.lat + dy }));
points 本身来自 props,且你频繁调用此 map,建议用 useMemo 缓存结果,避免每次渲染重建数组[...points].map(...) —— 数组浅拷贝无意义,纯属冗余开销