为了账号安全,请及时绑定邮箱和手机立即绑定

初试Vue3-手动实现render挂载

初试Vue3-手动实现render挂载
Vue3发布后一直没机会研究,最近感兴趣,一点一点的看看,感兴趣的可以一起哈,有什么问题一起研究😜

    <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>

这里只实现了最简单的render渲染并挂载,并没有实现数据响应式,千里之行始于足下,慢慢慢的走也是在进步!代码里面加了很多备注,记录一下以后看。
千里之行始于足下,慢慢慢的走也是在进步!代码里面加了很多备注,记录一下以后看。千里之行始于足下,慢慢慢的走也是在进步!代码里面加了很多备注,记录一下以后看。

点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消