关键词搜索

全站搜索
×
密码登录在这里
×
注册会员
×

已有账号? 请点击

忘记密码

已有账号? 请点击

使用其他方式登录

vue-demi构建兼容Vue2和Vue3的组件库

发布2022-08-04 浏览1235次

详情内容

Vue Demi 是一个很棒的包,具有很多潜力和实用性。我强烈建议在创建下一个 Vue 库时使用它。

,Vue Demi 是一个开发实用程序,它允许用户为 Vue 2 和 Vue 3 编写通用的 Vue 库,而无需担心用户安装的版本。

以前,要创建支持两个目标版本的 Vue 库,我们会使用不同的分支来分离对每个版本的支持。对于现有库来说,这是一个很好的方法,因为它们的代码库通常更稳定。

github: https://github.com/vueuse/vue-demi


你会不会一直在考虑要不要上vue3?疑虑无非以下几点

老项目都是vue2写的,上了vue3,怎么跟vue2的代码进行融合?

老项目vue2太大了,不想全部翻成3,但是ts真香,特别适合团队开发,怎么搞?

新开工程用的vue3新技术研发出来的,老板一看不错!给其中原来老项目也加上这个模块,继续卖!咱要不要把代码降级?

赶紧上vue3,使用vue-demi,打穿vue2-vue3的壁垒,这么操作直接解决上面所讲的三个问题。


image.png

缺点是,你需要维护两个代码库,这让你的工作量翻倍。对于想要支持Vue的两个目标版本的新Vue库来说,我不推荐这种方法。实施两次功能请求和错误修复根本就不理想。

这就是 Vue Demi 的用武之地。Vue Demi 通过为两个目标版本提供通用支持来解决这个问题,这意味着您只需构建一次即可获得两个目标版本的所有优点,从而获得两全其美的优势。


Vue Demi 入门

要开始使用 Vue Demi,您需要将其安装到您的应用程序中。在本文中,我们将创建一个集成 Paystack 支付网关的 Vue 组件库。

// Npm 
npm i vue-demi 

// Yarn 
yarn add vue-demi

您还需要添加 vue 和@vue/composition-api 作为库的对等依赖项,以指定它应该支持的版本。

<script> 
import {defineComponent, PropType, h, isVue2} from "vue-demi" 

export default defineComponent({
  // ... 
}) 
</script>

此处所示,我们可以使用已经存在的标准 Vue API,例如 defineComponent、PropType 和 h。

现在我们已经导入了Vue Demi,让我们来添加我们的props。这些是用户在使用组件库时需要(或不需要,取决于你的口味)传入的属性。

<script>
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"
    )
}


注意点

期间为了做这个测试是踩了不少坑, 要不然也不会等到现在才出来这篇文章, 首先vue-demi的官方案例并没有template的打包, 其他案例要么是使用jsx,要么使用render, 反正我没有找到打包template的, 最终实践证明是可行的.

无论开发还是打包,都要注意vue版本的切换, 要不然很容易报错,出现诡异事件,要么就是vue2可以,vue3时不行,要么就是开发可以,打包生产环境不行

最后

其实就在我写这篇文章时,我都还是觉得我这个demo不够完美,我这么组建工程的方式,只实现了需要打包的代码公用,并没有实现demo也能共用,  咱能不能一个工程里面就把vue2/3的包都打了?我认为是可以的, 大家可以去尝试一下, 好了可以给我提一个pr,或者留言区贴上你的demo地址, 咱讨论讨论


点击QQ咨询
开通会员
返回顶部
×
  • 微信支付
微信扫码支付
微信扫码支付
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
确定支付下载