• 初试Vue3-手动实现render挂载


    初试Vue3-手动实现render挂载
    只实现了最简单的render新增节点挂载到指定dom上,数据响应式没实现,一点一点的研究吧

    <!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>
        <div id="app"></div>
        <script>
            // const {createApp} = Vue;
            const createAppAPI = (render) => {
                return function createApp(rootComponent) {
                    // 返回真正的应用程序实例,执行mount方法
                    const app = {
    
                        // 将传入的容器选择器 把vnode转变成dom 并挂载到容器
                        mount(rootContainer) {
                            // rootContainer 就是#app
                            // rootComponent 是传进来的 {data(){return{}},render(){tag:"h2",children:this.foo}}
                            // v3里面虚拟dom的变化
                            const vnode = {
                                tag: rootComponent
                            }
    
                            // 这一步非常重要哦,执行渲染
                            render(vnode, rootContainer)
                        }
                    }
    
    
                    return app
                }
            }
    
            // 2.实现renderer工厂函数
            const createRenderer = options => {
                const patch = (n1, n2, container) => {
                    /**
                     * n1 旧的虚拟节点
                     * n2 新的虚拟节点 根组件的配置在这里
                     * container 容器挂载
                     * */
    
                    const rootComponent = n2.tag; //为啥是n2.tag 可以往上找,createAppAPI里面定义的,当然也可以不叫tag
    
                    // 数据的上下文,要指向data的执行结果
                    const ctx = {...rootComponent.data()
                        }
                        /*
                         *ctx 的值是{foot:'hellov3'}
                         **/
    
                    // 执行render获取vnode
                    const vnode = rootComponent.render.call(ctx);
                    /**
                        执行实例里面render方法,拿到data里面的数据
                    **/
    
                    // 转换vnode dom 拿到要挂载的节点dom
                    const parent = options.querySelector(container);
    
                    // render里要添加的tagname,创建新节点
                    const child = options.createElement(vnode.tag);
    
                    //这里只判断了最简单的情况,其他类型还得再去源码中好好看
                    if (typeof vnode.children === 'string') {
                        child.textContent = vnode.children;
                        // textContent 文本内容
                    }
                    // 最后一步将虚拟dom转完的真实dom挂载到指定元素上
                    options.insert(child, parent)
                }
                const render = (vnode, container) => {
                    // 把虚拟dom变成真实dom并添加到container里
    
                    // 判断container上有没有虚拟dom
                    patch(container._vode || null, vnode, container);
    
                    container._vode = vnode;
                }
    
                // 该对象就是renderer
                return {
                    render,
                    createApp: createAppAPI(render)
                }
            }
    
    
            // 1.createApp  runtimedom->index.js createApp ensureRender  createRenderer
            const Vue = {
                createApp(options) {
                    // 执行的实际是renderer.createApp()
                    return renderer.createApp(options)
                }
            }
            const renderer = createRenderer({
                querySelector(sel) {
                    return document.querySelector(sel)
                },
                createElement(tag) {
                    return document.createElement(tag)
                },
                insert(child, parent) {
                    parent.appendChild(child)
                }
            })
            const {
                createApp
            } = Vue;
            createApp({
                data() {
                    return {
                        foo: "hello,vue3!"
                    }
                },
                render() {
                    return {
                        tag: "h2",
                        children: this.foo
                    }
                }
            }).mount('#app');
        </script>
    </body>
    
    </html>
    
  • 相关阅读:
    第02组 Beta版本演示
    2020系统综合实践8 大作业 智能门禁
    2020系统综合实践6 树莓派基本入门
    2020系统综合实践5 使用Dokcer部署Python运行环境
    2020系统综合实践4 Dokcer专题实践
    2020系统综合实践3 使用Docker Compose部署LNMP
    2020系统综合实践2 使用Dokcer部署Nginx和MySQL容器
    2020系统综合实践1 WSL 2的安装和基本使用
    2020系统综合实践1 VirtualBox下安装Debian踩坑小结
    团队第六次——beta冲刺日志集合
  • 原文地址:https://www.cnblogs.com/angfl/p/13858730.html
Copyright © 2020-2023  润新知