Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Commit

Permalink
fix(vdom): unmount domChild children cause removeNode error
Browse files Browse the repository at this point in the history
  • Loading branch information
zeromake committed Jul 21, 2017
1 parent acbe1c2 commit 4ec1c67
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 217 deletions.
8 changes: 7 additions & 1 deletion src/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export function setAccessor(
if (name === "className") {
name = "class";
}
if ("ref" === name) {
if (name === "key") {
// no set
} else if ("ref" === name) {
if (old) {
old(null);
}
Expand Down Expand Up @@ -129,6 +131,10 @@ export function getLastChild(node: Node): Node| null {
return node.lastChild;
}

export function isTextNode(node: Text | any): boolean {
return node.splitText !== undefined;
}

function addEventListener(node: any, name: string, useCapture: boolean, child: any) {
const eventProxyFun = eventProxy(child);
if (!child.event) {
Expand Down
56 changes: 56 additions & 0 deletions src/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,59 @@ if (!Function.prototype.bind) {
return fBound;
};
}
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {

var T, A, k;

if (this == null) {
throw new TypeError(" this is null or not defined");
}

// 1. 将O赋值为调用map方法的数组.
var O = Object(this);

// 2.将len赋值为数组O的长度.
var len = O.length >>> 0;

// 3.如果callback不是函数,则抛出TypeError异常.
if (Object.prototype.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}

// 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
if (thisArg) {
T = thisArg;
}

// 5. 创建新数组A,长度为原数组O长度len
A = new Array(len);

// 6. 将k赋值为0
k = 0;

// 7. 当 k < len 时,执行循环.
while(k < len) {

var kValue, mappedValue;

//遍历O,k为原数组索引
if (k in O) {

//kValue为索引k对应的值.
kValue = O[ k ];

// 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
mappedValue = callback.call(T, kValue, k, O);

// 返回值添加到新数组A中.
A[ k ] = mappedValue;
}
// k自增1
k++;
}

// 8. 返回新数组A
return A;
};
}
4 changes: 2 additions & 2 deletions src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ const child = {};
* @param parent 挂载的dom元素
* @param merge 原dom元素
*/
export function render(vnode: VNode, parent: Element, merge: Element) {
return diff(merge, vnode, {}, false, parent, false, child);
export function render(vnode: VNode, parent: Element, merge: Element, domChild?: any) {
return diff(merge, vnode, {}, false, parent, false, domChild || child);
}
13 changes: 10 additions & 3 deletions src/vdom/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,17 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
// 子组件已存在且key未变化只改变props
setComponentProps(inst, childProps, SYNC_RENDER, context, false);
} else {
// 设置到toUnmount等待unmount
toUnmount = inst;
if (inst) {
// 设置到toUnmount等待unmount
toUnmount = inst;
toUnmount.child = {...toUnmount.child};
// 防止共享子dom
inst.child.children = [];
}
// 新建Component
inst = createComponent(childComponent, childProps, context);
// 子组件索引保证下次相同子组件不会重新创建
component._component = inst;
// 设置好缓存dom
inst.nextBase = inst.nextBase || nextBase;
// 设置父组件索引
Expand Down Expand Up @@ -248,6 +255,7 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
// } catch (e) {}
component.child._component = componentRef;
component.child._componentConstructor = componentRef.constructor;
// component.child.base = base;
}
}
if (!isUpdate || mountALL) {
Expand Down Expand Up @@ -304,7 +312,6 @@ export function buildComponentFromVNode(
}
c.child = child;
// child._component = c;
child.base = c.base;
setComponentProps(
c,
props,
Expand Down
26 changes: 12 additions & 14 deletions src/vdom/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
removeNode,
getPreviousSibling,
getLastChild,
isTextNode,
} from "../dom/index";
import options from "../options";
import { VNode } from "../vnode";
Expand Down Expand Up @@ -97,12 +98,12 @@ function idiff(
if (typeof vnode === "string" || typeof vnode === "number") {
if (
dom
&& dom.splitText !== undefined
&& isTextNode(dom)
&& dom.parentNode
&& (!child._component || componentRoot)
) {
if (child.nodeValue !== vnode) {
child.nodeValue = vnode;
if (dom.nodeValue !== vnode) {
dom.nodeValue = vnode;
}
} else {
const data: any = vnode;
Expand All @@ -111,9 +112,9 @@ function idiff(
if (dom.parentNode) {
dom.parentNode.replaceChild(out, dom);
}
if (child.base !== dom) {
child.base = dom;
}
// if (child.base !== dom) {
// child.base = dom;
// }
recollectNodeTree(child, true);
}
}
Expand All @@ -131,19 +132,16 @@ function idiff(
vnodeName = String(vnodeName);
if (!dom || !isNamedNode(dom, vnodeName)) {
out = createNode(vnodeName, isSvgMode);
if (child._component) {
child._component = undefined;
}
if (dom) {
while (dom.firstChild) {
out.appendChild(dom.firstChild);
}
if (dom.parentNode) {
dom.parentNode.replaceChild(out, dom);
}
if (child.base !== dom) {
child.base = dom;
}
// if (child.base !== dom) {
// child.base = dom;
// }
recollectNodeTree(child, true);
}
}
Expand All @@ -167,7 +165,7 @@ function idiff(
&& vchildren.length === 1
&& typeof vchildren[0] === "string"
&& fc != null
&& fc.splitText !== undefined
&& isTextNode(fc)
&& fc.nextSibling == null
) {
if (fc.nodeValue !== vchildren[0]) {
Expand Down Expand Up @@ -234,7 +232,7 @@ function innerDiffNode(
} else if (
props
|| (
pchild.base.splitText !== undefined
isTextNode(pchild.base)
? (isHydrating ? pchild.base.nodeValue.trim() : true)
: isHydrating
)
Expand Down
5 changes: 3 additions & 2 deletions src/vdom/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { VNode } from "../vnode";
import { Component } from "../component";
import { isTextNode } from "../dom/index";

export function isSameNodeType(node: any, vnode: VNode, hydrating: boolean) {
if (typeof vnode === "string" || typeof vnode === "number") {
return node.base.splitText !== undefined;
return isTextNode(node.base);
}
if (typeof vnode.nodeName === "string") {
return !node._componentConstructor && isNamedNode(node, vnode.nodeName);
return !node._componentConstructor && isNamedNode(node.base, vnode.nodeName);
}
return hydrating || node._componentConstructor === vnode.nodeName;
}
Expand Down
1 change: 0 additions & 1 deletion test/browser/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ describe('Components', () => {
});

it('should be ignored when explicit children exist', () => {
console.log("-------", scratch.innerHTML)
const Foo = props => <div {...props}>a</div>;

render(<Foo children={'b'} />, scratch);
Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 4ec1c67

Please sign in to comment.