鸿蒙开发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/772473.html

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

相关文章

如视“VR+AI”实力闪耀2024世界人工智能大会

7月4日,2024世界人工智能大会暨人工智能全球治理高级别会议(以下简称为“WAIC 2024”)在上海盛大开幕,本届大会由外交部、国家发展和改革委员会、教育部等部门共同主办,围绕“以共商促共享 以善治促善智”主题&#xf…

算法力扣刷题 三十一【150. 逆波兰表达式求值】

前言 栈和队列篇。 记录 三十一【150. 逆波兰表达式求值】 一、题目阅读 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意: 有效的算符为 、-、* 和 / 。 每个操作…

初尝PaddleOCR识别图片中的文字

引言 PaddleOCR是一个基于飞桨深度学习框架的OCR工具包,它集成了丰富的文字检测、识别和后处理算法,能够高效、准确地识别出图片中的文字。 说明 OpenVINO.NET是一个由开源开发者sdcb发布的,一个个强大的工具集,通过优化神经网…

科普文:Linux服务器性能调优概叙

概叙 Java web应用性能分析之服务端慢和优化概叙_cpu飙高java-CSDN博客 Java web应用性能分析之【CPU飙升分析概述】_web页面性能分析cpu占满是因为死循环,还是循环过多-CSDN博客 在我们的软件服务中,软件部署的服务器,一般都是linux服务器&#xff0c…

【每天学会一个渗透测试工具】SQLmap安装教程及使用

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 ✨SQLmap简介 Sqlmap是一款开源的渗透测试工具 🚀下载及安装 下载地址:http://sqlmap.org/ windo…

两个Activity之间切换时UI部分重叠

书籍 《第一行代码 Android》第三版 开发 环境 Android Studio Jellyfish | 2023.3.1 setContentView android studio自动生成的SecondActivity.kt中自动生成的代码中已经绑定了second_layout.xml的布局资源,通过代码:setContentView(R.layout.secon…

windows@资源管理器中的地址栏@访问共享文件夹的各种方法@管理共享文件夹

文章目录 资源管理器中的地址栏可以访问什么访问共享文件夹👺UNC路径资源管理器打开共享文件夹纯命令行方式访问共享文件夹 共享文件夹相关操作查看所有已经共享的文件夹👺停止某个文件的共享 共享文件夹的访问控制补充匿名访问问题😊强制启用…

【Linux】高级IO——五种IO模型和基本概念 ,非阻塞IO,fcntl,实现非阻塞IO,同步通信和异步通信

文章目录 Linux高级IO1. 五种IO模型1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 IO多路转接1.5 异步IO 2. 同步通信和异步通信3. 阻塞和非阻塞 Linux高级IO 1. 五种IO模型 IO是什么? IO是计算机领域中的缩写,指的是输入/输出(Input/Output&…

【vue3|第15期】Vue3模板语法入门指南

日期:2024年7月2日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

上海网站建设如何做

上海是中国最繁华的城市之一,作为全国的经济、文化和科技中心,网站建设在上海变得越来越重要。如何做好上海网站建设,让网站更加吸引人,成为企业和个人宣传自身的重要平台呢? 首先,要有清晰的定位和目标。在…

IT之旅启航:高考后IT专业预习全攻略

✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点赞、关注、收藏、评论,是对我最大…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【密钥生成介绍及算法规格】

密钥生成介绍及算法规格 当业务需要使用HUKS生成随机密钥,并由HUKS进行安全保存时,可以调用HUKS的接口生成密钥。 注意: 密钥别名中禁止包含个人数据等敏感信息。 开发前请熟悉鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harm…

Java实现电子围栏的小例子

主要需求是实现一个电子围栏判断的小例子其中包括前端和后端的demo代码 引入对应的依赖库 <!--jts库通常用于几何计算和表示地理空间数据--> <dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><…

web学习笔记(七十五)

目录 1.小程序修改响应式数据 1.1修改基本数据类型的值 1.2修改复合数据类型的值 2. 发送请求 3.小程序解决跨域问题 1.小程序修改响应式数据 1.1修改基本数据类型的值 在小程序中需要先将data中的数据拿过来并结构&#xff0c;才可以在this.setdata中修改数据&#xf…

2024攻防演练:亚信安全推出MSS/SaaS短期定制服务

随着2024年攻防演练周期延长的消息不断传出&#xff0c;各参与方将面临前所未有的挑战。面对强大的攻击队伍和日益严格的监管压力&#xff0c;防守单位必须提前进行全面而周密的准备和部署。为应对这一形势&#xff0c;亚信安全特别推出了为期三个月的MSS/SaaS短期订阅方案。该…

SpringBoot Task 定时任务

springboot中使用Task定时任务非常简单 springboot 中自带的都有注解不需要引入依赖 第一步&#xff1a;在启动类上添加启用定时任务注解 EnableScheduling //开启任务调度 第二步&#xff1a;创建一个springboot组件用于定时任务管理 package cn.lsy.api.Task;import cn.ls…

【LeetCode】十一、滑动窗口:长度最小的子数组 + 定长子串的元音最大数目

文章目录 1、滑动窗口2、leetcode209&#xff1a;长度最小的子数组3、leetcode1456&#xff1a;定长子串中元音的最大数目 1、滑动窗口 如下&#xff0c;有一个数组&#xff0c;现三个元素为一组&#xff0c;求最大的和&#xff0c;自然可以while循环实现&#xff1a;i 、i1、…

着色器预热?为什么 Flutter 需要?为什么原生 App 不需要?那 Compose 呢?Impeller 呢?

依旧是来自网友的问题&#xff0c;这个问题在一定程度上还是很意思的&#xff0c;因为大家可能会想&#xff0c;Flutter 使用 skia&#xff0c;原生 App 是用 skia &#xff0c;那为什么在 Flutter 上会有着色器预热&#xff08;Shader Warmup&#xff09;这样的说法&#xff1…

使用getline()从文件中读取一行字符串

我们知道&#xff0c;getline() 方法定义在 istream 类中&#xff0c;而 fstream 和 ifstream 类继承自 istream 类&#xff0c;因此 fstream 和 ifstream 的类对象可以调用 getline() 成员方法。 当文件流对象调用 getline() 方法时&#xff0c;该方法的功能就变成了从指定文件…

lnternet 发展史

一&#xff0c;lnternet 发展史 ARPA net &#xff08;上世纪50年代二战结束&#xff09; 无线 战场指挥通信协议落后 TCP/IP 包交换 WEB (70年代 ) 80年代 90年代 二&#xff0c;互联网的典型应用&#xff1a; 96年到2008年 第一代技术…