#夏日挑战赛# HarmonyOS - 自定义组件之消息弹窗 原创 精华

中软国际鸿蒙生态
发布于 2022-6-29 09:34
浏览
4收藏

作者:潘宏熙

本文正在参加星光计划3.0–夏日挑战赛

前言

刚接触鸿蒙开发不久,在最近接触的一个项目中,发现有很多类似的消息提示弹窗。对项目所有弹窗进行分析,开发一个公共的消息弹窗组件

效果演示

#夏日挑战赛# HarmonyOS - 自定义组件之消息弹窗-鸿蒙开发者社区

组件说明

组件属性定义

组件属性

名称 类型 默认值 必填 描述
visible object {show: false} 控制弹窗显示状态,由于现在的组件属性没有双向绑定功能。所以采用对象格式,确保每次改变visible值的时候,组件都可以监听到
options object 弹窗显示属性,包括标题,内容,按钮等,具体格式参考下面options属性说明

组件options属性

名称 类型 默认值 必填 描述
title string 弹窗标题
content string|string 弹窗文本内容,当content为字符串类型显示为单行文本,为字符串数组显示为多行文本,单行文本会自动居中展示
buttons (string|button) 弹窗标题,底部按钮,具体属性 最多显示2个按钮,如果超过2个后面部分自动舍去。具体格式参考下面button属性说明

组件options属性中的button属性

名称 类型 默认值 必填 描述
text string 按钮显示文本,当button为string时,即为该属性
handle function 按钮点击触发事件,会在弹窗关闭后调用此事件

组件实现代码

htm代码:

<!-- index.hml -->
<dialog ref="messageBoxDialog">
    <div class="box">
        <div class="header {{!title?'no-title':''}}">
            <text class="header-text color-text">{{title}}</text>
        </div>
        <div class="content {{isTextCenter?'content-center':''}}">
            <text for="item in content" class="content-text color-text">{{item}}</text>
        </div>
        <div class="btn-bar {{!firstBtn.show?'no-btn':''}}">
            <button if="{{firstBtn.show}}" class="btn" type="text" @click="firstBtnClick">{{firstBtn.text}}</button>
            <divider if="{{secondBtn.show}}" vertical="true" class="btn-divider"></divider>
            <button if="{{secondBtn.show}}" class="btn" type="text" @click="secondBtnClick">{{secondBtn.text}}</button>
        </div>
    </div>
</dialog>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

样式代码:

/* index.css */
.box{
    flex-direction: column;
    width: 100%;
}
.header {
    height: 56px;
    align-items: center;
    padding: 0px 24px;
    width: 100%;
}
.header-text {
    font-size: 20px;
}
.content {
    width: 100%;
    flex-direction: column;
    padding: 0px 24px;
}
.content-center {
    align-items: center;
}
.content-text {
    font-size: 16px;
    line-height: 20px;
}
.btn-bar{
    height: 56px;
    margin-top: 8px;
    padding: 0px 16px;
    justify-content: center;
}
.btn{
    height: 40px;
    background-color: #fff;
    width: 100%;
    border-radius: 0px;
}
.btn-divider {
    height: 40px;
    padding: 8px 0px;
    flex: 0 0 40px;
}
.no-title {
    height: 24px;
}
.no-btn {
    margin-top: 0px;
    height: 24px;
}
.color-text{
    color: rgba(0,0,0,0.9);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.

js代码:

// index.js
export default {
    props: {
        // 属性visible控制弹窗是否显示
        visible:{
            default(){
                return {
                    show:false
                }
            }
        },
        // 属性options弹窗显示内容控制
        options: {
            default(){
                return {
                    content:''
                }
            }
        }
    },
    data : {
        // 组件内部记录当前打开或关闭状态
        isShow:false
    },
    // 对传入的各种属性进行逻辑处理
    computed:{
        title(){
            return this.options.title || ''
        },
        content(){
            const content = this.options.content
            if(Array.isArray(content)){
                return content
            }
            if(typeof content === 'string'){
                return [content]
            }
            return []
        },
        // 处理文本居中显示逻辑
        isTextCenter(){
            const content = this.options.content
            if(Array.isArray(content)){
                return false
            }
            if(typeof content === 'string'){
                return  true
            }
            return false
        },
        firstBtn(){
            const buttons = this.options.buttons || [];
            const button = buttons[0];
            const butOpt = { show:true }
            if(button){
                if(typeof button === 'string'){
                    butOpt.text = button
                } else if(typeof button === 'object') {
                    butOpt.text = button.text
                    butOpt.handle = button.handle
                }else {
                    butOpt.show = false
                }
            }else{
                butOpt.show = false
            }
            return butOpt
        },
        secondBtn(){
            const buttons = this.options.buttons || [];
            const button = buttons[1];
            const butOpt = { show:true }
            console.log('secondBtn: ' + JSON.stringify(button))
            if(button){
                if(typeof button === 'string'){
                    butOpt.text = button
                } else if(typeof button === 'object') {
                    butOpt.text = button.text
                    butOpt.handle = button.handle
                }else {
                    butOpt.show = false
                }
            }else{
                butOpt.show = false
            }
            return butOpt
        }
    },
    onInit() {
        // 监听visible属性,控制弹窗打开或关闭
        this.$watch('visible', 'onVisibleChange');
    },
    onVisibleChange(val){
        if(val.show){
            if(!this.isShow){
                this.$refs.messageBoxDialog.show();
                this.isShow = true;
            }
        }else{
            if(this.isShow){
                this.$refs.messageBoxDialog.close();
                this.isShow = false;
            }
        }
    },
    firstBtnClick(){
        if(this.isShow){
            this.$refs.messageBoxDialog.close();
            this.isShow = false;
        }
        if(typeof this.firstBtn.handle === 'function'){
            this.firstBtn.handle()
        }
    },
    secondBtnClick(){
        if(this.isShow){
            this.$refs.messageBoxDialog.close();
            this.isShow = false;
        }
        if(typeof this.secondBtn.handle === 'function'){
            this.secondBtn.handle()
        }
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.

组件使用

在其他组件或页面hml引入组件

<element name="message-box" src="../../component/message-box/index.hml"></element>
<div class="container">
    ...
    <message-box id="message-box-dialog" visible="{{visible}}" options="{{message}}"></message-box>
</div>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

在其他组件或页面js中如下使用

    // 在data中定义组件属性,具体属性格式可以参考组件属性定义
    data: {
        ...
        visible: {
            show:false
        },
        message:{
            content:''
        }
    },
    ...
    // 重新连接方法
    connect(){
        console.log('connect is called')
    }
    // 调用此方法可以在页面打开弹窗
    openDialog(){
        this.message = {
            title:'连接失败',
            content:[
                "1.请确认设备电量充足,并处开机状态请确认设备电量充足,并处开机状态",
                "2.将设备靠近要连接的手机(10米以内)"
            ],
            buttons:['稍后再试',{text:'重新连接',handle:this.connect}]
        };
        this.visible = { show:true };
    },
    // 其他参数调用,只有一个按钮
    openDialog2(){
        this.message = {
            title:'配网失败',
            content:[
                "1.检查设备是否接通电源",
                "2.请按开关键至ON",
                "3.再次碰一碰",
                "4.听到“嘀”一声提示音表示设置成功"
            ],
            buttons:['我知道了']
        }
        this.visible = {show:true};
    },
    // 无标题
    openDialog3(){
        this.message = {content:'检查设备是否接通电源检',buttons:['我知道了']}
        this.visible = {show:true};
    },
    // 无按钮,3秒后自动关闭
    openDialog4(){
        this.message = {title:'温馨提示',content:'检查设备是否接通电源检'}
        this.visible = {show:true};
        setTimeout(()=>{
            this.visible = {show:false};
        },3000)
    },
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.

总结

以上就是消息弹窗组件开发以及使用的全部内容。此组件可以更加灵活的控制打开或关闭。也可以动态的显示弹窗内容。

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
7
收藏 4
回复
举报
7
2
4
2条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

赞,学习了。

回复
2022-6-29 10:17:53
中软小助手
中软小助手

确实很实用,收藏了

回复
2022-6-29 11:40:21


回复
    相关推荐