-
-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JSON2DOM = react的render函数 #37
Comments
// 真正的渲染函数
function _render(vnode) {
// 如果是数字类型转化为字符串
if (typeof vnode === "number") {
vnode = String(vnode);
}
// 字符串类型直接就是文本节点
if (typeof vnode === "string") {
return document.createTextNode(vnode);
}
// 普通DOM
const dom = document.createElement(vnode.tag);
if (vnode.attrs) {
// 遍历属性
Object.keys(vnode.attrs).forEach((key) => {
const value = vnode.attrs[key];
dom.setAttribute(key, value);
});
}
// 子数组进行递归操作
vnode.children.forEach((child) => dom.appendChild(_render(child)));
return dom;
} |
|
仅完成题目要求版本,可以直接F12查元素看结果 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function render(vnode) {
const { tag, attrs = {}, children } = vnode;
//创建dom
let el = document.createElement(tag);
//添加attr
for (const key in attrs) {
el.setAttribute(key, attrs[key]);
}
//处理children
if (Array.isArray(children) && children.length > 0) {
children.forEach(child => el.appendChild(render(child)));//子元素添加在父元素中
}
return el
}
const vnode = {
tag: 'DIV',
attrs: {
id: 'app'
},
children: [
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] }
]
},
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] }
]
}
]
}
document.body.appendChild(render(vnode))
</script>
</body>
</html> |
你忘记把子元素要添加到父元素中了吧? |
function renderer(vnode) {
const el = document.createElement(vnode.tag.toLocaleLowerCase());
// 处理attrs
for (const k in vnode.attrs) {
el.setAttribute(k, vnode.attrs[k]);
}
// 如果children是字符串
if (typeof vnode.children === "string") {
const textNode = document.createTextNode(vnode.children);
el.appendChild(textNode);
}
// 如果chidlren是数组,并且不是空数组时,就递归转化
if (Array.isArray(vnode.children) && vnode.children.length > 0) {
vnode.children.forEach((child) => {
el.appendChild(renderer(child, el));
});
}
return el;
} |
function _render(vNode) { |
function _render(vnode) {
// 考虑非一般性, 临界值
if (typeof vnode === "number") {
vnode = String(vnode);
}
if (typeof vnode === "string") {
return document.createTextNode(vnode);
}
// 不失一般性
const dom = document.createElement(vnode.tag);
if (vnode.attrs) {
for (const key in vnode.attrs) {
dom.setAttribute(key, vnode.attrs[key]);
}
}
if (vnode.children) {
vnode.children.forEach((newVnode) => {
dom.appendChild(_render(newVnode));
});
}
return dom;
} |
/**
* {
tag: 'DIV',
attrs:{
id:'app'
},
children: [
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] }
]
},
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] }
]
}
]
}
把上诉虚拟Dom转化成下方真实Dom
<div id="app">
<span>
<a></a>
</span>
<span>
<a></a>
<a></a>
</span>
</div>
*/
function render(vnode) {
if (typeof vnode === "string") {
return document.createTextNode(vnode);
}
if (typeof vnode === "number") {
vnode = String(vnode);
}
let dom = document.createElement(vnode.tag);
if (vnode.attrs) {
for (const key in vnode.attrs) {
dom.setAttribute(key, vnode.attrs[key]);
}
}
if (vnode.children) {
if (typeof vnode.children === "object") {
vnode.children.forEach((child) => {
dom.appendChild(render(child));
});
} else if (
typeof vnode.children === "string" ||
typeof vnode.children === "number"
) {
if (typeof vnode.children === "number") {
vnode.children = String(vnode.children);
}
dom.appendChild(document.createTextNode(vnode.children));
}
}
return dom;
}
function test() {
const vnode = {
tag: "DIV",
attrs: {
id: "app",
},
children: [
{
tag: "SPAN",
children: [
{
tag: "A",
children: [{ tag: "P", attrs: { text: "p" }, children: 123213 }],
},
],
},
{
tag: "SPAN",
children: [
{ tag: "A", children: [] },
{ tag: "A", children: [] },
],
},
],
};
const dom = render(vnode);
console.log(dom);
}
test(); |
题目要求,这里增加了具体的节点内容,便于理解。 把上诉虚拟Dom转化成下方真实Dom
<div id="app">
<span>
<a></a>
</span>
<span>
<a>123</a>
<a>456</a>
789
</span>
</div> 实现 const vDom = {
tag: 'DIV',
attrs: {
id: 'app'
},
children: [
{
tag: 'SPAN',
children: [{tag: 'A', children: []}]
},
{
tag: 'SPAN',
children: [
{tag: 'A', children: [123]},
{tag: 'A', children: [456]},
789
]
}
]
};
function render(vNode) {
// 递归终止条件
if (typeof vNode === 'number')
return document.createTextNode(String(vNode));
if (typeof vNode === 'string') return document.createTextNode(vNode);
const {tag, attrs = {}, children = []} = vNode;
const dom = document.createElement(tag);
Object.keys(attrs).forEach((attr) => {
dom.setAttribute(attr, attrs[attr]);
});
children.forEach((child) => {
dom.append(render(child));
});
return dom;
}
const dom = render(vDom); |
function render(vnode) {
if (typeof vnode === 'number') {
vnode = String(vnode)
}
if (typeof vnode === 'string') {
return document.createTextNode(vnode)
}
let dom = document.createElement(vnode.tag)
if (vnode.attrs) {
Object.keys(vnode.attrs).map(key => {
let value = vnode.attrs[key]
dom.setAttribute(key, value)
})
}
vnode.children && vnode.children.map(item => {
dom.appendChild(render(item))
})
return dom
} |
function render(data) {
const curNode = document.createElement(data.tag);
for (let key in curNode.attrs) {
curNode.setAttribute(key, curNode.attrs[key]);
}
for (let child of data.children) {
curNode.append(render(child));
}
return curNode;
} |
const renderDom = function (jsonDom) {
const mainEl = document.createElement(jsonDom?.tag?.toLowerCase());
if (jsonDom.attrs) {
Object.keys(jsonDom.attrs).forEach((attr) => {
mainEl.setAttribute(attr, jsonDom.attrs[attr]);
});
}
jsonDom.children.forEach((child) => {
mainEl.appendChild(renderDom(child));
});
return mainEl;
}; |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const jump = () => {
alert(666);
};
const vnode = {
tags: "div",
props: {
id: "box",
style: "width:100px; color:red",
},
children: [
{
tags: "a",
props: {
onClick: jump,
},
children: "hahaha",
},
],
};
const render = (vnode) => {
const { tags, props, children } = vnode;
const el = document.createElement(tags);
if (props) {
for (const key in props) {
const value = props[key];
if (key.startsWith("on")) {
el.addEventListener(key.slice(2).toLowerCase(), value);
} else {
el.setAttribute(key, value);
}
}
}
console.log(children);
if (children) {
if (typeof children === "string") {
el.textContent = children;
} else {
children.forEach((item) => {
el.appendChild(render(item));
});
}
}
return el;
};
document.body.appendChild(render(vnode));
</script>
</body>
</html> 就是mount的一些步骤 |
const render = (root) => {
const dfs = (vdom) => {
const { tag, attrs, children } = vdom
if (!vdom) {
return
}
const dom = document.createElement(tag)
if (attrs) {
Object.keys(attrs).forEach(key => {
dom.setAttribute(key, attrs[key])
})
}
if (Array.isArray(children) && children.length) {
children.forEach(item => {
dom.appendChild(dfs(item))
})
}
return dom
}
const res = dfs(root)
return res
} |
The text was updated successfully, but these errors were encountered: