const Didact = {
createElement,
render,
};
function createTextElement(text) {
return {
type: "TEXT_ELEMENT",
props: {
nodeValue: text,
children: [],
},
};
}
function createElement(type, props, ...children) {
return {
type,
props: {
...props,
children: children.map((child) =>
typeof child === "object" ? child : createTextElement(child)
),
},
};
}
/** @jsx Didact.createElement */
const element = (
);
// const element = Didact.createElement(
// "div",
// { id: "foo" },
// Didact.createElement("a", null, "bar"),
// Didact.createElement("b")
// );
function render(element, container) {
const dom =
element.type == "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type);
const isProperty = (key) => key !== "children";
Object.keys(element.props)
.filter(isProperty)
.forEach((name) => {
dom[name] = element.props[name];
});
element.props.children.forEach((child) => render(child, dom));
container.appendChild(dom);
}
const container = document.getElementById("root");
Didact.render(element, container);
/** @jsx Didact.createElement */
是告诉babel jsx在转换的时候使用我们自己的方法Didact.createElement。
Didact.render(element, container);
element是jsx转换过后的数据结构,再根据我们自己的数据结构渲染element。
render过程如下
1 创建dom
const dom =
element.type == "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type);
2 把除去children属性的其他属性赋值到真实dom上面
const isProperty = (key) => key !== "children";
Object.keys(element.props)
.filter(isProperty)
.forEach((name) => {
dom[name] = element.props[name];
});
3 如果dom还有子节点,那么通过render递归把子节点添加到父节点上面
element.props.children.forEach((child) => render(child, dom));
4 把子节点dom添加到父节点dom上
container.appendChild(dom);