用 jsx 寫 vue 組件

2021-12-24 前端大全

(點擊上方公眾號,可快速關注)

來源:AlloyTeam

www.alloyteam.com/2017/07/12918/

如有好文章投稿,請點擊 → 這裡了解詳情

前言

我們平常寫vue的組件時,一般都是用的是模版,這種方式看起來比較簡潔,而且vue作者也推薦使用這個方式,但是這種方式也有一些它的弊端,例如模版調試麻煩,或者在一些場景下模版描述可能沒那麼簡單和方便。

下面我們要講的是如何在vue裡面寫jsx,知道react的人應該都知道jsx,jsx的一個特性就是非常靈活,雖然有的人覺得jsx很醜陋,把邏輯都寫到模版的感覺,但蘿蔔青菜各有所愛,適合自己適合團隊的就是最好的。

在使用jsx之前我們需要安裝一個babel插件(babel-plugin-transform-vue-jsx )

安裝方式:

npm install\

  babel-plugin-syntax-jsx\

  babel-plugin-transform-vue-jsx\

  babel-helper-vue-jsx-merge-props\

  babel-preset-es2015\

  --save-dev

然後再.babelrc裡面添加:

{

  "presets": ["es2015"],

  "plugins": ["transform-vue-jsx"]

}

 

接著我們就可以愉快地在vue裡面編寫jsx了。

Test.vue

<script>

export default {

    props: ['onClick', 'isShow'],

    data() {

        return {

            test: 123

        };

    },

    render() {

        return (

            <div class="test" onClick={ this.onClick }>

                { this.test }

                { this.isShow + '' }

            </div>

        );

    }

}

</script>

 

可以看到我們把jsx寫在了render方法裡面,render方法是vue2.0才支持的,用來提供對虛擬DOM的支持,也就是說只有vue2.0才支持jsx語法轉換。

這裡要注意的一點是vue裡面編寫jsx和在react裡面的jsx語法還是有一點不一樣的。

一下是一段覆蓋大部分語法的vue jsx代碼:

render (h) {

  return (

    <div

      // normal attributes or component props.

      id="foo"

      // DOM properties are prefixed with `domProps`

      domPropsInnerHTML="bar"

      // event listeners are prefixed with `on` or `nativeOn`

      onClick={this.clickHandler}

      nativeOnClick={this.nativeClickHandler}

      // other special top-level properties

      class={{ foo: true, bar: false }}

      style={{ color: 'red', fontSize: '14px' }}

      key="key"

      ref="ref"

      // assign the `ref` is used on elements/components with v-for

      refInFor

      slot="slot">

    </div>

  )

}

可以看到DOM屬性要加domProps前綴,但這裡lass和style卻不需要,因為這兩個是特殊的模塊,而且react的class用的是className,vue卻用的class。事件監聽是以「on」或者「nativeOn」為開始。

實際上vue2.0的模版最後都會被編譯為render方法,所以模版聲明的組件和jsx聲明的組件最後都是一樣的。

上面的jsx最後會被編譯成下面這樣:

render (h) {

  return h('div', {

    // Component props

    props: {

      msg: 'hi'

    },

    // normal HTML attributes

    attrs: {

      id: 'foo'

    },

    // DOM props

    domProps: {

      innerHTML: 'bar'

    },

    // Event handlers are nested under "on", though

    // modifiers such as in v-on:keyup.enter are not

    // supported. You'll have to manually check the

    // keyCode in the handler instead.

    on: {

      click: this.clickHandler

    },

    // For components only. Allows you to listen to

    // native events, rather than events emitted from

    // the component using vm.$emit.

    nativeOn: {

      click: this.nativeClickHandler

    },

    // class is a special module, same API as `v-bind:class`

    class: {

      foo: true,

      bar: false

    },

    // style is also same as `v-bind:style`

    style: {

      color: 'red',

      fontSize: '14px'

    },

    // other special top-level properties

    key: 'key',

    ref: 'ref',

    // assign the `ref` is used on elements/components with v-for

    refInFor: true,

    slot: 'slot'

  })

}

這也意味著兩種形式的組件是可以相互引用的。

有時候我們難免會在模版裡引入jsx編寫的vue組件或者在jsx編寫的vue組件裡引入模版組件,這裡還是有些需要注意的事項:

1.在模版裡面引入jsx的組件,可以通過components引用,另外props的編寫從駝峰式改為連接符:

<template>

  <div class="wrapper">

    <Test :on-click="clickHandler" :is-show="show"></Test>

  </div>

</template>

<script>

import Test from './Test.vue';

export default {

  name: 'hello',

  components: {

    Test

  },

  data() {

    return {

      msg: 'Welcome to Your Vue.js App',

      show: true

    };

  },

  methods: {

    clickHandler(){

      this.show = !this.show;

    }

  }

};

</script>

 

2.在jsx裡面引入vue模版組件,這裡沒有什麼要注意的,除了連接符式的屬性要轉換成駝峰式,還有一個需要注意的是指令,如果用了jsx,那麼內置的指令都不會生效(除了v-show),好在內置指令大部分都可以用jsx描述。那麼自定義指令要怎麼用呢?

自定義指令可以使用「v-name={value}」語法,如果要支持指令參數和modifier可以用「v-name={{ value, modifier: true }}」語法:

<script>

import Vue from 'vue';

Vue.directive('my-bold', {

  inserted: function (el) {

    el.style.fontWeight = 900;

  }

})

export default {

    props: ['onClick', 'isShow'],

    data() {

        return {

            test: 123

        };

    },

    methods: {

        afterLeave() {

            console.log('afterLeave')

        }

    },

    render() {

        const directives = [

            { name: 'my-bold', value: 666, modifiers: { abc: true } }

        ];

        return (

            <transition onAfterLeave={this.afterLeave} name="fade">

                <div class="test" onClick={this.onClick} v-show={ this.isShow } v-my-bold>

                    {this.test}

                    {this.isShow + ''}

                </div>

            </transition>

        );

    }

}

</script>

<style>

.fade-enter-active, .fade-leave-active {

  transition: opacity .5s

}

.fade-enter, .fade-leave-to {

  opacity: 0

}

</style>

我們還可以用原生vnode的數據格式使用自定義指令:

const directives = [

  { name: 'my-dir', value: 123, modifiers: { abc: true } }

]

return <div {...{ directives }}/>

擴展

如果有人覺得在vue組件裡面要寫data,props,computed和methods不夠優雅,可以參考下這個插件vue-class-component,它能讓你使用ES6的class和ES7的裝飾器編寫vue組件。

相關連結:

babel-plugin-transform-vue-jsx(https://github.com/vuejs/babel-plugin-transform-vue-jsxhttps://github.com/vuejs/babel-plugin-transform-vue-jsx)

覺得本文對你有幫助?請分享給更多人

關注「前端大全」,提升前端技能

相關焦點

  • 前端神器:一行命令,React 組件轉 Vue 組件!
    而基本react component的定義更多是基於props和state來渲染的組件,其中也可以包括發請求。本文先介紹兩個框架的組件共性和不兼容的地方,再介紹react-to-vue的使用和原理。在實際業務中,陸金所100多個的react基礎業務組件,react-to-vue可以轉化90%以上,變成vue組件。
  • 來聊聊Vue中使用Render函數和JSX
    當然這裡肯定有人會問,這樣寫有什麼用,跟template寫不一樣嘛,render函數這樣寫還麻煩可讀性不強。分情況,有時候用render更加靈活,咱就拿官網最典型的案例來「舉個例子」。為什麼要用JSX有的人肯定覺得用render函數寫如果嵌套子級太多層看著太彆扭了,可讀性太差。
  • 【組件庫從0到1】Vite + Vue3 + TSX開發指南
    實踐中,我們如何刻意提升自己這方面的能力,我覺得給公司搭建一套組件庫就很好。在這個過程中大家需要解決不少工程問題,比如:這些任務對於日常和業務打交道的同學來說當然很有挑戰性,12月16日,村長特意準備了一節0元公開課《vue3+ts組件庫開發實戰》,本次課準備給小夥伴們實戰一下Tree組件的開發,深度體驗vue3+tsx開發的各種知識點。
  • vue高級進階系列——用typescript玩轉vue和vuex
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫用過vue的朋友大概對vuex也不陌生,vuex的官方解釋是專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
  • 全面了解 Vue.js 函數式組件
    基本是原汁原味;唯一的問題是受限於單個根元素的限制,多套了一層 div,這一點上也可以用 vue-fragment 等加以解決。h,並且即便在 jsx 用法中表面上不用調用 h,還是需要寫上的;在 Vue3 中,則可以用 import { h } from 'vue' 全局引入了。
  • 如何在Vue項目中使用JSX?
    JSX是一種JavaScript和XML的結合,即JavaScript + XML = JSX,JSX源於Facebook,可以在JavaScript裡寫XML,因為這個特性,所以具備了JavaScript的靈活性,同時又兼具html的語義化和直觀性為什麼使用 JSX?
  • 一文搞定前端自動化測試(Vue 實戰)
    ,這裡選用了 `Vite`[5] 作為構建工具來創建項目,用 @vitejs/app 創建一個 vue-ts 項目。/preset-env @babel/preset-typescript @vue/babel-plugin-jsx @vitejs/plugin-vue-jsx windicss vite-plugin-windicss @testing-library/jest-dom -D依賴很多,看暈了是吧?
  • 一個niubility的Vue遊戲,真厲害!(收藏)
    點擊上方「程式設計師黑叔」,選擇「置頂或者星標」用Vue、Vuex 做俄羅斯方塊本項目靈感來源於 React 版的俄羅斯方塊,由於對其實現原理較感興趣,而且相比於 React 更喜歡 Vue, 於是把 React 版的重構為了 Vue 版的,大致思路是把組件當成一個個函數,保證一個輸入(props)能得到一個確定的輸出(view),然後對不同方法也是做同樣處理,對於
  • 如何寫一個vue組件專題及常見問題 - CSDN
    轉自:https://www.cnblogs.com/pengchenggang/p/10880437.html如何寫好一個vue組件一個適用性良好的組件,一種是可配置項很多,另一種就是容易覆寫,從而擴展功能Vue 組件的 API 來自三部分——prop、事件和插槽:prop 允許外部環境傳遞數據給組件event 允許從組件內觸發外部環境的副作用slot
  • Vue全家桶&vue-router原理
    原理 Vue全家桶:vue + vue-router(路由)+ vuex(狀態管理)+ axios(請求)本次主要分析並實現簡版vue-router,從源碼中學習借鑑,更好的理解源碼vue-routerVue Router 是 Vue.js 官⽅的路由管理器。
  • Vue隱藏技能:運行時渲染用戶寫入的組件代碼!
    大致說一下項目的背景:我們做了一個拖拽生成報表的系統,通過拖拽內置的組件供用戶定製自己的報表形態,但畢竟內置的組件有限,可定製性不高,那麼給用戶開放一個 code 組件,讓用戶自己通過寫template + js + css的方式自由定製豈不是妙哉。重提漸進式那麼該怎麼實現呢?
  • vue中組件的使用(下)
    組件插槽在應用組件的時候,我們可以利用vue自定義的<slot>標籤,為組件內部插入自定義內容,就像<h1>那。vue中的slot插槽怎麼用?:上述的效果可以用組件的一個特殊屬性「is」來實現,它的值是已註冊組件的名字。
  • Vue-使用vue-video-player組件
    在實際開發過程中會有添加視頻的需求在vue項目中添加視頻可以使用vue-video-player組件來實現實現步驟:1.安裝在控制臺輸入: npm install vue-video-player –s
  • 【乾貨】Vue的class語法與常規語法對照表
    項目中使用的是vue-class-component、vue-property-decorator配合TypeScript來進行開發的,其中vue-class-component提供了class語法,而vue-property-decorator提供了一些裝飾器來方便代碼的組織和編寫。
  • 使用 JSX 建立 Markup 組件風格
    這裡我們一起從 0 開始搭建一個組件系統。首先通過上一篇《前端組件化基礎知識》和《用 JSX 建立組件 Parser(解析器)》中知道,一個組件可以通過 Markup 和 JavaScript 訪問的一個環境。所以我們的第一步就是建立一個可以使用 markup 的環境。
  • 這些超火的Vue組件你還沒有用過嗎?
    這些超火的Vue組件你還沒有用過嗎? 本文這些 Vue 組件,不論對於 Vue 初學者還是使用 Vue 的熟練工,都是具有很高使用價值的組件,對你的 Vue 之路一定很有幫助。
  • Vue.js 框架作者公布 Vue 3 最新進展
    Vue Router目前存在部分與 vue-router@3.x 相關的路由鉤子 (router hook)行為一致性問題,這也是 Vue Router 沒有被標記為 Beta 的原因。不過在非關鍵項目上可以使用新的路由。
  • Vue3 的 7 種和 Vue2 的 12 種組件通信,值得收藏
    Vue2.x組件通信12種方式寫在後面了,先來 Vue3 的奧力給!函數裡的屬性,接收不到 data 裡的屬性官方也說了,既然用了 3,就不要寫 2 了,所以不推薦混合寫法。下面的例子,一律只用純 Vue3 的寫法,就不寫混合寫法了2.
  • Vue.js說說組件
    在較高層面上,組件是自定義的元素,Vue.js的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生HTML元素的形式,以is特性擴展。    如何註冊組件?    需要使用Vue.extend方法創建一個組件,然後使用Vue.component方法註冊組件。
  • Vue2.0父子組件間通信
    介紹SRC文件流程及根組件App腳手架搭建完成後,project裡面各個文件夾及文件,如下圖:腳手架各個文件和文件夾src文件流程介紹index.html(入口文件)=>main.js=>App.vue(根組件),根組件中模板內容就直接插入到入口文件中#app處,然後再將頁面呈現出來。