一、为什么需要render函数
为了弥补一些template的弱项
- vue官方文档例子
<script type="text/x-template" id="anchored-heading-template">
<h1 v-if="level === 1">
<slot></slot>
</h1>
<h2 v-else-if="level === 2">
<slot></slot>
</h2>
<h3 v-else-if="level === 3">
<slot></slot>
</h3>
<h4 v-else-if="level === 4">
<slot></slot>
</h4>
<h5 v-else-if="level === 5">
<slot></slot>
</h5>
<h6 v-else-if="level === 6">
<slot></slot>
</h6>
</script>
Vue.component('anchored-heading', {
template: '#anchored-heading-template',
props: {
level: {
type: Number,
required: true
}
}
})
根据level去渲染对应的h标签,用template实现不但代码冗长,而且在每一个级别的标题中重复书写了 <slot></slot>
- 用render函数重写
Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // 标签名称
this.$slots.default // 子节点数组
)
},
props: {
level: {
type: Number,
required: true
}
}
})
这就是render函数的作用
二、render的用法
在vue中,我们使用HTML模板语法来构建DOM,而render函数可以让我们使用js来构建DOM.
vue官方提供了一个createElement方法,简称为h.
createElement方法一共分为3部分,依次为
- 最终渲染的标签,必要参数。
该值可以为常见的HTML标签字符串,如"div","a"等,可以为一个组件等。
(官方文档中描述为{String | Object | Function},一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数) - 相关属性,可选参数,由{ }包含。
常见的class,style,事件绑定等都在这里完成。
详细属性见官方文档 - 子节点,可选参数,由[ ]包含
如果我们要渲染一个div中一个a标签和p标签,就用createElement方法再创建,依次包含在子节点中
上个简单例子:
render: (h) => {
return h('div', {
class: {
warpper: true
},
on: {
click: () => {
console.log('点击事件')
}
},
"我是子节点"
})
}
// 以上代码最终会渲染出一个以下dom
<div class="warpper" onClick="console.log('点击事件')">
我是子节点
</div>
三、JSX
如果render函数很多,写起来会很费劲,这时,我们就需要用到jsx了
以上例子就可以简化为:
render: (h) => {
return (
<div class={{ warpper: true }} onClick="console.log('点击事件')">
我是子节点
</div>
)
}
以下是一些常用的用法
render (h) {
return (
<div
// normal attributes or component props.
id="foo"
// DOM properties are prefixed with `domProps`
domPropsInnerHTML="bar"
// event listeners are prefixed with `on` or `nativeOn`
onClick={this.clickHandler}
nativeOnClick={this.nativeClickHandler}
// other special top-level properties
class={{ foo: true, bar: false }}
style={{ color: 'red', fontSize: '14px' }}
key="key"
ref="ref"
// assign the `ref` is used on elements/components with v-for
refInFor
slot="slot">
</div>
)
}
v-if
v-if
render(){
return (
<div>
{this.show?'你帅':'你丑'}
</div>
)
}
复制代码
写三元表达式只能写简单的,那么复杂的还得用if/else
render(){
let ifText
if(this.show){
ifText=<p>你帅</p>
}else{
ifText=<p>你丑</p>
}
return (
<div>
{ifText}
</div>
)
}
v-for
data(){
return{
show:false,
list:[1,2,3,4]
}
},
render(){
return (
<div>
{this.list.map((v)=>{
return <p>{v}</p>
})}
</div>
)
}
v-model
<script>
export default {
name: "item",
data(){
return{
show:false,
list:[1,2,3,4],
text:'',
}
},
methods:{
input(e){
this.text=e.target.value
}
},
render(){
return (
<div>
<input type="text" value={this.text} onInput={this.input}/>
<p>{this.text}</p>
</div>
)
}
}
</script>
自定义组件
<script>
import HelloWolrd from './HelloWorld'
export default {
name: "item",
render(){
return (
<HelloWolrd/>
)
}
}
</script>