装饰器,状态管理和if判断(HarmonyOS学习第六课)

news2024/11/15 13:47:12

@Builder装饰器-自定义构建函数

前面介绍了如何创建一个自定义组件。该自定义组件内部UI结构固定,仅与使方法进行数据传递。ArkUI还提供了一种更轻量的UI 元素复用机制@Builder,@Builder

所装饰的函数遵循build( )函数语法规则,开发者可以将重复使用的UI 元素抽象成一个方法,在 build 方法里调用。 为了简化语言,我们将@Builder 装饰的函数也称为“自定义构建函数”。从API version 9开始,该装饰器支持在ArkTS卡片中使用。

装饰器使用说明:

语法的定义

@Builder MyBuilderFunction( ){...}

使用方法

this.MyBuilderFunction(){...}

  • 允许在自定义组件内定义一个或多个@Builder 方法,该方法被认为是该组件的私有、特殊类型的成员函数。

  • 自定义构建函数可以在所属组件的build 方法和其他自定义构建函数中调用,但不允许在组件外调用。

  • 在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递

全局自定义构建函数

语法的定义

@BUilder function MyGlobalBuilderFunction(){...}

使用方法

MyGlobalBuilderFunction()
  • 全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。

  • 如果不涉及组件状态变化,建议使用全局的自定义构建方法

参数传递规则

自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:

参数的类型必须与参数声明的类型一致,不允许undefined、nu1l和返回undefined、null的表达式

引用传参(最常用)

//自定义一个构建函数
//引用传参使用$$符号
@Builder
function  MyBulilder($$:{username:string}){
​
//用的时候也要使用$$
  Column(){
    Text(`hello ${$$.username}`)
      .fontSize(40)
      .margin(20)
  }
}
​
@Entry
@Component
​
struct  Parent{
​
  @State person_name: string='张三'
​
  build(){
    Column(){
      Divider()
      MyBulilder({username: this.person_name})
      Button('改变值').onClick(()=>{
        this.person_name ='李四'
      })
    }
  }
}

值传参(了解 并不实用)

//自定义一个构建函数
//按值传参
@Builder
function  MyBulilder(username:string){
​
​
  Column(){
    Text(`hello ${username}`)
      .fontSize(40)
      .margin(20)
  }
}
​
@Entry
@Component
​
struct  Parent{
​
  @State person_name: string='张三'
​
  build(){
    Column(){
      Divider()
      MyBulilder(this.person_name)
      Button('改变值').onClick(()=>{
        this.person_name ='李四'
      })
    }
  }
}

状态管理

状态管理概述

在前文的描述中,我们构建的页面多为静态界面。如果希望构建一个动态的、有交互的界面,就需要引入“状态”的概念

在本章节开始的案例中,用户与应用程序的交互触发了文本状态变更,状态变更引起了UI 渲染,UI 从“Hello world”变更为“Hello rkUI”,这个过程就用到了状态。

在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个U模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。

自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。下图展示了state和iew(UI)之间的关系

  • View(UI):UI 渲染,指将build 方法内的 UI 描述和@Builder 装饰的方法内的UI 描述映射到界面。

  • state:状态,指驱动U更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。

基本概念

  • 状态变量:被状态装饰器装饰的变量,状态变量值的改变会引起UI的染更新。示例:@State num: number=1,其中,@State是状态装饰器,num是状态变量。

  • 常规变量:没有被状态装饰器装饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。以下示例中increaseBy 变量为常规变量。

  • 数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。以下示例中数据源为count:1。

  • 命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:CompA:({aPrp:this.aProp})。

  • 从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。子组件初始化的默认值在有父组件传值的情况下,会被覆盖。

  • 初始化子节点:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。

  • 本地初始化:在变量声明的时候赋值,作为变量的默认值。示例:@statecount:number =0

管理组件拥有的状态

@State装饰器-组件内状态

@state 装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。

在状态变量相关装饰器中,@state是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。从Pversion9开始,该装饰器支持在ArkTs 卡片中使用。

概述

@State装饰的变量,与声明式范式中的其他被装价变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。

装饰器使用说明

使用场景

装饰简单类型的变量 以下示例为@state装饰的简单类型,count被@state装饰成为状态变量,count的改变引起Button组件的刷新:

  1. 当状态变量count改变时,查询到只有Button组件关联了它;

  2. 执行Button组件的更新方法,实现按需刷新。

示例

点击修改姓名将会在张三,李四之间进行切换

点击修改年龄将会按照你设定的规则进行年龄的加减

当子组件上传参数的时候将使用子组件的参数

当没有的时候默认是父组件的数据

@Prop装饰器-父子单项同步

@Prop 装饰的变量可以和父组性建立单向的同步关系。@Prop装饰的变量是可变但是变化不会同步回其父组件。从API version 9开始,该装饰器支持在rkTS 卡中使用。

概述

  • @Prop 装饰的变量和父组件建立单向的同步关系:

  • @Prop变量允许在本地修改,但修改后的变化不会同步回父组件

  • 当父组件中的数据源更改时,与之相关的@Prop 装饰的变量都会自动更新。如果子组件已经在本地修改了@Prop 装饰的相关变量值,而在父组件中对应的@state装饰的变量被修改后,子组件本地修改的@Prop装饰的相关变量值将被覆盖

限制条件

  • @Prop 修饰复杂类型时是深拷贝,在拷贝的过程中除了基本类型、Map、Set、Date、Array 外,都会丢失类型。

  • @Prop装饰器不能在@Entry装饰的自定义组件中使用

装饰器使用规则说明

使用场景:

父组件@State 到子组件@Prop简单数据类型同步

以下示例是@state 到子组件@Prop 简单数据同步,父组件ParentComponent的状态变量 countDownstartValue 初始化子组件 CountDowncomponent 中eprop 装饰的 count,点击“Try again”,,count 的修改仅保留在 CountDownComponent不会同步给父组件ParentComponent。

ParentComponent的状态变量countDownstartValue 的变化将重冒CountDownComponent的count。

代码:

@Component
struct MyChid{
  @Prop
  age: number  =33
  private increase: number=1 //私有
  build(){
    Column(){
      if (this.age>=18){
        Text(`已经age成年了:${this.age}`).height(80)
      }else
      {
        Text(`age未成年了:${this.age}`).height(80)
      }
      Button('-修改子组件age').onClick(()=>{
        this.age-=this.increase
      })
        .height(80)
        .width(250)
        .margin(5)
    }
  }
}
​
@Entry
@Component
struct Myparent {
  @State
  init_age: number =16
​
  build(){
    Column(){
      Text(`父组件初始值:${this.init_age}`).height(80)
​
      Button('+修改父组件age').onClick(()=>{
        this.init_age+=1
      })
        .height(80)
        .margin(5)
        .width(250)
​
      Divider()
      MyChid({age:this.init_age,increase:2})
    }
  }
}

@Link装饰器-父子双向同步

子组件中被@Link 装饰的变量与其父组件中对应的数据源建立双向数据绑定。从APIversion 9开始,该装饰器支持在ArkTS卡片中使用。

需要注意:@Link 装饰的变量与其父组件中的数据源共享相同的值。@Link 装饰器不能在@Entry 装饰的自定义组件中使用。

代码示例展示:

//自定义按钮的信息类型
class ButtonState{
  value:string;
  width:number=0;
​
  constructor(value:string, width:number){
    this.value = value;
    this.width = width;
  }
}
​
​
@Component
​
struct MyChildGreenButton{
  //拥有 绿色按钮的组件,Link装饰器 实现双向同步
  @Link
  buttonState:ButtonState   //自定义对象类型
​
  build(){
      Button(`${this.buttonState.value}`)
        .width(this.buttonState.width)
        .height(150)
        .backgroundColor(Color.Green)
        .onClick(()=>{
          //点击按钮  实现宽度的变化
          if(this.buttonState.width<700){
            this.buttonState.width+=100
          }else {
            //按钮宽度回到初始值
            this.buttonState = new ButtonState('绿色按钮',100)
          }
        })
  }
}
​
​
@Component
struct MyChildRedButton{
  //拥有 红色按钮的组件,Link装饰器 实现双向同步
  @Link
  value: string
  @Link
  buttomWidth: number;
​
  build(){
    Button(`${this.value}`)
      .width(this.buttomWidth)
      .height(150)
      .backgroundColor(Color.Red)
      .onClick(()=>{
        //点击按钮  实现宽度的变化
        if(this.buttomWidth<700){
          this.buttomWidth+=100
        }else {
          //按钮宽度回到初始值
          this.buttomWidth = 100
        }
      })
  }
}
​
@Entry
@Component
struct MYParent{
  @State parentGreenButton:ButtonState=new ButtonState('一号',100)  //状态变量
  @State parentRedValue: string = '二号子组件'  //状态变量
  @State parentRedWidth: number = 200   //状态变量  //绿色按钮的宽度
​
  build(){
     Column(){
       //父组件中调整按钮宽度
       Button(`父组件中修改绿色按钮的宽度:${this.parentGreenButton.width}`)
         .onClick(()=>{
           this.parentGreenButton.width = this.parentGreenButton.width < 700 ? this.parentGreenButton.width+100:100
         })
​
       Button(`父组件中修改红色按钮的宽度:${this.parentRedWidth}`)
         .onClick(()=>{
           this.parentRedWidth = this.parentRedWidth < 700 ? this.parentRedWidth+100:100
         })
​
       Divider()
​
       MyChildGreenButton({buttonState:$parentGreenButton})  //传递Link装饰器的变量时候加 $ 符号
       MyChildRedButton({value:$parentRedValue,buttomWidth:$parentRedWidth})
     }
  }
}

if/else 条件渲染

ArkTS 提供了渲染控制的能力。条件渲染可根据应用的不同状态,使用if、else 和else if 渲染对应状态下的UI内容。从API version 9开始,该接口支持在 ArkTS卡片中使用。

使用规则

  • 支持if、else和else if 语句。

  • if、else if 后跟随的条件语句可以使用状态变量

  • 允许在容器组件内使用,通过条件渲染语句构建不同的子组件。

  • 条件渲染语句在涉及到组件的父子关系时是“透明”的,当父组件和子组件之间存在一个或多个if语句时,必须遵守父组件关于子组件使用的规则。

  • “每个分支内部的构建函数必须遵循构建函数的规则,并创建一个或多个组件。无法创建组件的空构建函数会产生语法错误。

  • 某些容器组件限制子组件的类型或数量,将条件渲染语句用于这些组件内时,这些限制将同样应用于条件渲染语句内创建的组件。例如,Grid容器组件的子组件仅支持GridItem 组件,在Grid 内使用条件渲染语句时,条件渲染语句内仅允许使用GridItem组件

更新机制

当if、else if 后跟随的状态判断中使用的状态变量值变化时,条件渲染语句会进行更新,更新步骤如下:

  1. 评估if和else if的状态判断条件,如果分支没有变化,请无需执行以下步骤。如果分支有变化,则执行2、3步骤:

  2. 删除此前构建的所有子组件。

  3. 执行新分支的构造函数,将获取到的组件添加到if 父容器中。如果缺少适用的 else分支,则不构建任何内容。

    条件可以包括 Typescript 表达式。对于构造函数中的表达式,此类表达式不得更改应用程序状态。

使用if进行条件渲染

if 语句的每个分支都包含一个构建函数。此类构建函数必须创建一个或多个子组件。在初始渲染时,if语句会执行构建函数,并将生成的子组件添加到其父组件中。

“每当if或else if条件语句中使用的状态变量发生变化时,条件语句都会更新并重新评估新的条件值。如果条件值评估发生了变化,这意味着需要构建另一个条件分支。此时ArkUI 框架将:

  1. 删除所有以前渲染的(早期分支的)组件。

  2. 执行新分支的构造函数,将生成的子组件添加到其父组件中

代码演示

分为两种 :第一种 点击“是否真假的按钮的时候” 计数器的值会归零

//定义子组件
@Component
struct MyChild{
​
  //计数器
  @State   counter:number=0
  label: string;
​
  build(){
    Row(){
      Text(`${this.label}`)
        .width(100)
        .height(100)
        .fontSize(20)
​
​
      Button(`计数器的值:${this.counter}`)
        .width(200)
        .height(60)
        .onClick(()=>{
           this.counter += 1;
        })
    }
  }
}
​
@Entry
@Component
struct MyParent{
  @State flag:boolean=false;
  build(){
    Column(){
      //根据判断决定子组件
      if(this.flag){
        MyChild({label:'zhenzhen'})
      }else {
        MyChild({label:'jiajia'})
      }
      Divider()
      Button(`是否真假:${this.flag}`)
        .width(300)
        .height(60)
        .fontSize(30)
        .margin(40)
        .onClick(()=>{
          this.flag=!this.flag
        })
    }
  }
}

第二种 点击是否真假的时候计数器的值不会进行更新归零

//定义子组件
@Component
struct MyChild{
​
  //计数器
  @Link counter:number;
  label: string;
​
  build(){
    Row(){
      Text(`${this.label}`)
        .width(100)
        .height(100)
        .fontSize(20)
​
​
      Button(`计数器的值:${this.counter}`)
        .width(200)
        .height(60)
        .onClick(()=>{
           this.counter += 1;
        })
    }
  }
}
​
​
@Entry
@Component
struct MyParent{
  @State flag:boolean=false;
  @State parentCount: number=0
  build(){
    Column(){
      //根据判断决定子组件
      if(this.flag){
        MyChild({counter:$parentCount,label:'zhenzhen'})
      }else {
        MyChild({counter:$parentCount,label:'jiajia'})
      }
      Divider()
      Button(`是否真假:${this.flag}`)
        .width(300)
        .height(60)
        .fontSize(30)
        .margin(40)
        .onClick(()=>{
          this.flag=!this.flag
        })
    }
  }
}

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

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

相关文章

AutoMQ 生态集成 Tigris

Tigris[1]是一个全球分布式的兼容 S3 的对象存储服务&#xff0c;它允许你存储和访问任意数量的数据&#xff0c;具有广泛的使用场景。Tigris 会自动且智能地将数据分布到靠近用户的位置&#xff0c;让用户无需担心数据复制和缓存复杂性。 你可以将 Tigris 用于多种场景&#x…

探究MySQL中的“树”结构

1 引言 树高千丈,叶落求索 – 唐代杜牧 树结构在MySQL中常用于表示层次关系,如组织结构或分类体系。引入树结构可使数据之间建立父子关系,便于查询和管理。益处包括快速检索子节点、方便展示层次关系、支持递归查询等。 2 基础概念 2.1 名词解析 程序就像是一张有向图,你…

全能大模型AIGC产品的体验与未来展望

目录 前言1 使用体验分享1.1 字节豆包1.2 百度文心一言1.3 阿里通义千问1.4 腾讯元宝 2 大模型产品的对比与选择2.1 产品功能对比2.2 使用成本与便捷性2.3 安全性与隐私保护 3 大模型产品的未来发展方向3.1 技术创新3.2 可持续与可拓展性3.3 用户体验3.4 应用场景 结语 前言 随…

vue 如何制作一个跟随窗口大小变化而变化的组件

vue 如何制作一个跟随窗口大小变化而变化的组件 像下图中展示的那些统计数件就是跟随窗口变化而变化的&#xff0c;而且是几乎等比缩放的。 实现原理 只简略说一下原理。 pinia 中记录一个窗口变化的高度值给要变化的组件添加一个高度值组件内部所有关于长度距离的值都通过这…

利用同时预测节点和边的图神经网络 实现鲁棒的椎骨识别

文章目录 Robust Vertebra Identification Using Simultaneous Node and Edge Predicting Graph Neural Networks摘要方法实验结果 Robust Vertebra Identification Using Simultaneous Node and Edge Predicting Graph Neural Networks 摘要 该论文指出,在CT扫描中自动定位和…

神经网络 torch.nn---Convolution Layers

torch.nn — PyTorch 2.3 documentation torch.nn - PyTorch中文文档 (pytorch-cn.readthedocs.io) torch.nn和torch.nn.functional的区别 torch.nn是对torch.nn.functional的一个封装&#xff0c;让使用torch.nn.functional里面的包的时候更加方便 torch.nn包含了torch.nn.…

使用API有效率地管理Dynadot域名,删除已设置的文件夹

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

几种更新 npm 项目依赖的实用方法

几种更新 npm 项目依赖的实用方法 引言1. 使用 npm update 命令2. 使用 npm-check-updates 工具3. 使用 npm outdated 命令4. 直接手动更新 package.json 文件5. 直接安装最新版本6. 使用自动化工具结语 引言 在软件开发的过程中&#xff0c;我们知道依赖管理是其中一个至关重…

Linux基础指令磁盘管理002

LVM&#xff08;Logical Volume Manager&#xff09;是Linux系统中一种灵活的磁盘管理和存储解决方案&#xff0c;它允许用户在物理卷&#xff08;Physical Volumes, PV&#xff09;上创建卷组&#xff08;Volume Groups, VG&#xff09;&#xff0c;然后在卷组上创建逻辑卷&am…

【Unity性能优化】使用多边形碰撞器网格太多,性能消耗太大了怎么办

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…

【多模态】35、TinyLLaVA | 3.1B 的 LMM 模型就可以实现 7B LMM 模型的效果

文章目录 一、背景二、方法2.1 模型结构2.2 训练 pipeline 三、模型设置3.1 模型结构3.2 训练数据3.3 训练策略3.4 评测 benchmark 四、效果 论文&#xff1a;TinyLLaVA: A Framework of Small-scale Large Multimodal Models 代码&#xff1a;https://github.com/TinyLLaVA/T…

Stable Diffusion——四种模型 LoRA(包括LyCORIS)、Embeddings、Dreambooth、Hypernetwork

目前 Stable diffusion 中用到主要有四种模型&#xff0c;分别是 Textual Inversion &#xff08;TI&#xff09;以 Embeddings 为训练结果的模型、Hypernetwork 超网络模型、LoRA&#xff08;包括 LoRA 的变体 LyCORIS&#xff09;模型、Dreambooth 模型。 视频博主 koiboi 用…

儿童护眼灯哪个好?带你了解适合儿童的护眼灯款式分享

儿童护眼灯哪个好&#xff1f;作为我们日常生活中极为实用的小家电&#xff0c;为了确保使用台灯时的舒适性并且保护视力&#xff0c;选择一款专业的护眼台灯成为了一个明智的决定。这样的台灯能够提供更舒适、均匀的照明环境&#xff0c;那么到底儿童护眼灯哪个好你&#xff1…

LeetCode刷题之HOT100之不同路径

2024/6/6 小雨&#xff0c;没停。明天就要高考啦&#xff0c;回想五年前我也带着紧张与期待走过这些天&#xff0c;祝高考学子一切顺利。Anyway&#xff0c;早上一到实验室我就去看望我的栀子花&#xff0c;带着满怀的期待去看它长大了多少&#xff0c;是的&#xff0c;花苞还在…

umijs 服务端渲染(SSR) 指南

umijs 服务端渲染&#xff08;SSR&#xff09; 指南 Umi 是什么&#xff1f; Umi&#xff0c;中文可发音为乌米&#xff0c;是可扩展的企业级前端应用框架。Umi 以路由为基础的&#xff0c;同时支持配置式路由和约定式路由&#xff0c;保证路由的功能完备&#xff0c;并以此进…

科普!终于把手机副卡给搞清楚了!

你知道什么是手机副卡吗&#xff1f; 你开通过手机副卡吗&#xff1f; 小小的脑袋&#xff0c;大大的疑问&#xff1f; 可能很多朋友对手机副卡这个词比较懵&#xff0c;那不要紧&#xff0c;接下来小编给大家介绍的这是关于手机副卡。 ​ 十个问题&#xff0c;带你搞清楚什…

专用于恢复iOS系统的数据恢复软件

一、简介 1、一款专门为苹果iOS设备设计的数据恢复软件&#xff0c;支持iPhone、iPad和iPod Touch等设备的数据恢复。这款软件能够恢复包括微信聊天记录、通讯录、短信、备忘录等多种类型的数据。用户可以通过设备扫描恢复、iTunes备份恢复和iCloud备份恢复三种模式来进行数据恢…

【MySQL数据库】MySQL 高可用搭建方案——MHA实战

MHA&#xff08;Master High Availability&#xff09; MHA实战 MHA&#xff08;Master High Availability&#xff09; 一、MHA简介二、MHA搭建准备要求&#xff1a;mha集群搭建&#xff0c;4台服务器&#xff0c;1主2从&#xff0c;1台mha2.1实验思路2.2实验准备 三、搭建MyS…

Python代码关系图生成,帮助快速熟悉一个项目

一、静态代码关系图 工具1、pyreverse pyreverse 是一个由 Logilab 开发的 Python 工具&#xff0c;它能够自动生成 UML (统一建模语言) 类图&#xff0c;这些类图基于 Python 源代码。pyreverse 可以分析 Python 代码&#xff0c;并从中提取出类、模块、函数、方法和它们之间…

如何通过Python SMTP配置示例发附件邮件?

Python SMTP配置的步骤&#xff1f;SMTP服务器的优缺点有哪些&#xff1f; 当我们需要发送包含附件的邮件时&#xff0c;自动化的解决方案显得尤为重要。Python提供了SMTP库&#xff0c;使我们能够轻松配置并发送带有附件的邮件。AokSend将通过一个示例来展示如何操作&#xf…