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