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

Commit

Permalink
fix: copy code ok
Browse files Browse the repository at this point in the history
  • Loading branch information
zeromake committed Jul 16, 2017
1 parent aa8f650 commit d482619
Show file tree
Hide file tree
Showing 15 changed files with 748 additions and 38 deletions.
27 changes: 15 additions & 12 deletions src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ export class Component {
public state: any;
public props: any;
public context: any;
public base: HTMLElement;
public defaultProps?: any;
public base?: Element;
public name?: string;
public prevProps?: any;
public prevState?: any;
public prevContext?: any;
public nextBase?: any;
public component?: Component;
public nextBase?: Element;
public componentWillMount?: () => void;
public componentDidMount?: () => void;
public componentWillUnmount?: () => void;
Expand All @@ -20,13 +21,15 @@ export class Component {
public componentWillUpdate?: (nextProps: any, nextState: any, nextContext: any) => void;
public componentDidUpdate?: (previousProps: any, previousState: any, previousContext: any) => void;
public getChildContext?: () => any;
public dirty: boolean;
public renderCallbacks?: any[];
public __key?: string;
public _component?: Component;
public _parentComponent?: Component;
public _dirty: boolean;
public _renderCallbacks?: any[];
public _key?: string;
public _disable?: boolean;
public __ref: string;
public _ref?: (component: Component | null) => void;
constructor(props: any, context: any) {
this.dirty = true;
this._dirty = true;
this.context = context;
this.props = props;
this.state = this.state || {};
Expand All @@ -38,15 +41,15 @@ export class Component {
}
s = {...(typeof state === "function" ? state(s, this.props) : state)};
if (callback) {
this.renderCallbacks = this.renderCallbacks || [];
this.renderCallbacks.push(callback);
this._renderCallbacks = this._renderCallbacks || [];
this._renderCallbacks.push(callback);
}
// enqueueRender(this);
}
public forceUpdate(callback: () => void) {
if (callback) {
this.renderCallbacks = this.renderCallbacks || [];
this.renderCallbacks.push(callback);
this._renderCallbacks = this._renderCallbacks || [];
this._renderCallbacks.push(callback);
}
renderComponent(this, FORCE_RENDER);
}
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export const FORCE_RENDER = 2;
export const ASYNC_RENDER = 3;

export const ATTR_KEY = "__preactattr_";

export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
115 changes: 115 additions & 0 deletions src/dom/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { IS_NON_DIMENSIONAL } from "../constants";
import options from "../options";

export function createNode(nodeName: string, isSvg: boolean): HTMLElement {
const node: any = isSvg
? document.createElementNS("http://www.w3.org/2000/svg", nodeName)
: document.createElement(nodeName);
node.normalizedNodeName = nodeName;
return node;
}

export function removeNode(node: HTMLElement) {
const parentNode = node.parentNode;
if (parentNode) {
parentNode.removeChild(node);
}
}

export function setAccessor(
node: HTMLElement,
name: string,
old: any,
value: any,
isSvg: boolean,
) {
if (name === "className") {
name = "class";
}
if ("ref" === name) {
if (old) {
old(null);
}
if (value) {
value(node);
}
} else if ("class" === name) {
node.className = value || "";
} else if ("style" === name) {
if (!value || typeof value === "string" || typeof old === "string") {
node.style.cssText = value || "";
}
if (value && typeof value === "object") {
if (typeof old !== "string") {
for (const i in old) {
if (!(i in value)) {
node.style[i] = "";
}
}
}
for (const i in value) {
node.style[i] = typeof value[i] === "number"
&& IS_NON_DIMENSIONAL.test(i) === false ? (value[i] + "px") : value[i];
}
}
} else if ("dangerouslySetInnerHTML" === name) {
if (value) {
node.innerHTML = value._html || "";
}
} else if (name[0] === "o" && name[1] === "n") {
const oldName = name;
name = name.replace(/Capture$/, "");
const useCapture = oldName !== oldName;
name = name.toLowerCase().substring(2);
if (value) {
if (!old) {
node.addEventListener(name, eventProxy, useCapture);
}
} else {
node.removeEventListener(name, eventProxy, useCapture);
}
const n: any = node;
if (!n._listeners) {
n._listeners = {};
}
n._listeners[name] = value;
} else if (name !== "list" && name !== "type" && !isSvg && name in node) {
setProperty(node, name, value == null ? "" : value);
if (value == null || value === false) {
node.removeAttribute(name);
}
} else {
const ns = isSvg && (name !== (name = name.replace(/^xlink\:?/, "")));
// null || undefined || void 0 || false
if (value == null || value === false) {
if (ns) {
node.removeAttributeNS(
"http://www.w3.org/1999/xlink",
name.toLowerCase(),
);
} else {
node.removeAttribute(name);
}
} else if (typeof value !== "function") {
if (ns) {
node.setAttributeNS(
"http://www.w3.org/1999/xlink",
name.toLowerCase(),
value,
);
} else {
node.setAttribute(name, value);
}
}
}
}

function setProperty(node, name, value) {
try {
node[name] = value;
} catch (e) { }
}

function eventProxy(e) {
return this._listeners[e.type](options.event && options.event(e) || e);
}
5 changes: 3 additions & 2 deletions src/h.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Component } from "./component";
import options from "./options";
import { VNode } from "./vnode";

Expand All @@ -6,12 +7,12 @@ import { VNode } from "./vnode";
/** JSX/hyperscript reviver
* Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0
* 标准JSX转换函数
* @param {string} nodeName 组件或者原生dom组件名
* @param {string|Component} nodeName 组件{@link Component}或者原生dom组件名
* @param {{key: string => value: string}} attributes 组件属性
* @see http://jasonformat.com/wtf-is-jsx
* @public
*/
export function h(nodeName: string, attributes: any, ...args: any[]) {
export function h(nodeName: string | Component, attributes: any, ...args: any[]) {
// 初始化子元素列表
const stack: any[] = [];
const children: any[] = [];
Expand Down
3 changes: 3 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { VNode } from "./vnode";
import { Component } from "component";

const options: {
beforeUnmount?: (component: Component) => void;
afterMount?: (component: Component) => void;
syncComponentUpdates?: boolean;
debounceRendering?: (render: () => void) => void;
vnode?: (vnode: VNode) => void;
Expand Down
30 changes: 30 additions & 0 deletions src/render-queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Component } from "./component";
import options from "./options";
import { defer } from "./util";
import { renderComponent } from "./vdom/component";

let items: Component[] = [];

export function enqueueRender(component: Component) {
if (!component._dirty) {
component._dirty = true;
const len = items.push(component);
if (len === 1) {
const deferFun = options.debounceRendering || defer;
deferFun(rerender);
}
}
}

export function rerender() {
let p: Component;
const list = items;
items = [];
p = list.pop();
while (p) {
if (p._dirty) {
renderComponent(p);
}
p = list.pop();
}
}
5 changes: 5 additions & 0 deletions src/render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { diff } from "./vdom/diff";

export function render(vnode, parent, merge) {
return diff(merge, vnode, {}, false, parent, false);
}
5 changes: 5 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare const Promise: any;

export const defer = typeof Promise === "function"
? Promise.resolve().then
: setTimeout;
42 changes: 42 additions & 0 deletions src/vdom/component-recycler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Component } from "../component";

const components: {
[name: string]: Component[];
} = {};

declare class Function {

}

export function collectComponent(component: Component) {
const constructor: any = component.constructor;
const name = constructor.name;
const list = components[name] || [];
list.push(component);
}

export function createComponent(Ctor: any, props: any, context: any) {
const list = components[Ctor.name];
let inst: Component;
if (Ctor.prototype && Ctor.prototype.render) {
inst = new Ctor(props, context);
Component.call(inst, props, context);
} else {
inst = new Component(props, context);
inst.constructor = Ctor;
inst.render = function doRender(tprops: any, state: any, tcontext: any) {
return this.constructor(tprops, tcontext);
};
}
if (list) {
for (let i = list.length; i-- ; ) {
const item = list[i];
if (item.constructor === Ctor) {
inst.nextBase = item.nextBase;
list.splice(i, 1);
break;
}
}
}
return inst;
}

0 comments on commit d482619

Please sign in to comment.