如何寫出一個confirm組件

前言

一直都想寫一個組件庫,做爲一個前端的我一直都有這麼一個夢想,在寫項目的過程當中一直都在引用別人的組件庫長久而言本身也開始想寫一個組件庫。什麼是組件呢?這裏再也不過的贅述,下面咱們先談一談confirm組件的封裝過程。在有些平臺使用過程當中刪除操做經常伴隨着確認的狀況畢竟要避免客戶的誤操做麼,廢話很少說開懟!!! 前端

我是確認框

第一個瞭解一些前置的API

Vue.extend方法 vue

extend
這是vue的官方文檔可能看到了有點矇蔽,extend建立的是一個組件構造器,而不是一個具體的組件實例。一般是配合組件使用的,由於咱們最終須要使用this.$confirm的方式進行調用。那麼咱們須要這個方法來構造一個組件。 如何全局引入組件

const components = {
    ConfirmModal
}
const install = function (Vue) {
  if (install.installed) return
  Object.keys(components).forEach(key => {
    Vue.component(components[key].name, components[key])
  })

  Vue.prototype.$confirm=ConfirmModal
}

if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

const API = {
  install,
  ...components
}
複製代碼

上面的代碼裏面components表明數組對象咱們同過Object.keys的方式使用Vue.component語法將組件註冊。上面有一行將confirm的對象掛載到Vue對象的原型鏈下,咱們就能夠經過this.confirm的方法調用這個組件了。node

開始寫組件

組件代碼以下:web

<template>
    <div class="alertModal">
        <!--social post彈框-->
        <transition name="fade">
            <div class="alertbox">
                <div class="alert-dialog">
                    <div class="alert-content">
                        <div class="alert-header">
                            <span class="alertclose" @click="close">×</span>
                            <span class="alert-title">{{modelTitle}}</span>
                        </div>
                        <div class="alert-body">{{modelContent}}</div>
                        <div class="alert-footer">
                            <button class="alertbtn" @click="close">{{modelClose}}</button>
                            <button class="alertbtn alert-info" @click="confirm">{{modelSave}}</button>
                        </div>
                    </div>
                </div>
            </div>
        </transition>
        <div class="modal-backdrop"></div>
    </div>
</template>

<script>
import confirmMixin from'./confirmMixin.js'
export default {
  mixins:[confirmMixin],
  props: {
    modelTitle: {
      type: String,
      default: "確認框" 
    },
    modelSave: {
      type: String,
      default: "確認"
    },
    modelClose: {
      type: String,
      default: "取消"
    },
    modelContent: {
      type: String,
      default: "我是確認框"
    },
    callBack: {
      type: Function,
      default() {}
    },
    closeAction: {
      type: Function,
      default() {}
    }
  },
  methods: {
    close() {
      this.$emit("close");
      this.isVisible = false;
      this.closeAction();
      this.destroyed();
    },
    //點擊肯定按鈕彈窗消失
    confirm() {
      this.$emit("confirm");
      this.isVisible = false;
      this.callBack();
      this.destroyed();
    },
    destroyed() {
      setTimeout(() => {
        this.$destroy();
      }, 200);
    }
  },
  mounted() {
    setTimeout(() => {
      this.isVisible = true;
    }, 100);
  }
};
</script>
<style  scoped>
.modal.fade .alert-dialog {
  -webkit-transition: -webkit-transform 0.3s ease-out;
  -o-transition: -o-transform 0.3s ease-out;
  transition: transform 0.3s ease-out;
  -webkit-transform: translate(0, -25%);
  -ms-transform: translate(0, -25%);
  -o-transform: translate(0, -25%);
  transform: translate(0, -25%);
}
.modal.in .alert-dialog {
  -webkit-transform: translate(0, 0);
  -ms-transform: translate(0, 0);
  -o-transform: translate(0, 0);
  transform: translate(0, 0);
}
.alertbox {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  text-align: center;
  z-index: 99999;
}
.alert-dialog {
  display: inline-block;
  width: 420px;
  padding-bottom: 10px;
  vertical-align: middle;
  background-color: #fff;
  border-radius: 4px;
  border: 1px solid #e6ebf5;
  font-size: 18px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  text-align: left;
  overflow: hidden;
  backface-visibility: hidden;
  position: relative;
  top: 140px;
  padding: 10px 15px;
}
.modal-backdrop.fade {
  filter: alpha(opacity=0);
  opacity: 0;
}
.modal-backdrop.in {
  filter: alpha(opacity=50);
  opacity: 0.5;
}
.alert-footer {
  float: right;
  margin-top: 5px;
}
.alert-scrollbar-measure {
  position: absolute;
  top: -9999px;
  width: 50px;
  height: 50px;
  overflow: scroll;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
  opacity: 0;
}
.modal-backdrop {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1040;
  background-color: #000;
  opacity: 0.5;
}

.el-icon-date {
  cursor: pointer;
}
.alert-header {
}
.alert-title {
  font-size: 18px;
  line-height: 1;
  color: #2d2f33;
}
.alert-body {
  padding: 10px 0px;
  color: #5a5e66;
  font-size: 14px;
  line-height: 17px;
}
.alertbtn {
  text-align: center;
  font-weight: 500;
  cursor: pointer;
  padding: 9px 15px;
  font-size: 12px;
  border-radius: 3px;
  line-height: 1;
  background: #fff;
  border: 1px solid #d8dce5;
  border-color: #d8dce5;
  color: #5a5e66;
}
.alert-info {
  color: #fff;
  background-color: #409eff;
  border-color: #409eff;
}
.alertclose {
  float: right;
  cursor: pointer;
}
</style>
複製代碼

能夠看到裏面使用了mixin的語法我把有些公共的邏輯抽離了出來萬一能複用呢?數組

const ConfirmMixin = {
    props: {
      isVisible: {
        type: Boolean,
        default: false
      }
    },
    data () {
      return {
        isActive: false
      }
    },
    methods: {
      active () {
        this.isActive = true
      },
      close () {
        this.$emit('close')
        this.isActive = false
      }
    },
  
    watch: {
      isVisible (val) {
        this.isActive = val
      }
    },
  
    mounted () {
      this.$nextTick(() => {
        document.body.appendChild(this.$el)
        if (this.isVisible) {
          this.active()
        }
      })
    },
  
    beforeDestroy () {
      this.$el.remove()
    }
  }
  export default ConfirmMixin;
複製代碼

這個就是mixin的代碼bash

最後寫一個入口文件 index.JS文件這個文件很是關鍵將會使用上面咱們說到的API建立組建的構造器 而後實例化組件並返回一個方法。app

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

function open(propsData) {
  const confirmComponent = Vue.extend(confirm);
  return new confirmComponent({
    el: document.createElement('div'),
    propsData
  })
}
export default {
  confirm(opts) {
    const defaultOpts={ modelTitle: "確認框",modelSave:  "確認",modelClose: "取消",modelContent:  "我是確認框",callBack() {},closeAction() {}}
    const propsOpts=Object.assign(defaultOpts,opts);
    return open(propsOpts)
  }
}
複製代碼

這就是index.js的主要邏輯,咱們構造過一個組件以後,就可使用vnode裏面的一些屬性,咱們能夠經過這個屬性吧組件須要的值傳遞過去。列入這裏面的props和el元素。最後寫一個confirm的方法並返回這個方法,方法裏面主要是一些默認配置,當沒有內容合併進去的時候就會展現這個默認值。函數

如何使用

咱們如何這個組件呢?post

this.$confirm.confirm({
        modelTitle: "確認框",modelSave:  "確認",modelClose: "取消",modelContent:  "我是確認框",callBack() {
          alert(1111)
        },closeAction() {alert(222)}
      })
複製代碼

最後的效果ui

效果圖

寫在最後

哈哈最後寫一個組件也是挺費勁的得想到各類狀況,各類回調函數如何調用。一個小小的組件多麼的考驗js的功底,撒花完成。

相關文章
相關標籤/搜索