鸿蒙开辟学习笔记2

打印 上一主题 下一主题

主题 656|帖子 656|积分 1968

一、class 类

类是用于 创建对象模版。同时类声明也会引入一个 新范例,可界说其 实例属性方法构造函数
  1. // 类名 首字母大写(规范)
  2. class 类名 {
  3.         // 1、实例属性(字段)
  4.         // 2、构造函数
  5.         // 3、方法
  6. }
复制代码
1、属性(字段)

  1. class Person {
  2.         // 字段名: 类型 = 初始值
  3.         name: string = 'jack'       
  4.         // 可选字段可以不设置初始值
  5.         food?: string
  6. }
  7. const p: Person = new Person()
  8. console.log(p.name)
  9. // 可选字段在使用时需要配合 可选链操作符,避免出错
  10. // p.food?.length 表示:如果food存在,就取 length
  11. console.log(p.food?.length)
复制代码
2、构造函数 constructor

差别实例,将来必要有差别的字段初始值,必要通过构造函数来实现。
  1. /*
  2. class 类{
  3.         字段1:类型
  4.         字段2:类型
  5.         constructor(参数1...) {
  6.                 this.字段A = 参数1
  7.         }
  8. }
  9. const 实例1 = new 类(参数1...)
  10. */
  11. // 法1:构造函数接收一系列参数,所有参数都需要在 constructor 中列出来
  12. class Food {
  13.   name: string
  14.   price: number
  15.   constructor(name:string, price:number) {
  16.     this.name = name
  17.     this.price = price
  18.   }
  19. }
  20. let  f1: Food = new Food('西红柿', 6)
  21. console.log('f1 name:', f1.name)
  22. console.log('f1 price:', f1.price)
  23. // 法2:构造函数接收一个对象
  24. // 接口
  25. interface interfaceFood {
  26.   name: string
  27.   price: number
  28.   desc: string
  29. }
  30. class Food2 {
  31.   name: string
  32.   price: number
  33.   desc: string
  34.   constructor(paramsObj: interfaceFood) {
  35.     this.name = paramsObj.name
  36.     this.price = paramsObj.price
  37.     this.desc = paramsObj.desc
  38.   }
  39. }
  40. let f2 = new Food2({name: '土豆', price: 5, desc: '酸辣土豆丝'})
  41. console.log('name:',f2.name, 'price:', f2.price, 'desc:', f2.desc )
复制代码
3、界说方法

  1. /*class 类名{
  2.   方法名(参数...):返回值类型{
  3.     逻辑...
  4.     可以通过 this 获取实例对象
  5.   }
  6. }*/
  7. class Person {
  8.   name: string
  9.   constructor(name: string) {
  10.     this.name = name
  11.   }
  12.   sayHi(name):string {
  13.     console.log(`你好,${name},我是${this.name}`)
  14.     return `你好,${name},我是${this.name}`
  15.   }
  16. }
  17. let p: Person = new Person('张三')
  18. p.sayHi('李四')
复制代码
4、静态属性和方法

类可以添加属性、方法,后续访问必要通过 类 来完成,无法通过实例利用。
  1. /*class 类 {
  2.   static 字段: 类型
  3.   // 通常当作工具方法使用
  4.   static 方法() {}
  5. }
  6. 类.字段
  7. 类.方法()*/
  8. class Car {
  9.   static version: string = '1.9.0'
  10.   static getRandomNumber() {
  11.     return Math.random()
  12.   }
  13. }
复制代码
5、继承 extends 和 super 关键字

类可以通过 继承 快速获取别的一个类的 字段方法
  1. /*class 父类 {
  2.   // 字段
  3.   // 方法
  4.   // 构造函数
  5.   方法(){}
  6. }
  7. class 子类 extends 父类 {
  8.   // 自己的字段(属性)
  9.   // 自己的方法
  10.   // 可以重写父类方法
  11.   constructor() {
  12.     super()
  13.   }
  14.   方法() {
  15.     super.方法()// 调用父类方法
  16.   }
  17. }*/
  18. class Person {
  19.   name: string
  20.   constructor(name:string) {
  21.     this.name = name
  22.   }
  23.   sayHi() {
  24.     console.log(`你好,我叫${this.name}`)
  25.   }
  26. }
  27. class Student extends Person{
  28.   grade:string
  29.   // 子类中有额外的属性时,需要重写自己的构造函数
  30.   constructor(name:string, grade:string) {
  31.     // 子类的构造函数中,可以通过 super 去访问父类的属性和方法
  32.     // super() 父类构造函数、super.方法名(),super.属性名
  33.     // 使用 super() 调用父类的构造函数时,要将父类所需要的参数,依次传递过去
  34.     super(name)
  35.     // 完成自己属性的初始化
  36.     this.grade = grade
  37.   }
  38.   // 同名方法、属性的情况下,子类的优先级高于父类
  39.   sayHi():void {
  40.     super.sayHi()
  41.     console.log(`我是学生,今年${this.grade}`)
  42.   }
  43. }
  44. let s: Student = new Student('张三', '三年级')
  45. s.sayHi()
复制代码
6、instanceof

instanceof 运算符可以用来检测某个对象是否是某个类的实例。
  1. class Person {
  2. }
  3. class Student extends Person {
  4. }
  5. class Teacher extends Person {
  6. }
  7. let s: Student = new Student()
  8. console.log('s是否是Student的实例', s instanceof Student)        // true
  9. console.log('s是否是Person的实例', s instanceof Person)        // true
  10. console.log('s是否是Teacher的实例', s instanceof Teacher)        // true
复制代码
7、修饰符

类的方法和属性可以通过修饰符限制访问。
修饰符包括:readonly、private、protected、public。省略不写默以为 public。

  1. class Person {
  2.   // public 在程序的任何可访问该类的地方都是可见的(默认)
  3.   name: string
  4.   // readonly 只读,不可修改
  5.   readonly desc: string = '人类'
  6.   // private 私有,只能在 Person 类里面访问
  7.   private drink: string = '喝酒'
  8.   // protected 保护,在Person和Student中,都可以访问,其他地方不能访问
  9.   protected eat: string = '吃东西'
  10.   constructor(name) {
  11.     this.name = name
  12.     console.log(this.drink)
  13.   }
  14. }
  15. class Student extends Person {
  16.   constructor(name) {
  17.     super(name)
  18.     console.log(super.eat)
  19.   }
  20. }
复制代码
二、剩余参数和展开运算符

1、剩余参数

可以将函数或方法中一个不定数量的参数表示为一个数组。
  1. function sum(num1: number,num2: number,...argArr:number[]) {
  2.   let total = num1 + num2
  3.   for(let i of argArr) {
  4.     total += i
  5.   }
  6.   console.log('total', total)
  7. }
  8. sum(1,2)
  9. sum(1,2,3,4)
  10. sum(1,2,3,4,5,6)
复制代码
2、展开运算符

用于数组的平铺合并。(ArkTs 中,展开运算符只能用在数组上。)
  1. let arr1 = [1,2,3]
  2. let arr2 = [4,5,6]
  3. let arr3 = [...arr1, arr2]
  4. console.log('arr3', arr3)
复制代码
三、接口

1、继承 extends

  1. interface Animal {
  2.   name: string
  3.   age: number
  4. }
  5. interface Cat extends Animal {
  6.   hair: string
  7. }
  8. let c1: Cat = {
  9.   name: '布偶',
  10.   age: 2,
  11.   hair: '白色'
  12. }
复制代码
2、接口实现

接口实现:界说一个接口,约束 类 =》 类必要按照接口的要求,实现类的主体
  1. interface IDog {
  2.   name: string
  3.   age: number
  4.   eat: () => void
  5. }
  6. class Dog implements IDog {
  7.   name: string
  8.   age: number
  9.   constructor(name:string, age:number) {
  10.     this.name = name
  11.     this.age = age
  12.   }
  13.   eat: ()=> {
  14.   }
  15. }
复制代码
四、泛型

泛型可以让 函数 等,与多种 差别的范例 一起工作,灵活可复用。
通俗一点就是:范例是可变的。
1、泛型函数

  1. // 泛型函数:Type 是实际调用时,传过来的类型参数
  2. // 第一个 Type 是需要传递的参数,第二个Type是约束参数的类型,第三个Type是约束返回值的类型
  3. // function 函数名<Type>(形参:Type): Type {
  4. //   return 形参
  5. // }
  6. function f1<T>(arg:T): T {
  7.   return arg
  8. }
  9. console.log('str',f1<string>('abc'))
  10. // 会根据传参,进行类型推断,动态配置 T 类型参数的值
  11. console.log('arr',f1([1,2,3]))
  12. console.log('num',f1<number>(123))
复制代码
练习
  1. // 练习1:定义函数,参数是数组(数组值的类型不定),返回数组的长度
  2. function f2<T>(arg: T[]): number {
  3.   return arg.length
  4. }
  5. console.log('num',f2<number>([2,3,4]))
  6. console.log('str',f2(['2','3','4']))
  7. // 练习1:定义函数,参数是数组(数组值的类型不定),返回数组的最后一项
  8. function f3<T>(arg: T[]): T {
  9.   return arg[arg.length-1]
  10. }
  11. console.log('num',f3<number>([2,3,4]))
  12. console.log('str',f3(['a','b','c']))
复制代码
2、泛型约束

之前的范例参数,可以传递任何范例,没有限制。
如果盼望有限制 -》 泛型约束
  1. /*
  2. interface 接口 {
  3. }
  4. function 函数<Type extends 接口> {}
  5. */
  6. interface Ilength {
  7.   length: number
  8. }
  9. function fn<T extends Ilength>(params: T) {
  10.   console.log('',params.length);
  11. }
  12. fn<string>('123')
复制代码
3、多个泛型参数

  1. function func<T,T2>(param1: T, param2: T2) {
  2.   console.log('参数1',param1)
  3.   console.log('参数2',param2)
  4. }
  5. func<string, number[]>('abc', [123,22])
复制代码
4、泛型接口

界说接口的时候,团结泛型界说,就是泛型接口。
  1. /*interface 接口<Type> {
  2.   // 内部使用 Type
  3. }*/
  4. interface IdFunc<Type> {
  5.   id: (value:Type) => Type,
  6.   ids: () => Type[]
  7. }
  8. let obj: IdFunc<number> = {
  9.   id(value: number) {
  10.     return value
  11.   },
  12.   ids() {
  13.     return [1,2,3]
  14.   }
  15. }
  16. let obj2:IdFunc<string> = {
  17.   id(value:string) {
  18.     return value
  19.   },
  20.   ids() {
  21.     return ['1','2']
  22.   }
  23. }
复制代码
5、泛型类

界说类的时候,团结泛型界说,就是泛型类。
  1. class Person<T> {
  2.   id: T
  3.   constructor(id:T) {
  4.     this.id = id
  5.   }
  6.   getId() {
  7.     return this.id
  8.   }
  9. }
  10. // 使用
  11. let p = new Person<number>(13)
复制代码
五、模块化语法

模块化:把一个大的步伐,拆分为多少的小模块,通过特定的语法,可以进行恣意组合。
1、默认导出和导入

默认导出:指一个模块,只能默认导出 一个 对象。利用时,可以通过 as 自界说导出名称。
  1. // 导出
  2. export default XXX
  3. //导入
  4. import XXX from '模块路径'
  5. import XXX as YYY from '模块路径'
复制代码
2、按需导出和导入

按需导出:指一个模块,可以按照必要,导出多个特性。
  1. // modules.ets 导出
  2. let name: string = '张三'
  3. let age: number = 18
  4. let sayHello = () => {
  5.   console.log('你好')
  6. }
  7. export {name, age, sayHello}
  8. // index.ets导入
  9. import {name, age as myAge, sayHello} from '../tools/modules'
复制代码
3、全部导入

将所有的按需导入,全部导入进来。
  1. // modules.ets 导出
  2. let name: string = '张三'
  3. let age: number = 18
  4. let sayHello = () => {
  5.   console.log('你好')
  6. }
  7. export {name, age, sayHello}
  8. // index.ets导入
  9. import * as result from '../tools/modules'
  10. console.log('结果是:', result.name, result.age)
复制代码
六、自界说组件

由框架直接提高的称为体系组件,由开辟者界说的称为自界说组件。
语法:
  1. @Component
  2. struct 组件名 {
  3.   build() {
  4.   }
  5. }
复制代码
案例:
  1. @Component
  2. struct MyContent {
  3.   @State count: number = 0
  4.   build() {
  5.     Row() {
  6.       Text(this.count.toString()).fontSize(26)
  7.       Button('按钮')
  8.         .onClick(() => {
  9.           this.count ++
  10.         })
  11.     }
  12.       .width('100%')
  13.       .justifyContent(FlexAlign.Center)
  14.   }
  15. }
  16. @Entry
  17. @Component
  18. struct Index {
  19.   build() {
  20.     Column() {
  21.         MyContent()
  22.         MyContent()
  23.         MyContent()
  24.     }
  25.   }
  26. }
复制代码
1、通用属性和方法

自动移组件可以通过点语法,设置通用样式、通用变乱。
  1. // header.ets
  2. // 组件可以使用 @Preview 预览
  3. // @Preview
  4. @Component
  5. export struct Header {
  6.   build() {
  7.     Row() {
  8.       Text('头部')
  9.       Button('按钮')
  10.     }
  11.       .width(200)
  12.       .height(80)
  13.       .backgroundColor(Color.Pink)
  14.   }
  15. }
  16. // index.ets
  17. import { Header } from '../components/Header'
  18. @Entry
  19. @Component
  20. struct Index {
  21.   build() {
  22.     Column() {
  23.       Header()
  24.         .width(260)
  25.         .height(100)
  26.         .backgroundColor(Color.Gray)
  27.         .onClick(() => {
  28.           AlertDialog.show({
  29.             message: '点击了Header组件'
  30.           })
  31.         })
  32.     }
  33.   }
  34. }
复制代码
拓展:
组件可以作为一个模块,通过按需导入导出,大概默认导入导出利用。
2、成员变量和成员函数



  • 成员变量要有赋值动作,值可以是普通数据,也可以是一个函数;
    可以在父组件利用子组件时传入,而且覆盖子组件成员变量的默认值。(类似于Vue中的prop)
    如果必要状态管理,可以加上 @State 修饰符
  • 成员函数只能在子组件内部利用,外部无法传入覆盖。没有赋值动作。
  1. @Component
  2. struct MyPanel {
  3.   // 成员变量 - 可以外部传入覆盖,若需要状态管理,可以使用 @State
  4.   // 成员变量 - 数据
  5.   title: string = '我的订单'
  6.   extra: string = '全部订单'
  7.   @State count: number = 0
  8.   // 成员变量 - 函数
  9.   getMore = () => {
  10.     AlertDialog.show({
  11.       message: '获取更多'
  12.     })
  13.   }
  14.   // 成员函数 - 不可以外部传入覆盖
  15.   getContent() {
  16.     AlertDialog.show({
  17.       message: '查看内容'
  18.     })
  19.   }
  20.   build() {
  21.     Column() {
  22.       Row() {
  23.         Text(this.title)
  24.           .fontSize(20)
  25.         Text(this.extra)
  26.           .fontSize(20)
  27.           .onClick(() => {
  28.             this.getMore()
  29.           })
  30.       }
  31.         .width('100%')
  32.         .justifyContent(FlexAlign.SpaceBetween)
  33.       Column() {
  34.         Text(this.count.toString())
  35.         Button('按钮')
  36.           .onClick(() => {
  37.             this.count ++
  38.           })
  39.         Text('内容')
  40.           .fontSize(20)
  41.           .onClick(() => {
  42.             this.getContent()
  43.           })
  44.       }.padding(20)
  45.     }
  46.       .width('100%')
  47.       .height(200)
  48.       .padding(20)
  49.       .margin({bottom: 10})
  50.       .borderRadius(10)
  51.       .backgroundColor(Color.White)
  52.   }
  53. }
  54. @Entry
  55. @Component
  56. struct Index {
  57.   build() {
  58.     Column() {
  59.       MyPanel({
  60.         title: '我的订单',
  61.         extra: '全部订单 >',
  62.         count: 10,
  63.         getMore: () => {
  64.           AlertDialog.show({
  65.             message: '查看全部订单'
  66.           })
  67.         }
  68.       })
  69.       MyPanel({
  70.         title: '小米有品众筹',
  71.         extra: '7款众筹中 >',
  72.         count: 20,
  73.         getMore: () => {
  74.           AlertDialog.show({
  75.             message: '查看7款众筹'
  76.           })
  77.         }
  78.       })
  79.     }
  80.     .width('100%')
  81.     .height('100%')
  82.     .padding(20)
  83.     .backgroundColor('#ccc')
  84.   }
  85. }
复制代码
3、@BuilderParam 传递 UI

利用 @BuilderParam 构建函数,可以让自界说组件 允许外部传递 UI。(类似于 vue 中的插槽)
  1. @Component
  2. struct MyComp {
  3.   // 1、定义构建函数,接收外部传入的 ui,并设置默认值
  4.   @BuilderParam customerBuilder: () => void = this.defaultBuilder
  5.   @Builder defaultBuilder() {
  6.     Text('默认显示内容')
  7.   }
  8.   build() {
  9.     Column() {
  10.       // 2、使用 @BuilderParam 装饰的成员函数,构建函数,构建结构
  11.       this.customerBuilder()
  12.     }
  13.   }
  14. }
  15. @Entry
  16. @Component
  17. struct Index {
  18.   build() {
  19.     Column() {
  20.       MyComp(){
  21.       // 3、传入新的结构
  22.         Button('传入的显示内容')
  23.       }
  24.     }
  25.   }
  26. }
复制代码
4、多个 @BuilderParam

子组件有多个 BuilderParam,必须通过参数的方式传入。
  1. @Component
  2. struct MyCard {
  3.   @BuilderParam hBuilder: () => void = this.hDefaultBuilder
  4.   @BuilderParam cBuilder: () => void = this.cDefaultBuilder
  5.   @Builder hDefaultBuilder() {
  6.     Text('默认标题部分')
  7.   }
  8.   @Builder cDefaultBuilder() {
  9.     Text('默认内容部分')
  10.   }
  11.   build() {
  12.     Column() {
  13.       Row() {
  14.         this.hBuilder()
  15.       }
  16.       .width('100%')
  17.       .padding(10)
  18.       .border({width:{bottom:1},color:'#999'})
  19.       Row() {
  20.         this.cBuilder()
  21.       }
  22.       .height(80)
  23.       .width('100%')
  24.       .padding(10)
  25.     }
  26.     .borderRadius(6)
  27.     .backgroundColor(Color.White)
  28.   }
  29. }
  30. @Entry
  31. @Component
  32. struct Index {
  33.   @Builder pHBuilder() {
  34.     Text('父组件传递的标题')
  35.   }
  36.   @Builder pCBuilder() {
  37.     Text('父组件传递的内容')
  38.   }
  39.   build() {
  40.     Column({space:10}) {
  41.       MyCard({
  42.         hBuilder: this.pHBuilder,
  43.         cBuilder: this.pCBuilder
  44.       })
  45.       MyCard()
  46.     }
  47.     .width('100%')
  48.     .height('100%')
  49.     .padding(20)
  50.     .backgroundColor('#ccc')
  51.   }
  52. }
复制代码
七、状态管理-@state增补

状态管理:当运行时的状态变量变化,带来 UI 的重新渲染,在 ArkUI 中统称为 状态管理机制
变量必须被装饰器@state修饰才气称为状态变量。


  • string、number、boolean 可以直接监督到变化
  • 复杂范例 object、class,可观察 自身的赋值的变化,第一层属性修改可以被监督到,嵌套对象必要对整个对象进行重新赋值
  1. interface Car {
  2.   name: string
  3. }
  4. interface Person {
  5.   name: string
  6.   car: Car
  7. }
  8. @Entry
  9. @Component
  10. struct Index {
  11.   @State message:string = '你好'
  12.   @State p: Person = {
  13.     name: '张三',
  14.     car: {
  15.       name: '奥迪'
  16.     }
  17.   }
  18.   build() {
  19.     Column({space:10}) {
  20.       Text(this.message)
  21.       Button('修改message')
  22.         .onClick(() => {
  23.           this.message = '修改了message'
  24.         })
  25.       Text(JSON.stringify(this.p))
  26.       Button('修改 obj 的name')
  27.         .onClick(() => {
  28.           this.p.name = '李四'
  29.         })
  30.       Button('修改 obj.car 的name')
  31.         .onClick(() => {
  32.           // 直接修改嵌套对象的属性,状态不会被检测到,页面ui不会更新
  33.           // this.p.car.name = '保时捷'
  34.           // 嵌套对象重新赋值,可以进行状态检测
  35.           this.p.car = {
  36.             name: '保时捷'
  37.           }
  38.           console.log(this.p.car.name)
  39.         })
  40.     }
  41.     .width('100%')
  42.     .height('100%')
  43.     .padding(20)
  44.     .backgroundColor('#ccc')
  45.   }
  46. }
复制代码
八、@Prop 父向子单向传值

@Prop装饰的变量可以和父组件创建单向的同步关系。
@Prop装饰的变量时可变的,但是变化不会同步回其父组件,子组件若要更新父组件的数据,可通过成员变量,从父组件传递一个方法给子组件。
  1. @Component
  2. struct Son {
  3.   @Prop sCar:string = ''
  4.   changeCar = (newCar:string) => {}
  5.   build() {
  6.     Column() {
  7.       Text(`子组件--${this.sCar}`)
  8.       Button('换车')
  9.         .onClick(() => {
  10.           this.changeCar('宝马')
  11.         })
  12.     }
  13.       .width(200)
  14.       .height(100)
  15.       .backgroundColor(Color.Pink)
  16.   }
  17. }
  18. @Entry
  19. @Component
  20. struct Index {
  21.   @State car:string = '奔驰'
  22.   build() {
  23.     Column({space:10}) {
  24.       Text(`父组件--${this.car}`)
  25.       Button('换车').onClick(() => {
  26.         this.car = this.car === '奔驰'? '保时捷' : '奔驰'
  27.       })
  28.       Son({
  29.         sCar: this.car,
  30.         changeCar: (newCar:string) => {
  31.           this.car = newCar
  32.         }
  33.       })
  34.     }
  35.     .padding(50)
  36.     .backgroundColor('#ccc')
  37.   }
  38. }
复制代码
九、@Link 双向同步

子组件通过 @Link 修饰的变量,在子组件内部修改,回同步到父组件中。
  1. @Component
  2. struct sonComp {
  3.   @Link count:number
  4.   @Link person: Person
  5.   build() {
  6.     Column() {
  7.       Text('子组件').fontSize(30)
  8.       Text(this.count.toString()).fontSize(28)
  9.       Text(JSON.stringify(this.person)).fontSize(28)
  10.       Button('修改数据').fontSize(24).margin({top:10})
  11.         .onClick(() => {
  12.           this.count --
  13.           this.person.name = 'ls'
  14.         })
  15.     }
  16.     .width(300)
  17.     .height(200)
  18.     .justifyContent(FlexAlign.Center)
  19.     .margin({top: 60})
  20.     .borderRadius(10)
  21.     .backgroundColor('#acc4a0')
  22.   }
  23. }
  24. interface Person {
  25.   name: string
  26.   age: number
  27. }
  28. @Entry
  29. @Component
  30. struct Index {
  31.   @State count:number = 0
  32.   @State person:Person = {
  33.     name: 'zs',
  34.     age: 18
  35.   }
  36.   build() {
  37.     Column() {
  38.       Text('父组件').fontSize(30)
  39.       Text(this.count.toString()).fontSize(28)
  40.       Text(JSON.stringify(this.person)).fontSize(28)
  41.       Button('修改数据').fontSize(28)
  42.         .onClick(() => {
  43.           this.count ++
  44.           this.person.name = 'ww'
  45.         })
  46.       sonComp({
  47.         count: this.count,
  48.         person: this.person
  49.       })
  50.     }
  51.     .width('100%')
  52.     .height('100%')
  53.     .padding({top: 60})
  54.     .backgroundColor('#ddd')
  55.   }
  56. }
复制代码
十、@Provide 和 @Consume 祖孙级组件传值

将数据传递给后代,和后代的数据进行双向数据绑定。
步调:
1、将父组件的状态属性利用@Provide修饰
2、后代组件将必要的属性通过@Consume修饰
  1. interface Person {
  2.   name: string
  3.   age: number
  4. }
  5. @Entry
  6. @Component
  7. struct RootComp {
  8.   @Provide count:number = 20
  9.   @Provide person:Person = {
  10.     name: 'aaa',
  11.     age: 18
  12.   }
  13.   build() {
  14.     Column() {
  15.       Text('根组件').fontSize(30)
  16.       Text(this.count.toString()).fontSize(28)
  17.       Text(JSON.stringify(this.person)).fontSize(30)
  18.       Button('修改数据').fontSize(28).onClick(() => {
  19.         this.count ++
  20.         this.person.name = 'bbb'
  21.       })
  22.       parentComp()
  23.     }
  24.     .width('100%')
  25.     .height('100%')
  26.     .padding({top: 60})
  27.     .backgroundColor('#ddd')
  28.   }
  29. }
  30. @Component
  31. struct parentComp {
  32.   build() {
  33.     Column() {
  34.       Text('父组件').fontSize(30)
  35.       sonComp()
  36.     }
  37.     .width('100%')
  38.     .height(500)
  39.     .backgroundColor('#999')
  40.     // sonComp()
  41.   }
  42. }
  43. @Component
  44. struct sonComp {
  45.   @Consume count:number
  46.   @Consume person:Person
  47.   build() {
  48.     Column() {
  49.       Text('子组件').fontSize(30)
  50.       Text(this.count.toString()).fontSize(30)
  51.       Text(JSON.stringify(this.person)).fontSize(30)
  52.       Button('修改数据').fontSize(28).onClick(() => {
  53.         this.count --
  54.         this.person.name = 'ccc'
  55.       })
  56.     }
  57.     .width(300)
  58.     .height(200)
  59.     .justifyContent(FlexAlign.Center)
  60.     .margin({top: 60})
  61.     .borderRadius(10)
  62.     .backgroundColor('#acc4a0')
  63.   }
  64. }
复制代码
十一、@Observed 和 @ObjectLink 嵌套对象数组属性变化

阐明:装饰器仅能观察到 第一层 的变化,对于多层嵌套的环境,好比数组对象等,他们的第二层属性变化是无法观察到的,这就引出了 @Observed 和 @ObjectLink 装饰器。
作用:用于在涉及嵌套对象或数组的场景中进行双向数据同步。
属性更新的逻辑:当 @Observed 装饰过的数据,属性改变时,就会监听到遍历依赖它的 @ObjectLink 包装类,通知数据更新
注意:@ObjectLink 修饰符不能用在 Entry 修饰的组件中,可以将 Entry 中对应部分,拆分为一个子组件。
  1. interface IPerson {
  2.   name: string
  3.   age: number
  4. }
  5. @Observed
  6. class Person {
  7.   name: string
  8.   age: number
  9.   constructor(obj: IPerson) {
  10.     this.name = obj.name
  11.     this.age = obj.age
  12.   }
  13. }
  14. @Entry
  15. @Component
  16. struct RootComp {
  17.   @State persons: Person[] = [
  18.     new Person({ name: '张三', age: 18 }),
  19.     new Person({ name: '李四', age: 18 }),
  20.     new Person({ name: '王五', age: 18 })
  21.   ]
  22.   build() {
  23.     Column() {
  24.       ForEach(this.persons, (item: Person, index: number) => {
  25.         itemComp({
  26.           item: item,
  27.           addAge: () => {
  28.             item.age ++
  29.             // this.persons.splice(index, 1, item)
  30.           }
  31.         })
  32.       })
  33.     }
  34.     .width('100%')
  35.     .height('100%')
  36.     .padding({top: 30,left: 10, right: 10})
  37.     .backgroundColor('#ddd')
  38.   }
  39. }
  40. @Component
  41. struct itemComp {
  42.   // 属性更新的逻辑:当 @Observed 装饰过的数据,属性改变时,
  43.   // 就会监听到遍历依赖它的 @ObjectLink 包装类,通知数据更新
  44.   // 注意:entry 组件无法直接使用 @ObjectLink ,需要包一层
  45.   @ObjectLink item: Person
  46.   addAge = () => {}
  47.   build() {
  48.     Column() {
  49.       Row(){
  50.         Row() {
  51.           Text(`姓名:${this.item.name}`).fontSize(20)
  52.           Text(`年龄:${this.item.age}`).fontSize(20)
  53.         }
  54.         Button('修改数据').fontSize(18)
  55.           .onClick(() => {
  56.             // this.addAge()
  57.             this.item.age ++
  58.           })
  59.       }
  60.       .width('100%')
  61.       .height(100)
  62.       .padding({left: 10, right: 10})
  63.       .justifyContent(FlexAlign.SpaceBetween)
  64.       .margin({bottom: 10})
  65.       .borderRadius(10)
  66.       .backgroundColor('#eee')
  67.     }
  68.   }
  69. }
复制代码
十二、新建页面、路由跳转

1、新建页面



  • 直接新建 page 页面(不必要手动设置页面,可直接利用)
  • 新建 ArkTs File,然后去src/main/resources/base/profile/main_pages.json 中手动设置 页面路径

    注:页面必要用@Entry修饰。
2、页面跳转和退却


  • router.pushUrl():利用此方法跳转的页面,可以进行退却操作。
  1. router.pushUrl({
  2.    url: "pages/Index"
  3. })
复制代码

  • router.replaceUrl():利用此方法跳转的页面,不能进行退却操作。(貌似利用 replace 会把当前页面烧毁,然后绘制新的页面)
  1. router.replaceUrl({
  2.   url: "pages/Index"
  3. })
复制代码

  • router.back()
    :退却
  1. router.back()
复制代码
3、页面栈

页面栈是用来存储步伐运行时页面的一种 数据结构,遵照先辈先出的原则。
页面栈的最大容量为 32 个页面


  • 获取页面栈长度router.getLength()
  • 清空页面栈router.clear()
4、路由模式

路由提供了两种差别的跳转模式:

  • Standard:无论之前是否添加过,一直添加到页面栈(默认常用)
  • Single:如果目标页面已经存在,会将已有的最近同 url 页面移到栈顶(看环境利用)
    在跳转方法的第二个参数里设置路由模式
  1. router.pushUrl({
  2.   url: "pages/Index"
  3. }, router.RouterMode.Single)
  4. router.pushUrl({
  5.   url: "pages/Index"
  6. }, router.RouterMode.Standard)
复制代码
5、路由传参


  • 页面 A 将参数以对象的形式,通过 params 属性传递
  1. router.pushUrl({
  2.   url: 'pages/Details',
  3.   params: {
  4.     msg: '测试信息',
  5.     name: this.name
  6.   }
  7. })
复制代码

  • 页面 B 在页面显示的声明周期内里接收并剖析参数
  1. aboutToAppear() {
  2.     // as 为类型断言,这里要把获取到的路由参数转为具体的类型,否则无法通过点语法获取值
  3.     let info = router.getParams() as Info
  4.     console.log(info.name)
  5.   }
复制代码
十二、生命周期


页面嵌套组件时,生命周期钩子执行顺序为:
父 aboutToAppear -》子 aboutToAppear -》父 onPageShow -》父 aboutToDisappear -》子 aboutToDisappear
十三、Stage 模型



1)

AppScope/app.json5:设置应用信息,对应的图片放在 AppScope/resources/base/media 目录下。
AppScope/resources/base/element/string.json:设置设置-》应用-》app 的描述信息
好像json5中设置的信息是在对应目录下的 string.json 中,对应的资源在对应 media 目录中。

2)

src/main/resources/base/element/string.json:设置变量的key和value,在 module.json5 中通过"$string:module_desc"($string是指 string.json 文件, 背面是指name为module_desc对应的value值)取值设置对应信息。
src/main/module.json5:abilities 设置显示信息,包括在桌面的图标和名称等。对应的图片等资源放在src/main/resources/base/media目录下。

3)UIAbility

好像就是手机上运行的 app 任务,单 UIAbility 就是一个 app 只能运行 1 个任务,多 UIAbility 就是1个 app 可以运行多个任务,好比 微信和微信小步伐


1. 同模块新建其他 ability



  • 从模块 entry 中新建完 Ability 后,生成的 Ability 会放置在 ets 目录下
  • 同时会在 entry 模块的 module.json5 的 abilities 数组中,新增这个任务的设置默认信息(可以设置图标和名字)
  • 生成的 ets 下的 TwoAbility1.ts 中的 windowStage.loadContent() 可以修改启动页面
  • 可以通过 module.json5 中修改 ability 的 exported、skills 设置,绝对默认显示哪个 ability


2.差别模块新建其他 ability


3. 同模块 Ability 拉起

从一个 Ability 中唤起另一个 Ability(同模块)
1、准备 want 作为 UIAbility 的启动参数
2、利用上下文对象 context,调用 startAbility 传入 want 启动
  1. import Want from '@ohos.app.ability.Want'
  2. import common from '@ohos.app.ability.common'
  3. @Entry
  4. @Component
  5. struct Index {
  6.   // 从一个 Ability 中唤起另一个 Ability(同模块)
  7.   // 1、准备 want 作为 UIAbility 的启动参数
  8.   // 2、利用上下文对象 context,调用 startAbility 传入 want 启动
  9.   // 获取上下文对象
  10.   context = getContext(this) as common.UIAbilityContext
  11.   build() {
  12.     Column() {
  13.       Text('entryability----Index').fontSize(30).fontWeight(FontWeight.Bold)
  14.       Button('唤起功能').onClick(() => {
  15.         // 1、准备 want (参数信息)
  16.         let wantInfo: Want = {
  17.           deviceId: '', //  空表示本设备
  18.           bundleName: 'com.example.myapplication', // AppScope/app.json5 中的 bundleName
  19.           moduleName: 'entry', // 模块名
  20.           abilityName: 'TwoAbility1', // src/main/module.json5 中的对应的 abilitie name
  21.           parameters: {
  22.             info: '来自 entryability'
  23.           }
  24.         }
  25.         // 2、利用 context startAbility 调起 UIAbility
  26.         this.context.startAbility(wantInfo)
  27.       })
  28.     }
  29.   }
  30. }
复制代码
4. 差别模块拉起

跟 3. 同模块 Ability 拉起 方法一样,只是必要修改 wantInfo 中的 moduleName、abilityName
  1. Button('唤起不同模块的 abilitie 功能').onClick(() => {
  2.   // 1、准备 want (参数信息)
  3.   let wantInfo: Want = {
  4.     deviceId: '', //  空表示本设备
  5.     bundleName: 'com.example.myapplication', // AppScope/app.json5 中的 bundleName
  6.     moduleName: 'TestModule', // 模块名
  7.     abilityName: 'TestModuleAbility', // src/main/module.json5 中的对应的 abilitie name
  8.     parameters: {
  9.       info: '来自 TestModuleAbility'
  10.     }
  11.   }
  12.   // 2、利用 context startAbility 调起 UIAbility
  13.   this.context.startAbility(wantInfo)
  14. })
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表