亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

初試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下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消