vue extend的使用以及自定义弹窗实例

本文档介绍了如何使用 Vue.extend 创建一个自定义弹窗组件,以简化在 Vue 开发中频繁使用组件来实现弹窗的需求。通过 Vue.extend 创建一个子类,将模板插入现有 DOM 中,实现 API 接口式的弹窗调用,减少重复工作。详细步骤包括创建构造器、定义模板、挂载到 Vue 实例,以及如何自定义配置弹窗的样式、内容和按钮。这种方式使得在项目中使用弹窗更加便捷,减少了代码的复杂性。
摘要由CSDN通过智能技术生成

白话Vue.extend(自定义弹窗)

​ 在使用vue开发中,大部分情况下我们都使用组件的方式进行渲染,但是在某些情况下,组件渲染确实带来很多问题(主要是麻烦),比如说,我需要一个确认弹窗,那么,一般情况下,大概会有下面一个流程:引入弹窗组件 =》声明部分弹窗需要的变量 =》 点击弹窗触发按钮 =》临时存储弹窗可能需要的部分变量参数 =》 弹窗回调方法;

​ 如果一个文件中包含多个弹窗信息,那么其中的重复工作量可以想象,确实比较麻烦,那么问题来,可不可以把这个问题简单化呢,嗯,,,我想到了一个偷懒的方法,如果我可以通过api式的接口来渲染弹窗来解决问题呢,类似一下方式:

this.$yioks_confirm()
      .then(res => {
        console.log('用户确认了操作', res)
      })
      .catch(err => {
        console.log('用户取消了该操作', err)
      })

​ 如果使用上面的方法,我不用引入组件,不用为组件声明变量数据,不用额外写用户操作的回调方法。完美!所以,为了实现上面的功能,我想到了*vue.extend()*来建立一个单独的渲染组件;

​ 官方文档中提到,Vue.extend,使用基础vue构造器,创建一个子类,参数是一个包含组建选项的对象;data选项是特例,在这里必须是一个函数;

<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

渲染结果就是:

<p>Walter White aka Heisenberg</p>

​ emmm,乍一看之下,这个文档似乎想告诉我点什么,但是又好像没有。好吧,就上面实例来看,Vue.textend可以创建一个Vue子类,然后大概可以使用js的方式,渲染html;这好像跟没说一样,我们可以这么理解,通过Vue.extend我们可以把一个html模板插入到现有dom中;想想我们的需求,把我们需要的弹窗模板,插入到现有的html中,很好,可以满足我们的需求!

弹窗实例

​ 直接上代码,在根目录下新建extend文件夹,并下该文件夹下建立我们需要的弹窗文件夹;在confirm文件夹下建立src文件夹存放模板源码,新建index.js文件,方便将模板挂载到Vue上,供我们调用(以上是我个人喜好,各位看官大佬随意哈!);

模板文件:src/extend/confirm/src/confirm.vue

<template>
  <transition name="fade">
    <div class="confirm-box" v-if="isShow" ref="confirmDom">
      <div class="modal-bg" >
        <div class="confirm-content">
          <!-- 标题区域 -->
          <div class="title-content">
            <p>{{ confirmTitle || "提示" }}</p>
            <span
              v-show="isShowClose"
              class="close-btn"
              @click="handleConfirm('close')"
              >X</span
            >
          </div>
          <!-- 提示区域 -->
          <div class="msg-content">
            <img
              v-if="type === 'success'"
              src="https://img-blog.csdnimg.cn/2022010704413484175.png"
              alt="error"
            />
            <img
              v-if="type === 'warning'"
              src="https://img-blog.csdnimg.cn/2022010704413495696.png"
              alt="error"
            />
            <img
              v-if="type === 'error'"
              src="https://img-blog.csdnimg.cn/2022010704413530613.png"
              alt="error"
            />
            <p class="tips-text">{{ confirmMsg }}</p>
          </div>
          <!-- 自定义配置按钮项 -->
          <div v-if="btnList.length" class="action-content">
            <div
              v-for="(btnItem, index) in btnList"
              :key="index"
              :class="btnItem.classType"
              class="btn"
              @click="handleConfirm(btnItem.funFlag)"
            >
              {{ btnItem.benText }}
            </div>
          </div>
          <!-- 默认按钮项目 -->
          <div v-else class="action-content">
            <div
              class="btn confirm"
              v-if="confirmBtnText"
              @click="handleConfirm('confirm')"
            >
              {{ confirmBtnText }}
            </div>
            <div
              class="btn other"
              v-if="otherBtnText"
              @click="handleConfirm('other')"
            >
              {{ otherBtnText }}
            </div>
            <div
              class="btn cancel"
              v-if="cancelBtnText"
              @click="handleConfirm('cancel')"
            >
              {{ cancelBtnText }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  data() {
    return {
      isShow: true,
      confirmTitle: "",
      confirmMsg: "",
      type: "success", // success, error, warning
      confirmBtnText: "确定",
      cancelBtnText: "取消",
      otherBtnText: "", // 冗余
      btnList: [], //  { classType: 'success', funFlag: 'suc', benText: 'confirm' }
      isShowClose: true,
    };
  },
  methods: {
    handleConfirm(status) {
    },
    closeConfirm() {
      this.isShow = false;
      if (this.$refs.confirmDom) this.$refs.confirmDom.remove();
    },
  },
};
</script>

<style lang="stylus" scoped>
@import '~./css/confirm'
.fade-enter-active, .fade-leave-active
  transition opacity 0.4s
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */
  opacity 0
</style>

样式文件src/extend/confirm/src/css/confirm.styl

.confirm-box
  position: fixed
  top 0px
  left 0px
  display: flex
  justify-content: center
  align-items: center
  background-color: rgba(14,14,14,.3)
  width: 100vw
  height: 100vh
  user-select: none
  .modal-bg
    .confirm-content
      width: 460px
      // height: 300px
      background: #fff
      border-radius: 4px
      margin-bottom: 100px
      .title-content
        height: 40px
        width: 100%
        padding 25px 15px 15px
        box-sizing: border-box
        display: flex
        align-items: center
        justify-content: space-between
        user-select: none
        border-radius: 4px 4px 0 0
        position: relative
        p
          font-size: 1.4em
        .close-btn
          box-sizing: border-box
          background-color: #4cd964
          color: #fff
          padding: 5px 10px
          cursor pointer
          border-radius: 50%
          position: absolute
          top: -13px
          right: -13px
      .msg-content
        min-height: 200px
        padding: 5px 15px
        box-sizing: border-box
        display: flex
        justify-content: center
        align-items: center
        flex-direction: column
        img
          width: 64px
          height: 64px
          margin-bottom: 35px
        .tips-text
          font-size: 1.2em
          font-weight: 500
          display: flex
          align-items: center
          justify-content: center
      .action-content
        display: flex
        height: 40px
        align-items: center
        justify-content: space-around
        width: 80%
        margin: 0 auto
        padding-bottom: 20px
        margin-top: 20px
        .btn
          padding: 8px 25px
          cursor pointer
          border-radius 4px
          color #fff
          margin: 0px 10px
          &.confirm
            background-color: #7bed9f
          &.cancel
            background-color: #ff4757
          &.other
            background-color: #ffa502
        

js配置文件extend/confirm/src/confirm.js

import Vue from "vue";
import confirm from './confirm.vue';

let ConfirmConstructor = Vue.extend(confirm);
let instance;

const Confirm = function(options = {}) {
  return new Promise((resolve,reject) => {
    instance = new ConfirmConstructor({
      el: document.createElement('div'),
      data: options,
    }).$mount();
    document.body.appendChild(instance.$el);
    instance.content = options;
    instance.handleConfirm = function(status) {
      const { btnList } = instance;
      if('close' === status) {
          reject(status);
          instance.isShow = false;
          // instance.closeConfirm();
      }
      if(btnList && btnList.length) {
        btnList.forEach(element => {
          if(['err','error','cancel'].includes(element.funFlag)) {
            reject(element.funFlag)
            instance.isShow = false;
            instance.closeConfirm();
          } else {
            resolve(element.funFlag)
            instance.isShow = false;
            instance.closeConfirm();
          }
        });
      } else {
        if(status === 'cancel') {
          reject(status);
          instance.isShow = false;
          // instance.closeConfirm();
        } else {
          resolve(status)
          instance.isShow = false;
          // instance.closeConfirm();
        }
      }
    }
  })
}

export default Confirm;

js配置文件src/extend/confirm/index.js

import Vue from "vue";
import Confirm from "./src/confirm";

Vue.prototype.$yioks_confirm = Confirm;	//在vue实例上挂载我们的组件

最后,需要在main.js文件中使用本文件即可

import './extend/confirm';	// 执行关联

之后,就可以在需要的地方放心使用就可以了;

// 点击按钮,提示信息
handleBtnClick() {
 	this.$yioks_confirm({
        confirmMsg: '这是一条警示信息',
        type: 'error',
        btnList: [{ classType: 'confirm', funFlag: 'suc', benText: 'confirm' },
          { classType: 'cancel', funFlag: 'err', benText: 'cancel' }
        ]
      }).then(res => {
        console.log('用户确认了操作', res)
      }).catch(err => {
        console.log('用户取消了该操作', err)
      })   
}

通过btnList自定义配置的弹窗按钮:
在这里插入图片描述

默认配置弹窗:
在这里插入图片描述

以上就是我提供的方法;这里解释下该方法的使用方便道友们自己扩展编辑:

在confirm.vue文件中的data方法所定义的变量,均可以通过配置参数重新定义到渲染的插件中;例如修改按钮的文字,

自定义配置项
this.$yioks_confirm({
    confirmTitle: ""// 弹窗标题
    confirmMsg: "", // 弹窗提示信息
    type: "success", // 默认提供三种样式;success, error, warning;默认success
    confirmBtnText: '确定',// 确认按钮文字
    cancelBtnText: '取消'// 取消按钮文字
    otherBtnText: '', // 提供额外的第三个按钮,注意按钮文字如果配置为空,则弹窗不显示按钮
    btnList: [], // 如果需要多个按钮,则可以通过btnList配置。注意配置按钮的参数
    isShowClose: true, //  是否显示右上角关闭按钮
})
自定义按钮列表

​ 注意,按钮标记funFlag字段如果配置成err,error,cancel,则会被一部reject处理,即用户只能通过catch方法处理该按钮的结果。按钮样式,在我的样式文件中提供了三种不同的风格:success,error,warning;

btnList: [
    { 
        classType: 'success', 	// 按钮样式,默认提供三种样式:success, error, warning;默认success
        funFlag: 'suc',		// 按钮标记,用户可以在then中活到到按钮标记区分用户的操作,用户可以自己定义
        benText: 'confirm' 	// 按钮文字
    }
]

​ 以上,就完成一个自定义的弹窗,以后就可以在代码中愉快的使用了;详细代码丢码云了,有需要的道友自己去爬;这个东西只是方便我自己使用,参考了elementUI代码的处理方式,有什么问题欢迎大家指正。大家也可以自己修改使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值