推荐答案
// www.javascriptcn.com code example
function render(vdom, container) {
if (typeof vdom === 'string' || typeof vdom === 'number') {
// 如果 vdom 是字符串或数字,直接创建文本节点
container.appendChild(document.createTextNode(vdom));
return;
}
// 创建元素节点
const element = document.createElement(vdom.type);
// 处理属性
if (vdom.props) {
Object.keys(vdom.props).forEach(prop => {
if (prop === 'children') {
// 递归处理子节点
vdom.props.children.forEach(child => render(child, element));
} else if (prop.startsWith('on') && typeof vdom.props[prop] === 'function') {
// 处理事件
const eventType = prop.toLowerCase().substring(2);
element.addEventListener(eventType, vdom.props[prop]);
} else {
// 处理普通属性
element.setAttribute(prop, vdom.props[prop]);
}
});
}
// 将元素插入到容器中
container.appendChild(element);
}本题详细解读
1. 函数功能
render(vdom, container) 函数的作用是将虚拟 DOM(vdom)渲染成真实 DOM,并将其插入到指定的容器(container)中。
2. 参数说明
vdom: 虚拟 DOM 对象,通常是一个包含type和props属性的对象。container: 真实 DOM 容器,通常是document.getElementById('root')这样的 DOM 元素。
3. 实现步骤
- 处理文本节点:如果
vdom是字符串或数字,直接创建文本节点并插入到容器中。 - 创建元素节点:根据
vdom.type创建对应的 DOM 元素。 - 处理属性:
- 如果属性是
children,递归调用render函数处理子节点。 - 如果属性是事件(以
on开头),则添加事件监听器。 - 其他普通属性直接通过
setAttribute方法设置。
- 如果属性是
- 插入容器:将创建好的 DOM 元素插入到指定的容器中。
4. 代码分析
- 递归处理子节点:通过递归调用
render函数,可以处理任意深度的虚拟 DOM 树。 - 事件处理:通过判断属性名是否以
on开头,可以动态添加事件监听器。 - 属性设置:使用
setAttribute方法可以处理大部分 HTML 属性。
5. 使用示例
// www.javascriptcn.com code example
const vdom = {
type: 'div',
props: {
className: 'container',
children: [
{ type: 'h1', props: { children: 'Hello, World!' } },
{ type: 'p', props: { children: 'This is a paragraph.' } }
]
}
};
render(vdom, document.getElementById('root'));这个示例会将一个包含 h1 和 p 标签的 div 渲染到 id 为 root 的容器中。