先上效果:



组件源码:slot-modal.vue

<template>
<view class="modal-container" v-if="show" @click.stop="cancel(2)">
<view class="modal-content">
<view class="modal-head modal-title-padding">
<slot name="modal-head"></slot>
</view>
<view class="modal-body">
<slot name="modal-body"></slot>
</view>
<view class="modal-footer">
<view class="modal-col" hover-class="modal-hover" v-if="cancelText" @click.stop="cancel('cancel')">
<text :style="cancelStyle" class="modal-row-text">{{cancelText}}</text>
</view>
<view :style="confirmStyle" class="modal-col modal-confirm" hover-class="modal-hover" @click.stop="confirm">
<text :style="confirmStyle" class="modal-row-text">{{confirmText}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'modal',
props: {
//默认是否显示
show: {
type: Boolean,
default: true
},
//取消按钮文字
cancelText: {
type: String,
default: ''
},
//取消样式
cancelStyle: {
type: [String, Object]
},
//确定按钮文字
confirmText: {
type: String,
default: '确定'
},
//确定样式
confirmStyle: {
type: [String, Object]
},
//阻止点击对话框外侧锁屏
disableScreenClick: {
type: Boolean,
default: false
}
},
methods: {
confirm() {
this.$emit('confirm')
},
cancel(type) {
if (!this.disableScreenClick || type === 'cancel') {
this.$emit('cancel')
}
}
}
}
</script>
<style lang="scss" scoped>
$fontSizeLg:17px;
$fontSizeSm:15px; .modal-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
background-color: rgba(0, 0, 0, .6);
transition: all 5s;
display: flex;
align-items: center;
justify-content: center; .modal-content {
width: 80%;
border-radius: 26rpx;
background: #FFFFFF;
overflow: hidden;
animation: fadeZoom .15s linear; .modal-head {
padding: 30rpx 30rpx 0;
text-align: center;
color: #000;
font-size: $fontSizeLg;
font-weight: 700;
} .modal-title-padding {
padding-bottom: 30rpx;
} .modal-body {
overflow:auto;
padding: 40rpx 30rpx;
font-size: $fontSizeSm;
color: #000;
text-align: center;
} .modal-footer {
display: flex;
position: relative;
text-align: center;
font-size: $fontSizeLg;
line-height: 100rpx;
color: #007AFF;
border-top: 0.5px solid rgba(9, 20, 31, 0.13); .modal-col {
flex: 1;
width: 100%;
position: relative;
} .modal-col:first-child::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: 0;
border-right: 1px solid rgba(9, 20, 31, 0.13);
transform: scaleX(.36);
} .modal-confirm {
color: rgb(0, 122, 255);
} .modal-hover {
background-color: #f2f2f2;
}
} .modal-footer::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
border-top: 0.5px solid rgba(9, 20, 31, 0.13);
transform: scaleY(.36);
}
} @keyframes fadeZoom {
0% {
transform: scale(.7);
opacity: .6;
} 80% {
transform: scale(1.2);
opacity: .3;
} 100% {
transform: scale(1);
opacity: 1;
}
}
}
</style>

使用示例:

<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<view><button type="default" @click="privacyDialogShow=true">用户协议</button></view>
<slot-modal
class="modal-privacy"
:show="privacyDialogShow"
:disableScreenClick="true"
confirmText="同意"
cancelText="不同意"
@cancel="cancelPrivacy"
@confirm="confirmPrivacy">
<template slot="modal-head">
<text>用户协议及隐私政策</text>
</template>
<template slot="modal-body">
<view class="index-content">
<text>
我们非常重视隐私和个人信息保护,请您先认真阅读
<text class="privacyPolicy" @click.stop="goPage('agreement')">《用户服务协议》</text>和
<text class="privacyPolicy" @click.stop="goPage('privacy')">《隐私政策》</text>的全部条款,接受全部条款后再开始使用我们的服务。
<text v-for="item in 40">我们非常重视隐私和个人信息保护,请您先认真阅读我们非常重视隐私和个人信息保护,请您先认真阅读我们非常重视隐私和个人信息保护,请您先认真阅读</text>
</text>
</view> </template>
</slot-modal>
</view>
</template> <script>
export default {
data() {
return {
title: 'Hello',
privacyDialogShow:false
}
},
onLoad() { },
methods: {
goPage(pageUrl){
console.log(pageUrl)
uni.navigateTo({
url:'../agreement/agreement'
})
},
confirmPrivacy(){
console.log('同意了用户协议')
console.log(this.privacyDialogShow)
this.privacyDialogShow = false
console.log(this.privacyDialogShow)
},
cancelPrivacy(){
console.log('拒绝了用户协议')
this.privacyDialogShow=false
}
}
}
</script> <style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
} .logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
} .text-area {
display: flex;
justify-content: center;
} .title {
font-size: 36rpx;
color: #8f8f94;
}
.index-content{
max-height: 800rpx;
}
</style>

通过这次学习,遗留了一个问题还未解决:如何限制modal-body的高度为80%,尝试了多种方法无效,只能写固定高度了。

练习了

  • (1). 组件自定义事件
  • (2). 对话框的css布局

uniapp 自定义弹窗组件的更多相关文章

  1. 基于JQ的自定义弹窗组件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 微信小程序 - 自定义弹窗组件

    2019-01-06:简化了一些代码,以及增加了可用性. // 弹窗配置 dialogConfig: { // 弹窗 dialogvisible: false, options: { // 显示关闭按 ...

  3. uni-app自定义Modal弹窗组件|仿ios、微信弹窗效果

    介绍 uniapp自定义弹窗组件uniPop,基于uni-app开发的自定义模态弹窗|msg信息框|alert对话框|confirm确认框|toast弱提示框 支持多种动画效果.多弹窗类型ios/an ...

  4. 百度智能小程序弹窗组件wcPop|智能小程序自定义model弹窗模板

    百度智能小程序自定义弹窗组件wcPop|百度小程序model对话框|智能小程序弹窗界面模板 最近百度也推出了自己的智能小程序,如是就赶紧去试了下,官方提供的api还不是狠完整.而且官方提供的弹窗组件也 ...

  5. 基于React.js网页版弹窗|react pc端自定义对话框组件RLayer

    基于React.js实现PC桌面端自定义弹窗组件RLayer. 前几天有分享一个Vue网页版弹框组件,今天分享一个最新开发的React PC桌面端自定义对话框组件. RLayer 一款基于react. ...

  6. vue3系列:vue3.0自定义全局弹层V3Layer|vue3.x pc桌面端弹窗组件

    基于Vue3.0开发PC桌面端自定义对话框组件V3Layer. 前两天有分享一个vue3.0移动端弹出层组件,今天分享的是最新开发的vue3.0版pc端弹窗组件. V3Layer 一款使用vue3.0 ...

  7. svelte组件:Svelte自定义弹窗Popup组件|svelte移动端弹框组件

    基于Svelte3.x自定义多功能svPopup弹出框组件(组件式+函数式) 前几天有分享一个svelte自定义tabbar+navbar组件,今天继续带来svelte自定义弹窗组件. svPopup ...

  8. 支付宝小程序自定义弹窗插件|支付宝dialog插件|model插件

    支付宝小程序自定义弹窗组件wcPop|小程序自定义对话框|actionSheet弹窗模板 支付宝小程序官方提供的alert提示框.dialog对话框.model弹窗功能比较有限,有些都不能随意自定义修 ...

  9. js实现自定义弹窗

    众所周知,浏览器自带的原生弹窗很不美观,而且功能比较单一,绝大部分时候我们都会按照设计图自定义弹窗或者直接使用注入layer的弹窗等等.前段时间在慕课网上看到了一个自定义弹窗的实现,自己顺便就学习尝试 ...

随机推荐

  1. Spring Boot整合Spring Data JPA

    1.JPA 2.Spring Data JPA 3.导入依赖 4.连接数据库 5.实体类 6.Repository 7.测试 1.JPA JPA是Java Persistence API的简称,中文名 ...

  2. ES6(四)用Promise封装一下IndexedDB

    indexedDB IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据,它可以被网页脚本创建和操作. IndexedDB 允许储存大量数据,提供查找接口,还能建立索引,这些都是 ...

  3. The 2019 Asia Nanchang First Round Online Programming Contest C. Hello 2019(动态dp)

    题意:要找到一个字符串里面存在子序列9102 而不存在8102 输出最小修改次数 思路:对于单次询问 我们可以直接区间dpOn求出最小修改次数 但是对于多次询问 我在大部分题解看到的解释一般是用线段树 ...

  4. 要习惯用vector代替数组

    cin>>n>>m; vector<int>a(n),b(m); 或者: vector<int>a(n,0),b(m,0);

  5. cmath取整函数

    #include <iostream> #include <cmath>//头文件 using namespace std; int main () { double n; c ...

  6. 2017, X Samara Regional Intercollegiate Programming Contest M. Last Man Standing (贪心,双指针)

    题意:有\(n\)个吃鸡玩家,在某个时间段给你他们每个人的杀敌数,判断数据是否合法,并输出每个人对应的杀敌情况. 题解:刚开始写的是直接暴力枚举,向后去找并且标记,然后存到vector最后输出,结果一 ...

  7. Git命令回退代码并同步到远程仓库

    git log 找到要回退的commit版本号并复制 git reset --hard [commitid] 本地库版本回退 git push -f origin [branchName] 同步到远端 ...

  8. Entity Framework中Remove、Modified实体时,在修改或删除时引发主键冲突的问题

    问题: try { string fileId = context.NewsT.Where(t => t.Id == Model.Id).FirstOrDefault().FileId; str ...

  9. 服务注册与发现-Eureka (高可用设计)

    什么是高可用 部署需要考虑的是什么: 1.系统遇到单点失效问题,如何能够快速切换到其他节点完成任务 2.如何应对网络故障,即系统如何设计成"故障开放型"(expecting fai ...

  10. 鸟哥的linux私房菜——第十章学习(BASH)

    第十章 BASH 1.0).认识BASH 作用:通过" Shell "可以将我们输入的指令与 Kernel 沟通,好让Kernel 可以控制硬件来正确无误的工作! 应用程序其实是在 ...