鸿蒙开发HarmonyOS NEXT (三) 熟悉ArkTs (上)

一、自定义组件

1、自定义组件

自定义组件,最基础的结构如下:

@Component
struct Header {
  build() {
    
  }
}

提取头部标题部分的代码,写成自定义组件。

1、新建ArkTs文件,把Header内容写好。

2、在需要用到的地方,导入引用即可

@Component
export struct Header {
  private title: ResourceStr = ''

  build() {
    Row() {
      Text(this.title)
        .fontWeight(FontWeight.Bold)
        .fontSize(24)
    }
    .width('100%')
    .margin({ bottom: 10 })
  }
}
import { Header } from "../conponents/CommonHeader"

@Entry
@Component
struct Index {
  @State

  build() { // UI描述,内部声明式UI结构
    Column({ space: 10 }) {
      Header({ title: "商品列表" })
      }
      .width('100%')
    }
    .backgroundColor('#f0f8ff')
    .padding(20)
    .width('100%')
    .height('100%')
  }
}

2、构建函数 

如果是仅在该页面内部运用的组件,就可以用构建函数的方式来定义组件

分两类:全局和局部,区别就是写在struct函数外还是内,若是放在struct之内,就不需要些‘function’字段了

这样封装,就保证了代码易读易维护

3、公共样式

类似的,样式也可以这样封装

但是Styles只能封装所有组件都有的公共属性,那对于个别的如何处理呢

就需要用到Extend(注意:只能定义成全局的,不能写在struct函数内部)

二、状态管理-装饰器

1、@State

@State装饰器官网文档

@State类似于react中的UseState,只在组件内部使用

@Entry
@Component
struct StatePage {
  @State message: string = "hello"

  build() {
    Column() {
      Text(this.message)
        .fontSize(20)
        .onClick(()=>{
          this.message = '测试'
        })
    }.width('100%')
  }
}

2、@Props

@Prop装饰器官网文档

父组件单向传值给子组件,类似于react里的props参数,可以理解为父组件参数拷贝一份给子组件

子组件数值的变化不会同步到父组件

//子组件
@Component
struct CountDownComponent {
  @Prop count: number = 0;
  costOfOneAttempt: number = 1;

  build() {
    Column() {
      if (this.count > 0) {
        Text(`You have ${this.count} Nuggets left`)
      } else {
        Text('Game over!')
      }
      // @Prop装饰的变量不会同步给父组件
      Button(`Try again`).onClick(() => {
        this.count -= this.costOfOneAttempt;
      })
    }
  }
}

//父组件
@Entry
@Component
struct ParentComponent {
  @State countDownStartValue: number = 10;

  build() {
    Column() {
      Text(`Grant ${this.countDownStartValue} nuggets to play.`)
      // 父组件的数据源的修改会同步给子组件
      Button(`+1 - Nuggets in New Game`).onClick(() => {
        this.countDownStartValue += 1;
      })
      // 父组件的修改会同步给子组件
      Button(`-1  - Nuggets in New Game`).onClick(() => {
        this.countDownStartValue -= 1;
      })

      CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 })
    }
  }
}

3、@Link

变量与其父组件中对应的数据源建立双向数据绑定

可以理解为父组件把地址给子组件,所以改变能够同步

@Link装饰器官网文档


//子组件接收变量
 @Link count: number
 @Link costOfOneAttempt: number

//调用子组件,因为是引用的方式,所以要加上$
 CountDownComponent({ count: $countDownStartValue})

4、@Provide 和 @Consume

应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景,实现跨层级传递

就是爷爷和孙子之间直接沟通

不需要一级一级的显示传参

@Provide装饰的变量是在祖先组件中,@Consume装饰的变量是在后代组件中

感觉很方便,但一般咱不用,因为比较消耗性能

@Entry
@ComponentV2
struct Parent {
  @Provider() str: string = 'hello';

  build() {
    Column() {
      Button(this.str)
        .onClick(() => {
          this.str += '0';
        })
      Child()
    }
  }
}



@ComponentV2
struct Child {
  @Consumer() str: string = 'world';

  build() {
    Column() {
      Button(this.str)
        .onClick(() => {
          this.str += '0';
        })
    }
  }
}

5、@Observed 和 @ObjectLink

用于在涉及嵌套对象或数组的场景中进行双向数据同步

因为对于非简单类型,比如class、Object或者数组,是需要被@Observed装饰的,否则将观察不到其属性的变化

/**子组件定义包包的类型*/
@Observed
class Bag {
  public id: number;
  public size: number;

  constructor(size: number) {
    this.id = NextID++;
    this.size = size;
  }
}
@Observed
class User {
  public bag: Bag;

  constructor(bag: Bag) {
    this.bag = bag;
  }
}

/**子组件*/
@Component
struct ViewA {
  label: string = 'ViewA';
  //被引用的类需要用ObjectLink装饰
  @ObjectLink bag: Bag;

  build() {
    Column() {
      Text(`ViewA [${this.label}] this.bag.size = ${this.bag.size}`)
        .fontColor('#ffffffff')
        .backgroundColor('#ff3d9dba')
        .width(320)
        .height(50)
        .borderRadius(25)
        .margin(10)
        .textAlign(TextAlign.Center)
        }
       Button(`ViewA: this.bag.size add 1`)
        .width(320)
        .backgroundColor('#ff17a98d')
        .margin(10)
        .onClick(() => {
          this.bag.size += 1;
        })
    }
}
}

/**父组件*/
@Entry
@Component
struct ViewB {
  @State user: User = new User(new Bag(0));

  build() {
    Column() {
      ViewA({ label: 'ViewA #1', bag: this.user.bag })
        .width(320)
    }
  }
}

三、页面路由

把所有访问记录存在栈里,类似于出栈入栈,跳转就添加一条记录,回到上一页就是把当前记录弹出栈,就回到了上一页(ps:页面栈的最大容量是32)

如果新访问的页面是栈里存在的,把它挪到栈顶即可,这样节省空间性能

1、跳转

有两种方式:保留访问记录就用pushUrl,如果要销毁记录,就用replaceUrl

import router from '@ohos.router';
class DataModelInfo {
  age: number = 0;
}

class DataModel {
  id: number = 0;
  info: DataModelInfo|null = null;
}

function onJumpClick(): void {
  // 在Home页面中
  let paramsInfo: DataModel = {
    id: 123,
    info: {
      age: 20
    }
  };

  router.pushUrl({
    url: 'pages/Detail', // 目标url
    params: paramsInfo // 添加params属性,传递自定义参数
  }, (err) => {
    if (err) {
      console.error(`跳转失败, ${err.code}, ${err.message}`);
      return;
    }
    console.info('跳转成功!');
  })
}

2、回到上一页

返回用即可

import router from '@ohos.router';
//回退到指定的home页
router.back({
  url: 'pages/Home'
});
//不传参,即是回退到上一页
//router.back();

3、综合小案例

跳转到对应页面

如果新建页面时,选择的是新建page,则自动配置路径,若是选择ArkTs,则是没有的

import router from '@ohos.router';

class RouterInfo {
  url: string
  title: string

  constructor(url: string, title: string) {
    this.url = url;
    this.title = title
  }
}

@Entry
@Component
struct Index {
  @State message: string = '页面列表'
  private routers: RouterInfo[] = [
    new RouterInfo("pages/Shopping", "商品"),
    new RouterInfo("pages/Mine", "我的"),
  ]

  build() {
    Column() {
      Text(this.message)
        .fontSize(30)
      List({ space: 15 }) {
        ForEach(
          this.routers,
          (router: RouterInfo, index) => {
            ListItem() {
              this.RouterItem(router, index + 1)
            }
          }
        )
      }
    }.width('100%')
  }

  @Builder
  RouterItem(r: RouterInfo, i: number) {
    Row() {
      Text(i + '.').fontSize(20).fontColor(Color.White)
      Blank()
      Text(r.title).fontSize(20).fontColor(Color.White)
    }
    .width(120)
    .padding(12)
    .backgroundColor('#38f')
    .borderRadius(20)
    .onClick(() => {
      router.pushUrl(
        {
          url: r.url,
          params: i
        },
        router.RouterMode.Single,
        err => {
          if (err) {
            console.log(`跳转失败${err.message}${err.code}`)
          }
        }
      )
    })
  }
}

写在最后,可结合Harmony_鸿蒙专栏阅读

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

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

相关文章

C语言入门基础题:奇偶 ASCII 值判断(C语言版)和ASCII码表,什么是ASCII码,它的特点和应用?

1.题目描述: 任意输入一个字符,判断其 ASCII 是否是奇数,若是,输出 YES ,否则,输出 NO例如,字符 A 的 ASCI 值是 65 ,则输出 YES ,若输入字符 B(ASCII 值是 66)&#xff…

C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用

C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用 一、Invoke Invoke的本质只是一个方法,方法一定是要通过对象来调用的。 一般来说,Invoke其实用法只有两种情况: Control的Invoke Delegate的Invoke 也就是说,Invoke前…

C++初探究(2)

引用 对于一个常量,想要将其进行引用,则使用普通的引用相当于权限扩大(常量为只读,但此处的引用参数为可读可写),C编译器会报错. 例如: const int a 10;int& ra a;//权限放大&#xff0…

SDIO CMD 数据部分 CRC 计算规则

使用的在线 crc 计算工具网址:http://www.ip33.com/crc.html CMD CRC7 计算 如下图为使用逻辑分析仪获取的SDIO读写SD卡时,CMD16指令发送的格式,通过逻辑分析仪总线分析,可以看到,该部分的CRC7校验值得0x05,大多数情况…

说说iOS苹果的“开发者模式”什么时候需要打开 需不需要提前打开

在 iOS 开发过程中,开发者模式(Developer Mode)是一个非常重要的功能,它允许开发者在设备上运行和调试自己的应用程序。 经常有人私信或在群里问到,“我没有开发者模式,怎么办”,“开发者模式是…

4:表单和通用视图

表单和通用视图 1、编写一个简单的表单&#xff08;1&#xff09;更新polls/detail.html文件 使其包含一个html < form > 元素&#xff08;2&#xff09;创建一个Django视图来处理提交的数据&#xff08;3&#xff09;当有人对 Question 进行投票后&#xff0c;vote()视图…

Github绑定自己的域名

Github绑定自己的域名 1.注册自己的域名2.在GitHUb上创建一个自己的仓库&#xff0c;添加域名2.1 创建仓库2.2 添加域名2.3 在Setting中将域名添加到Custom domain中 3.添加域名解析获取ip地址4.在阿里云修改域名解析记录5.ping 域名即可成功 详细内容可参该博客&#xff1a; …

AutoHotKey自动热键(五)添加WINDOWS秘笈指令-输入瞬间启动功能

在AUTOHOTKEY的使用中,不仅仅可以监听组合热键,还可以监听正常文本击键录入,这是另一种监听方式,比如依次击键jsq之后直接弹出<计算器>工具,或者依次击键sj之后直接输出135****5564的手机号码,等等,这就是autohotkey的录入击键监听,以双冒号为开头:: 因这种录入监听像极了…

Word文件打开密码设置:掌握这两种方法,保护你的文档安全

在日常工作和学习中&#xff0c;我们经常会使用Microsoft Word来创建和编辑文档。有时候&#xff0c;为了保护文档内容不被未经授权的人员查看或修改&#xff0c;我们通常会采用加密的方式来增加其安全性。那么Word文档怎么加密&#xff1f; 方法一&#xff1a;使用Word软件内置…

CTF php RCE (一)

0x01 引言 首先进入题目 应该是大部分都是一段白盒PHP审计&#xff0c;然后我们为了命令执行&#xff0c;绕过或者是钻空子等等操作&#xff0c;来拿到flag 0x02 基础 0x01 传参方式 这里有两个工具&#xff0c;hackbar和burpsuite,这两个工具非常实用 大家可以自己Googl…

力扣第一题

1. 两数之和 提示 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可…

OpenFWI代码

重点关注文章第4部分 一、代码模块概览 这一部分了解代码主要实现的功能有哪些。 二、运行 这一部分关注如何跑通。 三、数据集 12个数据集&#xff08;11个2D1个3D&#xff09; 对计算机而言&#xff0c;上述输入、输出维度大小是按次数定义的。 以“Vel&#xff0c;F…

javaweb个人主页设计(html+css+js)

目录 1 前言和要求 1.1 前言 1.2 设计要求 2 预览 2.1 主页页面 2.2 个人简介 2.3 个人爱好 2.4 个人成绩有代码&#xff0c;但是图片已省略&#xff0c;可以根据自己情况添加 2.5 收藏夹 3 代码实现 3.1 主页 3.2 个人简介 3.3 个人爱好 3.4 个人成绩&#xff…

图吧工具箱:装机爱好者必备工具合集

名人说:莫道谗言如浪深,莫言迁客似沙沉。 ——刘禹锡《浪淘沙》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、概述二、主要功能1、硬件检测2、测试与故障诊断三、使用方法四、总结很高兴你打开了这篇博客,更多好用的软件工具,请关注我、订阅专栏…

0302GPIO外设输入功能

GPIO外设输入功能 输入部分硬件电路按键简介传感器模块简介按键和传感器模块的硬件电路 C语言的学习C语言数据类型宏定义typedef结构体枚举C语言知识总结 按键控制LED灯&光敏传感器蜂鸣器GPIO总结GPIO使用方法总结模块化编程的方法&#xff1a; 两个程序&#xff1a;按键控…

图像分割-编码解码网络的训练-kreas实现

一、数据集加载&#xff1a; 纯手工打造一个函数用来加载数据&#xff0c;数据分别为image和mask 我们所需要的类型&#xff1a;&#xff08;B数量&#xff0c;长&#xff0c;宽&#xff0c;通道数&#xff09;&#xff0c;只要将数据加载成这样并mask和image对应就行。 第一步…

S271系列RTU在旅游景区人流监控中的应用案例

S271系列RTU在旅游景区人流监控中的应用案例 随着全球旅游业的迅猛发展&#xff0c;旅游景区的管理者越来越关注如何利用先进的技术手段提升游客体验、优化管理效率以及确保安全。S271系列RTU作为一款先进的无线工业物联网设备&#xff0c;在旅游景区的人流监控中展现出了其独…

PTA - 编写函数计算圆面积

题目描述&#xff1a; 1.要求编写函数getCircleArea(r)计算给定半径r的圆面积&#xff0c;函数返回圆的面积。 2.要求编写函数get_rList(n) 输入n个值放入列表并将列表返回 函数接口定义&#xff1a; getCircleArea(r); get_rList(n); 传入的参数r表示圆的半径&#xff0c…

批量下载手机中APP程序中文件

需求 利用 adb pull 下载手机中app的某目录 adb pull 命令本身不支持直接下载整个目录&#xff08;文件夹&#xff09;及其所有子目录和文件作为一个单一的操作。但是&#xff0c;可以通过一些方法来间接实现这一目的。 方法 1. 首先将要下载的目录进行 tar 打包 # 在 And…

2020 ICPC Shanghai Site B. Mine Sweeper II 题解 构造 鸽巢原理

Mine Sweeper II 题目描述 A mine-sweeper map X X X can be expressed as an n m n\times m nm grid. Each cell of the grid is either a mine cell or a non-mine cell. A mine cell has no number on it. Each non-mine cell has a number representing the number of…