目的:
Vue 推荐在绝大多数情况下使用模板(template)来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
render函数是什么:
简单的说,在vue中我们使用模板 (template) 语法组建页面的,也可以使用 Render函数利用js语言来构建DOM
因为Vue是虚拟DOM,所以在拿到(template)模板时也要转译成VNode的函数,而用render函数构建DOM,vue就免去了转译的过程。
当使用Render函数描述虚拟DOM时,Vue提供一个函数,这个函数是就构建虚拟DOM所需要的工具。官网给他起了个名字叫createElement。
传统创建模板 | render创建模板 |
---|---|
|
|
页面 渲染过程图:
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 接收参数 |
---|---|
|
|
以上两种方法最终呈现效果一致:
3、on: {} 给元素绑定事件
a、Render写法。 这里除了 click, mouseover、keyup 等事件以外, 也是接收组件内$emit 自定义事件的地方
demo | |
---|---|
| 点击按钮前: 点击按钮后: |
b、template 写法
父组件 | 子组件 c-inner |
---|---|
|
|
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 |
---|---|
对应代码:
| 对应代码:
|
在c-contents 组件内 this.$slots 打印信息:
最终呈现在页面中的效果: