创建自定义插件 Vuejs + Typescript 时出错

Error creating custom plugin Vuejs + Typescript

我的索引和服务插件有这样的结构:

service.ts

declare interface Params {
  title: string;
  description?: string;
  type?: string;
  duration?: number;
}

export default class ServiceToast {
  public toastRef: any; // component

  public constructor(modalRef: any) {
    this.toastRef = modalRef;
    console.log(this.toastRef);
  }

  public open(params: Params) {
    this.toastRef.open(params);
  }
}

基本上我已经创建了一个接收组件的服务,以便它可以轻松地与组件交互。

index.ts:

import _Vue from 'vue';
import Toast from '@/components/_includes/layouts/Toast.vue';
import ServiceToast from './service';

const ToastPlugin = {
  install: (Vue: typeof _Vue, options?: any) => {
    Vue.mixin({
      created() {
        Vue.prototype.$toast = new ServiceToast(Toast);
      },
    });
  },
};

export default ToastPlugin;

我在哪里安装插件并使用上面显示的服务。

这里我调用插件并使它成为对应的Vue.use但是当我想在任何组件中调用它时:

<a @click="$toast.open({ title: 'Hola mundo' })">Hola, dame click!</a>

我收到以下错误:“类型错误:this.toastRef.open 不是函数”

En el shims-vue-plugin.d.ts:

/* eslint-disable */
import Vue from 'vue';
import { AxiosInstance } from 'axios';
import 'webpack-env';
import { FieldFlagsBag } from 'vee-validate';
import { SnackbarProgrammatic as Snackbar, DialogProgrammatic as Dialog } from 'buefy';
import ServiceToast from './app-config/toast/service';

declare module 'vue/types/vue' {
  interface Vue {
    $auth: any;
    $axios: AxiosInstance;
    veeFields: FieldFlagsBag;
    $dialog: typeof Dialog;
    $snackbar: typeof Snackbar;
    $toast: ServiceToast;
  }
}


declare namespace NodeJS {
  interface Process extends __WebpackModuleApi.NodeProcess {
    server: boolean;
  }
}

有谁知道它可能是什么?或者因为我找不到错误而丢失了:/

this.$toast 在任何组件中都不会成为 Toast.vue 的实例。是出口。要获得实际实例,您需要 $mount() 它:

import _Vue from 'vue'; 

// create a class
const ToastClass = _Vue.extend(this.$toast.toastRef);

// get an instance of the class
const instance = new ToastClass();

// mount it
instance.$mount();
// now you have an instance, so you can call any of its methods, i.e: 
// instance.open();
// but it's not yet appended to DOM. to append it to the current component:

this.$el.appendChild(instance.$el);

我不知道您要实现什么目标,但乍一看,在您的应用程序的每个组件中都有一个组件实例似乎不是一个好主意。每个 toast 实例还将有一个 this.$toast。 Toast-ception:)

您可能最好在 $store 中添加一个 toast 数组,并在您的应用程序的根元素上附加一个容器,使用简单的

<toast v-for="toast in toasts" />

当 toast 过期时,提交它并将其从状态中删除。
当你想添加另一个时,只需推送一个新的。

从tao的方案来看,还是这样。

import _Vue from 'vue';
import Toast from '../../components/_includes/layouts/Toast.vue';
import ServiceToast from './service';

export default {
  install: (Vue: typeof _Vue, options?: any) => {
    const toastComponent = new Toast();
    Vue.mixin({
      created() {
        Vue.prototype.$toast = new ServiceToast(toastComponent);
      },
      mounted() {
        const el = document.createElement('div');
        document.body.append(el);
        toastComponent.$mount(el);
      },
    });
  },
};

现在可以正常工作了:)