diff --git a/packages/amis-core/src/utils/helper.ts b/packages/amis-core/src/utils/helper.ts index 3565ca423..c5d3781ff 100644 --- a/packages/amis-core/src/utils/helper.ts +++ b/packages/amis-core/src/utils/helper.ts @@ -252,7 +252,7 @@ export function isObjectShallowModified( next: any, strictMode: boolean = true, ignoreUndefined: boolean = false, - statck: Array = [] + stack: Array = [] ): boolean { if (Array.isArray(prev) && Array.isArray(next)) { return prev.length !== next.length @@ -263,7 +263,7 @@ export function isObjectShallowModified( next[index], strictMode, ignoreUndefined, - statck + stack ) ); } @@ -277,8 +277,10 @@ export function isObjectShallowModified( null == next || !isObject(prev) || !isObject(next) || - isObservable(prev) || - isObservable(next) + // 不是 Object.create 创建的对象 + // 不是 plain object + prev.constructor !== Object || + next.constructor !== Object ) { return strictMode ? prev !== next : prev != next; } @@ -298,11 +300,11 @@ export function isObjectShallowModified( } // 避免循环引用死循环。 - if (~statck.indexOf(prev)) { + if (~stack.indexOf(prev)) { return false; } - statck.push(prev); + stack.push(prev); for (let i: number = keys.length - 1; i >= 0; i--) { const key = keys[i]; @@ -312,7 +314,7 @@ export function isObjectShallowModified( next[key], strictMode, ignoreUndefined, - statck + stack ) ) { return true; diff --git a/packages/amis-editor-core/src/store/node.ts b/packages/amis-editor-core/src/store/node.ts index c0314dfc6..fd1d26962 100644 --- a/packages/amis-editor-core/src/store/node.ts +++ b/packages/amis-editor-core/src/store/node.ts @@ -635,10 +635,6 @@ export const EditorNode = types let schema = root.getSchema(info.id); let patched = schema; - if (!patched?.id) { - patched = {...patched, id: 'u:' + guid()}; - } - if ( (Array.isArray(info.regions) && info.regions.length) || Array.isArray(info.patchContainers) @@ -662,9 +658,15 @@ export const EditorNode = types }, component?.props ) || patched; - patched = JSONPipeIn(patched); + if (patched !== schema) { - root.changeValueById(info.id, patched, undefined, true, true); + root.changeValueById( + info.id, + JSONPipeIn(patched), + undefined, + true, + true + ); } }, diff --git a/packages/amis-editor-core/src/util.ts b/packages/amis-editor-core/src/util.ts index f2094f848..1e131ce94 100644 --- a/packages/amis-editor-core/src/util.ts +++ b/packages/amis-editor-core/src/util.ts @@ -8,11 +8,11 @@ import {isExpression, resolveVariableAndFilter} from 'amis-core'; import type {VariableItem} from 'amis-ui'; import {isObservable, reaction} from 'mobx'; import DeepDiff, {Diff} from 'deep-diff'; -import assign from 'lodash/assign' -import cloneDeep from 'lodash/cloneDeep' -import isPlainObject from 'lodash/isPlainObject' -import isEqual from 'lodash/isEqual' -import isNumber from 'lodash/isNumber' +import assign from 'lodash/assign'; +import cloneDeep from 'lodash/cloneDeep'; +import isPlainObject from 'lodash/isPlainObject'; +import isEqual from 'lodash/isEqual'; +import isNumber from 'lodash/isNumber'; const { guid, @@ -70,13 +70,30 @@ export function cleanUndefined(obj: any) { * 给每个节点加个 $$id 这样方便编辑 * @param obj */ -export function JSONPipeIn(obj: any): any { - if (!isObject(obj) || obj.$$typeof) { - return obj; - } - +export function JSONPipeIn( + obj: any, + reGenerateId = false, + idMap: any = {} +): any { if (Array.isArray(obj)) { - return obj.map(JSONPipeIn); + let flag = false; // 有必要时才去改变对象的引用 + const ret = obj.map(item => { + const patched = JSONPipeIn(item, reGenerateId, idMap); + if (patched !== item) { + flag = true; + } + return patched; + }); + return flag ? ret : obj; + } else if (!isObject(obj) || obj.constructor !== Object) { + if (typeof obj === 'string') { + Object.keys(idMap).forEach(oldId => { + const newId = idMap[oldId]; + obj = obj.replaceAll(oldId, newId); + }); + } + + return obj; } let toUpdate: any = {}; @@ -95,35 +112,33 @@ export function JSONPipeIn(obj: any): any { // } // }); + if (obj.type) { + // 重新生成组件ID + if (reGenerateId) { + flag = true; + + /** 脚手架构建的Schema提前构建好了组件 ID,此时无需生成 ID,避免破坏事件动作 */ + if ( + (!obj.__origin || obj.__origin !== 'scaffold') && + (typeof obj.id !== 'string' || !obj.id || obj.id.startsWith('u:')) + ) { + const newId = generateNodeId(); + obj.id && (idMap[obj.id] = newId); + toUpdate.id = newId; + } + } else if (!obj.id) { + flag = true; + toUpdate.id = generateNodeId(); + } + } + Object.keys(obj).forEach(key => { - let prop = obj[key]; + let item = obj[key]; + let patched = JSONPipeIn(item, reGenerateId, idMap); - if (Array.isArray(prop)) { - // 如果没有修改过还是用原来的对象 - // 为了方便上层diff。 - let flag2 = false; - - let patched = prop.map((item: any) => { - let patched = JSONPipeIn(item); - - if (patched !== item) { - flag2 = true; - } - - return patched; - }); - - if (flag2) { - flag = true; - toUpdate[key] = patched; - } - } else { - let patched = JSONPipeIn(prop); - - if (patched !== prop) { - flag = true; - toUpdate[key] = patched; - } + if (patched !== item) { + flag = true; + toUpdate[key] = patched; } }); @@ -1094,7 +1109,10 @@ export function needFillPlaceholder(curProps: any) { } // 支持在plugin中配置 - return !!(curProps.$$editor?.needFillPlaceholder || curProps.regionConfig?.needFillPlaceholder); + return !!( + curProps.$$editor?.needFillPlaceholder || + curProps.regionConfig?.needFillPlaceholder + ); } // 设置主题数据 export function setThemeConfig(config: any) {