點燈坊

失くすものさえない今が強くなるチャンスよ

Vue + JSX 初體驗

Sam Xiao's Avatar 2021-01-05

Vue 傳統都會以 Template 處理 HTML,Script 處理 JavaScript,事實上 Vue 有另外一種寫法:在 redner() 以 JSX 完全在 JavaScript 處理 HTML。

Version

Vue 2.6.11

Setup

$ yarn add @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props --dev

Vue CLI 目前還沒有支援 JSX,需要自行安裝以上 package。

babel.config.js

module.exports = {
  presets: [
    '@vue/babel-preset-jsx'
  ]
}

修改 babel.config.jspresets

.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true
  },
  'extends': [
    'plugin:vue/essential',
    'eslint:recommended'
  ],
  parserOptions: {
    parser: 'babel-eslint'
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-unused-vars': 'off'
  }
}

16 行

'no-unused-vars': 'off'

加上 no-unused-vars': 'off',因為 render(h)h 為必要,但 ESLint 會檢查而導致編譯失敗。

JSX

jsx000

以 JSX 實現 Hello World。

let render = function(h) {
  let { message } = this

  return <p>Hello { message }</p>
}

export default {
  data: () => ({
    message: 'World'
  }),
  render
}

第 2 行

let render = function(h) {
  let { message } = this

  return <p>Hello { message }</p>
}

HTML 改在 render() 內直接 return,不必如 jQuery 那樣將 HTML 視為 String,直接在 JavaScript 寫 HTML 即可,這就是 JSX。

Ramda

jsx001

使用 map() 取代 v-for

import { map } from 'ramda'

let render = function(h) {
  let { books } = this

  return (
    <ul>
      { map(({ id, title }) => <li key={ id }>{ title }</li>, books) }
    </ul>
  )
}

export default {
  data: () => ({
    books: [
      { title: 'FP in JavaScript', price: 100 },
      { title: 'Programming Haskell', price: 200 },
      { title: 'Speaking JavaScript', price: 300 },
    ]
  }),
  render
}

第 4 行

let render = function(h) {
  let { books } = this

  return (
    <ul>
      { map(({ id, title }) => <li key={ id }>{ title }</li>, books) }
    </ul>
  )
}

直接以 Ramda 的 map() 取代 v-for 產生 HTML,這也使得 Ramda 不再只能處理資料,也能用在 HTML。

Conclusion

  • JSX 的優點在於直接是 JavaScript 一部分,因此 JavaScript 的強項如 first-class function、closure、IIFE、currying … 等技巧都能用於 JSX,也能使用 Ramda 組合出功能強大的 function 處理 HTML,不再如 template 只能用有限的 directive 處理

Reference

Vue, Babel Preset JSX