vue自定义全局弹出询问框、输入框、提示框、toast(附源码)

早前写过一篇关于vue自定义弹出询问框、输入框、提示框的贴子,当时只是实现了组件化,组件需要在各个业务模板进行引用,不能全局化使用,不太方便,本次将其改进成了全局使用,具体的业务模块不需要引入组件,直接调用main.js注册的全局方法即可。

涉及技术点:

遮罩层样式,自定义组件,子组件套用组件,子组件调用父组件方法,组件属性监听,输入框默认获得焦点,输入框数据双向绑定、组件注册

效果图如下:

询问框:

输入框:

扫描二维码关注公众号,回复: 17266580 查看本文章

提示框

Toast

询问框组件代码

<template>
  <div v-if="show" class="mask">
    <div class="dlg-msg-box flex flex-col">
      <div class="flex flex-space-between full-width">
        <div class="font-bold">{
    
    {caption}}</div>
        <div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
      </div>
      <div class="margin-top-l" style="height:45px;">{
    
    {msg}}</div>
      <div class="flex flex-end margin-top-xl">
        <div class="btn-huibai-auto pointer" style="width:80px" @click="cancelClick">取消</div>
        <div class="margin-left-m btn-blue-auto pointer" style="width:80px" @click="confirmClick">确定</div>
      </div>
    </div>
  </div>
</template>
 
<script>


export default {
    name: 'MsgBox',   
    props: {
        caption:{},
        show: {},
        msg:{},
        callback:{}
    },
    data() {
        return {
        }
    },

    methods: {
        init() {
          this.show = true;

        },
        close() {
          this.show = false;
          this.callback("close")
        },
        confirmClick() {
          this.show = false;
          this.callback("yes")
          //this.$emit('confirm');
        },
        cancelClick() {           
          this.show = false;
          this.callback("no")
        }

    }
}
</script>

<style>
    .dlg-msg-box {
        border-radius: 5px;
        width: 350px;
        height: 160px;
        background-color: #fff;
        padding: 30px;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
    }
</style>

输入框组件代码

<template>
  <div v-if="show" class="mask">
    <div class="dlg-input-box flex flex-col">
      <div class="flex flex-space-between full-width">
        <div class="font-bold">{
    
    {caption}}</div>
        <div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
      </div>
      <div class="margin-top-xl flex flex-col">
          <input class="input-box" placeholder="请输入" v-model="inputValue" ref="getfocus"/>
      </div>
      <div class="flex flex-end margin-top-xl">
        <div class="btn-huibai-auto pointer" style="width:80px" @click="cancelClick">取消</div>
        <div class="margin-left-m btn-blue-auto pointer" style="width:80px" @click="confirmClick">确定</div>
      </div>
    </div> 
  </div>
</template>
 
<script>


export default {
    name: 'InputBox',  
    props: {
        caption:{},
        value:{},
        show: {},
        callback: {}
    },
    watch: {
      show(val){
          if (val == true) {
              this.$nextTick(() => {
                  this.$refs.getfocus.focus();
              })
          }
      },
      value(val){
        this.inputValue = val;
      }

    },
    data() {
        return {
        }
    },
    
    methods: {
     
        close() {
          this.show = false;  
        },
        init() {
          this.show = true;

        },
        confirmClick() {
          if (this.inputValue == "") {
              this.$showToast({
                  msg: '内容未填写',
                  duration: 2000
              })               
              
          } else {
              this.callback(this.inputValue)
          }
          
        },
        cancelClick() {     
          this.show = false;      
        }

    }
}
</script>

<style>
    .dlg-input-box {
        border-radius: 5px;
        width: 350px;
        height: 160px;
        background-color: #fff;
        padding: 30px;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
    }
</style>

提示框组件代码

<template>
  <div v-if="show" class="mask">
    <div class="dlg-show flex flex-col">
      <div class="flex flex-space-between full-width">
        <div class="font-bold">{
    
    {caption}}</div>
        <div class="pointer" @click="close"><img class="logo-22" src="@/assets/images/guanbi.png"/></div>
      </div>
      <div class="margin-top-l" style="height:45px;">{
    
    {msg}}</div>
      <div class="flex flex-end margin-top-xl">
        <div class="margin-left-m btn-blue-auto pointer full-width" @click="confirmClick">确定</div>
      </div>
    </div>
  </div>
</template>
 
<script>

export default {
    name: 'MsgShow',
    props: {
        caption:{},
        show: {},
        msg:{},
        callback:{}
    },
    data() {
        return {
        }
    },

    methods: {
      init() {
          this.show = true;
      },
      close() {
          this.show = false;
      },
      confirmClick() {
          this.show = false;
          this.callback("yes");

      }
    }
}
</script>

<style>
    .dlg-show {
        border-radius: 5px;
        width: 300px;
        height: 140px;
        background-color: #fff;
        padding: 30px;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
    }
</style>

toast组件代码

<template>
    <div v-if="show" class="mask" style="z-index: 99999;">
      <div class="dlg-show1 flex flex-center-sp flex-center-cz">
        <div>{
    
    {msg}}</div>
      </div>
    </div>
  </template>
   
  <script>
  
  export default {
      name: 'Toast',   
      props: {
          show: {},
          msg:{},
          duration: {
            type: Number,
            default: 2000
        }
      },
      data() {
          return {
            timerDuration: null
          }
      },
      watch: {
        show(n) {
            if (!n && this.timerDuration) {
                clearTimeout(this.timerDuration)
                this.timerDuration = null
            }
        }

      },
      methods: {
        init() {
            this.show = true
            this.timerDuration = setTimeout(() => {
                this.show = false
            }, this.duration)
        },
        clear() {
            this.show = false
        } 
      }
  }
  </script>
  
  <style>
      .dlg-show1 {
          border-radius: 5px;
          width: 300px;
          background-color: #ffffff;
          padding: 10px;
          height: 30px;
          position: absolute;
          margin-left: auto;
          margin-right: auto;
          top: 20px;
          left: 0;
          right: 0;
          bottom: 0;
      }
  </style>
  

js代码

import MsgBox from '@/components/MsgBox.vue'
let ConfirmConstructor, instance

const showMsgBox = {
  install(Vue) {
    ConfirmConstructor = Vue.extend(MsgBox)
    instance = new ConfirmConstructor().$mount()
    document.body.appendChild(instance.$el)

    Vue.prototype.$showMsgBox = options => {
      Object.assign(instance, options)
      instance.init()
    }

  }
}

export default showMsgBox
import InputBox from '@/components/InputBox.vue'
let ConfirmConstructor, instance

const showInputBox = {
  install(Vue) {
    ConfirmConstructor = Vue.extend(InputBox)
    instance = new ConfirmConstructor().$mount()
    document.body.appendChild(instance.$el)

    Vue.prototype.$showInputBox = options => {
      Object.assign(instance, options)
      instance.init()
    }

  }
}

export default showInputBox
import MsgShow from '@/components/MsgShow.vue'
let ConfirmConstructor, instance

const showMsgShow = {
  install(Vue) {
    ConfirmConstructor = Vue.extend(MsgShow)
    instance = new ConfirmConstructor().$mount()
    document.body.appendChild(instance.$el)

    Vue.prototype.$showMsgShow = options => {
      Object.assign(instance, options)
      instance.init()
    }

  }
}

export default showMsgShow
import Toast from '@/components/Toast.vue'
let ConfirmConstructor, instance

const showToast = {
  install(Vue) {
    ConfirmConstructor = Vue.extend(Toast)
    instance = new ConfirmConstructor().$mount()
    document.body.appendChild(instance.$el)

    Vue.prototype.$showToast = options => {
      Object.assign(instance, options)
      instance.init()
    }
    Vue.prototype.$showToast.clear = () => {
      instance.clear()
    }
  }
}

export default showToast

调用代码

<template>
    <div class="body">
      <div class="table">
        <div class="filter font-bold">vue自定义全局弹出询问框、输入框、提示框、toast</div>
        <div class="padding-left-l padding-right-l">

          <div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="MsgBoxClick">询问框</div>
          <div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="InputBoxClick">输入框</div>
          <div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="MsgShowClick">提示框</div>
          <div class="pointer cannotselect margin-top-l margin-left-l btn-blue-full" @click="ToastClick">Toast</div>
          
        </div>  

      </div>
    </div>
</template>

<script>
/*
       名称:vue自定义全局弹出询问框、输入框、提示框、toast
       功能:自定义属于自己的弹出窗,涉及到技术点:遮罩层样式,自定义组件,子组件套用组件,子组件调用父组件方法,组件属性监听,输入框默认获得焦点,输入框数据双向绑定        
       作者:唐赢   
       时间:2023-3-5
*/

  export default {
    name: 'Main',
    data () {
      return {        
      }
    },
    methods: {
      MsgBoxClick() {
        this.$showMsgBox({
          caption:"询问",
          msg: '确定要删除该条记录吗?',
          callback:(data) => {
            if (data == "yes") {
              this.$showToast({
                msg: '点了确定',
                duration: 2000
              })
            } else {
              this.$showToast({
                msg: '点了取消',
                duration: 2000
              })
            }
          }
        })

      },
      InputBoxClick() {
        this.$showInputBox({
          caption:"提示",
          inputValue: '标题1',
          callback:(data) => {
            console.log("最新的值", data);
          }
        })
      },     
      MsgShowClick() {
        this.$showMsgShow({
          caption:"提示",
          msg: '操作完毕!',
          callback:(data) => {
            console.log(data);
          }
        })        

      },
      ToastClick(){
        this.$showToast({
          msg: '网络错误',
          duration: 2000
        })

      }
    },

    
  }
</script>

  <!-- Add "scoped" attribute to limit CSS to this component only -->
  <style scoped>
  .body {
    display: flex;
    justify-content: center;
    margin-top: 73px;
    width: 100%;    
  }
  .table {
    background-color: #fff;
    width: 1080px;
    min-height: 800px;
    box-shadow: 0px 3px 6px rgba(0, 0, 0, .1);
    margin-bottom: 10px;
  }
  .filter {
    display: flex;
    height: 60px;
    align-items:center;
    background-color: #fff;
    font-size: 18px;
    justify-content: center;
    border-bottom: 1px solid rgba(0, 0, 0, .2);;
  }


  </style>
  

main.js代码

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import "./assets/css/base.css"
import ShowToast from './assets/js/toast'
import ShowInputBox from './assets/js/inputBox'
import ShowMsgBox from './assets/js/msgBox'
import ShowMsgShow from './assets/js/msgShow'

Vue.use(ShowToast)
Vue.use(ShowInputBox)
Vue.use(ShowMsgBox)
Vue.use(ShowMsgShow)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

操作演示地址:https://lusun.com/v/cR9piucUW1r

源码地址:https://download.csdn.net/download/gdgztt/87535048

猜你喜欢

转载自blog.csdn.net/gdgztt/article/details/129344808