Match-id-8475cbc5c1b5d58f5e0dbbeb95e0267d2ce277e1
This commit is contained in:
commit
886237cfb7
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
jsxSingleQuote: false, // 在JSX中使用双引号
|
||||
trailingComma: 'es5', // 使用尾逗号(对象、数组等)
|
||||
bracketSpacing: true, // 对象的括号间增加空格
|
||||
jsxBracketSameLine: false, // 将多行JSX元素的>放在最后一行的末尾
|
||||
bracketSameLine: false, // 将多行JSX元素的>放在最后一行的末尾
|
||||
arrowParens: 'avoid', // 在唯一的arrow函数参数周围省略括号
|
||||
vueIndentScriptAndStyle: false, // 不缩进Vue文件中的<script>和<style>标记内的代码
|
||||
endOfLine: 'lf', // 仅限换行(\n)
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions"
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-modules-commonjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,6 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
],
|
||||
plugins: [
|
||||
/* eslint-disable-next-line global-require */
|
||||
[require('./dist/index.js')],
|
||||
],
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
};
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
module.exports = {
|
||||
transform: {
|
||||
'\\.(ts|tsx)$': 'ts-jest',
|
||||
},
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
babelConfig: true,
|
||||
},
|
||||
},
|
||||
'\\.(js|jsx|ts|tsx)$': 'babel-jest',
|
||||
}
|
||||
};
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/types": "^7.0.0",
|
||||
"babel-plugin-tester": "^10.1.0",
|
||||
"ts-jest": "^26.1.3"
|
||||
"babel-plugin-tester": "^10.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,39 @@ import SyntaxJSX from '@babel/plugin-syntax-jsx';
|
|||
import * as BabelCore from '@babel/core';
|
||||
import * as t from '@babel/types';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { JSXIdentifier, JSXMemberExpression, JSXNamespacedName } from '@babel/types';
|
||||
|
||||
function isHTMLTag(tagName: string) {
|
||||
return tagName && /^[a-z]/.test(tagName);
|
||||
}
|
||||
|
||||
const horizonJsx = t.memberExpression(t.identifier('Horizon'), t.identifier('jsx'));
|
||||
|
||||
function getTagNodeName(tagNode: JSXIdentifier | JSXMemberExpression | JSXNamespacedName) {
|
||||
let tagName;
|
||||
if (t.isJSXNamespacedName(tagNode)) {
|
||||
throw 'horizon jsx doesn\'t support JSX namespace: ' + tagNode;
|
||||
} else if (t.isJSXIdentifier(tagNode)) {
|
||||
/*
|
||||
this -> thisExpression
|
||||
HTML -> stringLiteral
|
||||
Others -> Identifier
|
||||
*/
|
||||
tagName = tagNode.name === 'this' ?
|
||||
t.thisExpression() : isHTMLTag(tagNode.name) ?
|
||||
t.stringLiteral(tagNode.name) :
|
||||
t.identifier(tagNode.name);
|
||||
} else if (t.isJSXMemberExpression(tagNode)) {
|
||||
tagName = t.memberExpression(
|
||||
getTagNodeName(tagNode.object),
|
||||
getTagNodeName(tagNode.property),
|
||||
);
|
||||
}
|
||||
return tagName;
|
||||
}
|
||||
|
||||
export default ({ types }: typeof BabelCore) => {
|
||||
|
||||
return {
|
||||
name: 'horizon-jsx-babel-plugin',
|
||||
inherits: SyntaxJSX,
|
||||
|
@ -14,12 +45,13 @@ export default ({types}: typeof BabelCore) => {
|
|||
},
|
||||
|
||||
JSXElement: {
|
||||
exit(path) {
|
||||
|
||||
exit(path: NodePath<t.JSXElement>) {
|
||||
const openingElement = path.get('openingElement');
|
||||
const tagName = getTagNodeName(openingElement.node.name);
|
||||
path.replaceWith(t.callExpression(horizonJsx, [tagName]));
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
var x = <div></div>;
|
||||
var y = <Eview.Table></Eview.Table>;
|
||||
var z = <this></this>;
|
|
@ -0,0 +1,3 @@
|
|||
var x = Horizon.jsx('div');
|
||||
var y = Horizon.jsx(Eview.Table);
|
||||
var z = Horizon.jsx(this);
|
|
@ -0,0 +1 @@
|
|||
<div className="123"></div>
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
|
@ -44,7 +44,7 @@ function buildElement(isClone, type, setting, children) {
|
|||
const props = isClone ? { ...type.props } : {};
|
||||
let vNode = isClone ? type.belongClassVNode : getProcessingClassVNode();
|
||||
|
||||
if (setting !== null) {
|
||||
if (setting !== null && setting !== undefined) {
|
||||
const keys = Object.keys(setting);
|
||||
const keyLength = keys.length;
|
||||
for (let i = 0; i < keyLength; i++) {
|
||||
|
@ -81,5 +81,5 @@ export function cloneElement(element, setting, ...children) {
|
|||
|
||||
// 检测结构体是否为合法的Element
|
||||
export function isValidElement(element) {
|
||||
return (element && element.vtype === TYPE_COMMON_ELEMENT);
|
||||
return !!(element && element.vtype === TYPE_COMMON_ELEMENT);
|
||||
}
|
||||
|
|
|
@ -196,11 +196,11 @@ export function calcStartUpdateVNode(treeRoot: VNode) {
|
|||
}
|
||||
}
|
||||
// 得到相等的路径
|
||||
let startNodePath = toUpdateNodes[0].path.slice(0, idx);
|
||||
const startNodePath = toUpdateNodes[0].path.slice(0, idx);
|
||||
|
||||
let node = treeRoot;
|
||||
for (let i = 1; i < startNodePath.length; i++) {
|
||||
let pathIndex = startNodePath[i];
|
||||
const pathIndex = Number(startNodePath[i]);
|
||||
node = getChildByIndex(node, pathIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,13 @@ import type { VNode } from '../Types';
|
|||
import { FlagUtils } from '../vnode/VNodeFlags';
|
||||
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType';
|
||||
import { DomText, DomPortal, Fragment, DomComponent } from '../vnode/VNodeTags';
|
||||
import {updateVNode, createVNodeFromElement, createFragmentVNode, createPortalVNode, createDomTextVNode} from '../vnode/VNodeCreator';
|
||||
import {
|
||||
updateVNode,
|
||||
createVNodeFromElement,
|
||||
createFragmentVNode,
|
||||
createPortalVNode,
|
||||
createDomTextVNode,
|
||||
} from '../vnode/VNodeCreator';
|
||||
import {
|
||||
isSameType,
|
||||
getIteratorFn,
|
||||
|
@ -112,7 +118,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
|||
return null;
|
||||
}
|
||||
|
||||
let resultNode = null;
|
||||
let resultNode: VNode | null = null;
|
||||
switch (newNodeType) {
|
||||
case DiffCategory.TEXT_NODE: {
|
||||
if (oldNode === null || oldNode.tag !== DomText) {
|
||||
|
@ -172,9 +178,9 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
|||
}
|
||||
|
||||
function transRightChildrenToArray(child) {
|
||||
const rightChildrenArray = [];
|
||||
const rightChildrenArray: VNode[] = [];
|
||||
|
||||
travelChildren(child, (node) => {
|
||||
travelChildren(child, node => {
|
||||
rightChildrenArray.push(node);
|
||||
});
|
||||
|
||||
|
@ -183,11 +189,11 @@ function transRightChildrenToArray(child) {
|
|||
|
||||
function transLeftChildrenToMap(
|
||||
startChild: VNode,
|
||||
rightEndVNode: VNode | null
|
||||
rightEndVNode: VNode | null,
|
||||
): Map<string | number, VNode> {
|
||||
const leftChildrenMap: Map<string | number, VNode> = new Map();
|
||||
|
||||
travelChildren(startChild, (node) => {
|
||||
travelChildren(startChild, node => {
|
||||
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
|
||||
}, node => node === rightEndVNode);
|
||||
|
||||
|
@ -221,18 +227,21 @@ function diffArrayNodesHandler(
|
|||
let prevNewNode: VNode | null = null;
|
||||
|
||||
let oldNode = firstChild;
|
||||
let nextOldNode = null;
|
||||
let nextOldNode: VNode | null = null;
|
||||
|
||||
let theLastPosition = 0;
|
||||
// 从左边开始的位置
|
||||
let leftIdx = 0;
|
||||
|
||||
function appendNode(newNode) {
|
||||
function appendNode(newNode: VNode) {
|
||||
if (prevNewNode === null) {
|
||||
resultingFirstChild = newNode;
|
||||
newNode.cIndex = 0;
|
||||
} else {
|
||||
prevNewNode.next = newNode;
|
||||
newNode.cIndex = prevNewNode.cIndex + 1;
|
||||
}
|
||||
newNode.path = newNode.parent.path + newNode.cIndex;
|
||||
prevNewNode = newNode;
|
||||
}
|
||||
|
||||
|
@ -269,15 +278,13 @@ function diffArrayNodesHandler(
|
|||
|
||||
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
||||
newNode.eIndex = leftIdx;
|
||||
newNode.cIndex = leftIdx;
|
||||
newNode.path = newNode.parent.path + newNode.cIndex;
|
||||
appendNode(newNode);
|
||||
oldNode = nextOldNode;
|
||||
}
|
||||
|
||||
let rightIdx = newChildren.length;
|
||||
let rightEndOldNode; // 老节点中最右边匹配的节点引用 abcde --> abfde 则rightEndOldNode = c;
|
||||
let rightNewNode = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
|
||||
let rightNewNode: VNode | null = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
|
||||
// 从后往前,新资源的位置还没有到最末端,旧的vNode也还没遍历完,则可以考虑从后往前开始
|
||||
if (rightIdx > leftIdx && oldNode !== null) {
|
||||
const rightRemainingOldChildren = transRightChildrenToArray(oldNode);
|
||||
|
@ -347,7 +354,9 @@ function diffArrayNodesHandler(
|
|||
let isDirectAdd = false;
|
||||
// TODO: 是否可以扩大至非dom类型节点
|
||||
// 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点
|
||||
if (parentNode.tag === DomComponent && parentNode.oldProps?.children?.length === 0 && rightIdx - leftIdx === newChildren.length) {
|
||||
if (parentNode.tag === DomComponent &&
|
||||
parentNode.oldProps?.children?.length === 0 &&
|
||||
rightIdx - leftIdx === newChildren.length) {
|
||||
isDirectAdd = true;
|
||||
}
|
||||
for (; leftIdx < rightIdx; leftIdx++) {
|
||||
|
@ -367,7 +376,7 @@ function diffArrayNodesHandler(
|
|||
|
||||
if (rightNewNode) {
|
||||
appendNode(rightNewNode);
|
||||
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
||||
setVNodesCIndex(rightNewNode.next, rightNewNode.cIndex + 1);
|
||||
}
|
||||
|
||||
return resultingFirstChild;
|
||||
|
@ -380,7 +389,7 @@ function diffArrayNodesHandler(
|
|||
const eIndexes: Array<number> = []; // 记录 eIndex 值
|
||||
const result: Array<number> = []; // 记录最长子序列在eIndexes中的 index 值
|
||||
const preIndex: Array<number> = []; // 贪心算法在替换的过程中会使得数组不正确,通过记录preIndex找到正确值
|
||||
const reuseNodes = []; // 记录复用的 VNode
|
||||
const reuseNodes: (VNode | null)[] = []; // 记录复用的 VNode
|
||||
let i = 0;
|
||||
let oldNodeFromMap;
|
||||
let last;
|
||||
|
@ -394,7 +403,7 @@ function diffArrayNodesHandler(
|
|||
}
|
||||
|
||||
if (oldNodeFromMap !== null) {
|
||||
let eIndex = newNode.eIndex;
|
||||
const eIndex = newNode.eIndex;
|
||||
eIndexes.push(eIndex);
|
||||
last = eIndexes[result[result.length - 1]];
|
||||
if (eIndex > last || last === undefined) { // 大的 eIndex直接放在最后
|
||||
|
@ -455,15 +464,15 @@ function diffArrayNodesHandler(
|
|||
|
||||
if (rightNewNode) {
|
||||
appendNode(rightNewNode);
|
||||
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
||||
setVNodesCIndex(rightNewNode.next, rightNewNode.cIndex + 1);
|
||||
}
|
||||
|
||||
return resultingFirstChild;
|
||||
}
|
||||
|
||||
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
||||
function setVNodesCIndex(startChild: VNode, startIdx: number) {
|
||||
let node = startChild;
|
||||
function setVNodesCIndex(startChild: VNode | null, startIdx: number) {
|
||||
let node: VNode | null = startChild;
|
||||
let idx = startIdx;
|
||||
|
||||
while (node !== null) {
|
||||
|
|
|
@ -187,6 +187,33 @@ export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
|
|||
return processing.child;
|
||||
}
|
||||
|
||||
// 当跳过子树更新时,父节点path更新时,需要更新所有子树path
|
||||
if (processing.child && processing.path !== processing.child.path.slice(0, processing.path.length)) {
|
||||
// bfs更新子树path
|
||||
const queue: VNode[] = [];
|
||||
|
||||
const putChildrenIntoQueue = (vNode: VNode) => {
|
||||
const child = vNode.child;
|
||||
if (child) {
|
||||
queue.push(child);
|
||||
let sibling = child.next;
|
||||
while (sibling) {
|
||||
queue.push(sibling);
|
||||
sibling = sibling.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
putChildrenIntoQueue(processing.child);
|
||||
|
||||
while (queue.length) {
|
||||
const vNode = queue.shift()!;
|
||||
|
||||
vNode.path = vNode.parent.path + vNode.cIndex;
|
||||
|
||||
putChildrenIntoQueue(vNode)
|
||||
}
|
||||
}
|
||||
// 子树无需工作
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"scripts": {
|
||||
"build": " webpack --config ./scripts/webpack/webpack.config.js",
|
||||
"build-3rdLib": "node ./scripts/gen3rdLib.js",
|
||||
"build-3rdLib-dev": "node ./scripts/gen3rdLib.js --dev",
|
||||
"build-3rdLib-dev": "npm run build & node ./scripts/gen3rdLib.js --dev",
|
||||
"debug-test": "yarn test --debug",
|
||||
"test": "jest --config=jest.config.js",
|
||||
"watch-test": "yarn test --watch --dev"
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
"prefer-object-spread": true,
|
||||
"typeof-compare": true,
|
||||
"cyclomatic-complexity": [true, 20],
|
||||
"max-file-line-count": [true, 500],
|
||||
"prefer-readonly": true,
|
||||
"prefer-const": true,
|
||||
"radix": true,
|
||||
|
|
Loading…
Reference in New Issue