What is JSX?
React JSX is a syntactic extension to JavaScript.
The template syntax is recommended in most cases in Vue for rapid development through the Vue directives in template. However, template also has some drawbacks, which make it difficult to expand and cause logical redundancy. This is where we need the full programming power of JavaScript to extend functionality with the Render function and JSX.
Basic usage
1. Embed expressions
In JSX, we can use any valid JS expression in braces
// Dynamically render content
let name = "Josh Perez"
let element = <h1>Hello {name}</h1>
// Dynamically bind attributes
let imgUrl = 'http://xxx.jpg'
let img = <img src={imgUrl} />
Copy the code
Write HTML tags in <> and JS code in {}
JSX code is itself a JS expression that represents a JS object.
// In vue's render function, the following two notations are equivalent
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
}
Copy the code
In fact, Babel escapes JSX syntax into JS objects, which is the latter version of the code above.
2. Bind events & V-on
In JSX, events are named in camelCase rather than pure lowercase.
methods: {
deleteRow(id) {
// todo}},render: (h) = > {
return <button onClick={(e)= > this.deleteRow(id, e)}>Delete Row</button>
}
Copy the code
3. Conditional rendering & V-if
The V-if-else directive in Vue cannot be used in JSX. The Javascript operator if or ternary operator can be used instead
// if operator
let isEnable = props.isEnable
render(h) {
if(isEnable) {
return <button>disable</button>
} else {
return <button>To enable the</button>}}Copy the code
// The ternary operator
let isEnable = props.isEnable
render(h) {
return <button>{isEnable ? 'Disable' : 'enable '}</button>
}
Copy the code
4. Lists & V-for
In JSX v-for can be implemented with map
render: (h) => {
const numbers = [1, 2, 3, 4, 5]
let listItems = numbers.map(number =>
<li>{number}</li>
)
return (
<ul>{listItems}</ul>
)
}
Copy the code
Implement the binding of the key property
render: (h) => {
const numbers = [1, 2, 3, 4, 5]
let listItems = numbers.map(number =>
<li key={number.toString()}>{number}</li>
)
return (
<ul>{listItems}</ul>
)
}
Copy the code
Embed a Map in JSX
render: (h) = > {
const numbers = [1.2.3.4.5]
let listItems =
return (
<ul>
{
numbers.map(number =>
<li key={number.toString()}>{number}</li>)}</ul>)}Copy the code
Practice & Table component encapsulation
Vue recommends using templates to create your HTML in most cases. However, the template does not meet all of our requirements during development, and is common in some component development
Here are some of the extensions I’ve made to the Table component of Element’S UI in my work, based on business scenarios, to perhaps deepen my understanding of JSX.
In the development of background management system, it is inevitable to display a large number of data lists. The list rendering code for Element UI, a popular third-party component library, is as follows:
<el-table :data="list">< el-table-column prop="name" lable=" name" width="150" align="center"></el-table-column> <el-table-column prop="age" Width ="150" align="center"></el-table-column>.. </el-table>Copy the code
The el-table-column label needs to be written once for each column, which is especially painful when dealing with financial statements that present large quantities of similar data.
Here’s what we’re looking for:
<table :data="list" :columns="columns">
Copy the code
data() {
return {
list: []
columns: []
}
}
Copy the code
Putting the column description into JS saves a lot of code and makes the code structure much clearer. The specific implementation process is as follows:
Encapsulation of the Table component
Secondary encapsulation of table components based on Element UI
<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>
Copy the code
The render function is implemented through the extend component
export default {
props: {
params: {
type: Object
},
render: {
type: Function
}
},
render(h) {
return this.render(h, this.params)
}
}
Copy the code
Specific usage & demo
<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: 'Name ', age: 0, width: 200}, {prop: 'age', label: 'age', age: 1}, {label: 'gender, render (h, scope) {return h (' span, {style: {color:' red '}}, the scope, row. Sex = = = 0? 'male' : 'female')}}, {label: Render (h,scope) {return (<span style="color: red">{scope.row. Sex === 0? 'female '}</span>)}}]}}</ script>Copy the code
Render effect:
reference
- react API
- Vue API
- Iview table component source code