Skip to content

Commit 2cad51f

Browse files
author
古映杰
committed
optimize virtual-dom
1 parent d38a392 commit 2cad51f

9 files changed

Lines changed: 228 additions & 409 deletions

File tree

dist/react-lite.common.js

Lines changed: 71 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,6 @@ var xlink = 'http://www.w3.org/1999/xlink';
1010
var xml = 'http://www.w3.org/XML/1998/namespace';
1111

1212
var SVGNamespaceURI = 'http://www.w3.org/2000/svg';
13-
14-
var VNODE_TYPE = {
15-
ELEMENT: 1,
16-
COMPONENT: 2,
17-
STATELESS_COMPONENT: 3,
18-
TEXT: 4
19-
};
20-
var DIFF_TYPE = {
21-
CREATE: 1,
22-
REMOVE: 2,
23-
REPLACE: 3,
24-
UPDATE: 4
25-
};
26-
2713
var COMPONENT_ID = 'liteid';
2814

2915
var propAlias = {
@@ -313,23 +299,6 @@ var notBubbleEvents = {
313299
oncontextmenu: TRUE
314300
};
315301

316-
var diff = function diff(vnode, newVnode) {
317-
if (vnode === newVnode) {
318-
return;
319-
} else if (newVnode === undefined) {
320-
return DIFF_TYPE.REMOVE;
321-
} else if (vnode === undefined) {
322-
return DIFF_TYPE.CREATE;
323-
} else if (vnode.type !== newVnode.type) {
324-
return DIFF_TYPE.REPLACE;
325-
} else if (newVnode.key !== null) {
326-
return vnode.key === null || newVnode.key !== vnode.key ? DIFF_TYPE.REPLACE : DIFF_TYPE.UPDATE;
327-
} else if (vnode.key !== null) {
328-
return DIFF_TYPE.REPLACE;
329-
}
330-
return DIFF_TYPE.UPDATE;
331-
};
332-
333302
var isType = function isType(type) {
334303
return function (obj) {
335304
return obj != null && Object.prototype.toString.call(obj) === '[object ' + type + ']';
@@ -656,46 +625,36 @@ if (!Object.freeze) {
656625
var noop$1 = noop;
657626
var refs = null;
658627

659-
var createVtext = function createVtext(text) {
660-
return {
661-
vtype: VNODE_TYPE.TEXT,
662-
text: text,
663-
init: initVtext,
664-
update: updateVtext,
665-
destroy: destroyVtext
666-
};
667-
};
628+
function Vtext(text) {
629+
this.text = text;
630+
}
668631

669-
var initVtext = function initVtext(parentNode) {
632+
var VtextPrototype = Vtext.prototype;
633+
VtextPrototype.isVdom = true;
634+
VtextPrototype.init = function (parentNode) {
670635
var textNode = document.createTextNode(this.text);
671636
appendNode(parentNode, textNode);
672637
return textNode;
673638
};
674-
675-
var updateVtext = function updateVtext(newVtext, textNode) {
639+
VtextPrototype.update = function (newVtext, textNode) {
676640
if (newVtext.text !== this.text) {
677641
textNode.replaceData(0, textNode.length, newVtext.text);
678642
}
679643
return textNode;
680644
};
681-
682-
var destroyVtext = function destroyVtext(textNode) {
645+
VtextPrototype.destroy = function (textNode) {
683646
removeNode(textNode);
684647
};
685648

686-
var createVelem = function createVelem(type, props) {
687-
return {
688-
vtype: VNODE_TYPE.ELEMENT,
689-
type: type,
690-
props: props,
691-
refs: refs,
692-
init: initVelem,
693-
update: updateVelem,
694-
destroy: destroyVelem
695-
};
696-
};
649+
function Velem(type, props) {
650+
this.type = type;
651+
this.props = props;
652+
this.refs = refs;
653+
}
697654

698-
var initVelem = function initVelem(parentNode, parentContext) {
655+
var VelemPrototype = Velem.prototype;
656+
VelemPrototype.isVdom = true;
657+
VelemPrototype.init = function (parentNode, parentContext) {
699658
var type = this.type;
700659
var props = this.props;
701660

@@ -727,8 +686,7 @@ var initVelem = function initVelem(parentNode, parentContext) {
727686
attachRef(this, node);
728687
return node;
729688
};
730-
731-
var updateVelem = function updateVelem(newVelem, node, parentNode, parentContext) {
689+
VelemPrototype.update = function (newVelem, node, parentNode, parentContext) {
732690
var props = this.props;
733691

734692
var newProps = newVelem.props;
@@ -782,8 +740,7 @@ var updateVelem = function updateVelem(newVelem, node, parentNode, parentContext
782740
updateRef(this, newVelem, node);
783741
return node;
784742
};
785-
786-
var destroyVelem = function destroyVelem(node) {
743+
VelemPrototype.destroy = function (node) {
787744
var children = this.props.children;
788745

789746
if (children) {
@@ -801,27 +758,22 @@ var destroyVelem = function destroyVelem(node) {
801758
removeNode(node);
802759
};
803760

804-
var createVstatelessComponent = function createVstatelessComponent(type, props) {
805-
return {
806-
id: getUid(),
807-
vtype: VNODE_TYPE.STATELESS_COMPONENT,
808-
type: type,
809-
props: props,
810-
init: initVstatelessComponent,
811-
update: updateVstatelessComponent,
812-
destroy: destroyVstatelessComponent
813-
};
814-
};
761+
function VstatelessComponent(type, props) {
762+
this.id = getUid();
763+
this.type = type;
764+
this.props = props;
765+
}
815766

816-
var initVstatelessComponent = function initVstatelessComponent(parentNode, parentContext) {
767+
var VstatelessComponentPrototype = VstatelessComponent.prototype;
768+
VstatelessComponentPrototype.isVdom = true;
769+
VstatelessComponentPrototype.init = function (parentNode, parentContext) {
817770
var vtree = renderVstatelessComponent(this, parentContext);
818771
var node = vtree.init(parentNode, parentContext);
819772
node.cache = node.cache || {};
820773
node.cache[this.id] = vtree;
821774
return node;
822775
};
823-
824-
var updateVstatelessComponent = function updateVstatelessComponent(newVstatelessComponent, node, parentNode, parentContext) {
776+
VstatelessComponentPrototype.update = function (newVstatelessComponent, node, parentNode, parentContext) {
825777
var id = this.id;
826778
var vtree = node.cache[id];
827779
delete node.cache[id];
@@ -834,8 +786,7 @@ var updateVstatelessComponent = function updateVstatelessComponent(newVstateless
834786
}
835787
return newNode;
836788
};
837-
838-
var destroyVstatelessComponent = function destroyVstatelessComponent(node) {
789+
VstatelessComponentPrototype.destroy = function (node) {
839790
var id = this.id;
840791
var vtree = node.cache[id];
841792
delete node.cache[id];
@@ -854,20 +805,16 @@ var renderVstatelessComponent = function renderVstatelessComponent(vstatelessCom
854805
return getVnode(vtree);
855806
};
856807

857-
var createVcomponent = function createVcomponent(type, props) {
858-
return {
859-
id: getUid(),
860-
vtype: VNODE_TYPE.COMPONENT,
861-
type: type,
862-
props: props,
863-
refs: refs,
864-
init: initVcomponent,
865-
update: updateVcomponent,
866-
destroy: destroyVcomponent
867-
};
868-
};
808+
function Vcomponent(type, props) {
809+
this.id = getUid();
810+
this.type = type;
811+
this.props = props;
812+
this.refs = refs;
813+
}
869814

870-
var initVcomponent = function initVcomponent(parentNode, parentContext) {
815+
var VcomponentPrototype = Vcomponent.prototype;
816+
VcomponentPrototype.isVdom = true;
817+
VcomponentPrototype.init = function (parentNode, parentContext) {
871818
var Component = this.type;
872819
var props = this.props;
873820
var id = this.id;
@@ -895,8 +842,7 @@ var initVcomponent = function initVcomponent(parentNode, parentContext) {
895842
attachRef(this, component);
896843
return node;
897844
};
898-
899-
var updateVcomponent = function updateVcomponent(newVcomponent, node, parentNode, parentContext) {
845+
VcomponentPrototype.update = function (newVcomponent, node, parentNode, parentContext) {
900846
var id = this.id;
901847
var component = node.cache[id];
902848
var updater = component.$updater;
@@ -917,8 +863,7 @@ var updateVcomponent = function updateVcomponent(newVcomponent, node, parentNode
917863
updateRef(this, newVcomponent, component);
918864
return cache.node;
919865
};
920-
921-
var destroyVcomponent = function destroyVcomponent(node) {
866+
VcomponentPrototype.destroy = function (node) {
922867
var id = this.id;
923868
var component = node.cache[id];
924869
var cache = component.$cache;
@@ -989,22 +934,34 @@ var clearPendingComponents = function clearPendingComponents() {
989934

990935
function compareTwoTrees(vtree, newVtree, node, parentNode, parentContext) {
991936
var newNode = node;
992-
var diffType = diff(vtree, newVtree);
937+
var isReplace = null;
993938

994-
if (diffType === DIFF_TYPE.UPDATE) {
995-
newNode = vtree.update(newVtree, node, parentNode, parentContext);
996-
} else if (diffType === DIFF_TYPE.REMOVE) {
939+
if (vtree === newVtree) {
940+
return newNode;
941+
} else if (newVtree === undefined) {
997942
vtree.destroy(node);
998-
} else if (diffType === DIFF_TYPE.REPLACE) {
943+
} else if (vtree === undefined) {
944+
newNode = newVtree.init(parentNode, parentContext);
945+
} else if (vtree.type !== newVtree.type) {
946+
isReplace = true;
947+
} else if (newVtree.key !== null) {
948+
if (vtree.key === null || newVtree.key !== vtree.key) {
949+
isReplace = true;
950+
}
951+
} else if (vtree.key !== null) {
952+
isReplace = true;
953+
}
954+
955+
if (isReplace) {
999956
var $removeNode = removeNode;
1000957
removeNode = noop$1;
1001958
vtree.destroy(node);
1002959
removeNode = $removeNode;
1003960
newNode = newVtree.init(function (nextNode) {
1004961
return parentNode.replaceChild(nextNode, node);
1005962
}, parentContext);
1006-
} else if (diffType === DIFF_TYPE.CREATE) {
1007-
newNode = newVtree.init(parentNode, parentContext);
963+
} else {
964+
newNode = vtree.update(newVtree, node, parentNode, parentContext);
1008965
}
1009966

1010967
return newNode;
@@ -1027,9 +984,9 @@ var appendNode = function appendNode(parentNode, node) {
1027984

1028985
var getVnode = function getVnode(vnode) {
1029986
if (vnode === null) {
1030-
vnode = createVelem('noscript', {});
1031-
} else if (!vnode || !vnode.vtype) {
1032-
vnode = createVtext(vnode);
987+
vnode = new Velem('noscript', {});
988+
} else if (!vnode || !vnode.isVdom) {
989+
vnode = new Vtext('' + vnode);
1033990
}
1034991
return vnode;
1035992
};
@@ -1041,7 +998,6 @@ var getDOMNode = function getDOMNode() {
1041998
var attachRef = function attachRef(vtree, refValue) {
1042999
var refKey = vtree.ref;
10431000
var refs = vtree.refs;
1044-
var vtype = vtree.vtype;
10451001

10461002
if (!refs || refKey == null || !refValue) {
10471003
return;
@@ -1072,24 +1028,7 @@ var detachRef = function detachRef(vtree) {
10721028
};
10731029

10741030
var updateRef = function updateRef(vtree, newVtree, refValue) {
1075-
if (!vtree.refs) {
1076-
attachRef(newVtree, refValue);
1077-
return;
1078-
}
1079-
if (!newVtree.refs) {
1080-
detachRef(vtree);
1081-
return;
1082-
}
1083-
if (vtree.refs !== newVtree.refs) {
1084-
detachRef(vtree);
1085-
attachRef(newVtree, refValue);
1086-
return;
1087-
}
1088-
var oldRef = vtree.ref;
1089-
var newRef = newVtree.ref;
1090-
if (newRef == null) {
1091-
detachRef(vtree);
1092-
} else if (oldRef !== newRef) {
1031+
if (vtree.ref !== newVtree.ref) {
10931032
detachRef(vtree);
10941033
attachRef(newVtree, refValue);
10951034
}
@@ -1404,7 +1343,7 @@ var createSyntheticEvent = function createSyntheticEvent(nativeEvent) {
14041343
var pendingRendering = {};
14051344
var vtreeStore = {};
14061345
var renderTreeIntoContainer = function renderTreeIntoContainer(vtree, container, callback, parentContext) {
1407-
if (!vtree.vtype) {
1346+
if (!vtree.isVdom) {
14081347
throw new Error('cannot render ' + vtree + ' to container');
14091348
}
14101349
var id = container[COMPONENT_ID] || (container[COMPONENT_ID] = getUid());
@@ -1442,9 +1381,9 @@ var renderTreeIntoContainer = function renderTreeIntoContainer(vtree, container,
14421381
var result = null;
14431382
if (isArr(argsCache)) {
14441383
result = renderTreeIntoContainer(argsCache[0], container, argsCache[1], argsCache[2]);
1445-
} else if (vtree.vtype === VNODE_TYPE.ELEMENT) {
1384+
} else if (isStr(vtree.type)) {
14461385
result = container.firstChild;
1447-
} else if (vtree.vtype === VNODE_TYPE.COMPONENT) {
1386+
} else if (isComponent(vtree.type)) {
14481387
result = container.firstChild.cache[vtree.id];
14491388
}
14501389

@@ -1506,7 +1445,7 @@ var ReactDOM = Object.freeze({
15061445
});
15071446

15081447
var isValidElement = function isValidElement(obj) {
1509-
return obj != null && !!obj.vtype;
1448+
return obj != null && !!obj.isVdom;
15101449
};
15111450

15121451
var cloneElement = function cloneElement(originElem, props) {
@@ -1543,14 +1482,14 @@ var createElement = function createElement(type, props) {
15431482
children[_key3 - 2] = arguments[_key3];
15441483
}
15451484

1546-
var createVnode = undefined;
1485+
var Vnode = null;
15471486

15481487
if (isStr(type)) {
1549-
createVnode = createVelem;
1488+
Vnode = Velem;
15501489
} else if (isComponent(type)) {
1551-
createVnode = createVcomponent;
1490+
Vnode = Vcomponent;
15521491
} else if (isStatelessComponent(type)) {
1553-
createVnode = createVstatelessComponent;
1492+
Vnode = VstatelessComponent;
15541493
} else {
15551494
throw new Error('React.createElement: unexpect type [ ' + type + ' ]');
15561495
}
@@ -1568,7 +1507,7 @@ var createElement = function createElement(type, props) {
15681507
}
15691508
}
15701509

1571-
var vnode = createVnode(type, mergeProps(props, children, type.defaultProps));
1510+
var vnode = new Vnode(type, mergeProps(props, children, type.defaultProps));
15721511
vnode.key = key;
15731512
vnode.ref = ref;
15741513
return vnode;

0 commit comments

Comments
 (0)