鸿蒙入门06-常见装饰器( 简单装饰器 )

  • 装饰器是鸿蒙开发中非常重要的一个环节
  • 因为在很多地方我们都需要用到装饰器
  • 并且如果我们想高度的复用, 那么装饰器就是必不可少的一环
  • 接下来我们就来介绍一些常见的装饰器
  • 注意 : 所有装饰器首字母大写

@Entry 

  • 用来装饰 struct 使用
  • 表示页面的入口

@Component 

  • 装饰 struct, 表示该 struct 具有基于组件的能力
  • 保证 struct 内部 包含一个且只能包含一个 build() 函数, 用于绘制 UI 界面
  • struct 内部, build() 函数外部, 用于存储数据的位置
  • 注意 : build() 函数内部必须要有容器组件
@Entry
@Component
struct Index {/* 这里存放数据 */build() {/* 这里构建 UI 界面 */}
}

 以上为基础内容结构

  • @Component 也可以单独定义组件
  • 单独定义的组件可以在其他组件内使用
@Entry
@Component
struct Index {/* 这里存放数据 */build() {/* 这里构建 UI 界面 */Row() {/* 可以直接使用子组件 */SonCom()}}
}// 定义一个子组件
@Component
struct SonCom {build() {/* 这里构建子组件 UI 结构 */}
}

@State

  • 用来装饰变量的装饰器( 其实就是用于定义变量 )
  • 必须本地初始化数据, 支持通过构造函数赋值
  • 当 @State 定义的数据被修改的时候, 所在组件的 build() 方法会被重新调用, 重新绘制所在 UI 界面
@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {/* 这里构建 UI 界面 */Column() {// 展示 @state 定义的变量Text(`${ this.count }`).fontSize(20)Divider().margin(10)// 按钮点击的时候修改 @state 定义的变量Button('Click Me').onClick(() => this.count++)}}
}

这里使用 Text() 组件展示了 @State 定义的 count 变量

通过 Button() 组件的点击事件修改了 @State 定义的 count 变量

因为变量的修改导致了 UI 界面的重新绘制

所以页面跟随出现变化

其实就是我们之前知道的响应式数据一个原理

  • 在子组件内也同样是使用 @State 定义数据
  • 在子组件内定义的数据, 可以通过父组件调用的时候进行赋值

 

@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {/* 这里构建 UI 界面 */Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')SonCom() // 不对初始内容进行赋值Blank().height(30)Text('子组件 UI 部分')SonCom({ count: 100 }) // 对初始内容进行赋值}}
}@Component
struct SonCom {@State count: number = 0build() {Column() {Text(`${ this.count }`).fontSize(20)}}
}

当你调用子组件的时候

如果不对 @State 定义的变量赋值, 那么就用子组件内初始化时候的赋值

如果对 @State 定义的变量赋值, 那么就会使用调用时所赋予的值

  • 通过 @State 在子组件内进行赋值
  • 父子组件是互不干扰的, 数据是相互独立的
@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {/* 这里构建 UI 界面 */Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')SonCom()}}
}@Component
struct SonCom {@State count: number = 0build() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改子组件 count').onClick(() => this.count++)}}
}

@Prop

  • 继承了 @State 的所有功能
  • 注意 :
    • 定义的时候可以不需要本地直接初始化, 调用子组件的时候需要对其进行赋值
    • 被 @Prop 装饰的变量可以和父组件建立单向同步关系
    • @Prop 装饰的变量是可变的, 但是修改时不会同步回父组件, 当父组件的 @State 变化时, 本地修改的 @Prop 会被覆盖
@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {/* 这里构建 UI 界面 */Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')// 调用自组件的时候, 将父组件 @State 定义的 count 赋值SonCom({ count: this.count })}}
}@Component
struct SonCom {// 使用 @Prop 定义一个初始变量@Prop count: numberbuild() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改子组件 count').onClick(() => this.count++)}}
}

  • 此时, 当你在子组件内修改 count 的时候, 子组件内的数据单独出现变换
  • 但是当你在父组件内修改 count 的时候, 会连带修改子组件内的 count, 并且会将覆盖子组件内的修改

@Link

  • @Link 装饰的变量和父组件会构建双向同步关系
    • 父组件会接受来自 @Link 装饰的变量的修改同步
    • 父组件的更新也会同步给 @Link 装饰的变量
  • @Link 装饰的变量与其父组件中的数据源共享相同的值
  • 注意 :
    • 子组件使用 @Link 定义变量的时候不需要赋值, 而是调用子组件的时候进行赋值
    • 调用子组件赋值的时候使用 "$变量名" 的形式进行赋值
    • @Link 装饰器不能再 @Entry 装饰的自定义组件中使用
@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {/* 这里构建 UI 界面 */Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')// 调用自组件的时候, 将父组件 @State 定义的 count 赋值// 注意: 使用 $变量名 的形式进行赋值SonCom({ count: $count })}}
}@Component
struct SonCom {// 使用 @Link 定义一个初始变量@Link count: numberbuild() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改子组件 count').onClick(() => this.count++)}}
}

  • 此时, 子组件内修改 count 的时候, 会同步影响到父组件内的 count
  • 修改父组件内的 count 的时候, 也会同步影响到子组件内的 count

@Provide 和 @Consume

  • 之前我们学习过了 @State/@Link 两个装饰器组合在一起, 可以实现父子组件的双向数据传递
  • 如果在父子组件之间进行数据传递的话, 使用起来还是相当方便的
  • 但是, 如果层级过高的话, 那么使用起来就比较麻烦来
  • 我们先来看一下 @State/@Link 进行层级组件嵌套
@Entry
@Component
struct Index {/* 这里存放数据 */@State count: number = 0build() {Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')// 调用子组件的时候, 将父组件 @State 定义的 count 赋值// 注意: 使用 $变量名 的形式进行赋值SonCom({ count: $count })}}
}@Component
struct SonCom {// 使用 @Link 定义一个初始变量@Link count: numberbuild() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改子组件 count').onClick(() => this.count++)Blank().height(30)Text('子子组件 UI 部分')// 调用子子组件的时候, 将子组件 @Link 定义的 count 赋值// 注意: 使用 $变量名 的形式进行赋值SonSonCom({ count: $count })}}
}@Component
struct SonSonCom {// 使用 @Link 定义一个初始变量@Link count: numberbuild() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改子组件 count').onClick(() => this.count++)}}
}

 

  • 此时我们就实现了跨组件传递数据
  • 但是想对来说就比较麻烦了, 相当繁琐
  • 如果组件嵌套的层级过深, 那么这个数据的传递就实在是太复杂了
  • 此时我们可以使用 @Provide 和 @Consume 进行跨组件数据传递
  • 使用语法 :
    • @Provide('名字') 变量名: 类型 = 赋值
    • @Consume('名字') 变量名
    • 注意 : @Provide 和 @Comsume 处使用的名字要一致, 但是变量名不需要一致

  • 使用发布订阅模式, 父类使用 @Provide, 其他需要观察的子类使用 @Consume, 就可以实现双向绑定
  • 当层级很深时, 不需要一层一层传递数据, 直接使用发布订阅进行监听就能实现相同的效果
  • @Provide 和 @Consume 可以通过相同的变量名或者相同的变量别名绑定, 但是变量类型必须相同
  • @Provide 必须设置初始值, @Consume 不可以设置默认初始值
  • @Provide 修饰的变量和 @Consume 修饰的变量可以是一对多的关系

@Watch

  • 使用观察者模式的装饰器
  • 注意 : 该装饰器不是触发变量变化, 而是绑定一个函数, 当监控的变量发生变化时, 该函数触发
  • 语法 : @Watch('函数名')
@Entry
@Component
struct Index {/* 这里存放数据 */// 在父组件内使用 @Provide 创建数据@State count: number = 0build() {Column() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)Blank().height(30)Text('子组件 UI 部分')SonCom({ count: this.count })}}
}@Component
struct SonCom {@Prop @Watch('onCountUpdate') count: numberonCountUpdate(): void {console.log('count 数据发生变化了')}build() {Column() {Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)}}
}

@Builder

  • @Builder 是 ArkUI 提供的一种更加轻量的复用机制
  • 因为在 @Component 内能且只能创建一个 build() 函数
  • 我们可以在组件内利用 @Builder 装饰器自定义一个构建函数
  • @Builder 创建的构建函数遵循 build() 函数的语法规则, 并且可以在 build() 函数内调用
  • 语法 :
    • 定义语法 : @Builder MyBuilder() {}
    • 使用语法 : this.MyBuilder() {}
  • 语法要点
    • 自定义构建函数可以在所属组件内的 build() 方法和其他自定义构建函数内调佣, 但不允许在组件外调用
    • 允许在自定义组件内定义一个或多个 @Builder 方法, 该方法被认为是该组件的私有成员
    • 在自定义函数体内, this 指代当前所属组件, 组件的状态变量可以在自定义构建函数内访问
    • 自定义构建函数不仅可以添加属性, 还可以添加事件

  • 在组件外也可以使用 @Builder 创建一个自定义构建函数
  • 注意 : 在组件外使用 @Builder 的时候, 构建函数内不能使用 this
@Entry
@Component
struct Index {/* 这里存放数据 */// 在父组件内使用 @Provide 创建数据@State count: number = 0// 创建一段组件内自定义构建函数@Builder CountUpdate() {Text('父组件 UI 部分').fontSize(20)Text(`${ this.count }`).fontSize(20)Divider().margin(10)Button('Click Me 修改父组件 count').onClick(() => this.count++)}build() {Column() {// 直接使用自定义构建函数this.CountUpdate()Blank().height(30)// 使用组件外自定义构建函数MyBuilder('Hello World')}}
}// 组件外定义自定义构建函数
@Builder
function MyBuilder(message: string) {Column() {Text(message)}
}

@Styles

  • 在开发中有的时候, 有的时候我们的一些样式也要重用
  • @Styles 装饰器就可以将多条样式提炼成一个方法, 以供复用
  • 和 @Builder 一样, 可以定义在 组件内 和 组件外
@Entry
@Component
struct Index {// 定义一个组件内样式方法@Styles MyStyles() {.width(200).height(200).backgroundColor(Color.Orange)}build() {Column() {Row() {}.MyStyles()Blank().margin(10)Row() {}.MyStyles()}}
}

  • 这是组件内定义样式方法
  • 我们再来定义一个组件外样式方法
@Entry
@Component
struct Index {// 定义一个组件内样式方法@Styles MyStyles() {.width(200).height(200).backgroundColor(Color.Orange)}build() {Column() {Row() {}.MyStyles()Blank().margin(10)Row() {}.MyStyles2()}}
}@Styles
function MyStyles2() {.width(100).height(100).backgroundColor(Color.Pink)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot的论坛管理系统

基于SpringbootVue的论坛管理系统的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页 公告 热门帖子 论坛新天地 新闻资讯 留言反馈 后台登录 用户管理 公告管理…

java宠物领养系统的设计与实现(springboot+mysql+源码)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的宠物领养系统的设计与实现。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于Spring Bo…

JavaWeb--04YApi,Vue-cli脚手架Node.js环境搭建,创建第一个Vue项目

04 1 Yapi2 Vue-cli脚手架Node.js环境搭建配置npm的全局安装路径 3 创建项目(这个看下一篇文章吧) 1 Yapi 前后端分离中的重要枢纽"接口文档",以下一款为Yapi的接口文档 介绍:YApi 是高效、易用、功能强大的 api 管理平台&#…

Springboot引入外部jar包并打包jar包

前言 spring boot项目开发过程中难免需要引入外部jar包&#xff0c;下面将以idea为例说明操作步骤 将需要的jar包导入到项目中 2.在maven中引入jar包 <dependency><groupId>com</groupId><!--随便填的文件夹名称--><artifactId>xxx</artif…

linux内核初始化成功后是如何过渡到android初始化的

Android用的linux内核&#xff0c;以完成OS该有的功能&#xff0c;例如&#xff0c;文件系统&#xff0c;网络&#xff0c;内存管理&#xff0c;进程调度&#xff0c;驱动等 &#xff0c;向下管理硬件资源向上提供系统调用。另一些Android特有驱动也放在内核之中。 当linux内核…

【Qt】Qt安装包、源码、子模块(submodules)下载

1、Qt 4.0 ~ Qt5.14 Qt 4.0 ~ Qt5.14 离线安装包、源码和子模块(submodules)源码下载路径: https://download.qt.io/new_archive/qt/以Qt5.7.1为例,注意子模块都是源码,需要独立编译 2、Qt5.15 ~ Qt6.7 Qt5.15 ~ Qt6.7源码和子模块(submodules)源码下载路径: htt…

LabVIEW供热管道泄漏监测与定位

LabVIEW供热管道泄漏监测与定位 在现代城市的基础设施建设中&#xff0c;供热管道系统起着极其重要的作用。然而&#xff0c;管道泄漏问题不仅导致巨大的经济损失&#xff0c;还对公共安全构成威胁。因此&#xff0c;开发一种高效、准确的管道泄漏监测与定位技术显得尤为关键。…

GUI02-在窗口上跟踪并输出鼠标位置(Win32版)

(1) 响应 WM_MOUSEMOVE 消息获得鼠标位置&#xff1b; (2) 响应 WM_PAINT 将鼠标位置输出到窗口中&#xff1b; (3) 学习二者之间的关键步骤&#xff1a;调用 InvalidateRect() 以通知窗口重绘。 零. 课堂视频 在窗口上跟踪输出鼠标位置-Win32版 一、关键知识点 1. BeginPaint…

HANA SQL消耗内存和CPU线程的限制参数

HANA再处理大数据表相关的复杂Sql时&#xff0c;如果没有设置Memory和CPU线程上限的话&#xff0c;会将HANA的资源占用殆尽&#xff0c;造成HANA无法响应其他Sql请求&#xff0c;导致表现在应用服务器上就是系统卡顿的情况。解决上述问题的办法就是按照下图设置Memory(图1&…

穿越物联网的迷雾:深入理解MQTT协议

目录标题 1、MQTT简介核心特性 2、MQTT的工作原理通信过程 3、MQTT的消息质量&#xff08;QoS&#xff09;4、安全机制5、实践应用环境准备示例项目发布者客户端订阅者客户端 6、最佳实践7、结论8、参考资料 在物联网&#xff08;IoT&#xff09;的海洋中&#xff0c;数据像水流…

软考 - 系统架构设计师 - 设计模式

概念 每一个设计模式描述了一个在我们周围不断重复发生的问题&#xff0c;以及该问题解决方案的核心&#xff0c;这样&#xff0c;就可以在遇到相同的问题时使用该解决方案进行解决&#xff0c;不必进行重复的工作&#xff0c;设计模式的核心在于提供了问题的解决方案&#xff…

uni-admin中引入uni-cms的缺少schema及uni-media-library缺少云函数的问题

1. 在管理端运行提示一些表找不到&#xff0c;因为是uni-admin关联的uni-starter的服务空间&#xff0c;在uni-admin的uniCloud中没有内容&#xff0c;在uni-starter的uniCloud中也没有发现对应的表&#xff0c;后面干脆在云端找到对应的表之后新建了&#xff0c;然后再下载到本…

Python 入门指南(四)

原文&#xff1a;zh.annas-archive.org/md5/97bc15629f1b51a0671040c56db61b92 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十章&#xff1a;哈希和符号表 我们之前看过列表&#xff0c;其中项目按顺序存储并通过索引号访问。索引号对计算机来说很有效。它们是整…

美团财务科技后端一面:如何保证数据一致性?延时双删第二次失败如何解决?

更多大厂面试内容可见 -> http://11come.cn 美团财务科技后端一面&#xff1a;项目内容拷打 美团财务科技后端一面&#xff1a;项目相关面试题&#xff0c;主要包含 Zset、延时双删失败重试、热点数据解决、ThreadLocal 这几个方面相关的内容 由于前几个问题是对个人项目的…

C++ STL 容器 list

目录 1. list 对象2. list 迭代器2.1 实现2.2 迭代器失效 本文测试环境为 gcc 13.1 1. list 对象 std::list 底层是一个双向循环链表 list 对象本身包含一个头节点&#xff0c;通过指针指向元素节点&#xff0c;节点定义如下 头节点 header 和元素节点 node 都继承于基类 no…

历史遗留问题1-Oracle Mysql如何存储数据、索引

在学习到Oracle redo和undo时&#xff0c;涉及到很多存储结构的知识&#xff0c;但是网上的教程都不是很详细&#xff0c;就去复习了一下mysql&#xff0c;感觉是不是开源的问题&#xff0c;Mysql的社区和知识沉淀远高于Oracle&#xff0c; 对于初学者很友好&#xff0c;我想请…

2025考研数学武忠祥强化班视频,百度网盘课程+讲义PDF更新

25考研的小伙伴们现在应该基础都学习的差不多了吧&#xff01; 是时候进入强化阶段的学习啦。 2025考研数学强化班全程网盘&#xff1a;https://pan.baidu.com/s/1Z029fuCLkyyhIRFqd5QKcg 提取码&#xff1a;p3ue 晚上好&#xff0c;聊聊17堂课的看课攻略。 今年的17堂课还…

IP-guard WebServer 权限绕过漏洞复现(QVD-2024-14103)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

Mac下brew安装php7.4

这里作者挂了梯子&#xff0c;所以很流畅&#xff01; brew的下载&#xff0c;可参考另外一篇博文&#xff5e;Homebrew 安装与卸载 1、将第三方仓库加入brew brew tap shivammathur/php2、安装指定版本的PHP brew install php7.43、替换Mac自带PHP环境并刷新环境变量 -> …

【ACM列表推荐会议 | EI稳定检索】2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)

2024年第四届人工智能、自动化与高性能计算国际会议&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)将于20…