在本文中,咱们通过思考其性能、工作原理以及如何开始应用它来理解 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 中,isvue2isvue3 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,例如 defineComponentPropTypeh

当初咱们曾经导入了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 acceptinterface 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