vue使用jsx语法
杨柒柒 人气:2为什么需要在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后大写即可,见上个例子
加载全部内容