携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
为什么需要在vue中使用jsx
几年前面试的时候,被问过这个问题,当时我一脸懵,这两个东西为啥要混用呢?
直到后来,我遇到了这种场景。
tab切换展示组件,大部分组件展示表格,除了2个tab需要展示不同,这个不同,怎么处理呢?
-
当然可以直接改封装的tab组件,v-if条件渲染嘛
-
那如果后面再有其他需求,tab组件继续写if么
-
这个时候,组件就过于冗余啦
-
那怎么让组件统一处理呢?当然可以用render函数来抽象组件啦
-
render函数写法有多恶心,想必大家都知道 => 不知道的看段简单的ul,li布局
with(this){ // this 就是 vm return _c( 'div', { attrs:{"id":"app"} }, [ _c( 'div', [ _c( 'input', { directives:[ { name:"model", rawName:"v-model", value:(title), expression:"title" } ], domProps:{ "value":(title) }, on:{ "input":function($event){ if($event.target.composing)return; title=$event.target.value } } } ), _v(" "), (!title) ? _c( 'button', { on:{ "click":add } }, [_v("submit")] ): _e() ] ), _v(" "), // 空字符串节点 _c('div', [ _c( 'ul', _l((list),function(item){return _c('li',[_v(_s(item))])}) ) ] ) ] ) }
-
这...日子没法过了
-
于是我们就发现了jsx的好用,同样上述代码,可读性更高,更加精简
在vue中如何使用jsx
主要是依赖babel插件
- 安装babel依赖,
npm install babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props
- 配置.babelrc文件
"plugins": [ [ "transform-vue-jsx" ] ]
- 子组件是函数式组件
// content.js
export default {
name: 'content',
functional: true,
props: {
render: Function,
column: {
type: Object,
default: null
},
params: {
type: Object,
default: () => {}
}
},
render: (h, ctx) => {
const params = ctx.props.params
return ctx.props.render && ctx.props.render(h, params)
}
}
- 父组件引入
<el-tabs
v-model="activeName">
<el-tab-pane
v-for="item in tabList"
:key="item.code"
:label="item.label">
<span v-if="item.render">
<content
:params="item.params"
:render="item.render"
></content>
</span>
</el-tab-pane>
</el-tabs>
<script>
import Content from './content'
components: {
Content
},
</script>
template转jsx的语法转换
v-model
,v-if
,v-for
,v-html
,v-text
,vue中的指令
- jsx语法是不会有对应的指令的,所以我们就要实现这些指令的功能,对于
v-model
// 在vue中
<el-input
v-model="searchParams.searchVal">
</el-input>
// 对应jsx语法
function _input (value) {
this.searchParams.searchVal = value
},
item.render = (h, params) => {
// 这里也可以从params传入参数
return (
<el-input
value={this.searchParams.searchVal}
onInput={_input}>
</el-input>
)
}
v-if
其实就是判断语句,用&&或三元表达式
// 在vue中
<el-button v-if="show"></el-button>
// 对应jsx语法
item.render = (h, params) => {
return (
this.show && <el-button></el-button>
)
}
v-for
其实就是循环语句,用map
// 在vue中
<ul>
<li v-for="item in list">{{item.label}}</li>
</ul>
// jsx语法
item.render = (h, params) => {
return (
<ul>
{
list.map((item, index) => (
<li>{item.label}</li>
)
}
</ul>
)
}
v-html
item.render = (h, params) {
return (
<div> <div domPropsInnerHTML={htmlStr}></div> </div>
)
}
vue中el-input
组件上触发原生enter事件,@keyup.enter.native
对应nativeOnKeyup
// 在vue中
<el-input
@keyup.enter.native="onSearch"
></el-input>
// 在jsx中
item.render = (h, params) => {
function _keyup (e) {
if (e.keyCode === 13) {
// 13为enter键的键盘码
this.onSearch()
}
}
return (
<el-input
nativeOnKeyup={e => _keyup(e)}>
</el-input>
)
}
vue中的插槽,在jsx中用scopedSlots
// 在vue中
<el-table
:data="tableData">
<el-table-column
v-for="column in columnData"
:key="column.value"
:prop="column.value"
:label="column.value"
sortable
:sort-change="change">
<template slot-scope="scope">
<span>{{scope.row[column.value]}}</span>
</template>
</el-table-column>
</el-table>
// 在jsx中
item.render = (h, params) => {
return (
<el-table
data={tableData}>
{
columnData.map((column, index) => (
<el-table-column
prop={column.value}
label={column.label}
sortable
onSort-change={(...args) => sortChange(...args)}
scopedSlots={{
default: (scope) => <span>{scope.row[column.value]}</span>
}}>
</el-table-column>
))
}
</el-table>
)
}
组件用-
分隔的事件,在jsx中在第一段on后大写即可触发
比如el-table
的sort-change
,在jsx中是onSort-change
,第一段在on后大写即可,见上个例子