学习下vue的渲染函数

124 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

前言

用vue开发项目,我们平时用的模板(template)比较多,因为我们还是在template上面写html代码,可读性相对渲染函数(render)好一些。

但是render相对template来说渲染快一点,因为template需要先转成render函数。而且有些组件库的源码就是用render函数写的,我之前的写的从el-table的slot自定义内容里学到的el-table就用到render函数和this.$scopedSlots

所以我们今天来学习vue的渲染函数,这样下次如果需要使用也能快速使用。

渲染函数

在vue中使用渲染函数,是通过render函数,一般是接受一个参数createElement(函数组件除外),这个createElement,也是函数,返回虚拟dom,一般简写h

{
 render (h) {
   return h('div', 'hello world!')
 }
}

// 最后渲染出来就是<div>hello world!</div>

它接受三个参数。

  • 第一个参数, 必填

    类型: string / object / function

    • 如果是string,则参数是标签名,比如是div,h1,span等标签。
    • 如果是object,则参数是组件选项对象。比如h(componentName),componentName为引入的组件。
    • 如果是funciton,则参数是async异步函数,然后resolve的是上面2种值其中的一种。
  • 第二个参数,选填

    类型: object

    虚拟dom的数据对象,会传给当前的虚拟dom。

    数据对象支持传以下属性

    • class

      类名,支持对象,字符串,或者对象组成的数组

    • style

      样式 支持对象,字符串,或者对象组成的数组

    • attrs

      标签的属性 最终赋值到标签身上,对象类型

    • domProps

      dom的属性,对象类型

    • props

      传给组件的props,对象类型

    • on

      事件监听,对象类型,不支持简写修饰符,比如.stop,.prevent

    • nativeOn

      需要写在组件上,监听原生事件,比如input,click等,vue的自定义事件不会触发。对象类型

    • directives

      vue的指令,数组类型

    • scopedSlots

      vue的作用域插槽,对象类型,键值可以是虚拟dom,或者虚拟dom组成的数组。

    • slot

      vue的插槽,字符串类型

    • key

      vue的key属性,字符串类型

    • ref

      template的ref一样,可以快速访问dom或者vue实例,字符串类型。

    用数据对象写个例子:

      {
        class: {
          'box': true, // 类名加上box
          'container': false // 类名不会container
        },
        style: {
          color: 'red'
        },
        attrs: {
          name: '答案cp3'
        },
        domProps: {
          innerHTML: '答案cp3'
        },
        props: {
          id: 'a'
        },
        on: {
          click: () => {
            console.log(this)
          }
        },
        nativeOn: {
          click: () => {
            console.log(this)
          }
        },
        scopedSlots: {
          a: (props) => h('div', 'hi')
        },
        slots: 'slotName',
        key: 'a',
        ref: 'refDom'
      }
    
    

    第三个参数,选填

    类型:String / Array

    子节点的虚拟dom,可以是字符串,代表子节点的内容,或者虚拟dom组成的数组。

例子

普通元素:

  render (h) {
    return h('div', {
      class: {
        box: true
      },
      style: {
        color: 'red'
      },
      attrs: {
        name: '答案cp3'
      },
      on: {
        click: () => {
          console.log(this)
        }
      },
      key: 'a',
    }, 'hello world!')
  }

渲染结果:

image.png

渲染自定义组件:

// child.vue
<template>
  <div>
    <slot></slot>
    <slot name="a"></slot>
  </div>
</template>
 import child from './child.vue'
  render (h) {
    return h(child, {
      scopedSlots: {
        a: (props) => h('h1', '答案cp3')
      },
    }, 'hello world!')
  }

image.png