Uni-app的Prompt組件實現

uni-app是個強大的框架,但是在官網上找了一下,還是沒發現有官網直接提供的Prompt組件。插件市場中倒是有,但是我還是想自己封裝一個比較穩妥。也不一定有插件市場的好,自己湊活着用。

目前測試了H5、Android,沒啥問題。IOS和小程序還沒有測試,不知道會不會有Bug。

話不多說,直接上代碼。

uni-prompt.vue

<!-- prompt組件 -->
<template>
	<view>
		<view v-show="show" class="uni-mask" :style="{ top: offsetTop + 'px' }" @touchmove.stop.prevent="maskMoveHandle"></view>
		<view v-show="show" class="prompt-content contentFontColor" :class="'uni-prompt-' + position + ' ' + 'uni-prompt-' + mode">
			<view class="prompt-title">{{title}}</view>
			<input class="prompt-input" type="text" :placeholder="text" @input="_input" :value="cost" />
			<view class="prompt-btn-group">
				<text class="btn-item prompt-cancel-btn contentFontColor" @tap="_cancel">{{btn_cancel}}</text>
				<text class="btn-item prompt-certain-btn" @tap="_confirm">{{btn_certain}}</text>
			</view>
		</view>
		<view v-if="position === 'middle' && mode === 'insert'" :class="{'uni-close-bottom': buttonMode === 'bottom','uni-close-right': buttonMode === 'right'}"
		 class=" uni-icon uni-icon-close" @click="_cancel" />
	</view>
	</view>
</template>
<script>
	export default {
		name: 'prompt',
		data() {
			return {
				offsetTop: 0,
				multipleSlots: true, // 在組件定義時的選項中啓用多slot支持
				cost: ''
			};
		},
		props: {
			/**
			 * 頁面顯示
			 */
			show: {
				type: Boolean,
				default: false
			},
			/**
			 * 對齊方式
			 */
			position: {
				type: String,
				// top - 頂部, middle - 居中, bottom - 底部
				default: 'middle'
			},
			/**
			 * 顯示模式
			 */
			mode: {
				type: String,
				default: 'insert'
			},
			/**
			 * h5遮罩是否到頂
			 */
			h5Top: {
				type: Boolean,
				default: false
			},


			title: {
				type: String,
				default: '提示'
			},
			text: {
				type: String,
				default: '請輸入內容'
			},
			btn_cancel: {
				type: String,
				default: '取消'
			},
			btn_certain: {
				type: String,
				default: '確定'
			},
			buttonMode: {
				type: String,
				default: 'bottom'
			}
		},
		watch: {
			h5Top(newVal) {
				if (newVal) {
					this.offsetTop = 44
				} else {
					this.offsetTop = 0
				}
			}
		},
		created() {
			let offsetTop = 0
			// #ifdef H5
			if (!this.h5Top) {
				offsetTop = 44
			} else {
				offsetTop = 0
			}
			// #endif
			this.offsetTop = offsetTop
		},
		methods: {
			maskMoveHandle() {},

			/*
			 * 內部私有方法建議以下劃線開頭
			 * triggerEvent 用於觸發事件
			 */
			_cancel() {
				//觸發cancel事件
				this.cost = '';
				this.$emit('onCancel');
			},
			_confirm() {
				this.$emit('onConfirm', this.cost);
				this.cost = '';
			},
			_input(e) {
				this.cost = e.detail.value;
			}
		}
	}
</script>

<style>
	/* components/vas-prompt/vas-prompt.wxss */
	.uni-mask {
		position: fixed;
		z-index: 998;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		background-color: rgba(0, 0, 0, 0.3);
	}

	.uni-prompt-middle {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
	}

	.uni-prompt-middle.uni-prompt-insert {
		transform: translate(-50%, -65%);
		box-shadow: none;
	}

	.uni-prompt-middle.uni-prompt-fixed {
		border-radius: 10upx;
		padding: 30upx;
	}

	.uni-close-bottom,
	.uni-close-right {
		position: absolute;
		bottom: -180upx;
		text-align: center;
		border-radius: 50%;
		color: #f5f5f5;
		font-size: 60upx;
		font-weight: bold;
		opacity: 0.8;
		z-index: -1;
	}

	.uni-close-bottom {
		margin: auto;
		left: 0;
		right: 0;
	}

	.uni-close-right {
		right: -60upx;
		top: -80upx;
	}

	.uni-close-bottom:after {
		content: '';
		position: absolute;
		width: 0px;
		border: 1px #f5f5f5 solid;
		top: -200upx;
		bottom: 56upx;
		left: 50%;
		transform: translate(-50%, -0%);
		opacity: 0.8;
	}

	.prompt-content {
		position: fixed;
		z-index: 999;
		background-color: #ffffff;
		width: 480upx;
		border-radius: 20upx;
	}

	.prompt-title {
		width: 100%;
		padding: 15upx 0 15upx 0;
		text-align: center;
		font-size: 32upx;
		position: relative;
	}

	.prompt-title::after {
		position: absolute;
		z-index: 3;
		right: 0;
		bottom: 0;
		left: 0;
		height: 1px;
		content: '';
		-webkit-transform: scaleY(.5);
		transform: scaleY(.5);
		background-color: #c8c7cc;
	}

	.prompt-input {
		margin: 8%;
		width: 80%;
		height: 70upx;
		border: 1px solid #ccc;
		border-radius: 10rpx;
		padding-left: 10upx;
		font-size: 28upx;
		font-weight: 100;
	}

	.prompt-btn-group {
		width: 100%;
		position: relative;
		height: 75upx;
	}

	.prompt-btn-group::before {
		position: absolute;
		z-index: 3;
		right: 0;
		top: 0;
		left: 0;
		height: 1px;
		content: '';
		-webkit-transform: scaleY(.5);
		transform: scaleY(.5);
		background-color: #c8c7cc;
	}

	.btn-item {
		width: 50%;
		display: inline-block;
		text-align: center;
		position: relative;
		height: 75upx;
		line-height: 75upx;
	}

	.prompt-cancel-btn::after {
		position: absolute;
		z-index: 3;
		right: 0;
		top: 0;
		bottom: 0;
		width: 1px;
		content: '';
		-webkit-transform: scaleX(.5);
		transform: scaleX(.5);
		background-color: #c8c7cc;
	}

	.dividing-line {
		width: 1upx;
		height: 100%;
		background-color: #d5d5d6;
	}

	.contentFontColor {
		color: #868686;
	}

	.uni-close-bottom,
	.uni-close-right {
		position: absolute;
		bottom: -180upx;
		text-align: center;
		border-radius: 50%;
		color: #f5f5f5;
		font-size: 60upx;
		font-weight: bold;
		opacity: 0.8;
		z-index: -1;
	}

	.uni-close-bottom {
		margin: auto;
		left: 0;
		right: 0;
	}

	.uni-close-right {
		right: -60upx;
		top: -80upx;
	}

	.uni-close-bottom:after {
		content: '';
		position: absolute;
		width: 0px;
		border: 1px #f5f5f5 solid;
		top: -200upx;
		bottom: 56upx;
		left: 50%;
		transform: translate(-50%, -0%);
		opacity: 0.8;
	}
</style>

調用部分代碼

<text class="iconfont iconxinzeng" @click="prompt('uni-prompt')"></text>
<prompt :show="promptType === 'uni-prompt'" @onConfirm="onConfirm" @onCancel="prompt('')" title="請輸入標題" text="請輸入標題"></prompt>

<script>
	import prompt from '../../components/uni-prompt/uni-promot.vue'
	export default {
		components: {
			prompt
		},
		data() {
			return {
				promptType: ''
			}
		},
		methods: {
			prompt(type) {
				console.log(type)
				this.promptType = type;
			},
			onConfirm(e) {
				console.log(e);
				let _cost = e;
				if (_cost == '') {
					this.showMsg({
						title: '請輸入標題!',
						position: 'bottom'
					})
					return;
				} else {
					this.prompt('')
					this.showLoading()
					uni.request({
						url: `${this.$serverUrl}/mysetting/addMySetting`,
						method: "POST",
						header: {
							"Content-Type": "application/x-www-form-urlencoded",
							'token': this.$store.state.userInfo.token
						},
						data: {
							'userId': this.$store.state.userInfo.userId,
							'title': _cost,
							'startArea': this.startArea,
							'endArea': this.endArea,
							'invoiceType': this.invoiceType,
							'invoiceTypeFlg': this.invoiceTypeFlg
						},
						success: (e) => {
							console.log(e);
							uni.hideLoading();
							this.showMsg({
								title: e.data.msg,
								position: 'bottom'
							})
						},
						fail: (e) => {
							uni.hideLoading();
							this.showMsg({
								title: "請求失敗,請重試!",
								position: 'bottom'
							})
						}
					})
				}
			},
		}
	}
</script>

效果圖

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章