vuetify封装全局组件 通过this.xx()直接调用

1,514 阅读1分钟

vuetify封装全局组件 通过this.xx()直接调用

添加全局组件

封装全局组件,类似 toast,modal 可以通过this.xx() 直接调用

以Vuetifyjs Dialog 为例子

最终效果 通过调用 this.dialog() 可以直接在界面上显示 该组件

实现内容

在components下创建Dialog.vue,代码如下:

<template>
  <v-row justify="center">
    <v-dialog
      v-model="visible"
      persistent
      :fullscreen="fullscreen"
      :max-width="maxWidth"
      :width="width"
      :hide-overlay="overlay"
    >
      <div class="overlay"></div>
      <v-card>
        <v-card-title
          ><span class="headline">{{ title }}</span></v-card-title
        >
        <v-card-text v-html="content"></v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn
            color="blue darken-1"
            text
            @click="m_cancel"
            v-if="showClose"
            >{{ cancelText }}</v-btn
          >
          <v-btn color="blue darken-1" text @click="m_ok">{{
            okText
          }}</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-row>
</template>
<script>
export default {
  props: {
    title: { default: "错误" }, // 标题
    width: { default: "auto" }, // 组件的宽度
    maxWidth: { default: "500px" },
    fullscreen: { default: false }, // 是否为全屏
    showClose: { default: false }, //是否显示关闭按钮
    okText: { default: "确定" }, // 确定按钮文字
    cancelText: { default: "取消" }, // 取消按钮文字
    content: { default: "" }, // 主体内容,可以传字符串 还有 html内容
    overlay: { default: true },
  },
  data() {
    return {
      visible: false,
    };
  },
  mounted() {
  },
  methods:{
    m_cancel(){
      this.close();
      this.$emit('cancel');
    },
    m_ok(){
      this.close();
      this.$emit('ok');
    },
    close(){
      this.visible = false;
    }
  }
};
</script>

在创建个 js文件作为注入文件,我是在utils/funs.js

/*
* @Author: liuchuangqiang
* @Date: 2021-03-17 10:40:34
 * @LastEditTime: 2021-03-18 16:23:00
 * @LastEditors: liuchuangqiang
 * @Descripttion: 
 */
import Vue from 'vue';
import Dialog from '@/components/Dialog'
import Vuetify from 'vuetify/lib';

const vms = {
  create(comp, obj) {
    let vm = new comp()
    vm.$vuetify = new Vuetify().framework;
    vm = vm.$mount();
    if (obj)
      for (let o in obj) {
        vm[o] = obj[o];
      }
    document.body.appendChild(vm.$el);
    return vm;
  }
}

const MyDialog = Vue.extend(Dialog);

const funs = {
  dialog(obj) {
      // utils.getType方法就不在这里说明了,主要是做类型检查的 (Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() ) 
    if (utils.getType(obj) === 'string' || utils.getType(obj) === 'number' || utils.getType(obj) === 'array') {
      obj = { content: obj }
    }
    const vm = vms.create(MyDialog);
    let promise = new Promise((resolve) => {
      vm.$on('ok', () => {
        // 确定返回
        resolve(true);
      });
      vm.$on('cancel', () => {
        // 取消返回
        resolve(false)
      })
    });
    Object.assign(vm, obj);
    vm.visible = true;
    return promise;
  },
}

Object.assign(Vue.prototype, {
  dialog: funs.dialog,
});

Vue.prototype.funs = funs;

export default funs;

最后在main.js中引入

...
import './utils/funs'
...

然后在vue文件中就可以通过 this.dialog(config) 调用了

config 对象 配置的参数内容可以在 Dialog.vue 中 props查看 回调写法为

this.dialog().then(r=>{
    // 确定返回的true
})

出现的问题

TypeError: Cannot read property ‘bar‘ of undefined“

Error in callback for watcher "isActive": "TypeError: Cannot read property 'smAndDown' of undefined"

Error in render: "TypeError: Cannot destructure property 'bar' of 'this.$vuetify.application' as it is undefined."

一开始遇到过前面这种问题,后面 在 funs.js再引入vuetify解决 vm.$vuetify = new Vuetify().framework

如果你有更好的解决方案 请联系我