美文网首页
Vue render 以及createElement 解析

Vue render 以及createElement 解析

作者: 南枫小谨 | 来源:发表于2021-05-23 10:43 被阅读0次

    Vue中的template 里面使用的模版是HTML语法组件的页面,在Vue中都会被编译成render函数,Vue会采用虚拟dom进行页面组件渲染。

    render函数基本使用

    render不能与template 一起使用,否则无效。

    <script>
    export default {
        name:'render',
        render(createElement){
            return createElement('h1',{},'hello')
        }
    }
    </script>
    

    在APP.vue中引入Render.vue

    <template>
      <div id="app">
        <Render></Render> 
      </div>
    </template>
    
    <script>
    
    import Render from './components/Render'
    export default {
      name: 'App',
      components: {
        Render
      }
    }
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    通过render动态渲染节点 Render.vue 修改为

    <script>
    export default {
        name:'render',
        props:{
            tag:{
                type:String,
                required:true,
            },
            data:{
                type:String
            }
        },
        render(createElement){
            return createElement(this.tag,{},this.data)
        }
    }
    </script>
    

    App.Vue 中使用 :tag :data 传参

    <template>
      <div id="app">
        <Render :tag="'div'" :data="'Hello World!'" ></Render> 
      </div>
    </template>
    

    createElement 第二个参数可以设置属性

     render(createElement){
            return createElement(this.tag,{
               class:'render-color'
            },this.data)
        }
    
    <style scoped>
    .render-color{
        background-color: aqua;
    }
    </style>
    

    也可以使用 domProps 进行设置

    render(createElement){
            return createElement(this.tag,{
            //    class:'render-color',
               domProps:{
                   className:'render-color',
                   innerHTML:'hahhaha',  // 会替换传进来的data的值
               }
            },this.data)
        }
    

    createElement 第三个参数可以传一个数组,从而实现嵌套

     render(createElement){
            return createElement(this.tag,{
               class:'render-color',
              
            },[createElement('p',{},'balabal')])
        }
    

    createElement 简易版

    1. 创建一个createElement
     function Element(type,props,children){
            this.type = type
            this.props = props
            this.children = children
            
        }
        function createElement(type,props,children){
            return new Element(type,props,children)
        }
    
    1. 实现render 函数
    function render(obj){
            // 创建节点
            let el = document.createElement(obj.type)
            for (let key in obj.props){
                el.setAttribute(key,obj.props[key])
            }
           
            if(Array.isArray(obj.children)){
                obj.children.forEach(element => {
                    // 递归操作,如果当前child不是文本,就继续进行操作,否则创建文本节点
                    element = element instanceof Element? render(element):document.createTextNode()
                    el.appendChild(element)
                });
            }
            else if (typeof obj.children === 'string'){ // 如果是字符串当成数组进行递归
                el.appendChild(document.createTextNode(obj.children))
            }
    
            return el
        }
    

    完整代码

    <!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>
        
    </body>
    <script>
        let myDom = createElement('div',{class:'container',style:'color:red'},
        [
            createElement('p',{class:'item'},'child1'),
            createElement('p',{class:'item'},'child2'),
            createElement('p',{class:'item'},'child3'),
            createElement('input',{class:'item',value:'I am input'},'child4')
        ])
        let myDom2 = createElement('p',{class:'item'},'child23233')
        function Element(type,props,children){
            this.type = type
            this.props = props
            this.children = children
            
        }
        function createElement(type,props,children){
            return new Element(type,props,children)
        }
        function render(obj){
            // 创建节点
            let el = document.createElement(obj.type)
            for (let key in obj.props){
                el.setAttribute(key,obj.props[key])
            }
           
            if(Array.isArray(obj.children)){
                obj.children.forEach(element => {
                    // 递归操作,如果当前child不是文本,就继续进行操作,否则创建文本节点
                    element = element instanceof Element? render(element):document.createTextNode()
                    el.appendChild(element)
                });
            }
            else if (typeof obj.children === 'string'){ // 如果是字符串当成数组进行递归
                el.appendChild(document.createTextNode(obj.children))
            }
    
            return el
        }
        function renderDom(node,target){
            node.appendChild(target)
        }
      
        let node2 = render(myDom2)
        let app = document.getElementById('app')
        renderDom(app,render(myDom))
        renderDom(app,render(myDom2))
    
    </script>
    </html>
    <style>
        .container{
            font-weight: 700;
        }
        .item{
            background-color: darkolivegreen;
        }
    </style>
    

    相关文章

      网友评论

          本文标题:Vue render 以及createElement 解析

          本文链接:https://www.haomeiwen.com/subject/eafojltx.html