JSX是React出的一种对JavaScript的语法扩展。javascript
在Vue中大多数状况推荐使用模板语法,经过template中的Vue指令进行快速开发。可是template也是存在一些缺陷的,扩展难度大,形成逻辑冗余。这时候咱们就须要JavaScript
的彻底编程能力,结合render函数
与JSX
进行功能扩展。html
在JSX中,咱们能够在大括号中使用任何有效的JS表达式vue
// 动态渲染内容
let name = "Josh Perez"
let element = <h1>Hello {name}</h1>
// 动态绑定属性
let imgUrl = 'http://xxx.jpg'
let img = <img src={imgUrl} /> 复制代码
在
<>
中写HTML标签,在{}
中写js代码java
JSX代码自己也是js表达式,它表示的是一个js对象。react
// 在vue的render函数中,如下两种写法是等价的
render: function(createElement) {
let name = "Josh Perez"
let element = <h1 class="title">Hello {name}</h1>
return element
}
// ===》》
render: function(createElement) {
let name = "Josh Perez"
let element = createElement(
'h1',
{class: title},
`Hello ${name}`
)
return element
}
复制代码
事实上, Babel会把JSX语法转义成JS对象,也就是上述代码的后一种写法。git
在JSX中事件的命名采用小驼峰式(camelCase),而不是纯小写。github
methods: {
deleteRow(id) {
// todo
}
},
render: (h) => {
return <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
}
复制代码
在JSX中没法使用Vue中的v-if-else
指令,可使用Javascript中的运算符if
或者三元运算符
代替编程
// if运算符
let isEnable = props.isEnable
render(h) {
if(isEnable) {
return <button>禁用</button>
} else {
return <button>启用</button>
}
}
复制代码
// 三元运算符
let isEnable = props.isEnable
render(h) {
return <button>{isEnable ? '禁用' : '启用'}</button>
}
复制代码
在JSX中能够经过map
实现v-for
bash
render: (h) => {
const numbers = [1, 2, 3, 4, 5]
let listItems = numbers.map(number =>
<li>{number}</li>
)
return (
<ul>{listItems}</ul>
)
}
复制代码
实现key
属性的绑定iview
render: (h) => {
const numbers = [1, 2, 3, 4, 5]
let listItems = numbers.map(number =>
<li key={number.toString()}>{number}</li>
)
return (
<ul>{listItems}</ul>
)
}
复制代码
在JSX中嵌入map
render: (h) => {
const numbers = [1, 2, 3, 4, 5]
let listItems =
return (
<ul> { numbers.map(number => <li key={number.toString()}>{number}</li> ) } </ul>
)
}
复制代码
Vue 推荐在绝大多数状况下使用模板来建立你的 HTML。可是在开发过程当中template
并不能知足咱们的全部需求,在一些组件开发中比较常见
下面是我在工做中根据业务场景对Element UI中的table组件进行的扩展,或许能够加深一些对JSX的理解.
在开发后台管理系统时,不可避免的要进行大量数据列表的展现。目前比较流行的第三方组件库 Element UI,其列表渲染的代码以下:
<el-table :data="list">
<el-table-column prop="name" lable="姓名" width="150" align="center"></el-table-column>
<el-table-column prop="age" lable="年龄" width="150" align="center"></el-table-column>
.
.
.
</el-table>
复制代码
每一列都须要写一次el-table-column
标签,尤为在处理财务报表这种展现大批量类似数据时,是很是痛苦的。
咱们期待的效果是这样的:
<table :data="list" :columns="columns">
复制代码
data() {
return {
list: []
columns: []
}
}
复制代码
将列的描述信息放到js中,这样能够省去很多代码,代码结构也会清晰不少。具体实现过程以下:
基于Element UI 对table组件进行二次封装
<template>
<el-table :data="data" v-bind="$attrs">
<template v-for="(column, index) of columns">
<!-- render -->
<el-table-column v-if="column.render" v-bind="Object.assign({}, defaultColumnConfig, column)" :key="index">
<template slot-scope="scope">
<extend :render="column.render" :params="scope"></extend>
</template>
</el-table-column>
<!-- no render -->
<el-table-column v-else v-bind="Object.assign({}, defaultColumnConfig, column)" :key="index"></el-table-column>
</template>
</el-table>
</template>
<script> import extend from './extend.js' export default { components: { extend }, props: { data: { type: Array }, columns: { type: Array }, defaultColumnConfig: { type: Object } } } </script>
复制代码
经过extend
组件实现render
函数
export default {
props: {
params: {
type: Object
},
render: {
type: Function
}
},
render(h) {
return this.render(h, this.params)
}
}
复制代码
<template>
<y-table :data="list" :columns="columns" :defaultColumnConfig="defaultColumnConfig" border></y-table>
</template>
<script>
import YTable from "./index"
export default {
components: {
YTable
},
data() {
return {
list: [
{name: 1, age: 2, sex: 0}
],
defaultColumnConfig: {
width: 100,
align: 'center'
},
columns:[
{
prop: 'name',
label: '姓名',
age: 0,
width: 200
},
{
prop: 'age',
label: '年龄',
age: 1
},
{
label: '性别',
render(h,scope) {
return h(
'span',
{
style: {color: 'red'}
},
scope.row.sex === 0 ? '男' : '女'
)
}
},
{
label: '性别',
render(h,scope) {
return (
<span style="color: red">{scope.row.sex === 0 ? '男' : '女'}</span>
)
}
}
]
}
}
}
</script>
复制代码
渲染效果: