img

Vue.extend创建动态组件的应用

2021-07-31 0条评论 3.6k次阅读 JavaScript


在使用ant design vue的时候,发现有一种消息弹窗可以直接这样调用:

this.$info({
        title: 'This is a notification message',
        content:'some messages...some messages...'
        onOk() {},
      });

然后我在想,能不能自己也封装一个这种组件,不用每次都import事先写好的组件,能全局调用呢?正好工作中做到一个删除确认框的功能,就研究了一下。

一、创建一个组件(deleteconfirm.vue)

<template>
  <a-modal
    :title="null"
    width="416px"
    :bodyStyle="{ padding: '0px' }"
    :visible="visible"
    :confirm-loading="confirmLoading"
    okType="danger"
    okText="删除"
    :closable="false"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <div class="delete-confirm-wrap">
      <div class="title-wrap mb10">
        <a-icon
          class="mr10"
          type="exclamation-circle"
          theme="filled"
          :style="{ color: '#f9ad15' }"
        />
        <span class="confirm-title">{{ title }}</span>
      </div>
      <div class="warning-title mb10">
        删除后相关数据一并删除,此操作不可逆!
      </div>
      <div class="confirm-tip mb10">如确认删除,请输入:{{ validateText }}</div>
      <a-input
        class="flex-one"
        :placeholder="placeholder"
        v-model="userInputText"
      />
    </div>
  </a-modal>
</template>
<script>
export default {
  name: "deleteConfirm",
  props: {
    title: {
      type: String,
      default: "您确定要删除吗?",
    },
    placeholder: {
      type: String,
      default: "",
    },
    validateText: {
      type: String,
      default: "",
    },
    onOk: {
      type: Function,
      default() {
        return () => {};
      },
    },
    onCancel: {
      type: Function,
      default() {
        return () => {};
      },
    },
  },
  data() {
    return {
      //是否显示
      visible: false,
      //确定Loading
      confirmLoading: false,
      //用户输入的确认文案
      userInputText: "",
    };
  },
  computed: {},
  methods: {
    //点击确定按钮
    async handleOk() {
      //点确定之前校验用户输入的与需要校验的文案是不是一致
      if (this.userInputText !== this.validateText) {
        this.$message.error("输入错误");
        return;
      }
      this.confirmLoading = true;
      //回调用户函数
      await this.onOk(this.userInputText);
      this.confirmLoading = false;
      this.visible = false;
    },
    //取消按钮
    handleCancel() {
      this.onCancel("cancel");
      this.visible = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.delete-confirm-wrap {
  border-radius: 6px;
  height: 170px;
  padding: 24px;
  .title-wrap {
    font-weight: 500;
    font-size: 16px;
    display: flex;
    align-items: center;
  }
  .warning-title {
    color: #ff4d4f;
  }
  .confirm-tip {
    color: #8591a1;
  }
}
</style>

二、在该组件同目录下新建index.js

import Vue from 'vue'
//导入组件
import deleteConfirmComp from './deleteconfirm'
//创建构造函数
const deleteConfirmConstructor = Vue.extend(deleteConfirmComp);
//构建删除方法
const deleteConfirm = (options = {}) => {
    //动态实例化组件
    let instance = new deleteConfirmConstructor({
        //此处针对子组件的props进行合并覆盖
        propsData: {
            ...options
        }
    });
    //挂载实例渲染
    instance.$mount();
    //绑定到body上
    document.body.appendChild(instance.$el);
    //显示出弹窗
    instance.visible = true;
}
//导出该方法
export default deleteConfirm;

三、在main.js中挂载deleteConfirm方法到Vue原型对象上,以便能够全局调用该方法

import Vue from 'vue'
import deleteConfirm from "./components/deleteconfirm/index";
Vue.prototype.$confirm = deleteConfirm;
...

四、使用

this.$confirm({
        title: `确定要删除「我叫你一声」吗?`,
        placeholder: "请输入要删除的页面名称",
        validateText:'我叫你一声',
        async onOk() {
          //此处是点击确定按钮的回调
          ...
        },
      });

五、效果

💬 COMMENT


🦄 支持markdown语法

👋友