zl程序教程

您现在的位置是:首页 >  其它

当前栏目

render函数

函数 render
2023-06-13 09:12:15 时间

import Vue from 'vue'

const component = {
  name: 'comp',
  template: `
    <div :style="style">
      <slot></slot>
    </div>
  `,
  data () {
    return {
      style: {
        width: '200px',
        height: '200px',
        border: '1px solid #aaa'
      },
      value: 'component value'
    }
  }
}

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },

  methods: {
    handleClick () {
      console.log('clicked')
    }
  },
  template: `
    <comp-one ref="comp">
      <span ref="span">{{value}}</span>
    </comp-one>
  `

})

如上一个简单的vue组件引用示例,通过tempalte渲染成html页面

但vue是怎样将template渲染成html的呢 这里就用到了render函数 在使用template的时候,最终会被编译成render方法

我们可以结合上面template自己实现一下render

 template: `
    <comp-one ref="comp">
      <span ref="span">{{value}}</span>
    </comp-one>
        `,
        render(){
            return  this.$createElement
        }
}
)

$createElement:vue提供的创建节点的函数,在每个实例上都有这个函数,同时在使用render方法的时候createElement也会作为参数被传入进来 createElement(NodeName,attrs) 第一个参数 string 为节点名称 第二个参数 object 为节点给属性如id、ref 第三个参数为节点内容 arrsy,可以是节点字符串等

render(createElement){
    return createElement(
        'comp-one',
        {
            ref:'comp'
        },
        [
            createElement(
                'span',
                {
                    ref:'span'
                },
                this.value
                )]
  )
}

上面的render等同于template

component组件的render写法

...
render(createElement){
    return createElement(
        'div',
        {
            style:this.style
        },
        this.$slots.default 
        //默认插槽相当于<slot >
      //具名插槽写 this.$slots.name
        )
}
...

createElement创建出来的并不是真正的html节点,而是虚拟dom(vNode)

createElement常用属性

  1. props
//vue
render(createElement){
    return createElement(
        'comp-one',
        {
            ref:'comp',
                props:{
                    prop1:this.value
                }
        },
        [
            createElement(
                'span',
                {
                    ref:'span'
                },
                this.value
                )]
  )
}
//component接收
cont component = {
    props:['props1'],
        name:'comp'
        ...

}

2.绑定事件

//vue
methods:{
    handleClick(){
        
        }
},
render(createElement){
    return createElement(
        'comp-one',
        {
            ref:'comp',
                props:{
                    prop1:this.value
                },
                    //事件
               on:{
                  click:this.handleClick
               },
                    //直接绑定到组件根节点原生dom
                nativeOn:{
                        click:this.handleClick
                }
        }, 
    
        [
            createElement(
                'span',
                {
                    ref:'span'
                },
                this.value
                )]
  )
}
//component触发事件
cont component = {
    props:['props1'],
        name:'comp'
        ...
        render(createElement){
    return createElement(
        'div',
        {
            style:this.style,
                on:{
                    click:()=>{this.$emit('click')}
                }
        },
        this.$slots.default 
        //默认插槽相当于<slot >
      //具名插槽写 this.$slots.name
        )
}

}

3.attrs

...
createElement('span',
{
    ...
        attrs:{
            id:"test"
        }
}
)
...

虽然render函数看上去比较麻烦,但我们要实现一些灵活的组件时候render函数将非常有用 如 vue 实现tab切换