在本文中,我們通過考慮其功能、工作原理以及如何開始使用它來了解 Vue Demi。
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 等。
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 函式幫助我們建立沒有 <template>
標籤的元件,並返回一個虛擬 DOM 節點。
如果你注意到,我們在條件語句中使用了Vue Demi的一個API,isVue2
,來有條件地渲染我們的按鈕。如果沒有這一點,如果我們想在Vue 2應用程式中使用我們的元件庫,我們可能會因為Vue 2不支援Vue 3的一些API而遇到錯誤。
現在,當我們構建我們的庫時,它可以在 Vue 2 和 Vue 3 中訪問。
完整的原始碼可在此處獲得:https://github.com/ECJ222/vue-paystack2