mini-react 动态渲染复杂的DOM结构

目标

实现一个更通用的虚拟DOM创建和渲染机制,能够动态渲染复杂的DOM结构

分析

  1. 创建虚拟DOM元素的函数 createElementcreateTextNodeElement
  2. 使用递归的方式将虚拟DOM转换为真实DOM并渲染到页面上
  3. 支持多层嵌套的虚拟DOM结构

关键点

  • 递归渲染函数 renderElement,根据虚拟DOM的类型创建对应的真实DOM节点
  • 处理文本节点和普通节点的区别
  • 遍历子节点并递归调用渲染函数

代码实现

创建文本虚拟DOM元素

javascript 复制代码
/**
 * 创建一个文本虚拟DOM元素
 * @param {*} text 
 * @returns 
 */
const createTextNodeElement = (text) => {
    return {
        type: 'TEXT_ELEMENT',
        props: {
            nodeValue: text,
            children: []
        }
    }
}

创建虚拟DOM元素

javascript 复制代码
/**
 * 创建一个虚拟DOM元素
 * @param {*} type 
 * @param {*} props 
 * @param  {...any} children 
 * @returns 
 */
const createElement = (type, props, ...children) => {
    return {
        type,
        props: {
            ...props,
            children: children.map(child => {
                // 如果子节点是对象,直接返回;如果是文本,则创建文本虚拟DOM元素
                return typeof child === 'object' ? child : createTextNodeElement(child);
            })
        }
    }
}

递归渲染虚拟DOM到真实DOM

javascript 复制代码
/**
 * 递归渲染虚拟DOM到真实DOM
 * 渲染算法实现逻辑:
 * 1. 判断虚拟DOM的类型,如果是文本节点则创建文本节点,否则创建对应的元素节点
 * 2. 设置元素节点的属性
 * 3. 遍历子节点,递归调用渲染函数,并将子节点添加到父节点下
 * 4. 返回创建的真实DOM节点
 * @param {*} element 
 * @returns 
 */
const renderElement = (element) => {
    let dom;
    if (element.type === 'TEXT_ELEMENT') {
        dom = document.createTextNode('');
        dom.nodeValue = element.props.nodeValue;
    } else {
        dom = document.createElement(element.type);
        // 设置属性
        for (const prop in element.props) {
            if (prop !== 'children') {
                dom[prop] = element.props[prop];
            }
        }
    }

    // 递归渲染子节点
    element.props?.children.forEach(child => {
        dom.appendChild(renderElement(child));
    });

    return dom;
}

创建复杂的虚拟DOM结构并渲染

javascript 复制代码
// 创建一个复杂的虚拟DOM结构, 可以无限的添加
const App = createElement(
    'div',
    { id: 'app' },
    createElement(
        'div',
        { id: 'div1' },
        createElement(
            'p',
            { id: 'p1' },
            createElement(
                'span', {},
                createTextNodeElement('Nested span inside paragraph.')
            )
        ),
        createTextNodeElement('Hello Mini React V5')
    ),
    "This is Mini React V5",
    createElement(
        'p',
        {},
        createTextNodeElement('This is a paragraph in Mini React V5.')
    )
);

// 渲染虚拟DOM到页面上
const dom = renderElement(App);
document.querySelector('#root').appendChild(dom);

console.log(dom);

实现总结

以上代码实现了一个更通用的虚拟DOM创建和渲染机制,包含以下几个步骤:

  1. 创建文本虚拟DOM元素函数 createTextNodeElement
  2. 创建普通虚拟DOM元素函数 createElement
  3. 递归渲染函数 renderElement,根据虚拟DOM的类型创建对应的真实DOM节点,并处理子节点的递归渲染
  4. 创建一个复杂的虚拟DOM结构 App,并将其渲染到页面上,最终在页面上显示出相应的内容

注意事项

当前实现方式支持多层嵌套的虚拟DOM结构,并能够动态渲染复杂的DOM结构

存在问题

并没有真正意义上的动态创建虚拟DOM元素对象,后续版本会改进这个问题,实现更完善的虚拟DOM创建和渲染机制。

相关推荐
少油少盐不要辣3 分钟前
前端如何处理AI模型返回的流数据
前端·javascript·人工智能
IT_陈寒6 分钟前
Java21新特性实战:5个杀手级改进让你的开发效率提升40%
前端·人工智能·后端
跟着珅聪学java6 分钟前
以下是使用JavaScript动态拼接数组内容到HTML的多种方法及示例:
开发语言·前端·javascript
BD_Marathon9 分钟前
NPM_配置的补充说明
前端·npm·node.js
巴拉巴拉~~14 分钟前
KMP 算法通用图表组件:KmpChartWidget 多维度可视化 + PMT 表渲染 + 性能对比
前端·javascript·microsoft
智算菩萨20 分钟前
基于spaCy的英文自然语言处理系统:低频词提取与高级文本分析
前端·javascript·easyui
刘一说30 分钟前
Vue单页应用(SPA)开发全解析:从原理到最佳实践
前端·javascript·vue.js
疯狂成瘾者31 分钟前
前端vue核心知识点
前端·javascript·vue.js
Laravel技术社区1 小时前
用PHP8实现斗地主游戏,实现三带一,三带二,四带二,顺子,王炸功能(第二集)
前端·游戏·php
m0_738120723 小时前
应急响应——知攻善防Web-3靶机详细教程
服务器·前端·网络·安全·web安全·php