VUE2实现事件驱动弹窗示例
程序员文章站
2022-04-09 22:14:52
前几天想了解vue如何写弹窗组件
有以下两种可取的写法:
1.状态管理 如果弹窗组件放在根组件,使用vuex来管理组件的show和hide。放在组件内,通过增加...
前几天想了解vue如何写弹窗组件
有以下两种可取的写法:
1.状态管理 如果弹窗组件放在根组件,使用vuex来管理组件的show和hide。放在组件内,通过增加v-show或v-if来控制,可结合slot,定义不同需求的弹窗
2.事件管理 注册一个全局事件来打开弹窗,传入需展示的文字和相关的逻辑控制,可结合promise,实现异步
觉得对用像confirme和propmt这类弹窗,还是事件驱动的好。最好就是能使用promise回调。
于是手痒就写了一个。下面是代码。
propmt.js
import vue from 'vue' import promptcomponent from './prompt.vue' // 引入弹窗的vue文件 const promptconstructor = vue.extend(promptcomponent); // 注册组件 let instance = new promptconstructor().$mount(''); // 获得组件的实例 document.body.appendchild(instance.$el); // 将组件的element插入到body中 const alert = (text,oktext)=>{ if(instance.show === true) { //防止多次触发 return; } // 为弹窗数据赋值 instance.show = true; instance.isalert = true; instance.oktext = oktext||'确定'; instance.message = text; //返回一个promise对象,并为按钮添加事件监听 return new promise(function(resolve,reject) { instance.$refs.okbtn.addeventlistener('click',function() { instance.show = false; resolve(true); }) }) }; const confirm = (text,oktext,canceltext)=>{ if(instance.show === true) { return; } instance.show = true; instance.oktext = oktext||'确定'; instance.canceltext = canceltext||'取消'; instance.message = text; return new promise(function(resolve,reject) { instance.$refs.cancelbtn.addeventlistener('click',function() { instance.show = false; resolve(false); }); instance.$refs.okbtn.addeventlistener('click',function() { instance.show = false; resolve(true); }) }) }; const prompt = (text,oktext,inputtype, defaultvalue)=>{ if(instance.show === true) { return; } instance.show = true; instance.isprompt = true; instance.oktext = oktext||'确定'; instance.message = text; instance.inputtype = inputtype || 'text'; instance.inputvalue = defaultvalue || ''; return new promise(function(resolve,reject) { instance.$refs.okbtn.addeventlistener('click',function() { instance.show = false; resolve(instance.inputvalue); }) }) }; export {alert,confirm,prompt}
prompt.vue
<style lang="less" scoped> .confirm-enter-active { transition: all .2s; } .confirm-leave-active { transition: opacity .2s; } .confirm-leave-to { opacity: 0; } .confirm-enter { opacity: 0; } .confirm { position: relative; font-family: pingfangsc-regular; font-size: 17px; -webkit-user-select: none; user-select: none; // 遮罩层样式 .masker { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, .4); -webkit-transition: opacity .1s linear; transition: opacity .1s linear; z-index: 100; } // 入库数据错误样式 .box { position: absolute; top: 50%; left: 50%; width: 72%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); text-align: center; border-radius: 12px; background-color: #fff; .message { height: 97px; line-height: 24px; font-family: pingfangsc-regular; font-size: 17px; vertical-align: middle; color: #999; letter-spacing: -0.41px; p { margin: 20px auto 0 auto; vertical-align: middle; } &::after { content: ''; height: 100%; } } .prompt { margin: 20px 0; width: 100%; p { margin: 5px auto; font-size: 17px; line-height: 24px; } input { margin: 5px auto; border: 1px solid #333; border-radius: 6px; width: 100px; height: 30px; font-size: 14px; line-height: 20px; text-align: center; } } .button-group { a { width: calc(50% - 0.5px); text-align: center; font-size: 17px; line-height: 43px; color: blue; } .max-width { width: 100% !important;; } } } } </style> <template> <transition name="confirm"> <div class="confirm" v-show="show"> <div class="masker" @touchmove.prevent> <div class="box"> <div class="message" v-if="!isprompt"> <p>{{message}}</p> </div> <div class="prompt" v-if="isprompt"> <p>{{message}}</p> <input type="text" v-model="inputvalue" v-if="inputtype === 'text'" ref="inputel"> <input type="tel" v-model.number="inputvalue" @keydown="entercheck" v-if="inputtype === 'tel'" ref="inputel"> </div> <div class="button-group clearfix bd-top"> <a class="bd-right fl" ref="cancelbtn" v-show="!isalert && !isprompt">{{canceltext}}</a> <a class="fr" ref="okbtn" :class="{'max-width': isalert || isprompt}">{{oktext}}</a> </div> </div> </div> </div> </transition> </template> <script type="text/ecmascript-6"> import {mapstate} from 'vuex' export default{ data() { return { show: false, message: '请输入提示语', oktext: '确定', canceltext: '取消', isalert: false, isprompt: false, inputvalue: '', inputtype: '' } }, methods: { // 金额输入框校验 entercheck(event) { // 只允许输入数字,删除键,11位数字 if (event.keycode === 46 || event.keycode === 8) { return; } if (event.keycode < 47 || event.keycode > 58 || event.keycode === 190) { event.returnvalue = false; } }, }, watch: { show(){ if (this.show) { this.$nexttick(() => { console.log(this.$refs.inputel); console.log(this.inputtype); this.$refs.inputel.focus(); }); } } } } </script>
main.js
import {alert,prompt,confirm} from '../lib/components/prompt/prompt.js' vue.prototype.alert = function(text,oktext) { return alert(text,oktext) }; vue.prototype.confirm = function(text,oktext,canceltext) { return confirm(text,oktext,canceltext) }; vue.prototype.prompt = function(text,oktext,inputtype, defaultvalue) { return prompt(text,oktext,inputtype, defaultvalue) }; component.vue: inputname() { this.prompt('请输入名称','确认','text').then(res =>{ // do something use res }); },
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。