uniapp自定义封装确认框

2022-07-11 10:08:13

最近的app项目有个从有下角弹出的确认框,但是uniapp没有合适的组件所以自己写了一个,功能确实都完成了,但是跟项目的耦合度还是略高,主要是原因有两个:
1、uniapp在除H5模式下都挂载不到根元素,需要在使用页引入组件;
2、由于确认框需要都网上一个个叠加,所以需要不同name,这个我是用vuex存值的,后期再改改,争取这部分去掉,解决耦合度太高的缺点。
好了,说完以上,如果大家有需求,那就直接粘代码。

先看效果:
成功
警告
使用方法:
template:

<confirm-box></confirm-box>

javascript:

this.$confirm({ type:'info', message:'当前警告内容'});

具体组件参数:

* confirm 确认框* @description 包括确认、警告、错误、成功* @event{Function(param)}$confirm(param)
			@param{Object{type,message}}{
								name,				值类型为 String,取唯一名称,避免多次弹出
								type,         		值为'info/warning/error/success'
								mask,		  		值类型为 Boolean(为true时为透明遮罩,进行其他操作无效,只能操作确认框)
								message,      		值类型为 String
								closed:true, 		值类型为 Boolean(type值为warning/error时使用,closed为true时可使用@close方法)
								confirmText,  		值类型为 String(type值为info时使用,更改确定按钮文字)
								cancelText,   		值类型为 String(type值为info时使用,更改取消按钮文字)
								confirm:()=>{},  type='info',确认方法
								cancel:()=>{},   type='info',取消方法
								close:()=>{}		type='warning/error',关闭方法}

具体代码

组件代码分三个文件:
confirm-box.vue

<template><viewclass="confirmBox":class="{padding0: this.componentNames.length == 0}"><template v-for="(name,index) in componentNames"><component:is="name.type==='success'?name.type:'confirm'":id="index":type="name.type":message="name.message":confirmText="name.confirmText":cancelText="name.cancelText":closed="name.closed":key="`${$moment().format('X')}-${index}`"
				@confirm="name.confirm"
				@cancel="name.cancel"
				@closeFunc="name.close"class="component"></component><viewclass="mask" v-if="name.mask":key="index"></view></template></view></template><script>/**
	 * confirm 确认框
	 * @description 包括确认、警告、错误、成功
	 * @event {Function(param)} $confirm(param)
			@param {Object{type,message}} {
								name,				值类型为 String,取唯一名称,避免多次弹出
								type,         		值为'info/warning/error/success'
								mask,		  		值类型为 Boolean(为true时为透明遮罩,进行其他操作无效,只能操作确认框)
								message,      		值类型为 String
								closed: true, 		值类型为 Boolean(type值为warning/error时使用,closed为true时可使用@close方法)
								confirmText,  		值类型为 String(type值为info时使用,更改确定按钮文字)
								cancelText,   		值类型为 String(type值为info时使用,更改取消按钮文字)
								confirm: () => {},  type='info',确认方法
								cancel: () => {},   type='info',取消方法
								close: () => {}		type='warning/error',关闭方法
							}  
	 * @example 
	 * 		template:
	 * 		<confirm-box></confirm-box>
	 * 		javascript:
	 * 		this.$confirm({ type: 'info', message: '当前警告内容' });
	 */import successfrom'./components/success.vue'import confirmfrom'./components/confirm.vue'import{ mapGetters}from'vuex'exportdefault{
		name:'confirm',data(){return{}},
		components:{
			success,confirm},
		computed:{...mapGetters({
				componentNames:'confirm/componentNames'})},
		methods:{}SET_COMPONENT_NAMES(state,names){if(names.hasOwnProperty('name')){let has= state.componentNames.filter(item=> item.name== names.name);if(has.length)return;}
			state.componentNames.push(names);},DELETE_COMPONENT_NAMES(state,id){
			state.componentNames.splice(id,1);}}</script><style lang="scss" scoped>.confirmBox{
		position: fixed;
		bottom:120rpx;
		right:0rpx;
		z-index:1001;
		max-height:70%;
		overflow: auto;
		padding:64rpx;.component{
			position: relative;
			z-index:1;}.mask{
			position: fixed;
			top:0;
			left:0;
			width:100%;
			height:100%;
			background-color: transparent;
			z-index:0;}}.padding0{
		padding:0!important;}</style>

confirm.vue

<template><uni-transition:duration="50":mode-class="[modeClass]":show="show"class="confirm clearfix"><viewclass="left"><uni-icons v-if="type !== 'warning'":type="iconType":color="iconColor" size="32"></uni-icons><image v-if="type === 'warning'" style="width: 32px;height: 32px;margin-top: 12px;" src="../../static/confirm/waring.svg" mode=""></image></view><viewclass="right"><viewclass="title">{{title}}</view><viewclass="tip">{{message}}</view><viewclass="footer" v-if="type === 'info'"><button type="default"class="button":class="[vtheme]" @click="confirm">{{confirmText}}</button><button type="default"class="button giveup" @click="cancel">{{cancelText}}</button></view><viewclass="close" v-else><uni-icons type="clear" size="20" color="#606367" @click="closeFunc"></uni-icons></view></view></uni-transition></template><script>exportdefault{
		props:{
			message: String,
			type: String,
			id:[Number,String],
			closed:{
				type: Boolean,default:false},
			confirmText:{
				type: String,default:'确定'},
			cancelText:{
				type: String,default:'取消'}},data(){return{
				modeClass:'slide-bottom',
				show:true,
				title:''}},
		computed:{iconType(){if(this.type==='info'){this.iconColor=this.themeColor;this.title="信息";return'info-filled';}elseif(this.type==='warning'){this.iconColor='#EDBE54';this.title="警告";return'warning';}elseif(this.type==='error'){this.iconColor='#F05151';this.title="错误";return'minus-filled'}}},
		watch:{
			type:{
				handler:function(val){if(val==='info'){this.title="信息";}elseif(val==='warning'){this.title="警告";}elseif(val==='error'){this.title="错误";}},
				deep:true,
				immediate:true}},mounted(){let self=this;if(this.type=="warning"&&!this.closed){this.timeOut=setTimeout(function(){
					self.modeClass='slide-right';
					self.show=false;
					self.$confirmDel(self.id);},3000)}},
		methods:{cancel(){this.common();this.$emit('cancel');},confirm(){this.common();this.$emit('confirm');},closeFunc(){this.common();if(this.closed)this.$emit('closeFunc');},common(){this.modeClass='slide-right';this.show=false;this.$confirmDel(this.id);}}}</script><style lang="scss" scoped>.confirm{
		display: flex;
		width:720rpx;// height: 360rpx;
		background-color:color(bg2);
		clear: both;
		margin-bottom:32rpx;
		box-shadow:5px5px30pxrgba(0,0,0,0.2);
		@includeradius(mini);.left{
			width:160rpx;
			text-align: center;
			float: left;
			padding-top:8rpx;}.right{
			float: left;
			padding:32rpx;
			padding-left:0;
			display: flex;
			height:100%;
			box-sizing: border-box;
			flex-direction: column;.title{
				color:color(tx);
				font-size:32rpx;}.tip{
				color:color(secondery);
				font-size:24rpx;
				flex:1;
				padding:16rpx0;
				margin:16rpx0;}.footer{
				display: flex;.button{
					height:56rpx;
					line-height:56rpx;
					font-size:28rpx;
					color: #fff;
					width:200rpx;
					margin-right:32rpx;
					@include base-background();
					@includeradius(large);&::after{
						border:0;}}.giveup{
					background-color: #D7D9DC;}}.close{
				position: absolute;
				right:8px;
				top:0;}}}.clearfix::after{
		content:"\20";
		display: block;
		height:0;
		clear: both;}.clearfix{
		zoom:1;}</style>

success.vue

<template><uni-transition:duration="500":mode-class="[modeClass]":show="show"class="success"><viewclass="left"><uni-icons type="checkbox-filled" color="#fff" size="32"></uni-icons></view><viewclass="right"><viewclass="top">
				成功</view><viewclass="bottom">{{message}}</view></view></uni-transition></template><script>exportdefault{
		props:['message','id'],data(){return{
				timeOut:null,
				modeClass:'slide-bottom',
				show:true}},mounted(){let self=this;this.timeOut=setTimeout(function(){
				self.modeClass='slide-right';
				self.show=false;
				self.$confirmDel(self.id);},3000)},
		methods:{open(){this.show=true;}}}</script><style lang="scss" scoped>.success{
		width:720rpx;
		height:160rpx;
		margin-bottom:32rpx;
		box-shadow:5px5px30pxrgba(0,0,0,0.2);
		background-color:color(bg2);
		@includeradius(mini);
		display: flex;
		overflow: hidden;.left{
			width:160rpx;
			background-color:color(success);
			line-height:160rpx;
			text-align: center;}.right{
			box-sizing: border-box;
			padding:32rpx;.top{
				color:color(tx);
				font-size:32rpx;}.bottom{
				color:color(secondery);
				font-size:24rpx;}}}</style>

vuex部分:
confirmBox.js

const state={
    componentNames:[],}const mutations={SET_COMPONENT_NAMES(state,names){if(names.hasOwnProperty('name')){let has= state.componentNames.filter(item=> item.name== names.name);if(has.length)return;}
        state.componentNames.push(names);},DELETE_COMPONENT_NAMES(state,id){
		state.componentNames.splice(id,1);}}const actions={}const getters={
    componentNames: state=> state.componentNames}exportdefault{
    namespaced:true,
    state,
    mutations,
    actions,
    getters}

全局混入

import{ mapMutations}from'vuex'import Vuefrom'vue'exportdefault{install(Vue){
        Vue.mixin
  • 作者:疯狂的小土蘑
  • 原文链接:https://blog.csdn.net/jijunqing321/article/details/122468466
    更新时间:2022-07-11 10:08:13