鸿蒙入门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 = 0
  build() {
    /* 这里构建 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 = 0
  build() {
    /* 这里构建 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 = 0
  build() {
    Column() {
      Text(`${ this.count }`).fontSize(20)
    }
  }
}

当你调用子组件的时候

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

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

  • 通过 @State 在子组件内进行赋值
  • 父子组件是互不干扰的, 数据是相互独立的
@Entry
@Component
struct Index {
  /* 这里存放数据 */
  @State count: number = 0
  build() {
    /* 这里构建 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 = 0
  build() {
    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 = 0
  build() {
    /* 这里构建 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: number
  build() {
    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 = 0
  build() {
    /* 这里构建 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: number
  build() {
    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 = 0
  build() {
    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: number
  build() {
    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: number
  build() {
    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 = 0
  build() {
    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: number

  onCountUpdate(): 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)
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法课程笔记——常用库函数

memset初始化 设置成0是可以每个设置为0 而1时会特别大 -1的补码是11111111 要先排序 unique得到的是地址 地址减去得到下标 结果会放到后面 如果这样非相邻 会出错 要先用sort排序 O(n)被O(nlogn)覆盖

Axure引用ECharts图表 解决火狐浏览器出错

Axure原型添加Echarts图表,没耐心看文章的可以直接下载示例 Axure中使用ECharts图表示例 1. 打开Axure新建页面 2. 页面添加元件 元件类型随意,矩形、动态面板、热区、图片 甚至段落都可以3. 命名元件 随意命名,单个页面用到多个图表时名…

【目标检测】Focal Loss

Focal Loss用来解决正负样本不平衡问题,并提升训练过程对困难样本的关注。 在一阶段目标检测算法中,以YOLO v3为例,计算置信度损失(图中第3、4项)时有目标的点少,无目标的点多,两者可能相差百倍…

为主机配置IP

第一种方法:nmcli #nmcli connection modify eth0 ipv4.method manual ipv4.addresses 172.25.254.100/24 ipv4.gateway 172.25.254.2 ipv4.dns 114.114.114.114 autoconnect yes #nmcli c up etho //激活网卡命令(网卡早就配好,只是修改ip就不用输入这条命令了) 第二…

SpringMVC(五)【拦截器】

前言 今天来把 SpringMVC 最后一部分学完,虽然课时很短,但是学起来还是很慢的,不过确收获很大。不得不感慨学大数据确实有必要把 SSM、SpringBoot 等各种 JavaEE 技术好好学一学,收获很大,尽管我们到现在 Java 代码写了…

循环双链表的操作

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 每一个裂缝都是为透出光而努力&#…

BIM数据管理快速指南

在我的日常工作中,作为数字协作协调员,我花费大量时间收集、检查和管理各种 BIM 数据。 很多次收到一组数据后我就无奈地举手——质量远远达不到我可以使用的程度。 然后我会开始一个普通的数据清理过程。 我无数次咒骂过这种情况——大多数建设项目的人…

qt 开发 缩放比例问题 修复中

在日常开中,需要开启 高分辨率的支持,windows环境下,不是 字体缩放,就是分辨率模糊,缩放机制,并且开启了150%缩放,有点搞不明白,最后还是不行,先做个记录,在找…

windows部署pgsql

1、下载:Download PostgreSQL Binaries 2、创建data目录作为数据目录 3、初始化 bin目录执行命令: .\initdb.exe -D E:\pgsql\data -E UTF-8 --localechs -U postgres -W 输入密码直到完成 4、启动数据库 .\pg_ctl.exe -D E:\pgsql\data -l logfil…

[大模型]MiniCPM-2B-chat WebDemo部署

MiniCPM-2B-chat WebDemo部署 MiniCPM-2B-chat 介绍 MiniCPM 是面壁智能与清华大学自然语言处理实验室共同开源的系列端侧大模型,主体语言模型 MiniCPM-2B 仅有 24亿(2.4B)的非词嵌入参数量。 经过 SFT 后,MiniCPM 在公开综合性…

吴恩达机器学习笔记:第 8 周-13 聚类(Clustering)13.1-13.2

目录 第 8 周 13、 聚类(Clustering)13.1 无监督学习:简介 第 8 周 13、 聚类(Clustering) 13.1 无监督学习:简介 在这个视频中,我将开始介绍聚类算法。这将是一个激动人心的时刻,因为这是我们学习的第一个非监督学习算法。我们…

Nexus 私服禁止 release 包覆盖发布

按照 maven 规范,对仓库中的包使用 snapshot 和 release 进行了区分,前者每次可以覆盖发布,会以时间的方式保留之前的包,并将 snapshot 包依赖下载地址指向最新覆盖发布的包,顾名思义快照包是为了解决我们开发测试过程…

React-css-in-js技术

​🌈个人主页:前端青山 🔥系列专栏:React篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:React-css-in-js技术 目录 1、简介 2、定义样式与使用 3、样式继承 4、属性传递 1、简介 …

Shortened LLaMA:针对大语言模型的简单深度剪枝法

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 论文标题 & 发表会议:Shortened LLaMA: A Simple Depth Pruning for Large Language Models(ICLR 2024 Workshop) 论文地址:https://arxiv.org/abs/…

Swift-22-复杂数据类型

枚举enum 本小节讨论的枚举是一种基础类型,并不是对象。在Swift中,枚举有很多高级特性。 语法结构 enum EnumName : Type { case... },其中Type可以省略,{}中定义的枚举体至少包含一个case语句。 一个简单的实现如下&#xff0c…

【Lattice FPGA 开发】Modelsim与Diamond联合仿真

本文讲解Modelsim与Diamond进行联合仿真步骤,以及对遇到问题的解决与说明。 文章目录 软件版本0. Diamond设置文件为仿真文件特别注意 1. Diamond设置仿真软件为Modelsim2. Modelsim编译Lattice的库文件2.1 新建文件夹存放库文件2.2 Modelsim中建立新的仿真库2.2.1…

推荐一款websocket接口测试工具

网址:Websocket在线测试-Websocket接口测试-Websocket模拟请求工具 http://www.jsons.cn/websocket/ 很简单输入以ws开后的网址就可以了 这个网址是你后台设置的 如果连接成功会砸提示框内显示相关字样,反之则不行

【计算机毕业设计】学习平台产品功能介绍——后附源码

🎉**欢迎来到我的技术世界!**🎉 📘 博主小档案: 一名来自世界500强的资深程序媛,毕业于国内知名985高校。 🔧 技术专长: 在深度学习任务中展现出卓越的能力,包括但不限于…

Grid Controller

完整、易于使用的基于网格的第一人称控制器,具有《格里姆洛克传奇》、《地下城大师》和《巫师》的风格。 网格控制器是一种基于网格的第一人称控制器,设置简单,但具有鲁棒性和通用性。不需要脚本。 特征: 实时或基于回合的移动 平滑移动或即时捕捉到网格位置 倾斜、下降和蹲…

vivado 使用 JTAG-to-AXI Master 调试核进行硬件系统通信

使用 JTAG-to-AXI Master 调试核进行硬件系统通信 JTAG-to-AXI Master 调试核为可自定义核 , 可在运行时生成 AXI 传输事务并驱动 FPGA 内部的 AXI 信号。该核支持所 有存储器映射型 AXI 接口和 AXI4-Lite 接口 , 并且可支持位宽为 32 或 64 …