Custom Renderer自定义渲染器

在vue3.0中,为了更好的实现多平台应用,将渲染器的创建函数createRenderer方法单独分离出来,这个API可以用来自定义渲染逻辑,将Virtual DOM渲染为web平台真实DOM

作用:实现脱离于源码之外的各种跨平台操作

<!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>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="app"></div>
    <script>
        console.log(Vue)
    </script>
</body>
</html>

 我们可以看到控制台输出

 

 

 Vue是一个对象,暴露了很多的api

<body>
    <div id="app">
        {{count}}
    </div>
    <script>
        // console.log(Vue)
        let {createApp} =Vue;
        //创建app的实例
        createApp({
            data(){
                return {
                    count:2
                }
            }
        }).mount("#app")   //挂载到#app上
    </script>
</body>

 此时我们打开浏览器就可以看到

 

 

 我们也可以渲染组件

<body>
    <div id="app">
        {{count}}
        <fun></fun>  //调用组件并渲染
    </div>
    <script>
        // console.log(Vue)
        let {createApp} =Vue;
        //创建app的实例
        createApp({
            data(){
                return {
                    count:2
                }
            }
        }).component('fun',{   //创建一个组件
            template:"<div>fun</div>"
        }).mount("#app")
    </script>
</body>

 

 

 手写简单的vue初始化操作

1>挂载根组件

//创建app的实例   接收的是根组件的配置
        Vue.createApp({
            data(){
                return {
                    count:2
                }
            }
        }).mount("#app")

2>创建一个Vue

    // 创建Vue
     let Vue={
            // Vue这个对象提供一个createApp的方法,接收一个初始化的选项
         createApp(options){
                // 真正用来创建app的是renderer渲染器
                return renderer.createApp(options)
         }
     }

 3>创建renderer

 //创建一个renderer的实例来自一个工厂函数createRenderer  参数是dom操作
        let renderer=createRenderer({
            createElement(tag){
                return document.createElement(tag)
            },
            insert(child,parent){
                parent.appendChild(child)
            }
        })

 4>创建createRenderer 工厂函数

let createRenderer=({createElement,insert})=>{
            // 把vnode渲染为真是的dom
            let render=(vnode,container)=>{
                //返回真正的渲染器
                //解析vnode变成真是的dom
                let child=createElement(vnode.tag)
                if(typeof vnode.children==='string'){
                    child.textContent=vnode.children;
                }
                //省略了多个子元素的情况
                //追加节点
                insert(child,container)
            }
            //   返回真正的渲染器
            return {
                render,
                createApp:createAppAPI(render)
            }
        }

 5>创建真正的createApp方法的createAppAPI

let createAppAPI=(render)=>{
            //返回一个真正的createApp函数
            return function createApp(rootComponent){
                //核心创建app实例
                //app实例需要定义mount方法    use  component方法等方法
                let app={
                    //rootcontainer是一个宿主元素
                    mount(rootcontainer){
                        //调用传进来的render函数
                        //手动创建一个虚拟dom
                        let vnode ={
                            tag:'h3',
                            props:null,
                            children:rootComponent.data().count+''
                        }
                        render(vnode,document.querySelector(rootcontainer))
                    }
                }
                return app
            }
        }

此时节点就以<h3>渲染

 

 

posted @ 2021-11-09 16:02  keyeking  阅读(1203)  评论(0编辑  收藏  举报