Skip to content
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

前端实现虚拟 dom 转化为真实dom #34

Open
zuopf769 opened this issue Apr 25, 2023 · 1 comment
Open

前端实现虚拟 dom 转化为真实dom #34

zuopf769 opened this issue Apr 25, 2023 · 1 comment

Comments

@zuopf769
Copy link

根据虚拟 dom 对象类型判断,

若为数字则强制类型转换为字符串,若为字符串,则创建文字节点并返回;
若为普通 dom,则迭代 attrs 属性并为 dom 赋值,并对 dom 的 children 数组进行迭代,
数组中的每一项都经过 _render 函数处理返回真实 dom ,
最终通过 appendChild 添加到父元素 dom 上。

注意能用递归方法,说明 dom 的结构都是类似的,只是层级上有包含与被包含的关系。

@zuopf769
Copy link
Author

<!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>
            const vDom = {
                tag: 'DIV',
                attrs: {
                    id: 'app'
                },
                children: [
                    {
                        tag: 'SPAN',
                        children: [
                            { tag: 'A', children: ['1'] }
                        ]
                    },
                    {
                        tag: 'SPAN',
                        children: [
                            { tag: 'A', children: [2,3] },
                            { tag: 'A', children: [] }
                        ]
                    }
                ]
            }
            // 真正的渲染函数
            function _render(vnode) {
                // 这里的数据结构没有涉及到字符串和数字,这两个 if 可以省略,重点关注普通 dom 元素的情况
                console.log(typeof vnode);


                // 如果是数字类型转化为字符串
                if (typeof vnode === 'number') {
                    vnode = String(vnode);
                }

                // 字符串类型直接就是文本节点
                if (typeof vnode === 'string') {
                    return document.createTextNode(vnode);
                }

                // 普通DOM
                let 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;
            }

            const res=_render(vDom);
            console.log(res);
            document.body.appendChild(res);

    </script>
</body>
</html>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant