From b33c5a9fec36d3c9713315c377752eca20ce6627 Mon Sep 17 00:00:00 2001 From: zhongwu Date: Wed, 26 Jan 2022 10:57:46 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9Ediff=20data,?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B0=8F=E7=A8=8B=E5=BA=8FsetData=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/jsx2mp-runtime/src/component.js | 6 +- packages/jsx2mp-runtime/src/diff.js | 121 +++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 packages/jsx2mp-runtime/src/diff.js diff --git a/packages/jsx2mp-runtime/src/component.js b/packages/jsx2mp-runtime/src/component.js index eacc7946..c2c021d2 100644 --- a/packages/jsx2mp-runtime/src/component.js +++ b/packages/jsx2mp-runtime/src/component.js @@ -35,6 +35,7 @@ import { import apiCore from './adapter/getNativeAPI'; import attachRef from './adapter/attachRef'; import Event from './events'; +import { diffData } from './diff'; const event = new Event(); @@ -401,7 +402,10 @@ export default class Component { ); } else if (isDifferentData(currentData[key], data[key])) { if (isPlainObject(data[key])) { - normalData[key] = Object.assign({}, currentData[key], data[key]); + // normalData[key] = Object.assign({}, currentData[key], data[key]); + // find the different path from data and currentData + const patch = diffData({ [key]: data[key] }, { [key]: currentData[key] }); + Object.assign(normalData, patch); } else { normalData[key] = data[key] === undefined ? null : data[key]; // Make undefined value compatible with Alibaba MiniApp incase that data is not sync in render and worker thread } diff --git a/packages/jsx2mp-runtime/src/diff.js b/packages/jsx2mp-runtime/src/diff.js new file mode 100644 index 00000000..6560b26a --- /dev/null +++ b/packages/jsx2mp-runtime/src/diff.js @@ -0,0 +1,121 @@ +const ARRAYTYPE = "[object Array]"; +const OBJECTTYPE = "[object Object]"; +const FUNCTIONTYPE = "[object Function]"; + +export function diffData(current, previous) { + const result = {}; + if (!previous) return current; + syncKeys(current, previous); + _diff(current, previous, "", result); + return result; +} + +function syncKeys(current, previous) { + if (current === previous) return; + const rootCurrentType = getType(current); + const rootPreType = getType(previous); + if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) { + for (let key in previous) { + const currentValue = current[key]; + if (currentValue === undefined) { + current[key] = null; + } else { + syncKeys(currentValue, previous[key]); + } + } + } else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) { + if (current.length >= previous.length) { + previous.forEach((item, index) => { + syncKeys(current[index], item); + }); + } + } +} + +function _diff(current, previous, path, result) { + if (current === previous) return; + const rootCurrentType = getType(current); + const rootPreType = getType(previous); + if (rootCurrentType == OBJECTTYPE) { + if ( + rootPreType != OBJECTTYPE || + (Object.keys(current).length < Object.keys(previous).length && + path !== "") + ) { + setResult(result, path, current); + } else { + for (let key in current) { + const currentValue = current[key]; + const preValue = previous[key]; + const currentType = getType(currentValue); + const preType = getType(preValue); + if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) { + if (currentValue !== previous[key]) { + setResult(result, concatPathAndKey(path, key), currentValue); + } + } else if (currentType == ARRAYTYPE) { + if (preType != ARRAYTYPE) { + setResult(result, concatPathAndKey(path, key), currentValue); + } else { + if (currentValue.length < preValue.length) { + setResult(result, concatPathAndKey(path, key), currentValue); + } else { + currentValue.forEach((item, index) => { + _diff( + item, + preValue[index], + concatPathAndKey(path, key) + "[" + index + "]", + result + ); + }); + } + } + } else if (currentType == OBJECTTYPE) { + if ( + preType != OBJECTTYPE || + Object.keys(currentValue).length < Object.keys(preValue).length + ) { + setResult(result, concatPathAndKey(path, key), currentValue); + } else { + for (let subKey in currentValue) { + const realPath = + concatPathAndKey(path, key) + + (subKey.includes(".") ? `["${subKey}"]` : `.${subKey}`); + _diff(currentValue[subKey], preValue[subKey], realPath, result); + } + } + } + } + } + } else if (rootCurrentType == ARRAYTYPE) { + if (rootPreType != ARRAYTYPE) { + setResult(result, path, current); + } else { + if (current.length < previous.length) { + setResult(result, path, current); + } else { + current.forEach((item, index) => { + _diff(item, previous[index], path + "[" + index + "]", result); + }); + } + } + } else { + setResult(result, path, current); + } +} + +function concatPathAndKey(path, key) { + return key.includes(".") + ? path + `["${key}"]` + : (path == "" ? "" : path + ".") + key; +} + +function setResult(result, k, v) { + if (getType(v) != FUNCTIONTYPE) { + result[k] = v; + } +} + +function getType(obj) { + return Object.prototype.toString.call(obj); +} From efa12cff93f81b1d8c0de5d155194dcf490a7199 Mon Sep 17 00:00:00 2001 From: zhongwu Date: Thu, 27 Jan 2022 16:03:12 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9EdiffData=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/jsx2mp-runtime/.babelrc | 7 ++ packages/jsx2mp-runtime/package.json | 8 +- .../jsx2mp-runtime/src/__tests__/arrayDiff.js | 85 +++++++++++++++++++ .../src/__tests__/createStyle.js | 2 +- .../jsx2mp-runtime/src/__tests__/propsDiff.js | 80 +++++++++++++++++ 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 packages/jsx2mp-runtime/.babelrc create mode 100644 packages/jsx2mp-runtime/src/__tests__/arrayDiff.js create mode 100644 packages/jsx2mp-runtime/src/__tests__/propsDiff.js diff --git a/packages/jsx2mp-runtime/.babelrc b/packages/jsx2mp-runtime/.babelrc new file mode 100644 index 00000000..35146ac7 --- /dev/null +++ b/packages/jsx2mp-runtime/.babelrc @@ -0,0 +1,7 @@ +{ + "env": { + "test": { + "plugins": ["@babel/plugin-transform-modules-commonjs"] + } + } +} \ No newline at end of file diff --git a/packages/jsx2mp-runtime/package.json b/packages/jsx2mp-runtime/package.json index 1ecf3cd6..ef8520fc 100644 --- a/packages/jsx2mp-runtime/package.json +++ b/packages/jsx2mp-runtime/package.json @@ -8,20 +8,26 @@ ], "scripts": { "build": "cross-env NODE_ENV=production rollup -c rollup.config.js", - "prepublishOnly": "npm run build" + "prepublishOnly": "npm run build", + "test": "jest --coverage --testPathIgnorePatterns=__modules__" }, "author": "Rax Team", "devDependencies": { "@babel/core": "^7.4.5", "@babel/plugin-proposal-class-properties": "^7.5.5", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", "@babel/preset-env": "^7.4.5", "@babel/types": "^7.8.3", "cross-env": "^5.2.0", + "jest": "^27.4.7", "rollup": "^1.13.1", "rollup-plugin-babel": "^4.3.2", "rollup-plugin-cleanup": "^3.1.1", "rollup-plugin-filesize": "^6.1.0", "rollup-plugin-replace": "^2.2.0", "universal-env": "^3.0.0" + }, + "jest": { + "collectCoverage": true } } diff --git a/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js b/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js new file mode 100644 index 00000000..a5314346 --- /dev/null +++ b/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js @@ -0,0 +1,85 @@ +const { diffData } = require("../diff"); + +describe("Array diff", () => { + it("add item to array", () => { + expect( + diffData({ list: [{ a: 1 }, { a: 2 }] }, { list: [{ a: 1 }] }) + ).toStrictEqual({ + "list[1]": { a: 2 }, + }); + }); + + it("diff with null/undefined", () => { + expect(diffData({ list: [{ a: 1 }, { a: 2 }] }, null)).toStrictEqual({ + list: [{ a: 1 }, { a: 2 }], + }); + }); + + it("delete item from array", () => { + expect( + diffData({ list: [{ a: 1 }] }, { list: [{ a: 1 }, { a: 2 }] }) + ).toStrictEqual({ + list: [{ a: 1 }], + }); + }); + + it("modify item of array", () => { + expect(diffData({ list: [{ a: 1 }] }, { list: [{ a: 2 }] })).toStrictEqual({ + "list[0].a": 1, + }); + }); + + it("modify item of array", () => { + expect(diffData({ list: [{ a: 1 }] }, { list: [{ a: 2 }] })).toStrictEqual({ + "list[0].a": 1, + }); + }); + + it("modify item of array & update props", () => { + expect( + diffData({ list: [{ a: 1 }], a: 1 }, { list: [{ a: 2 }], a: 2 }) + ).toStrictEqual({ + "list[0].a": 1, + a: 1, + }); + }); + + it("complex ", () => { + expect( + diffData( + { + a: 1, + b: 2, + c: "str", + d: { e: [2, { a: 4 }, 5] }, + f: true, + h: [1], + g: { a: [1, 2], j: 111 }, + }, + { + a: [], + b: "aa", + c: 3, + d: { e: [3, { a: 3 }] }, + f: false, + h: [1, 2], + g: { a: [1, 1, 1], i: "delete" }, + k: "del", + } + ) + ).toStrictEqual({ + a: 1, + b: 2, + c: "str", + "d.e[0]": 2, + "d.e[1].a": 4, + "d.e[2]": 5, + f: true, + h: [1], + "g.a": [1, 2], + "g.j": 111, + "g.i": null, + k: null, + }); + }); +}); diff --git a/packages/jsx2mp-runtime/src/__tests__/createStyle.js b/packages/jsx2mp-runtime/src/__tests__/createStyle.js index 9b4a620b..041b12f1 100644 --- a/packages/jsx2mp-runtime/src/__tests__/createStyle.js +++ b/packages/jsx2mp-runtime/src/__tests__/createStyle.js @@ -1,4 +1,4 @@ -import createStyle from '../createStyle'; +const createStyle = require('../createStyle'); describe('Create style', () => { describe('Types', () => { diff --git a/packages/jsx2mp-runtime/src/__tests__/propsDiff.js b/packages/jsx2mp-runtime/src/__tests__/propsDiff.js new file mode 100644 index 00000000..379c2670 --- /dev/null +++ b/packages/jsx2mp-runtime/src/__tests__/propsDiff.js @@ -0,0 +1,80 @@ +const { diffData } = require("../diff"); + +describe("Props diff", () => { + it("same props", () => { + expect(diffData({ a: 1 }, { a: 1 })).toStrictEqual({}); + }); + + it("update props", () => { + expect(diffData({ a: 1 }, { a: 2 })).toStrictEqual({ + a: 1, + }); + }); + + it("delete props", () => { + expect(diffData({ a: 1 }, { a: 1, b: 2 })).toStrictEqual({ + b: null, + }); + }); + + it("add props", () => { + expect(diffData({ a: 1, b: 2 }, { a: 1 })).toStrictEqual({ + b: 2, + }); + }); + + it("update deep props", () => { + expect( + diffData( + { user: { name: "dnt", age: 18 } }, + { user: { name: "dnt", age: 20 } } + ) + ).toStrictEqual({ + "user.age": 18, + }); + }); + + it("update deep props", () => { + expect( + diffData( + { user: { name: "dnt2", age: 18 } }, + { user: { name: "dnt", age: 20 } } + ) + ).toStrictEqual({ + "user.age": 18, + "user.name": "dnt2", + }); + }); + + it("add deep props", () => { + expect( + diffData({ user: { name: "dnt", age: 18 } }, { user: { name: "dnt" } }) + ).toStrictEqual({ + "user.age": 18, + }); + }); + + it("add deep props", () => { + expect( + diffData( + { user: { name: "dnt", age: 18, sex: 1 } }, + { user: { name: "dnt" } } + ) + ).toStrictEqual({ + "user.age": 18, + "user.sex": 1, + }); + }); + + it("delete deep props", () => { + expect( + diffData( + { user: { name: "dnt" } }, + { user: { name: "dnt", age: 18, sex: 1 } } + ) + ).toStrictEqual({ + "user.age": null, + "user.sex": null, + }); + }); +}); From a17a98ce0acf7e23374779296d83c7bf8561ed96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=80=86=E8=91=B5?= Date: Mon, 7 Feb 2022 17:15:08 +0800 Subject: [PATCH 3/7] fix: lint error --- .../jsx2mp-runtime/src/__tests__/arrayDiff.js | 48 ++++++++-------- .../jsx2mp-runtime/src/__tests__/propsDiff.js | 56 +++++++++---------- packages/jsx2mp-runtime/src/diff.js | 22 ++++---- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js b/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js index a5314346..ba35a33c 100644 --- a/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js +++ b/packages/jsx2mp-runtime/src/__tests__/arrayDiff.js @@ -1,21 +1,21 @@ -const { diffData } = require("../diff"); +const { diffData } = require('../diff'); -describe("Array diff", () => { - it("add item to array", () => { +describe('Array diff', () => { + it('add item to array', () => { expect( diffData({ list: [{ a: 1 }, { a: 2 }] }, { list: [{ a: 1 }] }) ).toStrictEqual({ - "list[1]": { a: 2 }, + 'list[1]': { a: 2 }, }); }); - it("diff with null/undefined", () => { + it('diff with null/undefined', () => { expect(diffData({ list: [{ a: 1 }, { a: 2 }] }, null)).toStrictEqual({ list: [{ a: 1 }, { a: 2 }], }); }); - it("delete item from array", () => { + it('delete item from array', () => { expect( diffData({ list: [{ a: 1 }] }, { list: [{ a: 1 }, { a: 2 }] }) ).toStrictEqual({ @@ -23,34 +23,34 @@ describe("Array diff", () => { }); }); - it("modify item of array", () => { + it('modify item of array', () => { expect(diffData({ list: [{ a: 1 }] }, { list: [{ a: 2 }] })).toStrictEqual({ - "list[0].a": 1, + 'list[0].a': 1, }); }); - it("modify item of array", () => { + it('modify item of array', () => { expect(diffData({ list: [{ a: 1 }] }, { list: [{ a: 2 }] })).toStrictEqual({ - "list[0].a": 1, + 'list[0].a': 1, }); }); - it("modify item of array & update props", () => { + it('modify item of array & update props', () => { expect( diffData({ list: [{ a: 1 }], a: 1 }, { list: [{ a: 2 }], a: 2 }) ).toStrictEqual({ - "list[0].a": 1, + 'list[0].a': 1, a: 1, }); }); - it("complex ", () => { + it('complex ', () => { expect( diffData( { a: 1, b: 2, - c: "str", + c: 'str', d: { e: [2, { a: 4 }, 5] }, f: true, h: [1], @@ -58,27 +58,27 @@ describe("Array diff", () => { }, { a: [], - b: "aa", + b: 'aa', c: 3, d: { e: [3, { a: 3 }] }, f: false, h: [1, 2], - g: { a: [1, 1, 1], i: "delete" }, - k: "del", + g: { a: [1, 1, 1], i: 'delete' }, + k: 'del', } ) ).toStrictEqual({ a: 1, b: 2, - c: "str", - "d.e[0]": 2, - "d.e[1].a": 4, - "d.e[2]": 5, + c: 'str', + 'd.e[0]': 2, + 'd.e[1].a': 4, + 'd.e[2]': 5, f: true, h: [1], - "g.a": [1, 2], - "g.j": 111, - "g.i": null, + 'g.a': [1, 2], + 'g.j': 111, + 'g.i': null, k: null, }); }); diff --git a/packages/jsx2mp-runtime/src/__tests__/propsDiff.js b/packages/jsx2mp-runtime/src/__tests__/propsDiff.js index 379c2670..97a8e2b9 100644 --- a/packages/jsx2mp-runtime/src/__tests__/propsDiff.js +++ b/packages/jsx2mp-runtime/src/__tests__/propsDiff.js @@ -1,80 +1,80 @@ -const { diffData } = require("../diff"); +const { diffData } = require('../diff'); -describe("Props diff", () => { - it("same props", () => { +describe('Props diff', () => { + it('same props', () => { expect(diffData({ a: 1 }, { a: 1 })).toStrictEqual({}); }); - it("update props", () => { + it('update props', () => { expect(diffData({ a: 1 }, { a: 2 })).toStrictEqual({ a: 1, }); }); - it("delete props", () => { + it('delete props', () => { expect(diffData({ a: 1 }, { a: 1, b: 2 })).toStrictEqual({ b: null, }); }); - it("add props", () => { + it('add props', () => { expect(diffData({ a: 1, b: 2 }, { a: 1 })).toStrictEqual({ b: 2, }); }); - it("update deep props", () => { + it('update deep props', () => { expect( diffData( - { user: { name: "dnt", age: 18 } }, - { user: { name: "dnt", age: 20 } } + { user: { name: 'dnt', age: 18 } }, + { user: { name: 'dnt', age: 20 } } ) ).toStrictEqual({ - "user.age": 18, + 'user.age': 18, }); }); - it("update deep props", () => { + it('update deep props', () => { expect( diffData( - { user: { name: "dnt2", age: 18 } }, - { user: { name: "dnt", age: 20 } } + { user: { name: 'dnt2', age: 18 } }, + { user: { name: 'dnt', age: 20 } } ) ).toStrictEqual({ - "user.age": 18, - "user.name": "dnt2", + 'user.age': 18, + 'user.name': 'dnt2', }); }); - it("add deep props", () => { + it('add deep props', () => { expect( - diffData({ user: { name: "dnt", age: 18 } }, { user: { name: "dnt" } }) + diffData({ user: { name: 'dnt', age: 18 } }, { user: { name: 'dnt' } }) ).toStrictEqual({ - "user.age": 18, + 'user.age': 18, }); }); - it("add deep props", () => { + it('add deep props', () => { expect( diffData( - { user: { name: "dnt", age: 18, sex: 1 } }, - { user: { name: "dnt" } } + { user: { name: 'dnt', age: 18, sex: 1 } }, + { user: { name: 'dnt' } } ) ).toStrictEqual({ - "user.age": 18, - "user.sex": 1, + 'user.age': 18, + 'user.sex': 1, }); }); - it("delete deep props", () => { + it('delete deep props', () => { expect( diffData( - { user: { name: "dnt" } }, - { user: { name: "dnt", age: 18, sex: 1 } } + { user: { name: 'dnt' } }, + { user: { name: 'dnt', age: 18, sex: 1 } } ) ).toStrictEqual({ - "user.age": null, - "user.sex": null, + 'user.age': null, + 'user.sex': null, }); }); }); diff --git a/packages/jsx2mp-runtime/src/diff.js b/packages/jsx2mp-runtime/src/diff.js index 6560b26a..aa03093a 100644 --- a/packages/jsx2mp-runtime/src/diff.js +++ b/packages/jsx2mp-runtime/src/diff.js @@ -1,12 +1,12 @@ -const ARRAYTYPE = "[object Array]"; -const OBJECTTYPE = "[object Object]"; -const FUNCTIONTYPE = "[object Function]"; +const ARRAYTYPE = '[object Array]'; +const OBJECTTYPE = '[object Object]'; +const FUNCTIONTYPE = '[object Function]'; export function diffData(current, previous) { const result = {}; if (!previous) return current; syncKeys(current, previous); - _diff(current, previous, "", result); + _diff(current, previous, '', result); return result; } @@ -39,8 +39,8 @@ function _diff(current, previous, path, result) { if (rootCurrentType == OBJECTTYPE) { if ( rootPreType != OBJECTTYPE || - (Object.keys(current).length < Object.keys(previous).length && - path !== "") + Object.keys(current).length < Object.keys(previous).length && + path !== '' ) { setResult(result, path, current); } else { @@ -64,7 +64,7 @@ function _diff(current, previous, path, result) { _diff( item, preValue[index], - concatPathAndKey(path, key) + "[" + index + "]", + concatPathAndKey(path, key) + '[' + index + ']', result ); }); @@ -80,7 +80,7 @@ function _diff(current, previous, path, result) { for (let subKey in currentValue) { const realPath = concatPathAndKey(path, key) + - (subKey.includes(".") ? `["${subKey}"]` : `.${subKey}`); + (subKey.includes('.') ? `["${subKey}"]` : `.${subKey}`); _diff(currentValue[subKey], preValue[subKey], realPath, result); } } @@ -95,7 +95,7 @@ function _diff(current, previous, path, result) { setResult(result, path, current); } else { current.forEach((item, index) => { - _diff(item, previous[index], path + "[" + index + "]", result); + _diff(item, previous[index], path + '[' + index + ']', result); }); } } @@ -105,9 +105,9 @@ function _diff(current, previous, path, result) { } function concatPathAndKey(path, key) { - return key.includes(".") + return key.includes('.') ? path + `["${key}"]` - : (path == "" ? "" : path + ".") + key; + : (path == '' ? '' : path + '.') + key; } function setResult(result, k, v) { From a99fe9fff6d4ca16377691c8515837d75013067c Mon Sep 17 00:00:00 2001 From: zhongwu Date: Tue, 8 Feb 2022 18:50:11 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E5=85=9C=E5=BA=95?= =?UTF-8?q?=E6=96=B9=E6=A1=88,=E5=BC=82=E5=B8=B8=E6=97=B6=E8=B5=B0?= =?UTF-8?q?=E5=8E=9F=E6=9C=89=E9=9D=9Ediff=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/jsx2mp-runtime/src/component.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/jsx2mp-runtime/src/component.js b/packages/jsx2mp-runtime/src/component.js index c2c021d2..d8885811 100644 --- a/packages/jsx2mp-runtime/src/component.js +++ b/packages/jsx2mp-runtime/src/component.js @@ -404,8 +404,12 @@ export default class Component { if (isPlainObject(data[key])) { // normalData[key] = Object.assign({}, currentData[key], data[key]); // find the different path from data and currentData - const patch = diffData({ [key]: data[key] }, { [key]: currentData[key] }); - Object.assign(normalData, patch); + try { + const patch = diffData({ [key]: data[key] }, { [key]: currentData[key] }); + Object.assign(normalData, patch); + } catch (err) { + normalData[key] = Object.assign({}, currentData[key], data[key]); + } } else { normalData[key] = data[key] === undefined ? null : data[key]; // Make undefined value compatible with Alibaba MiniApp incase that data is not sync in render and worker thread } From f551fa9787b2960fc1650a4a3ae30808c805f817 Mon Sep 17 00:00:00 2001 From: zhongwu Date: Tue, 8 Feb 2022 18:51:57 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:diff=E6=97=B6=E6=B5=85=E6=8B=B7?= =?UTF-8?q?=E8=B4=9DsetData=E4=BC=A0=E5=85=A5=E7=9A=84=E6=95=B0=E6=8D=AE,?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=9C=A8=E5=A4=96=E9=83=A8=E8=A2=AB=E9=94=81?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/jsx2mp-runtime/src/diff.js | 57 +++++++++++++---------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/packages/jsx2mp-runtime/src/diff.js b/packages/jsx2mp-runtime/src/diff.js index 6560b26a..de99381f 100644 --- a/packages/jsx2mp-runtime/src/diff.js +++ b/packages/jsx2mp-runtime/src/diff.js @@ -5,47 +5,33 @@ const FUNCTIONTYPE = "[object Function]"; export function diffData(current, previous) { const result = {}; if (!previous) return current; - syncKeys(current, previous); _diff(current, previous, "", result); return result; } -function syncKeys(current, previous) { - if (current === previous) return; - const rootCurrentType = getType(current); - const rootPreType = getType(previous); - if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) { - for (let key in previous) { - const currentValue = current[key]; - if (currentValue === undefined) { - current[key] = null; - } else { - syncKeys(currentValue, previous[key]); - } - } - } else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) { - if (current.length >= previous.length) { - previous.forEach((item, index) => { - syncKeys(current[index], item); - }); - } - } -} - function _diff(current, previous, path, result) { if (current === previous) return; const rootCurrentType = getType(current); const rootPreType = getType(previous); if (rootCurrentType == OBJECTTYPE) { + const $current = { ...current }; + if (rootPreType === OBJECTTYPE) { + for (let key in previous) { + const currentValue = $current[key]; + if (currentValue === undefined) { + $current[key] = null; + } + } + } if ( rootPreType != OBJECTTYPE || - (Object.keys(current).length < Object.keys(previous).length && + (Object.keys($current).length < Object.keys(previous).length && path !== "") ) { - setResult(result, path, current); + setResult(result, path, $current); } else { - for (let key in current) { - const currentValue = current[key]; + for (let key in $current) { + const currentValue = $current[key]; const preValue = previous[key]; const currentType = getType(currentValue); const preType = getType(preValue); @@ -71,17 +57,26 @@ function _diff(current, previous, path, result) { } } } else if (currentType == OBJECTTYPE) { + const $currentValue = { ...currentValue }; + if (preType === OBJECTTYPE) { + for (let key in preValue) { + const currentItem = $currentValue[key]; + if (currentItem === undefined) { + $currentValue[key] = null; + } + } + } if ( preType != OBJECTTYPE || - Object.keys(currentValue).length < Object.keys(preValue).length + Object.keys($currentValue).length < Object.keys(preValue).length ) { - setResult(result, concatPathAndKey(path, key), currentValue); + setResult(result, concatPathAndKey(path, key), $currentValue); } else { - for (let subKey in currentValue) { + for (let subKey in $currentValue) { const realPath = concatPathAndKey(path, key) + (subKey.includes(".") ? `["${subKey}"]` : `.${subKey}`); - _diff(currentValue[subKey], preValue[subKey], realPath, result); + _diff($currentValue[subKey], preValue[subKey], realPath, result); } } } From adb963a33e34ada5711a8d57b2f454ee1ee35151 Mon Sep 17 00:00:00 2001 From: zhongwu Date: Thu, 10 Feb 2022 11:42:13 +0800 Subject: [PATCH 6/7] feat:lint --- packages/jsx2mp-runtime/src/diff.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/jsx2mp-runtime/src/diff.js b/packages/jsx2mp-runtime/src/diff.js index de99381f..629e2bcf 100644 --- a/packages/jsx2mp-runtime/src/diff.js +++ b/packages/jsx2mp-runtime/src/diff.js @@ -1,11 +1,11 @@ -const ARRAYTYPE = "[object Array]"; -const OBJECTTYPE = "[object Object]"; -const FUNCTIONTYPE = "[object Function]"; +const ARRAYTYPE = '[object Array]'; +const OBJECTTYPE = '[object Object]'; +const FUNCTIONTYPE = '[object Function]'; export function diffData(current, previous) { const result = {}; if (!previous) return current; - _diff(current, previous, "", result); + _diff(current, previous, '', result); return result; } @@ -26,7 +26,7 @@ function _diff(current, previous, path, result) { if ( rootPreType != OBJECTTYPE || (Object.keys($current).length < Object.keys(previous).length && - path !== "") + path !== '') ) { setResult(result, path, $current); } else { @@ -50,7 +50,7 @@ function _diff(current, previous, path, result) { _diff( item, preValue[index], - concatPathAndKey(path, key) + "[" + index + "]", + concatPathAndKey(path, key) + '[' + index + ']', result ); }); @@ -75,7 +75,7 @@ function _diff(current, previous, path, result) { for (let subKey in $currentValue) { const realPath = concatPathAndKey(path, key) + - (subKey.includes(".") ? `["${subKey}"]` : `.${subKey}`); + (subKey.includes('.') ? `['${subKey}']` : `.${subKey}`); _diff($currentValue[subKey], preValue[subKey], realPath, result); } } @@ -90,7 +90,7 @@ function _diff(current, previous, path, result) { setResult(result, path, current); } else { current.forEach((item, index) => { - _diff(item, previous[index], path + "[" + index + "]", result); + _diff(item, previous[index], path + '[' + index + ']', result); }); } } @@ -100,9 +100,9 @@ function _diff(current, previous, path, result) { } function concatPathAndKey(path, key) { - return key.includes(".") - ? path + `["${key}"]` - : (path == "" ? "" : path + ".") + key; + return key.includes('.') + ? path + `['${key}']` + : (path == '' ? '' : path + '.') + key; } function setResult(result, k, v) { From 18bae4513d447bd419ea8a9db98ee843917c5efc Mon Sep 17 00:00:00 2001 From: zhongwu Date: Thu, 17 Feb 2022 13:53:24 +0800 Subject: [PATCH 7/7] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9isAppendArray?= =?UTF-8?q?=E7=9A=84=E5=AF=B9=E6=AF=94=E7=94=B1shadowEqual=E6=94=B9?= =?UTF-8?q?=E4=B8=BAdiff=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/jsx2mp-runtime/src/component.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jsx2mp-runtime/src/component.js b/packages/jsx2mp-runtime/src/component.js index d8885811..738dcb6f 100644 --- a/packages/jsx2mp-runtime/src/component.js +++ b/packages/jsx2mp-runtime/src/component.js @@ -494,8 +494,8 @@ function isAppendArray(prev, next) { // Only concern about list append case if (next.length === 0) return false; if (prev.length === 0) return true; - // When item's type is object, they have differrent reference, so should use shallowEqual - return next.length > prev.length && next.slice(0, prev.length).every((val, index) => shallowEqual(prev[index], val)); + // Use diffData replace shallowEqual + return next.length > prev.length && next.slice(0, prev.length).every((val, index) => Object.keys(diffData(prev[index], val)).length===0); } function isDifferentData(prevData, nextData) {