uniapp自带的模态框,不支持content部分插入可编辑的表单元素,这一点比较局限。首先看一下实现的效果图,再进一步附上源码加讲解。

1、编写公共的模态框组件,在components文件下创建一个文件叫uni-dialog.vue的文件    

<!-- 模态框公共部分界面 -->
<template>
    <view v-if="showPopup" class="uni-popup">
        <!-- 遮罩层结构 -->
        <view 
            :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" 
            class="uni-popup__mask" 
            @click="close(true)" 
        />
        <!-- 弹窗主题利用插槽 -->
        <view 
            :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" 
            class="uni-popup__wrapper" 
            @click="close(true)"
        >
            <view class="uni-popup__wrapper-box" @click.stop="clear">
                <slot />
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        name: 'UniPopup',
        props: {
            // 开启动画
            animation: {
                type: Boolean,
                default: true
            },
            // 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
            type: {
                type: String,
                default: 'center'
            },
            // 是否开启自定义
            custom: {
                type: Boolean,
                default: false
            },
            // maskClick
            maskClick: {
                type: Boolean,
                default: true
            },
            show: {
                type: Boolean,
                default: true
            }
        },
        data() {
            return {
                ani: '', // 动画样式类名
                showPopup: false
            }
        },
        watch: {
            show(newValue) {
                if (newValue) {
                    this.open()
                } else {
                    this.close()
                }
            }
        },
        created() {},
        methods: {
            clear() {},
            open() {
                this.$emit('change', {
                    show: true
                })
                this.showPopup = true
                this.$nextTick(() => {
                    setTimeout(() => {
                        this.ani = 'uni-' + this.type
                    }, 30)
                })
            },
            close(type) {
                if (!this.maskClick && type) return
                this.$emit('change', {
                    show: false
                })
                this.ani = ''
                this.$nextTick(() => {
                    setTimeout(() => {
                        this.showPopup = false
                    }, 300)
                })
            }
        }
    }
</script>
<style>
    @charset "UTF-8";

    .uni-popup {
        position: fixed;
        top: 0;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 998;
        overflow: hidden
    }

    .uni-popup__mask {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 998;
        background: rgba(0, 0, 0, .4);
        opacity: 0
    }

    .uni-popup__mask.ani {
        transition: all .3s
    }

    .uni-popup__mask.uni-bottom,
    .uni-popup__mask.uni-center,
    .uni-popup__mask.uni-top {
        opacity: 1
    }

    .uni-popup__wrapper {
        position: absolute;
        z-index: 999;
        box-sizing: border-box
    }

    .uni-popup__wrapper.ani {
        transition: all .3s
    }

    .uni-popup__wrapper.top {
        top: 0;
        left: 0;
        width: 100%;
        transform: translateY(-100%)
    }

    .uni-popup__wrapper.bottom {
        bottom: 0;
        left: 0;
        width: 100%;
        transform: translateY(100%)
    }

    .uni-popup__wrapper.center {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        transform: scale(1.2);
        opacity: 0
    }

    .uni-popup__wrapper-box {
        position: relative;
        box-sizing: border-box
    }

    .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
        padding: 30upx;
        background: #fff
    }

    .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
        position: relative;
        max-width: 80%;
        max-height: 80%;
        overflow-y: scroll
    }

    .uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box,
    .uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
        width: 100%;
        max-height: 500px;
        overflow-y: scroll
    }

    .uni-popup__wrapper.uni-bottom,
    .uni-popup__wrapper.uni-top {
        transform: translateY(0)
    }

    .uni-popup__wrapper.uni-center {
        transform: scale(1);
        opacity: 1
    }
</style>

2、去相应界面引用这个组件,类似elementUI中的el-dialog标签一样,类似的用法。点击回退按钮,显示弹窗。

<button type="warn" @click="returnClick">回退</button>

<!-- 回退弹窗 -->
        <uni-popup :show="showDailog" type="center" :custom="true" :mask-click="false" @change="change">
            <view class="uni-tip">
                <!-- 标题 -->
                <view class="uni-tip-title">回退原因:</view>
                <view class="uni-tip-content">
                    <!-- 中间内容进行自定义 -->
                     <textarea class="uni-tip-content-textarea" focus="true" placeholder="请输入回退原因" maxlength="-1" v-model="content" />
                </view>
                <!-- 按钮部分 -->
                <view class="uni-tip-group-button">
                    <button type="primary" @click="query">确定</button>
                    <button type="warn" @click="cancel">取消</button>
                </view>
            </view>
        </uni-popup>

import uniPopup from '@/components/uni-dialog.vue' // 自定义弹窗组件

export default {
        components: {
            uniPopup
        },
        data() {
            return {
                showDailog: false, // 是否显示弹窗
                content:'' // 回退原因
            }
        },
        onLoad:function(option){
        },
        methods: {
            /** 回退方法 */
            returnClick(){
                this.showDailog = true
            },
            /** 回退弹窗取消方法 */
            cancel() {
                this.showDailog = false
            },
            /** 回退弹窗确定方法 */
            query() {
                this.showDailog = false
            },
            /** 监听弹窗状态是否打开 */
            change(e) {
                console.log(e.show)
            }
        }
    }

/* 提示窗口 */
    .uni-tip {
        padding: 15px;
        width: 300px;
        background: #fff;
        box-sizing: border-box;
        border-radius: 10px;
    }

    .uni-tip-title {
        text-align: center;
        font-weight: bold;
        font-size: 16px;
        color: #333;
        text-align: left;
    }

    .uni-tip-content {
        padding: 15px;
        font-size: 14px;
        color: #666;
        /* background: #C8C7CC; */
        border:2upx solid #ccc;
        border-radius: 10upx;
    }
    
    .uni-tip-content-textarea{
        height: 300upx;
        width: 100%;
        text-align: left;
    }
    .uni-tip-group-button {
        margin-top: 10px;
        display: flex;
    }
    .uni-tip-group-button>button{
        font-size:24upx;
        height: 40upx;
        line-height: 40upx;
        
    }
    

要特别注意的是,uniapp中textarea组件,默认最大输入长度140,如果需要长度不受限制,需要加入一个属性maxlength="-1"

本文可以作为一个模板,中间内容及标题部分有变化,可以直接在此基础上修改。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐