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

Commit

Permalink
fix: global child,component replace not unmount
Browse files Browse the repository at this point in the history
  • Loading branch information
zeromake committed Jul 19, 2017
1 parent b391d04 commit 5f94e0e
Show file tree
Hide file tree
Showing 27 changed files with 6,760 additions and 191 deletions.
24 changes: 22 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,38 @@
"scripts": {
"build": "cross-env NODE_ENV=production rollup -c config/rollup.config.js",
"dev": "rollup -c config/rollup.config.js -w",
"test": "babel test/test.jsx -o test/test.js && node test/test.js"
"test": "babel test/test.jsx -o test/test.js && node test/test.js",
"test:karma": "karma start test/karma.conf.js --single-run"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-loader": "^7.1.1",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.6.0",
"babel-preset-es2015": "^6.24.1",
"chai": "^4.1.0",
"cross-env": "^5.0.1",
"isparta-loader": "^2.0.0",
"karma": "^1.7.0",
"karma-chai-sinon": "^0.1.5",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.3",
"karma-phantomjs-launcher": "^1.0.4",
"karma-source-map-support": "^1.2.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.4",
"mocha": "^3.4.2",
"rimraf": "^2.6.1",
"rollup": "^0.45.2",
"rollup-plugin-typescript": "zeromake/rollup-plugin-typescript",
"rollup-watch": "^4.3.1",
"sinon": "^2.3.8",
"sinon-chai": "^2.12.0",
"ts-loader": "^2.3.0",
"tslint": "^5.5.0",
"typescript": "^2.4.1"
"typescript": "^2.4.1",
"webpack": "^3.3.0"
}
}
2 changes: 2 additions & 0 deletions src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export class Component {
// 是否停用
public _disable?: boolean;
public _ref?: (component: Component | null) => void;
// 原生如果VNode,root为原生组件就创建并设置它的一些props,event
public child?: any;
constructor(props: any, context: any) {
// 初始化为true
this._dirty = true;
Expand Down
46 changes: 27 additions & 19 deletions src/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function setAccessor(
old: any,
value: any,
isSvg: boolean,
child: any,
) {
if (name === "className") {
name = "class";
Expand Down Expand Up @@ -63,15 +64,15 @@ export function setAccessor(
name = name.toLowerCase().substring(2);
if (value) {
if (!old) {
addEventListener(node, name, eventProxy, useCapture);
addEventListener(node, name, useCapture, child);
}
} else {
removeEventListener(node, name, eventProxy, useCapture);
removeEventListener(node, name, useCapture, child);
}
if (!node._listeners) {
node._listeners = {};
if (!child._listeners) {
child._listeners = {};
}
node._listeners[name] = value;
child._listeners[name] = value;
} else if (name !== "list" && name !== "type" && !isSvg && name in node) {
setProperty(node, name, value == null ? "" : value);
if (value == null || value === false) {
Expand Down Expand Up @@ -109,13 +110,15 @@ function setProperty(node: any, name: string, value: string) {
} catch (e) { }
}

function eventProxy(e: Event): (e: Event) => void {
const listener = this._listeners[e.type];
const event = options.event && options.event(e) || e;
if (options.eventBind) {
return listener.call(this._component, event);
}
return listener(event);
function eventProxy(child: any): (e: Event) => void {
return (e: Event) => {
const listener = child._listeners[e.type];
const event = options.event && options.event(e) || e;
if (options.eventBind) {
return listener.call(child._component, event);
}
return listener(event);
};
}

export function getPreviousSibling(node: Node): Node| null {
Expand All @@ -126,19 +129,24 @@ export function getLastChild(node: Node): Node| null {
return node.lastChild;
}

function addEventListener(node: any, name: string, eventFun: (e: Event) => void, useCapture: boolean) {
console.log("-----addEventListener------");
function addEventListener(node: any, name: string, useCapture: boolean, child: any) {
const eventProxyFun = eventProxy(child);
if (!child.event) {
child.event = {};
}
child.event[name] = eventProxyFun;
if (node.addEventListener) {
node.addEventListener(name, eventProxy, useCapture);
node.addEventListener(name, eventProxyFun, useCapture);
} else {
node.attachEvent("on" + name, eventProxy.bind(node));
node.attachEvent("on" + name, eventProxyFun);
}
}

function removeEventListener(node: any, name: string, eventFun: (e: Event) => void, useCapture: boolean) {
function removeEventListener(node: any, name: string, useCapture: boolean, child: any) {
const eventProxyFun = child.event[name];
if (node.removeEventListener) {
node.removeEventListener(name, eventProxy, useCapture);
node.removeEventListener(name, eventProxyFun, useCapture);
} else {
node.detachEvent("on" + name);
node.detachEvent("on" + name, eventProxyFun);
}
}
4 changes: 3 additions & 1 deletion src/render.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { diff } from "./vdom/diff";
import { VNode } from "./vnode";

const child = {};

/**
* 创建组件到dom上
* @param vnode jsx
* @param parent 挂载的dom元素
* @param merge 原dom元素
*/
export function render(vnode: VNode, parent: Element, merge: Element) {
return diff(merge, vnode, {}, false, parent, false);
return diff(merge, vnode, {}, false, parent, false, child);
}
55 changes: 38 additions & 17 deletions src/vdom/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ export function renderComponent(component: Component, opts?: number, mountALL?:

if (typeof childComponent === "function" && rendered) {
// 如果是自定义组件

if (component.child) {
component.child = undefined;
}
// 获取VNode上的props
const childProps = getNodeProps(rendered);
inst = initialChildComponent;
Expand Down Expand Up @@ -176,10 +180,15 @@ export function renderComponent(component: Component, opts?: number, mountALL?:

if (initialBase || opts === SYNC_RENDER) {
// 组件dom,缓存dom,同步渲染
if (cbase) {
if (component.child && component.child._component) {
// 清理component索引防止使用同一个component情况下却卸载了。
component.child._component = undefined;
//
const b: any = cbase;
b._component = undefined;
// const b: any = cbase;
// b._component = undefined;
}
if (!component.child) {
component.child = {};
}
// 渲染原生组件
base = diff(
Expand All @@ -194,6 +203,7 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
initialBase && initialBase.parentNode,
// 以原生组件这里执行说明是自定义组件的第一个原生组件
true,
component.child,
);
}
}
Expand All @@ -206,9 +216,12 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
baseParent.replaceChild(base, initialBase);
if (!toUnmount) {
// 没有
const initBase: any = initialBase;
// const initBase: any = initialBase;
// 去除dom上的component索引
initBase._component = null;
// initBase._component = null;
if (component.child && component.child.base) {
component.child.base = null;
}
//
recollectNodeTree(initialBase, false);
}
Expand All @@ -227,11 +240,15 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
componentRef = t;
componentRef.base = base;
}
const _base: any = base;
try {
_base._component = componentRef;
_base._componentConstructor = componentRef.constructor;
} catch (e) {}
// const _base: any = base;
// try {
// _base._component = componentRef;
// _base._componentConstructor = componentRef.constructor;
// } catch (e) {}
if (component.child) {
component.child._component = componentRef;
component.child._componentConstructor = componentRef.constructor;
}
}
}
if (!isUpdate || mountALL) {
Expand Down Expand Up @@ -260,11 +277,12 @@ export function buildComponentFromVNode(
vnode: VNode,
context: any,
mountALL: boolean,
child: any,
) {
let c = dom && dom._component;
let c = child && child._component;
const originalComponent = c;
let oldDom = dom;
const isDiectOwner = c && dom._componentConstructor === vnode.nodeName;
const isDiectOwner = c && child._componentConstructor === vnode.nodeName;
let isOwner = isDiectOwner;
const props = getNodeProps(vnode);
while (c && !isOwner && (c = c._parentComponent)) {
Expand All @@ -285,6 +303,9 @@ export function buildComponentFromVNode(
c.nextBase = dom;
oldDom = null;
}
c.child = child;
child._component = c;
child.base = c.base;
setComponentProps(
c,
props,
Expand All @@ -294,7 +315,7 @@ export function buildComponentFromVNode(
);
dom = c.base;
if (oldDom && dom !== oldDom) {
oldDom._component = null;
// oldDom._component = null;
recollectNodeTree(oldDom, false);
}
}
Expand All @@ -315,17 +336,17 @@ export function unmountComponent(component: Component) {
const anyBase: any = base;
if (inner) {
unmountComponent(inner);
} else if (anyBase) {
if (anyBase[ATTR_KEY] && anyBase[ATTR_KEY].ref) {
anyBase[ATTR_KEY].ref(null);
} else if (anyBase && component.child) {
if (component.child[ATTR_KEY] && component.child[ATTR_KEY].ref) {
component.child[ATTR_KEY].ref(null);
}
// 卸载组件dom前把它存到nextBase
component.nextBase = anyBase;
// 从dom上移除
removeNode(anyBase);
// 放入全局缓存对象保存
collectComponent(component);
removeChildren(anyBase);
removeChildren(component.child);
}
if (component._ref) {
component._ref(null);
Expand Down

0 comments on commit 5f94e0e

Please sign in to comment.