如何在 Vue 中使用 JSX 以及使用它的緣由

做者:JThtml

譯者:前端小智前端

來源:scotch.io/vue

點贊再看,養成習慣node

本文 GitHub github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。git

Vue.js 具備簡單的 API 和幾個選項,可用於在咱們的組件中定義HTML模板。github

咱們可使用<template>標籤選項,在根組件實例上定義template屬性,或者使用單文件組件。面試

上面的選項很棒而且能夠完美地工做,可是,在您的應用程序的生命週期中,有時會感到笨拙,設計過分或很是不靈活。npm

那麼,咱們爲何要使用 JSX 而不是其餘模板定義呢?編程

  • JSX 更易讀,<div></div> 的寫法一看就是比 this.$createElement('div', {}, [...]) 簡潔不少。
  • JSX 也是 JavaScript。
  • Vue支持JSX。
  • JSX 使自定義 Vue 組件更容易導入和管理。

簡介

先舉一個例子來講明爲何 JSX 是好的。json

咱們要構建一個<TextField/>組件,該組件能夠是普通的單行文本輸入或多行輸入(文本區域)。 咱們的模板聲明可能看起來像這樣。

<div>
   <textarea v-if="multiline" v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
   <input v-else v-model="content" :name="name" :placeholder="placeholder" :aria-invalid="false">
 </div>
複製代碼

從上面的代碼片斷中能夠看到,咱們很快就會遇到一些問題,好比重複代碼等等。想象一下,必須支持input上面所列的各類屬性。上面的這個小片斷將會增加併成爲一個難以維護的噩夢。

要解決這個問題,咱們須要使用Vue進行降級處理,所以須要使用理接近Vue的內部API來解決這個問題。

render() 方法

注意:這裏並非說沒有JSX就沒有一種簡單的方法來處理上面的問題,只是說將這個邏輯移動到帶有JSX的render()方法可使組件更直觀。

咱們在 Vue 中建立的每一個組件都有一個render方法。這個就是 Vue 選擇渲染組件的地方。即便咱們不定義這個方法,Vue 也會爲咱們作這件事。

這意味着當咱們在 Vue 中定義 HTML 模板時,Vue 的模板編譯器將其編譯爲一個createElement函數,該函數帶有幾個參數並從render函數返回結果。

爲了修復上一節中的代碼,咱們刪除了template屬性或template標籤,並在組件上定義了render()方法。 若是在組件上定義了render方法,則 Vue 將忽略template定義。

...
 export default {
     name: 'TextField',
     render (createElement) {
         const tag = this.multiline ? 'textarea' : 'input'

        return createElement(tag, {
             class: {
                 'text-input': true,
                 'is-disabled': false
             },
             attrs: {
                 name: this.name,
                 placeholder: this.placeholder,
                 'aria-invalid': false
             }
         })
     } 
 }
...
複製代碼

上面的代碼作了幾件事:

  1. render方法從Vue獲取一個createElement助手。
  2. 咱們以編程方式定義咱們的標籤。
  3. 而後,咱們建立標籤並將其屬性,類等做爲對象傳遞。 咱們能夠傳遞給createElement選項不少。
  4. 咱們返回新建立的元素進行渲染。

咱們爲 Vue 組件定義的每一個模板都將轉換爲可返回createElement函數的render方法。 由於這個緣由,render方法將優先於模板定義。

舉個例子:

// HTML
<div>
  <p>Only you can stop forest fires</p>
</div>
複製代碼

模板編譯器將把上面的 HTML 轉換成:

...
render (createElement) {
  return createElement(
    'div',
    {},
    createElement(
      'p',
      {},
      'Only you can stop forest fires'
    )
  )
}
...
複製代碼

如今你可能會問這個問題:「對可讀性來講這很差嗎?」 答案是確定的。 一旦定義了具備許多元素嵌套級別或具備多個同級元素的組件,咱們就會遇到這個新問題。

這就是 JSX 出現的緣由,它能夠很好的解決此類問題。

JSX 是什麼

JSX 是 Facebook 工程團隊創造的一個術語。

JSX 是 JavaScript 的相似XML的語法擴展,沒有任何定義的語義。

JSX 不打算由引擎或瀏覽器實現。相反,咱們將使用 Babel 之類的轉置器將JSX轉換成常規的 JS 。

// 此行是JSX的示例
const heading = <h1>Welcome to Scotch</h1>;
複製代碼

基本上,JSX 容許咱們在 JS 中使用相似 Html 的語法。

配置 Vue 以使用 JSX

若是使用的 Vue-cli 大於或等於 3.0 版本,那麼就直接可使用JSX的語法了。

若是您使用的是不支持 JSX 的Vue-cli較舊版本,則能夠經過安裝babel-preset-vue-app來添加它,並將其添加到您的.babelrc文件中。

# Using npm
 npm install --save-dev babel-preset-vue-app

# Using yarn
 yarn add --dev babel-preset-vue-app
複製代碼

.babelrc文件中,添加:

{
 "presets": ["vue-app"]
}
複製代碼

咱們如今能夠在組件的render函數中使用 JSX。

在 Vue 中使用 JSX 須要注意的地方

在 Vue 中使用JSX須要注意幾點。

要監聽 JSX 中的事件,咱們須要「on」前綴。 例如,將onClick用於單擊事件。

render (createElement) {
     return (
         <button onClick={this.handleClick}></button>
     )
 }
複製代碼

要修改事件,請使用

render (createElement) {
     return (
         <button onClick:prevent={this.handleClick}></button>
     )
 }
複製代碼

綁定變量,注意這裏不是使用 :

render (createElement) {
     return (
         <button content={this.generatedText}></button>
     )
 }
複製代碼

將HTML字符串設置爲元素的內容,使用domPropsInnerHTML而不是使用v-html

render (createElement) {
     return (
         <button domPropsInnerHTML={htmlContent}></button>
     )
 }
複製代碼

咱們也能夠展開一個大對象:

render (createElement) {
     return (
         <button {...this.largeProps}></button>
     )
 }
複製代碼

在 render 中使用JSX

回到咱們最初的「TextField」組件。如今咱們已經在 Vue 應用程序中啓用了 JSX,咱們如今能夠這樣作了。

render (createElement) {
     const inputAttributes = {
         class: 'input-field has-outline', // class definition
         onClick: this.handleClick // event handler
         backdrop: false // custom prop
     }
     const inputMarkup = this.multiline
         ? <textarea {...inputAttributes}></textarea>
         : <input {...inputAttributes}/>


    return inputMarkup
 }
複製代碼

導入 Vue JS 組件

在 Vue 中使用JSX的另外一個好處是,咱們再也不須要註冊所需的每一個組件。 咱們只是導入和使用。

import {Button} from '../components'

export default {
     render (createElement) {
         return <Button primary={true}>Edit</Button>
     }
 }
複製代碼

如何使 JSX 與 TypeScript 一塊兒使用

TypeScript 用做一種向 JavaScript添加類型檢查的機制。要在 JSX 支持 TypeScript中,須要修改 tsconfig.json

要在 TypeScript 中啓用 JSX,請先將該文件另存爲.tsx文件,而後將tsconfig.json修改成包括:

{
   "compilerOptions": {
     ....
     "jsx": "preserve",
   }
 }
複製代碼

jsx選項設置爲「preserve」意味着 TypeScript 不該處理JSX。 這樣作使 Babel 能夠控制全部JSX 和 TypeScript 堅持使用類型,由於它尚不支持 Vue JSX。

而後在項目中建立一個jsx.d.ts文件,併爲 Vue 添加 TypeScript JSX 聲明。

import Vue, {VNode} from 'vue'

declare global {
   namespace JSX {
     interface Element extends VNode {}
     interface ElementClass extends Vue {}
     interface ElementAttributesProperty {
       $props: {}
     }
     interface IntrinsicElements {
 [elemName: string]: any
     }
   }
 }
複製代碼

確保 TypeScript 能夠加載聲明文件。 或者,能夠經過如下方式在tsconfig.json中爲其添加自動加載功能:

{
   "compilerOptions": {
     ...
     "typesRoot": ["./node_modules/@types", "./types"]
   }
 }
複製代碼

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:scotch.io/tutorials/u…


交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub github.com/qq449245884… 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索