用Vue Demi 構建同時兼容Vue2與Vue3組件庫
前言:
Vue Demi 是一個很棒的包,具有很多潛力和實用性。我強烈建議在創建下一個 Vue 庫時使用它。
根據創建者 Anthony Fu
的說法,Vue Demi
是一個開發實用程序,它允許用戶為 Vue 2 和 Vue 3 編寫通用的 Vue 庫,而無需擔心用戶安裝的版本。
以前,要創建支持兩個目標版本的 Vue 庫,我們會使用不同的分支來分離對每個版本的支持。對於現有庫來說,這是一個很好的方法,因為它們的代碼庫通常更穩定。
缺點是,你需要維護兩個代碼庫,這讓你的工作量翻倍。對於想要支持Vue的兩個目標版本的新Vue庫來說,我不推薦這種方法。實施兩次功能請求和錯誤修復根本就不理想。
這就是 Vue Demi 的用武之地。Vue Demi 通過為兩個目標版本提供通用支持來解決這個問題,這意味著您隻需構建一次即可獲得兩個目標版本的所有優點,從而獲得兩全其美的優勢。
在本文中,我們將瞭解 Vue Demi 是做什麼的,它是如何工作的,以及如何開始構建一個通用的 Vue 組件庫。
一、Vue Demi 中的額外 API
除瞭 Vue 已經提供的 API 之外,Vue Demi 還引入瞭一些額外的 API 來幫助區分用戶的環境和執行特定於版本的邏輯。讓我們仔細看看它們!
請註意:Vue Demi 還包括 Vue 中已經存在的標準 API,例如 ref、onMounted 和 onUnmounted 等。
1.isVue2 and isVue3
在 Vue Demi 中,isvue2 和 isvue3 API 允許用戶在創建 Vue 庫時應用特定於版本的邏輯。
例如:
import { isVue2, isVue3 } from 'vue-demi' if (isVue2) { // Vue 2 only } else { // Vue 3 only }
vue2
Vue Demi 提供瞭 vue2 API,它允許用戶訪問 Vue 2 的全局 API,如下所示:
import { Vue2 } from 'vue-demi' // in Vue 3 `Vue2` will return undefined if (Vue2) { Vue2.config.devtools = true } install()
在 Vue 2 中,Composition API
作為插件提供,在使用它之前需要安裝在 Vue 實例上:
import Vue from 'vue' import VueCompositionAPI from '@vue/composition-api' Vue.use(VueCompositionAPI)
Vue Demi 會嘗試自動安裝它,但是對於您想要確保插件安裝正確的情況,提供瞭 install() API 來幫助您。
它作為 Vue.use(VueCompositionAPI) 的安全版本公開:
import { install } from 'vue-demi' install()
二、Vue Demi 入門
要開始使用 Vue Demi,您需要將其安裝到您的應用程序中。在本文中,我們將創建一個集成 Paystack 支付網關的 Vue 組件庫。
你可以像這樣安裝 Vue Demi:
// Npm npm i vue-demi // Yarn yarn add vue-demi
您還需要添加 vue
和@vue/composition-api
作為庫的對等依賴項,以指定它應該支持的版本。
現在我們可以將 Vue Demi 導入我們的應用程序:
<script lang="ts"> import {defineComponent, PropType, h, isVue2} from "vue-demi" export default defineComponent({ // ... }) </script>
此處所示,我們可以使用已經存在的標準 Vue API,例如 defineComponent、PropType 和 h。
現在我們已經導入瞭Vue Demi,讓我們來添加我們的props。這些是用戶在使用組件庫時需要(或不需要,取決於你的口味)傳入的屬性。
<script lang="ts"> import {defineComponent, PropType, h, isVue2} from "vue-demi" // Basically this tells the metadata prop what kind of data is should accept interface MetaData { [key: string]: any } export default defineComponent({ props: { paystackKey: { type: String as PropType<string>, required: true, }, email: { type: String as PropType<string>, required: true, }, firstname: { type: String as PropType<string>, required: true, }, lastname: { type: String as PropType<string>, required: true, }, amount: { type: Number as PropType<number>, required: true, }, reference: { type: String as PropType<string>, required: true, }, channels: { type: Array as PropType<string[]>, default: () => ["card", "bank"], }, callback: { type: Function as PropType<(response: any) => void>, required: true, }, close: { type: Function as PropType<() => void>, required: true, }, metadata: { type: Object as PropType<MetaData>, default: () => {}, }, currency: { type: String as PropType<string>, default: "", }, plan: { type: String as PropType<string>, default: "", }, quantity: { type: String as PropType<string>, default: "", }, subaccount: { type: String as PropType<string>, default: "", }, splitCode: { type: String as PropType<string>, default: "", }, transactionCharge: { type: Number as PropType<number>, default: 0, }, bearer: { type: String as PropType<string>, default: "", }, } </script>
上面看到的屬性是使用 Paystack
的 Popup JS
所必需的。
Popup JS 提供瞭一種將 Paystack 集成到我們的網站並開始接收付款的簡單方法:
data() { return { scriptLoaded: false, } }, created() { this.loadScript() }, methods: { async loadScript(): Promise<void> { const scriptPromise = new Promise<boolean>((resolve) => { const script: any = document.createElement("script") script.defer = true script.src = "https://js.paystack.co/v1/inline.js" // Add script to document head document.getElementsByTagName("head")[0].appendChild(script) if (script.readyState) { // IE support script.onreadystatechange = () => { if (script.readyState === "complete") { script.onreadystatechange = null resolve(true) } } } else { // Others script.onload = () => { resolve(true) } } }) this.scriptLoaded = await scriptPromise }, payWithPaystack(): void { if (this.scriptLoaded) { const paystackOptions = { key: this.paystackKey, email: this.email, firstname: this.firstname, lastname: this.lastname, channels: this.channels, amount: this.amount, ref: this.reference, callback: (response: any) => { this.callback(response) }, onClose: () => { this.close() }, metadata: this.metadata, currency: this.currency, plan: this.plan, quantity: this.quantity, subaccount: this.subaccount, split_code: this.splitCode, transaction_charge: this.transactionCharge, bearer: this.bearer, } const windowEl: any = window const handler = windowEl.PaystackPop.setup(paystackOptions) handler.openIframe() } }, },
scriptLoaded
狀態幫助我們知道是否添加瞭Paystack Popup JS
腳本,並且 loadScript 方法加載 Paystack Popup JS 腳本並將其添加到我們的文檔頭部。
payWithPaystack 方法用於在調用時使用 Paystack Popup JS 初始化交易:
render() { if (isVue2) { return h( "button", { staticClass: ["paystack-button"], style: [{display: "block"}], attrs: {type: "button"}, on: {click: this.payWithPaystack}, }, this.$slots.default ? this.$slots.default : "PROCEED TO PAYMENT" ) } return h( "button", { class: ["paystack-button"], style: [{display: "block"}], type: "button", onClick: this.payWithPaystack, }, this.$slots.default ? this.$slots.default() : "PROCEED TO PAYMENT" ) }
render
函數幫助我們創建沒有
標簽的組件,並返回一個虛擬 DOM 節點。
如果你註意到,我們在條件語句中使用瞭Vue Demi的一個API,isVue2,來有條件地渲染我們的按鈕。如果沒有這一點,如果我們想在Vue 2應用程序中使用我們的組件庫,我們可能會因為Vue 2不支持Vue 3的一些API而遇到錯誤。
現在,當我們構建我們的庫時,它可以在 Vue 2 和 Vue 3 中訪問。
到此這篇關於用Vue Demi 構建同時兼容Vue2與Vue3組件庫的文章就介紹到這瞭,更多相關 使用Vue Demi 構建內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue中正確使用jsx語法的姿勢分享
- Vue3 SFC 和 TSX 方式自定義組件實現 v-model的詳細過程
- Vue3編程流暢技巧使用setup語法糖拒絕寫return
- Vue3 Composition API的使用簡介
- Vue開發手冊Function-based API RFC