confirm插件封装

497 阅读1分钟

写在前面

和本博主一样的初学还不清楚怎么封装vue插件的道友,可以参考另一篇笔记: vue插件封装

基于回调封装confirm

// main.js
import ConfirmPlugin from "./components/confirm/confirmPlugin";
import Vue from "vue";
Vue.use(ConfirmPlugin)

new Vue({
  data () {
    return {
      confirmOptions: {
        isShow: true,
        title: '提示',
        content: '确定退出吗?'
      }
    }
  },
  methods: {
    handleClick () {
      this.$confirm({
        ...this.confirmOptions,
        confirmCallBack: this.confirmCallBack,
        cancelCallBack: this.cancelCallBack,
      })
    },
    confirmCallBack () {
      console.log('confirmCallBack this ======', this);
    },
    cancelCallBack () {
      console.log('cancelCallBack this ======', this);
    },
    fff () {
      console.log('fff', this);
    },
    FFF () {
      console.log('FFF', this);
    }
  },
  render () {
    return <div onClick={this.handleClick} style={{ border: '1px solid red', display: 'inline-block' }}>click</div>
  }
}).$mount("#app");
// confirm.vue
<template>
  <div class="confirm-wrapper" v-if="isShow">
    <div class="container">
      <div class="title">{{ title }}</div>
      <div class="content">{{ content }}</div>
      <div class="btn">
        <span class="btnCancel" v-if="cancelTxt" @click="onCancel">{{
          cancelTxt
        }}</span
        ><span class="btnConfirm" v-if="confirmTxt" @click="onConfirm">{{
          confirmTxt
        }}</span>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    isShow: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: ''
    },
    content: {
      type: String,
      default: ''
    },
    cancelTxt: {
      type: String,
      default: '取消'
    },
    confirmTxt: {
      type: String,
      default: '确定'
    },
    confirmCallBack: {
      type: Function,
      default: null
    },
    cancelCallBack: {
      type: Function,
      default: null
    }
  },
  data () {
    return {
      msg: '我是confirm组件'
    }
  },
  methods: {
    onCancel () {
      this.isShow = false
      this.cancelCallBack()
    },
    onConfirm () {
      this.isShow = false
      this.confirmCallBack();
    },
  }
}
</script>

<style>
.confirm-wrapper {
  width: 100%;
  height: 100%;
  position: fixed;
  left: 0;
  top: 0;
  background: rgba(0, 0, 0, 0.5);
}
.confirm-wrapper .container {
  background-color: #fff;
  position: fixed;
  top: 50%;
  left: 10%;
  right: 10%;
  padding: 30px 20px 0px 20px;
  border-radius: 16px;
  transform: translateY(-50%);
}
.confirm-wrapper .container .title {
  margin-bottom: 38px;
  color: #4a4a4a;
  font-size: 38px;
}
.confirm-wrapper .container .content {
  color: #999;
  font-size: 32px;
  text-align: center;
  margin-top: 60px;
  margin-bottom: 80px;
}
.confirm-wrapper .container .btn {
  width: 100%;
  margin: 0 auto;
  border-top: 0.5px solid #999;
}
.confirm-wrapper .container .btn span.btnCancel {
  display: inline-block;
  text-align: center;
  font-size: 34px;
  background-color: #fff;
  line-height: 48px;
  width: 50%;
  color: #666;
}
.confirm-wrapper .container .btn span.btnConfirm {
  display: inline-block;
  text-align: center;
  width: 50%;
  font-size: 34px;
  color: #db2c17;
  background-color: #fff;
  line-height: 48px;
}
</style>
// confirmPlugin.js
import Confirm from './confirm.vue'

const confirmPlugin = {
  install (Vue) {
    let ConfirmConstruct = Vue.extend(Confirm)
    Vue.prototype.$confirm = function (options) {
      let instance = new ConfirmConstruct({ propsData: options })
      document.body.appendChild(instance.$mount().$el)
    }
  }
}

export default confirmPlugin

基于promise封装confirm

// 在mains.js中使用
import Vue from "vue";
import ConfirmPlugin from "./components/confirm/confirmPlugin";
Vue.use(ConfirmPlugin)

new Vue({
  methods: {
    handleClick () {
      this.$confirm({
        isShow: true,
        title: '提示',
        content: '确定退出吗?',
        cancelTxt: 'cancel',
        confirmTxt: 'ok'
      }).then(() => {
        // 点击确定todo
      }).catch(() => {
        // 点击取消todo
      })
    },
  },
  render () {
    return <div onClick={this.handleClick} style={{ border: '1px solid red', display: 'inline-block' }}>click</div>
  }
}).$mount("#app");
// confirmPlugins.js
import Confirm from './confirm.vue'
const confirmPlugin = {
  install (Vue) {
    let ConfirmConstruct = Vue.extend(Confirm)
    Vue.prototype.$confirm = options => {
      let instance = new ConfirmConstruct({ propsData: options })
      document.body.appendChild(instance.$mount().$el)
      instance.$el.style.zIndex = 1000
      return instance.showConfirm()
    }
  }
}
export default confirmPlugin
// confirm.vue
<template lang="pug">
  .confirm-wrapper(v-if="isShow")
    .container
      .title(v-if="title") {{title}}
      .content {{content}}
      .doubleBtn(v-if="isShowCancelBtn")
        span.btnCancel(v-if="cancelTxt" @click="onCancel") {{cancelTxt}}
        span.btnConfirm(v-if="confirmTxt" @click="onConfirm") {{confirmTxt}}
      .singleBtn(v-if="!isShowCancelBtn")
        span.btnConfirm(v-if="confirmTxt" @click="onConfirm") {{confirmTxt}}
</template>
<script>
export default {
  props: {
    isShow: {             // 是否展示confirm弹窗
      type: Boolean,
      default: false,
      required: true
    },
    title: {              // confirm弹窗标题
      type: String,
      default: ''
    },
    content: {            // confirm弹窗内容
      type: String,
      default: ''
    },
    cancelTxt: {          // 确认按钮文字
      type: String,
      default: '取消'
    },
    confirmTxt: {         // 取消按钮文字
      type: String,
      default: '确定'
    },
    isShowCancelBtn: {    // 是否展示取消按钮
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      resolve: null,      // resolve回调
      reject: null,       // reject回调
    }
  },
  methods: {
    // 点击取消触发的回调
    onCancel() {
      this.reject()
      this.removeConfirm()
    },
    // 点击确定触发的回调
    onConfirm() {
      this.resolve()
      this.removeConfirm()
    },
    // 展示弹窗
    showConfirm() {
      return new Promise((resolve, reject) => {
        this.resolve = resolve
        this.reject = reject
      })
    },
    // 删除confirm组件
    removeConfirm() {
      this.isShow = false
      setTimeout(() => {
        document.body.removeChild(this.$el)
      }, 500)
    },
  }
}
</script>

<style scoped lang="stylus">
div
  line-height 0
  margin 0
  padding 0
.confirm-wrapper
  width: 100%
  height: 100%
  position: fixed
  left: 0
  top: 0
  background: rgba(0,0,0,0.50)
  .container
    background-color #fff
    position fixed
    top 50%
    left 10%
    right 10%
    padding 30px 20px 0px 20px
    border-radius 16px
    transform translateY(-50%)
    .title
      color #4a4a4a
      font-size 34px
      font-weight 400
      text-align left
      padding-left 20px
      line-height 68px
    .content
      color #999
      font-size 38px
      text-align center
      padding 50px 0px
      line-height 68px
      font-weight 400
    .doubleBtn
      width 100%
      margin 0 auto
      border-top 0.5px solid rgba(51, 51, 51, .06)
      span.btnCancel
        display inline-block
        text-align center
        font-size: 32px;
        background-color #fff
        line-height 68px
        width 50%
        color #666666
        border-right 0.5px solid rgba(51, 51, 51, .06)
        padding: 24px 0px
      span.btnConfirm
        display inline-block
        text-align center
        width: 50%
        font-size 32px
        color #DB2C17
        background-color #fff
        line-height 68px
        padding: 24px 0px
    .singleBtn
      width 100%
      margin 0 auto
      border-top 0.5px solid rgba(51, 51, 51, .06)
      span.btnConfirm
        display block
        text-align center
        font-size 32px
        color #DB2C17
        background-color #fff
        line-height 68px
        padding: 24px 0px
</style>

基于promise封装的思考

写出回调函数的方式很快,但是写出promise的过程并非一帆风顺;这里简单总结下封装promise过程中的思考。

可以留意下基于promise的封装代码的顺序,也是思考的顺序,先从confirm组件使用入手,希望用户怎么依赖promise使用confirm,接着想办法挂载方法或者对象到Vue原型上,使得返回是promise;最后就是promise和reject&resolve的理解了。

效果展示

封装过程中问题整理

关于vue的data&props思考

vue组件传递函数

mountmount和el心得

参考

Vue原理解析(十一):搞懂extend和$mount原理并实现一个命令式Confirm弹窗组件

vue封装一个全局toast和confirm(Vue.extend)

Vue.js开发一个全局调用的MessageBox组件