【问题标题】:Error creating custom plugin Vuejs + Typescript创建自定义插件 Vuejs + Typescript 时出错
【发布时间】:2020-09-28 01:09:17
【问题描述】:

我的索引和服务插件的结构如下:

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>

我收到以下错误:“TypeError: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;
  }
}

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

【问题讨论】:

  • @PeiroPajares 您是否在控制台中检查了this.$toast 的值是多少?我不确定你在导入什么import Toast from '@/components/_includes/layouts/Toast.vue'?能分享一下 github/codesandbox 项目吗?

标签: typescript vue.js plugins vuejs2


【解决方案1】:

任何组件中的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。祝酒:)

您最好在 $store 中添加一个 toast 数组,并在应用的根元素上附加一个容器,并使用纯文本

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

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

【讨论】:

    【解决方案2】:

    从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);
          },
        });
      },
    };
    

    现在可以正常工作了:)

    【讨论】:

      猜你喜欢
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-05
      • 1970-01-01
      相关资源
      最近更新 更多