Comments (14)
// 真正的渲染函数
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;
}
from js-challenges.
仅完成题目要求版本,可以直接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>
from js-challenges.
function _render(vNode) {
// 解构
const {tag, attrs, children} = vNode;
const root = document.createElement(tag.toLowerCase());
for (const key in attrs) {
root.setAttribute(key, attrs[key])
}
// 字符串
if (typeof children === 'string') {
root.appendChild(document.createTextNode(children));
// 数组
} else if (Array.isArray(children) && children.length > 0) {
// 递归添加
children.forEach(item => root.appendChild(_render(item)))
}
return root
}
from js-challenges.
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
}
from js-challenges.
function render(vnode) {
const { tag, attrs = {}, children } = vnode
// 开始通过vnode去创建dom
const el = document.createElement(String(tag).toLocaleLowerCase())
// 处理 attrs
for (const key in attrs) {
el.setAttribute(key, attrs[key])
}
// 处理children
if(typeof children === 'string') {
// 如果children是字符串,当做文本文本节点插入
el.appendChild(document.createTextNode(children))
} else if(Array.isArray(children) && children.length > 0) {
// 如果是数组需要递归的render
children.forEach(child => render(child, el))
}
return el
}
from js-challenges.
function render(vnode) { const { tag, attrs = {}, children } = vnode // 开始通过vnode去创建dom const el = document.createElement(String(tag).toLocaleLowerCase()) // 处理 attrs for (const key in attrs) { el.setAttribute(key, attrs[key]) } // 处理children if(typeof children === 'string') { // 如果children是字符串,当做文本文本节点插入 el.appendChild(document.createTextNode(children)) } else if(Array.isArray(children) && children.length > 0) { // 如果是数组需要递归的render children.forEach(child => render(child, el)) } return el }
你忘记把子元素要添加到父元素中了吧?
from js-challenges.
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;
}
from js-challenges.
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;
}
from js-challenges.
/**
* {
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();
from js-challenges.
题目要求,这里增加了具体的节点内容,便于理解。
把上诉虚拟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);
from js-challenges.
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;
}
from js-challenges.
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;
};
from js-challenges.
<!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的一些步骤
from js-challenges.
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
}
from js-challenges.
Related Issues (20)
- 代理模式 HOT 1
- 装饰器模式 HOT 1
- 手写new关键字 HOT 1
- 实现有序数组生成平衡二叉搜索树,ACM模式(2023美团暑期实习一面手撕)
- 版本号排序(2023美团暑期实习一面) HOT 2
- 将html字符串转为树状结构
- 对象去重 HOT 2
- 【开源自荐】推荐一个每日更新的前端面试题库
- bind
- 我的解决方案
- 【开源自荐】SolidUI 一句话生成任何图形
- 百度2023秋招:把数组排成最小的数 HOT 5
- 实现简易版的useState HOT 1
- 手写Instanceof详细 HOT 1
- 现在有一大段Markdown文本,解析Markdown文本。并且能够根据这段文本自动生成目录,点击目录可以跳转到Markdown文本对应的位置。类似语雀的目录树。
- 求更新 HOT 1
- 下拉菜单过渡
- 全排列
- 数组乱序(时间复杂度O(n))
- 排序找第几个最大
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from js-challenges.