鸿蒙常用基础

216 阅读3分钟

父传子 单向 不加修饰符 1-无响应式、2-可以写默认值、3-可以改但是父覆盖

步骤1:  传  调用组件传递数据   自定义组件名({  属性名:数据  })  
步骤2:  收  属性名:数据
步骤3:  用  this.属性名    

父传子 单向 @Prop 1-有响应式、不可以写默认值仅支持number/string/boolean

步骤1:  传  调用组件传递数据   自定义组件名({  属性名:数据  })  
步骤2:  收  @Prop 属性名:数据
步骤3:  用  this.属性名    

父子双向 @Link 1-双向 子直接改父、2-支持对象

步骤1:  传  调用组件传递数据   自定义组件名({  属性名:要把this.改成$  })  
步骤2:  收  @Link 属性名:数据
步骤3:  用  this.属性名    

子传父 调用父的方法 this指向

步骤1: 父定义方法       onUpdTile = (data:string) => {}
步骤2: 传递给子             Tabbar({ onUpdTile: this.onUpdTile  })
步骤3: 子收          onUpdTile: (data:string) => {}
步骤4: 子用                  this.onUpdTile(数据)

后代 1-双向、2-支持对象

步骤1:父   @Provide 状态:类型 = 数据
步骤2:子   @Consume 状态:类型

状态

原始类型
引用类型:修改二维的数据没有响应式  =》 解决修改一维的  
@State arr: {num:number}[] = [
    {num:1},
    {num:2}
]
​
this.arr[0].num++
this.arr[0] = {num: this.arr[0].num+1}
​
​
状态比较推荐的类型限制写法(鸿蒙项目开发命名规范)

判断:让大家知道在build层也可以写判断

循环

ForEach(数组, (item:类型, i:number) => {
        结构
})

图片.png

一、@ObjectLink item双向

@ObjectLink和@Observed类装饰器用于在涉及嵌套对象和数组的场景中进行双向数据同步

  • 被@Observed修饰的类,可以被观察到属性的变化

  • 子组件中通过@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例

    @Observed
    class Stu {
      name: string
      money: number
    
      constructor(name:string, money:number) {
        this.name = name
        this.money = money
      }
    }
    
    
    @Component
    struct Child {
    
      // @Prop item:Stu
      // @Link item:Stu
      @ObjectLink item:Stu
    
      build() {
        Column() {
          Row() {
            Text(`姓名-${this.item.name},`)
            Text(`资产-${this.item.money},`)
            Text(`+1 `).onClick(() => {
                this.item.money++
            })
            Text('删除')
          }
        }
          .width('100%')
          .padding(20)
          .margin({top:20})
          .border({
            width: 2,
            color: 'red',
            style: BorderStyle.Solid
          })
      }
    }
    
    @Entry
    @Component
    struct Index {
    
      @State data1:Stu[] = [
        new Stu('张三', 30),
        new Stu('李四', 40),
        new Stu('王五', 50),
      ]
    
      build() {
        Column() {
          Text('父组件')
          // Child(  {data1:this.data1}  )
          Button('造人👶🏻')
    
    
          // 子也是非常复杂的布局
          ForEach(
            this.data1,
            (item:Stu) => {
              // Child({ item:item })
              Child({ item:item })
            }
          )
    
          // 父有很多其他代码
        }
          .width('100%')
          .padding(20)
          .border({
            width: 2,
            color: 'red',
            style: BorderStyle.Solid
          })
      }
    }
    
    
    

    二、@Watch

@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当在严格相等为false的情况下,就会触发@Watch的回调。

  • 建议开发者避免无限循环。循环可能是因为在@Watch的回调方法里直接或者间接地修改了同一个状态变量引起的。为了避免循环的产生,建议不要在@Watch的回调方法里修改当前装饰的状态变量;
  • 不建议在@Watch函数中调用async await,因为@Watch设计的用途是为了快速的计算,异步行为可能会导致重新渲染速度的性能问题。

2.1 语法

@Prop @Wathc('onUpdMsg') msg:string

onUpdMsg = () => { 不行

onUpdMsg() {

}

2.2 案例

场景1: 百度搜索

@Entry
@Component
struct Index {
​
​
  // @State num:number = 1
  @State @Watch('onUpdNum') num:number = 1 // upd update@State @Watch('onUpdContent') content:string = ''
  @State mock:string[] = [
    'abcdefg',
    'aaaa123bbbb',
    'cccc123',
    '67898768dddddd'
  ]
​
  // onUpdContent = () => {}
  onUpdContent() {
    // 定义临时数组 存放筛选后的数据
    let temp: string[] = []
    // 遍历数据  筛选 判断当前输入的内容是否在数组中
    this.mock.forEach((item:string) => {
      // 语法: 字符串1.includes('字符串2')
      // 作用 :判断字符串2是否在字符串1中
      // 返回: 布尔类型
      if (item.includes(this.content)) {  // 当前输入的字符串content 是否在item中
        temp.push(item)
      }
    })
    // 保存 页面展示最新数据
    this.mock = temp
  }
​
  // onUpdNum = () => {
  // }
  onUpdNum() {
    console.log('num数据变化啦:'+this.num)
  }
​
  build() {
    Column() {
        Text(this.num.toString()).fontSize(60)
        Button('num++').onClick(() => this.num++)
        /*
        watch场景1  百度搜索
        1 布局  上述输入框、下面展示数据
        2 把【输入的数据】保存到【状态】里面
        3 监控状态变化  =》 实战:去数据库获取数据 ,学习咱们就筛选
        4 拿到数据保存到模型 页面展示
        */
​
        TextInput({
          placeholder:'请输入内容 实战去后端数据库获取,咱们这里准备一些假mock数据 筛选'
        })
          .onChange((content:string) => {
              console.log('当前输入的内容:'+content)
              // 实战:这边去后端数据库拿数据 根据用户输入的内容
              // 学习:需求咱就假数据过滤
              // 方案1:遍历mock数据,判断content 是否在里面  在就展示 不在就移除
              // 方案2:先别写逻辑   按照之前写的思路  把数据保存起来  后面监控数据变化
​
              // 思考🤔:上面哪个方案好呢
              // 回答:方案2   1-这里数据保存了 后面如果要做添加功能,2-减少UI层/视图层代表量  尽量的不要在Build里面写太多逻辑
              this.content = content
          })
        ForEach(
          this.mock,
          (item:string) => {
            Text(String(item)).width('100%').fontSize(30).margin({top:20,bottom:20})
          }
        )
    }
  }
}