目的:


Vue 推荐在绝大多数情况下使用模板(template)来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。

 

render函数是什么:


简单的说,在vue中我们使用模板 (template) 语法组建页面的,也可以使用 Render函数利用js语言来构建DOM

因为Vue是虚拟DOM,所以在拿到(template)模板时也要转译成VNode的函数,而用render函数构建DOM,vue就免去了转译的过程。

当使用Render函数描述虚拟DOM时,Vue提供一个函数,这个函数是就构建虚拟DOM所需要的工具。官网给他起了个名字叫createElement。

传统创建模板render创建模板
<template>
  <div>
    <h1>标题h1</h1>
  </div>
</template>
<script>
export default {
  created () {},
  mounted () {},
  data () {
    return {}
  }
}
</script>

 

Vue.component('some-title', {
  render (h) {
    return h('h1', '标题h1')
  },
  created () {},
  mounted () {},
  data () {
    return {}
  }
})

 

 

 

 

 

页面 渲染过程图:


 

render函数怎么用:


 

1.一个新的vue 实例

import Vue from 'vue'
  
let VNode = new Vue({
    created () { // 生命周期
    },
    props: { },
    render ( h ) { // render 创建虚拟DOM 直到渲染
       return h ('div', {...}, [...])
    },
    methods: { // 方法
    },
    on: {
    },
    data () {
        return { // 数据
        }
    }
}).$mount()
  
export default VNode

 2.局部组件注册

<template>
  <div>
    <custom-div></custom-div>
  </div>
</template>
<script>
export default {
  created () {},
  mounted () {},
  components: {
    'custom-div': {
      render (h) {
        return h('div', `${this.level}: 一段文字`)
      },
      created () {},
      props: {
        level: {
          type: Number,
          default: 1
        }
      }
    }
  },
  data () {
    return {}
  }
}
</script>

3.全局组件注册

Vue.component('some-title', {
  render (h) {
    let ospan = h('span', { // 在h2元素内 插入 span 标签
      style: {
        color: 'red'
      }
    }, ' *')
 
 
    return h('h2', {
      on: {
        click: () => {
          alert('标题的点击事件')
        }
      }
    }, [`${this.level}:一些标题`, ospan])
  },
  props: {
    level: {
      type: Number,
      default: 1
    }
  }
})

 

Render常用属性解释:


{
  class: { // 类名
    main: true,
    'title-color': false
  },
  style: { // 样式
    color: '#fff',
    'background-color': 'blue'
  },
  attrs: { // 元素属性
    id: 'foo'
  },
  props: { // 数据绑定
    level: 1
  },
  on: {
    click () {
      console.log('点击事件')
    },
    mouseover () {} // 等等。。
  },
  nativeOn: { // 只作用于组件标签上
    click () {
      console.log('nativeOn事件')
    }
  },
  // DOM 属性
  domProps: {
    // innerHTML: '',
    // value: ''
  },
  // 如果组件是其他组件的子组件,需为插槽指定名称
  slot: 'name-of-slot',
  // 当前节点的唯一标识
  key: 'mykey',
  // 用来给元素或子组件注册引用信息
  ref: 'mydom'
}

1、class、 style、attrs与 (template) v-bind 原理相同 。

a、template 方法:

 

b、render 方法:         

render:(h) => {
  return h('h1',{
  class: {
        main: true,
        'title-color': false
      },
      style: {
        color: '#fff',
        'background-color': 'blue'
      },
      attrs: {
        id: 'foo'
      }
  })

以上两种方法最终呈现效果一致:

 

2、props 用于组件绑定参数

a、emplate 方法:

b、render 方法:

// some-component 组件
Vue.component('some-component', {
  render (h) {
    return h('h1', this.level)
  },
  props: {
    level: {
      type: Number,
      default: 0
    }
  }
})
// 挂载 some-component 组件的页面
Vue.component('some-div', {
  render (h) {
    return h('some-component', {
      props: {
        level: 1
      }
    })
  }
})

*这里要注意的是 在render中区分以下两种写法 第一种是 绑定参数, 第二种 是组件内接收的参

1 绑定参数2 接收参数
props: {
level: 1
},

 

props: {
  level: {
    type: Number,
    default: 0
  }
}

 

以上两种方法最终呈现效果一致:

 

3、on: {} 给元素绑定事件

a、Render写法。 这里除了 click, mouseover、keyup 等事件以外, 也是接收组件内$emit 自定义事件的地方

demo 
Vue.component('c-inner', {
  render (h) {
    return h('button', {
      attrs: { id: 'c-inner' },
      on: {
        click: () => {
          this.$emit('custom-event', '自定义事件.')
        }
      }
    }, this.names)
  },
  props: {
    names: String,
    default: ''
  }
})
Vue.component('some-component', {
  render (h) {
    return h('div', [
      h('c-inner', {
        on: {
          'custom-event': (value) => {
            this.customValue = value
          }
        },
        props: {
          names: '按钮'
        }
      }),
      h('h3', this.customValue)
    ])
  },
  data () {
    return {
      customValue: ''
    }
  }
})

 

点击按钮前:

点击按钮后:

b、template 写法

父组件子组件 c-inner
<template>
  <div>
    <c-inner @custom-event="customEvent" names="按钮"></c-inner>
    <h3>{{customValue}}</h3>
  </div>
</template>
<script>
import cInner from './custom/c-inner'
export default {
  components: {
    cInner
  },
  data () {
    return {
      customValue: ''
    }
  },
  methods: {
    customEvent (value) {
      this.customValue = value
    }
  }
}
</script>

 

<template>
  <div>
    <button @click="btn" id="c-inner">{{names}}</button>
  </div>
</template>
<script>
export default {
  name: 'c-inner',
  props: {
    names: {
      type: String,
      default: ''
    }
  },
  methods: {
    btn () {
      this.$emit('custom-event', '自定义事件')
    }
  }
}
</script>

 

4、nativeOn 事件

a、官方解释:仅对于组件,用于监听原生事件,而不是组件内部使用 `vm.$emit` 触发的事件。

b、当父组件要在子组件上使用 click 事件时, 并不能像普通html标签一样写

c、例:

c-1、普通html标签 : 这样写并没有什么问题

<div @click=“someFn”></div>

c-2、c-inner 组件标签:
<c-inner @click=“someFn”> :这样写 someFn 函数并不会触发
<c-inner @click.native=“someFn”>:如果加上native 便可以触发
在render 中 nativeOn 事件就是与以上内容同理 但仅用于组件

Vue.component('some-component', {
  render (h) {
    return h('div', [
      h('c-inner', {
        nativeOn: {
          click: () => {
            console.log('c-inner 事件')
          }
        },
        props: {
          names: '按钮'
        }
      })
    ])
  }
})

5、domProps

a、domProps 内接收的是原生dom属性。

b、在render 中的写法就是:

domProps: { innerHTML: '' }

Vue.component('some-component', {
  render (h) {
    return h('div', {
      domProps: {
        innerHTML: 'some Text'
     }
    }, ['无论此处输入什么,都不会被显示。'])
  }
})

最终呈现在页面中的效果:

 

6、slot 插槽

a、Render 写法

以下面代码为例 h('div', '最后一条') 并不能被渲染出来 因为使用了 具名插槽, 只有符合名称的插槽才会被使用。

Vue.component('c-contents', {
  render (h) {
    return h('div', this.$slots['c-inner'])
  }
})
// 主组件
Vue.component('some-div', {
  render (h) {
    let inners = []
    for (let i = 1; i <= 5; i++) {
      inners.push(h('h1', {
        slot: 'c-inner'
      }, i))
    }
    return h('div', [
      h('c-contents', {}, [...inners, h('div', '最后一条')])
    ])
  }
})

b、template 写法

父组件子组件 c-content

对应代码: 

<template>
  <div>
    <c-conents>
      <h1 slot="c-inner" v-for="(item, index) in 5" :key="index">{{index + 1}}</h1>
      <div>最后一条</div>
    </c-conents>
  </div>
</template>
<script>
import cConents from './custom/c-conents'
export default {
  components: {
    cConents
  }
}
</script>

 

 

对应代码: 

<template>
  <div>
    <slot name="c-inner"></slot>
  </div>
</template>
<script>
export default {
  name: 'c-contents'
}
</script>

 

在c-contents 组件内 this.$slots 打印信息:

最终呈现在页面中的效果:

 

 

 

 

Logo

前往低代码交流专区

更多推荐