用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-tree-chart树形组件的实现(含鼠标右击事件)
栏 目:vue
下一篇:利用Vue.js指令实现全选功能
本文标题:用Vue Demi 构建同时兼容Vue2与Vue3组件库
本文地址:http://www.codeinn.net/misctech/209125.html