# propt
**Repository Path**: queling/propt
## Basic Information
- **Project Name**: propt
- **Description**: 弹出窗组件,根据不同配置,可以展现出message信息提示框,alert弹出窗,totast轻提示,dialog弹出窗
- **Primary Language**: JavaScript
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-09-01
- **Last Updated**: 2021-09-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 【openHarmony】基于JSUI实现的弹出对话框
## 前言
翻阅了一遍文档,发现原本的JSUI里面的弹出对话框比较单一,不能满足一些业务开发需求,
于是就自己分装了一个,包含了message信息提示框,alert弹提示,toatst轻提示,dialog对话框
## 实现效果


## 实现思路
- message 信息提示框
* 根基传入提示内容以及图片展示在屏幕的中间
* 每次点击即可显示或者隐藏
- alert 弹出提示
* 随机数字+随机大小写字母
* 文本内容+关闭按钮
* 点击关闭按钮会关不提示
* 事件:点击刷新
- toast轻提示
* 文本内+图片
* 宽高150x150
* 1500毫秒之后会自动关闭
- dianlog 对话框
* 带右反馈操作按钮,取消和确定按钮
* 点击取消或者确定按钮,dialog会自动关闭
- 组件抛出的事件
* close 关闭弹窗的事件,在message,toast无效
* cancel 取消事件
* confirm 确定事件
* cancel,confirm 时间只会在dialog有效
- Tips :
* message 根据内容自动撑开宽高
* diallog 宽度是80%
* alert 宽度是屏幕的宽度-20
* toast 宽高150x150
## 实现
### hml布局
- 布局图片

- hml页面布局分为两部分,一部分消息提示框,一部分dialog对话框
* 根据type传入的值,显示不同的弹窗
* 传入dialog则会显示对话框,传入其他的会改变布局显示提示框
* 所有type类型都会默人有四个样式,success,warning,info,error
- 详细代码
```html
```
### js组件内部实现
- 元素居中,需要获取到元素的宽度和屏幕的宽度,计算方法:屏幕宽度-元素宽度之间的差值除以2;注意获取元素信息需要在定时器内延时一段时间后才能获取到
```js
offsetInit{
this.getPhoneInfo();
if(this.type=="message" || this.type=="alert" || this.type=="toast"){
var el=this.$element("messagesContent").getBoundingClientRect();
}else if(this.type=="dialog"){
var el=this.$element("dialogBox").getBoundingClientRect();
}
let offsetLeft=(this.phoneInfo.width-el.width)/2;
let offsetTop=this.offsetTop;
if(this.phoneInfo){
this.offsetLeft=offsetLeft;
}
if(offsetTop=="center"){
this.offsetTop=(this.phoneInfo.height-el.height)/2
}
```
- 默认的情景 success,warning,info,error
```js
// 弹框类型颜色
propt_type(){
if(this.proptType=="success"){
this.bgColor="rgba(7,193,96,0.2)";
}else if(this.proptType=="warning"){
this.bgColor="rgba(230,162,60,0.2)";
}else if(this.proptType=="error"){
this.bgColor="rgba(245,108,108,0.2)";
}else if(this.proptType=="info"){
this.bgColor="rgba(147,147,153,0.2)";
}
if(this.proptType=="success"){
this.color="#07c160";
}else if(this.proptType=="warning"){
this.color="#e6a23c";
}else if(this.proptType=="error"){
this.color="#f56c6c";
}else if(this.proptType=="info"){
this.color="#909399";
}
this.tColor=this.color;
this.tBgColor=this.bgColor;
},
```
- 父组件需要传递给子组件的自定义的数据
```js
// 自动关闭时长
time:{default:1500},
// 弹窗是否显示
isShow: {default: false},
// 弹框类型:message消息提示框;alert警告框;toast请提示 ;dialog弹出框
type:{default:"message"},
// 提示内容信息
text:{default:"信息内容"},
// 提示类型:success,warning,error,info
proptType:{default:"success"},
// 背景色
bgColor:{default:""},
// 文字颜色
color:{default:""},
// 弹窗距离顶部位置,如果传递center,会垂直水平居中
offsetTop:{default:0},
// 小图标
icon:{default:""},
// 是否显示关闭按钮
isClose:{default:false},
// 确定按钮文本内容
confirmBtn:{default:"确认"},
// 取消按钮文本内容
cancelBtn:{default:"取消"}
```
- 弹窗宽度,以及对其方式
```js
setWidth(){
if(this.type=="alert"){
if(this.phoneInfo){
this.width=this.phoneInfo.width-20;
}
this.height=null;
this.iconWidth=25;
this.iconHeight=25;
this.isClose=true;
this.direction="row";
this.justifyContent="flex-start";
}
else if(this.type=="message"){
this.width=null;
this.height=null;
this.iconWidth=25;
this.iconHeight=25;
this.isClose=false;
this.direction="row";
this.justifyContent="flex-start";
}else if(this.type=="toast"){
this.width=150;
this.height=150;
this.iconWidth=60;
this.iconHeight=60;
this.direction="column";
this.justifyContent="center";
this.isClose=false;
}
},
```
- 自动关闭
```js
// 关闭弹窗
close(){
this.isMessage=false;
this.isDialog=false;
this.isShow=false;
this.$emit("close",this.isShow)
},
// 自动关闭
autoClose(){
if(this.time>0){
if(this.isShow==true || this.isMessage==true || this.isDialog==true){
this.timer=setTimeout(()=>{
this.isFlag=false;
this.close();
clearTimeout(this.timer);
},this.time);
}
}
},
```
- 详细代码
```js
// propt-tips.js
import device from '@system.device';
export default {
data(){
return {
// 消息提示框是否显示
isMessage:false,
// 对话框是否显示
isDialog:false,
// 设备信息
phoneInfo:null,
// 弹窗距离左侧位置
offsetLeft:0,
// 節流閥
timer:null,
// 是否运行重复点击
isFlag:false,
// 右侧边距,为关闭按钮留下位置
paddingRight:10,
// 弹窗宽度
width:null,
height:null,
// 对齐方式
direction:"row",
justifyContent:"flex-start",
// icon宽高
iconWidth:25,
iconHeight:25,
tColor: this.color,
tBgColot: this.bgCcolor
}
} ,
props:{
// 自动关闭时常
time:{default:1500},
// 弹窗是否显示
isShow: {default: false},
// 弹框类型:message消息提示框;alert警告框;toast请提示 ;dialog弹出框
type:{default:"message"},
// 提示内容信息
text:{default:"信息内容"},
// 提示类型:success,warning,error,info
proptType:{default:"success"},
// 背景色
bgColor:{default:""},
// 文字颜色
color:{default:""},
// 弹窗距离顶部位置,如果传递center,会垂直水平居中
offsetTop:{default:0},
// 小图标
icon:{default:""},
// 是否显示关闭按钮
isClose:{default:false},
// 确定按钮文本内容
confirmBtn:{default:"确认"},
// 取消按钮文本内容
cancelBtn:{default:"取消"}
},
onInit() {
this.getPhoneInfo();
this.$watch("isShow","isShowWatch");
this.$watch("type","typeWatch")
this.$watch("color","colorWatch")
this.$watch("bgColor","bgColorWatch")
this.type_init();
this.propt_type();
if(this.isClose==true){
this.paddingRight=50
}else{
this.paddingRight=10
}
setTimeout(()=>{
this.offsetInit();
},50)
},
// 弹出框类型初始化
type_init(){
if(this.isFlag==false){
this.isFlag==true;
if(this.isShow==true){
if(this.type=="message" || this.type=="alert" || this.type=="toast"){
this.isDialog=false;
this.isMessage=!this.isMessage;
}else if(this.type=="dialog"){
this.isMessage=false;
this.isDialog=!this.isDialog;
}
}else{
this.isMessage=false;
this.isDialog=false;
};
}
this.setWidth();
this.autoClose();
setTimeout(()=>{
this.offsetInit();
},50);
this.$emit("close",this.isShow)
this.$watch("proptType","proptTypeWatch")
},
// 弹框类型颜色
propt_type(){
if(this.proptType=="success"){
this.bgColor="rgba(7,193,96,0.2)";
}else if(this.proptType=="warning"){
this.bgColor="rgba(230,162,60,0.2)";
}else if(this.proptType=="error"){
this.bgColor="rgba(245,108,108,0.2)";
}else if(this.proptType=="info"){
this.bgColor="rgba(147,147,153,0.2)";
}
if(this.proptType=="success"){
this.color="#07c160";
}else if(this.proptType=="warning"){
this.color="#e6a23c";
}else if(this.proptType=="error"){
this.color="#f56c6c";
}else if(this.proptType=="info"){
this.color="#909399";
}
this.tColor=this.color;
this.tBgColor=this.bgColor;
},
// 关闭弹窗
close(){
this.isMessage=false;
this.isDialog=false;
this.isShow=false;
this.$emit("close",this.isShow)
},
// 自动关闭
autoClose(){
if(this.time>0){
if(this.isShow==true || this.isMessage==true || this.isDialog==true){
this.timer=setTimeout(()=>{
this.isFlag=false;
this.close();
clearTimeout(this.timer);
},this.time);
}
}
},
// 设置弹窗宽度,对齐方式
setWidth(){
if(this.type=="alert"){
if(this.phoneInfo){
this.width=this.phoneInfo.width-20;
}
this.height=null;
this.iconWidth=25;
this.iconHeight=25;
this.isClose=true;
this.direction="row";
this.justifyContent="flex-start";
}
else if(this.type=="message"){
this.width=null;
this.height=null;
this.iconWidth=25;
this.iconHeight=25;
this.isClose=false;
this.direction="row";
this.justifyContent="flex-start";
}else if(this.type=="toast"){
this.width=150;
this.height=150;
this.iconWidth=60;
this.iconHeight=60;
this.direction="column";
this.justifyContent="center";
this.isClose=false;
}
},
// 弹窗位置
offsetInit(){
this.getPhoneInfo();
if(this.type=="message" || this.type=="alert" || this.type=="toast"){
var el=this.$element("messagesContent").getBoundingClientRect();
}else if(this.type=="dialog"){
var el=this.$element("dialogBox").getBoundingClientRect();
}
let offsetLeft=(this.phoneInfo.width-el.width)/2;
let offsetTop=this.offsetTop;
if(this.phoneInfo){
this.offsetLeft=offsetLeft;
}
if(offsetTop=="center"){
this.offsetTop=(this.phoneInfo.height-el.height)/2
}
},
confirm(){
this.isFlag=false;
this.isDialog=false;
this.isShow=false;
this.$emit("confirm",this.isShow);
},
cancel(){
this.isFlag=false;
this.isDialog=false;
this.isShow=false;
this.$emit("cancel",this.isShow);
},
// 获取设备信息
getPhoneInfo(){
let that=this;
device.getInfo({
success: function(data) {
that.phoneInfo=data;
that.phoneInfo["width"]=data.windowWidth/data.screenDensity;
that.phoneInfo["height"]=data.windowHeight/data.screenDensity;
}
});
},
isShowWatch(newV,oldV){
this.isShow=newV;
this.type_init();
},
proptTypeWatch(newV,oldV){
this.proptType=newV;
this.propt_type();
},
typeWatch(newV,oldV){
this.type=newV;
this.setWidth();
setTimeout(()=>{
this.offsetInit();
},50);
},
colorWatch(newV,oldV){
this.tColor=newV;
},
bgColorWatch(newV,oldV){
this.tBgColor=newV;
},
}
```
## 父组件调用方式
- 代码
```html
```
- 父组件调用子组件的验证方法
```js
data: {
isShow:true,
proptType:"success",
color:"",
bgColor:"",
type:"message",
icon:"/common/icon/success.png",
},
btn(option,type){
console.info("type:"+type)
this.isShow=!this.isShow;
this.proptType=option;
this.type=type;
if(option=="success"){
this.icon="/common/icon/success.png"
}else if(option=="warning"){
this.icon="/common/icon/warning.png"
}else if(option=="info"){
this.icon="/common/icon/info.png"
}else if(option=="error"){
this.color="#955620";
this.icon="/common/icon/error.png"
}
},
close(e){;
this.isShow=e.detail;
},
confirm(e){
console.info("确认:"+JSON.stringify(e));
this.isShow=e.detail;
},
cancel(e){
console.info("取消:"+JSON.stringify(e))
this.isShow=e.detail;
}
```
- 参数使用说明
**time:** {default: 1500};自动关闭时长.
**isShow:** {default: false}, 默认是否显示
**type:** {default:"message"}, 弹框类型:message消息提示框;alert警告框;toast请提示 ;dialog弹出框
**text:**{default:"信息内容"},提示内容信息
**proptType:**{default:"success"},提示类型,可取值 success,warning,error,info
**bgColor:**{default:""}, 背景色
**color:**{default:""}, 文字颜色
**offsetTop:**{default:0},弹窗距离顶部位置,如果传递center,会垂直水平居中
**icon:**{default:""}, 小图标
**isClose**:{default:false},是否显示关闭按钮
**confirmBtn:**{default:"确认"},确定按钮文本内容
**cancelBtn:**{default:"取消"}, 取消按钮文本内容
**@close:** 关闭按钮回调事件
**@confirm:** 确定按钮回调事件
**@cancel:** 取消按钮回调事件
#### Tips
1. isClose属性在type=dialo或者alert有效。
2. confirmBtn,cancelBtn,confirm,cancel 在type=dialog有效
3. icon 在type=dialog无效
## 结语
原文demo在 https://gitee.com/queling/propt,感谢您的每一次耐心阅读。