前言
真的,一定会有一些小伙伴直到完整了几个项目都做完了,却从未用过渲染函数和JSX,所以一旦遇到需要复杂处理的模板元素,其中就会夹杂大量的v-if
、v-else
、v-else-if
……以及各种三元操作符。是时候了解一下渲染函数和JSX了,即便Vue 3在几个月后就要问世,学习一下JSX绝对没有坏处,也不会过时,JSX是React一直推崇的描述模板的方法,算是业界通用的一项技术。
官网
https://cn.vuejs.org/v2/guide/render-function.html
为什么有官网介绍,还要来个教程
官网教程是基于运行时版本的Vue.js,按照全局组件的模式为例,而我们通常是使用完整版的Vue.js,且使用单文件组件,所以本文以单文件组件为例说明。
渲染函数和JSX适用场景
当你模板中存在大量条件判断时,就适用渲染函数和JSX。比如在class中、style中、文本中、属性中存在条件判断时,会将模板搞得很冗长,而且不容易阅读,这时候适用渲染函数和JSX会让代码变得很清晰。
Hello World
- 在components文件夹创建HelloWorld.vue,内容是:
- 父组件按照常规的子组件调用方法调用即可:
xyz
JS代码从略。
效果是渲染出一段DOM:
。
-
讲一下HelloWorld.vue。其中props和methods不解释,只说render。render负责渲染一段DOM,前提是要给它传入VDOM,而createElement就是负责构建VDOM,我们只需要关心createElement的参数就行了。这里官网都有介绍,简单说:
第一个参数负责声明顶级元素的标签名,也就是说,标签名到底是button还是div还是h2还是span还是其他什么。
第二个参数就是对顶级元素的所有修饰,官网都有解释,这里只列一下:
- class
- style
- attrs
- props
- domProps
- on
- nativeOn
- directives
- scopedSlots
- slot
- key
- ref
- refInFor
第三个参数是可选的,是一个数组,每一个数组元素也就是一个子元素,如果是文本,直接写字符串,如果是元素,就要继续写
create('标签名', {修饰对象})
,这样一层一层写下去。从实践说,如果层数太多,反而不如单文件的标签直观,所以尽量保持2层即可。
循环创建元素
使用v-for可以在模板中循环创建元素,在createElement里当然也可以。
官方举了一个例子,但实践中一般用不到,因为实践中往往将一个数组映射成一系列元素:
官网例子:
render: function (createElement) {
return createElement('div',
Array.apply(null, { length: 20 }).map(function () {
return createElement('p', 'hi')
})
)
}
更贴近实践的例子,dataList靠父组件传入,然后利用map返回一系列相似的子元素:
render: function (createElement) {
return createElement('div',
this.dataList.map(function () {
return createElement('p', {
// ...
})
})
)
}
如何对应里的v-for/v-model/v-if/v-else指令
如何对应v-for上面已经说了,就用map就可以了。
如何对应v-model略复杂,官网有专门介绍,不说了。
v-if这类条件指令,用JS的原生if...else...即可。这里不介绍用法,但是强调一点,这就是渲染函数最有优势的地方。比如,一套条件语句如下所示,想象一下,如果将这套判断逻辑实现到标签里,会是多么的恐怖,多么难以理解,某个else是哪个if的else?看的眼花。而在JS中,if...else...就会直观得多。
if () {
if () {
if () {
}
} else {
}
} else {
}
事件和插槽
很容易,阅读官网即可。
JSX
终于到JSX了,官网的介绍比较简单。JSX说白了就是将里的标签直接写到JS里,这本身在JS里是行不通的,只能依靠插件来编译。比如官方的示例:
render: function (h) {
return (
Hello world!
)
}
在JS里用括号包裹一段像DOM的东西,而且还不是字符串,这在JS里是绝对行不通的,因此想用JSX就必须用插件编译成正常的模板,https://github.com/vuejs/jsx有介绍。
注意几点:
JSX的一个原则是从简、小片段原则,所以不要将计算过程写入JSX中,如果写入的话,又跟一样了,比如你要计算class的值,你需要在return之前,先声明一个变量比如叫classVal,然后通过一系列的JS运算算出classVal的值,然后JSX里面只能写上像上文那样比较简单的内容,比如
。
JSX默认不支持v-if等v-*指令,只支持非常少的几个指令,需要再额外装插件来弥补。
JSX支持三元操作符,在
{}
里使用即可。
总之,vue没有主打JSX,而且JSX本身也比较弱,至少在Vue里,不是良药。