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

Commit

Permalink
fix(vdom): domChild attr no clear
Browse files Browse the repository at this point in the history
  • Loading branch information
zeromake committed Jul 20, 2017
1 parent 5f94e0e commit cac0c49
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 55 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ typings/
.env
/dist/
/test/test.js
/build/
/coverage/

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"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:karma": "karma start test/karma.conf.js --single-run"
"test:karma": "karma start test/karma.conf.js --single-run",
"test:karma:watch": "npm run test:karma -- no-single-run"
},
"devDependencies": {
"babel-cli": "^6.24.1",
Expand All @@ -23,13 +24,13 @@
"chai": "^4.1.0",
"cross-env": "^5.0.1",
"isparta-loader": "^2.0.0",
"istanbul-instrumenter-loader": "^2.0.0",
"karma": "^1.7.0",
"karma-chai-sinon": "^0.1.5",
"karma-coverage": "^1.1.1",
"karma-chrome-launcher": "^2.2.0",
"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",
Expand Down
35 changes: 21 additions & 14 deletions src/vdom/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
if (typeof childComponent === "function" && rendered) {
// 如果是自定义组件

if (component.child) {
component.child = undefined;
}
// if (component.child) {
// component.child = undefined;
// }
// 获取VNode上的props
const childProps = getNodeProps(rendered);
inst = initialChildComponent;
Expand All @@ -157,6 +157,8 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
inst.nextBase = inst.nextBase || nextBase;
// 设置父组件索引
inst._parentComponent = component;
// 设置domchild
inst.child = component.child;
// 设置props但是不进行render
setComponentProps(inst, childProps, NO_RENDER, context, false);
// 递归调用renderComponent保证子组件的子组件创建
Expand Down Expand Up @@ -207,6 +209,7 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
);
}
}

if (initialBase && base !== initialBase && inst !== initialChildComponent) {
// 存在缓存dom,现dom和缓存dom不相同且新建过自定义子组件
// 获取当前组件缓存dom的父级dom
Expand All @@ -219,15 +222,13 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
// const initBase: any = initialBase;
// 去除dom上的component索引
// initBase._component = null;
if (component.child && component.child.base) {
component.child.base = null;
}
//
recollectNodeTree(initialBase, false);
component.child.base = initialBase;
component.child._component = null;
recollectNodeTree(component.child, false);
component.child.base = null;
}
}
}

if (toUnmount) {
unmountComponent(toUnmount);
}
Expand All @@ -245,10 +246,8 @@ export function renderComponent(component: Component, opts?: number, mountALL?:
// _base._component = componentRef;
// _base._componentConstructor = componentRef.constructor;
// } catch (e) {}
if (component.child) {
component.child._component = componentRef;
component.child._componentConstructor = componentRef.constructor;
}
component.child._component = componentRef;
component.child._componentConstructor = componentRef.constructor;
}
}
if (!isUpdate || mountALL) {
Expand Down Expand Up @@ -304,7 +303,7 @@ export function buildComponentFromVNode(
oldDom = null;
}
c.child = child;
child._component = c;
// child._component = c;
child.base = c.base;
setComponentProps(
c,
Expand Down Expand Up @@ -352,3 +351,11 @@ export function unmountComponent(component: Component) {
component._ref(null);
}
}

export function removeDomChild(child: any) {
child.base = null;
child._component = null;
child[ATTR_KEY] = null;
child.event = null;
child._listeners = null;
}
7 changes: 5 additions & 2 deletions src/vdom/diff.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ATTR_KEY } from "../constants";
import { isSameNodeType, isNamedNode } from "./index";
import { buildComponentFromVNode, unmountComponent } from "./component";
import { buildComponentFromVNode, unmountComponent, removeDomChild } from "./component";
import {
setAccessor,
createNode,
Expand Down Expand Up @@ -324,6 +324,7 @@ export function recollectNodeTree(node: any, unmountOnly: any) {
if (component) {
// 如果存在
unmountComponent(component);
node._component = null;
} else {
if (node[ATTR_KEY] != null && node[ATTR_KEY].ref) {
// ref用于取消引用dom
Expand All @@ -343,11 +344,13 @@ export function removeChildren(node: any) {
const nodeList = node.children;
node.children = [];
let len = nodeList ? nodeList.length : 0;
node = getLastChild(node && node.base);
// node = getLastChild(node && node.base);
while (len--) {
// 不需要移除因为父级已经移除
recollectNodeTree(nodeList[len], true);
}
// removeDomChild
removeDomChild(node);
}

function diffAttributes(dom: any, attrs: any, old: any, child: any) {
Expand Down
32 changes: 23 additions & 9 deletions test/karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*eslint no-var:0, object-shorthand:0 */
const path = require('path')

var coverage = String(process.env.COVERAGE)!=='false',
ci = String(process.env.CI).match(/^(1|true)$/gi),
Expand Down Expand Up @@ -61,9 +62,9 @@ var localBrowsers = realBrowser ? Object.keys(travisLaunchers) : ['PhantomJS'];

module.exports = function(config) {
config.set({
browsers: ['PhantomJS'], //sauceLabs ? Object.keys(sauceLabsLaunchers) : localBrowsers,
browsers: ['Chrome'], //sauceLabs ? Object.keys(sauceLabsLaunchers) : localBrowsers,

frameworks: ['source-map-support', 'mocha', 'chai-sinon'],
frameworks: ['mocha', 'chai-sinon'],

reporters: ['mocha'].concat(
coverage ? 'coverage' : [],
Expand Down Expand Up @@ -138,18 +139,20 @@ module.exports = function(config) {
loader: "ts-loader"
},
/* Only Instrument our source files for coverage */
coverage ? {
test: /\.jsx?$/,
loader: 'isparta-loader',
include: /src/
} : {}
coverage ?
{
test: /\.jsx?$/,
use: 'istanbul-instrumenter-loader',
include: /build/,
exclude: /(node_modules|\.spec\.js$)/
}: {}
]
},
resolve: {
// The React DevTools integration requires preact as a module
// rather than referencing source files inside the module
// directly
alias: { preact: '../build/zreact' },
alias: { preact: '../src/zreact.ts' },
modules: [__dirname, 'node_modules']
},
plugins: [
Expand All @@ -164,6 +167,17 @@ module.exports = function(config) {

webpackMiddleware: {
noInfo: true
}
},
coverageIstanbulReporter: {
reports: ['html', 'lcovonly', 'text-summary'],
dir: path.join(__dirname, 'coverage'),
fixWebpackSourcePaths: true,
'report-config': {
html: {
subdir: 'html'
}

}
}
});
};
95 changes: 77 additions & 18 deletions test/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,83 @@

// comp.setState({ alt:true });
// comp.forceUpdate();
const Foo = props => Zreact.h("div", Object.assign({}, props));

Zreact.render(Zreact.h(Foo,
{
a: "b",
children:[
Zreact.h("span", { class: "bar" }, "bar"),
'123',
456]
}
), scratch);
const Empty = () => null;
let c = scratch.firstElementChild;
if (c) Zreact.render(Zreact.h(Empty), scratch, c);
//scratch.innerHTML = '';
const Foa = props => Zreact.h("div", Object.assign({}, props), "a");

//Zreact.render(Zreact.h(Foa, {children: 'b'}), scratch);
// const Foo = props => Zreact.h("div", Object.assign({}, props));

// Zreact.render(Zreact.h(Foo,
// {
// a: "b",
// children:[
// Zreact.h("span", { class: "bar" }, "bar"),
// '123',
// 456]
// }
// ), scratch);
// const Empty = () => null;
// let c = scratch.firstElementChild;
// if (c) Zreact.render(Zreact.h(Empty), scratch, c);
// //scratch.innerHTML = '';
// const Foa = props => Zreact.h("div", Object.assign({}, props), "a");

//Zreact.render(Zreact.h(Foa, {children: 'b'}), scratch);

// const PROPS = { foo:'bar', onBaz:()=>{} };

// const C3 = props => Zreact.h("div", Object.assign({}, props));
// console.log(Zreact.h(C3, Object.assign({}, PROPS)))

// Zreact.render(Zreact.h(C3, Object.assign({}, PROPS)), scratch);
// let doRender = null,
// alt = false;

// class Outer extends Zreact.Component {
// componentDidMount() {
// let i = 1;
// doRender = () => this.setState({ i: ++i });
// }
// componentWillUnmount() {}
// render(props, { i }) {
// if (alt) return Zreact.h("div", { "is-alt": true });
// return Zreact.h(Inner, Object.assign({i: i}, props));
// }
// }

// let j = 0;
// class Inner extends Zreact.Component {
// constructor(...args) {
// super();
// this._constructor(...args);
// }
// _constructor() {}
// componentWillMount() {}
// componentDidMount() {}
// componentWillUnmount() {}
// render(props) {
// return Zreact.h("div", Object.assign({ j: ++j }, props), "inner");
// }
// }

// Zreact.render(Zreact.h(Outer, { foo: "bar" }), scratch);


// // update & flush
// doRender();
// Zreact.rerender();

// console.log(scratch.firstElementChild)
class Comp extends Component {
render() {
return <span>span in a component</span>;
}
}

let root;
function test(content) {
root = render(content, scratch, root);
}

test(<Comp />);
test(<div>just a div</div>);
test(<Comp />);
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"module": "es6", // 目标代码模块方式
"module": "es2015", // 目标代码模块方式
"outDir": "build", // 输出目录
"sourceMap": true,
"target": "es5", // 目标代码平台
Expand Down

0 comments on commit cac0c49

Please sign in to comment.