用Vue Demi 构建同时兼容Vue2与Vue3组件库

2022-10-14

这篇文章主要介绍了 用Vue Demi 构建同时兼容Vue2与Vue3组件库,我们通过考虑其功能、工作原理以及如何开始使用它来了解 Vue Demi,下面我们一起进入文章学起来吧

目录
  • 前言:
  • 一、Vue Demi 中的额外 API
    • 1.isVue2 and isVue3
  • 二、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 等。

    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 构建内容请搜索北冥有鱼以前的文章或继续浏览下面的相关文章希望大家以后多多支持北冥有鱼!

    您可能感兴趣的文章:

    • 前端插件库之vue3使用vue-codemirror插件的步骤和实例
    • CodeMirror实现代码对比功能(插件react vue)
    • vue codemirror实现在线代码编译器效果
    • vue实现codemirror代码编辑器中的SQL代码格式化功能
    • 在vue项目中使用codemirror插件实现代码编辑器功能
    • vue demi支持sfc方式的vue2vue3通用库开发详解

    《 用Vue Demi 构建同时兼容Vue2与Vue3组件库.doc》

    下载本文的Word格式文档,以方便收藏与打印。