render方法的实质就是生成template模板,在项目中vue文件是通过template渲染的虚拟dom(VNode),render方法的实质就是生成template模板。(render函数只能用作组件来使用,不可以整个页面都用render函数js手写页面)
render函数的作用
有些场景中用 template
实现起来代码冗长繁琐而且有大量重复(写死的模式),这时候就可以用 render 函数
。
官网的例子:
//未使用render函数
Vue.component('anchored-heading', {
template: '#anchored-heading-template',
props: {
level: {
type: Number,
required: true
}
}
})
//使用render函数
Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // tag name 标签名称
this.$slots.default // 子组件中的阵列
)
},
props: {
level: {
type: Number,
required: true
}
}
})
如何使用
render函数涉及到vue里的一个核心思想:虚拟dom
vue通过建立一个虚拟的dom来追踪自己要如何改变真实dom
render函数的函数也是一个函数(createElement)
- render函数的返回值是VNode(虚拟节点)
- 有三个参数
- 第一个参数(必要参数):要渲染的html标签(类型字符串、对象或函数)
- 第二个参数(可选择):用于html标签的一些样式、属性、传的组件的参数、绑定事件之类(类型是对象)
- 第三个参数(可选择):虚拟子节点(VNodes),当前html标签的子元素(类型是数组,数组)
render:(createElement) {
// createElement函数返回结果是VNode
return createElement(
div,
{
//设置style
style:{ color:'#f00', fontSize:'20px' },
//设置html内容
//domProps:{ innerHtml: '我是小黄,今天很开心' },
//设置html的属性
attrs:{ id:'XXXID' }
},[
//creteElement(标签,innerHtml)
creteElement('h1','我是小黄,今天很开心')
creteElement('p','wo ai qian duan')
]
)
}
render函数使用场景
在封装一套通用的按钮组件的时候,按钮有四个样式(success、error、warning、default)
<div class="btn btn-success" v-if="type === 'success'">{{ text }}</div>
<div class="btn btn-danger" v-else-if="type === 'danger'">{{ text }}</div>
<div class="btn btn-warning" v-else-if="type === 'warning'">{{ text }}</div>
如果按钮10几个的话,使用template写死的方式就显得很无力了。遇上类似这样的情况,使用render函数可以说最优选择了。
export default {
props: {
type: {
type: String,
default: 'normal'
},
text: {
type: String,
default: 'normal'
}
},
computed: {
tag() {
switch (this.type) {
case 'success':
return 1;
case 'danger':
return 2;
case 'warning':
return 3;
default:
return 1;
}
}
},
render(h) {
return h('div', {
class: {
btn: true,
'btn-success': this.type === 'success',
'btn-danger': this.type === 'danger',
'btn-warning': this.type === 'warning'
},
domProps: {
innerText: this.text
},
on: {
click: this.handleClick
}
});
},
methods: {
handleClick() {
console.log('-----------------------');
console.log('do something');
}
}
};
然后在父组件调用
<Button type="danger" text="test"></Button>
使用jsx
要记住每个参数的类型同用法,按序传参实在是太麻烦了。那么其实可以用jsx来优化这个繁琐的过程。
render() {
return (
<div
class={{
btn: true,
'btn-success': this.type === 'success',
'btn-danger': this.type === 'danger',
'btn-warning': this.type === 'warning'
}}
onClick={this.handleClick}>
{this.text}
</div>
);
},
template和render函数对比
template --------- html的方式做渲染
render -------------- js的方式做渲染
render里有一个函数h,这个h的作用是将组件进行虚拟DOM的创建,然后再通过render进行解析。
- render渲染方式可以让我们将js发挥到极致,逻辑性比较强,适合复杂的组件封装。
- template是类似于html一样的模板来进行组件的封装。
- render的性能比template的性能好很多
- render函数优先级大于template