鸿蒙基础组件:自定义组件@conponet基础

235 阅读3分钟

鸿蒙基础组件:自定义组件@conponet基础

基本使用

上班的的时候使用的时候需要特别注意名字的规范!!!

需要谨慎使用

正常来说@Builder更实用虽然都差不多

/*
 * 1 使用自定义组件 分两个步骤
 *  1 创建自定义组件
 *      在公司使用的时候需要谨慎起名字需要进行
 *  2 在页面和 使用它
 *   使用时直接写自定义组件的名字即可
 *
 * */

// 1 自定义 组件
@Component
struct son {
  build() {
    Row() {
      Button("按钮")
        .type(ButtonType.Normal)
        .borderRadius(3)

      Text()
        .width(10)
        .height(10)
        .backgroundColor("#007DFE")
        .translate({ x: -5 })
        .rotate({ angle: 45 })
    }
  }
}


@Entry
@Component
struct Index {
  
  build() {
    Column() {
      //使用自定义组件
      son()
      son()
      son()
      son()
      son()
      son()
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

@State加不加的一些情况

如果需要状态变量,初次渲染有用,但是其他的时候的渲染不会变化

@Component
struct Mybook {
  //如果不加状态变量,初次的渲染有用,后期修改数据,ui不会变化
  @State
  tittle:number = 100
  bgcolor: string = '#007dfe'

  build() {
    Row() {
      Button(this.tittle.toString())
        .type(ButtonType.Normal)
        .borderRadius(3)
        .borderRadius(10)
        .backgroundColor(this.bgcolor)
        .onClick(()=>{
          //数据到底减少了没有??
          //已经建减少
          this.tittle--
        })
      Text()
        .width(10)
        .height(10)
        .backgroundColor(this.bgcolor)
        .translate({ x: -5 })
        .rotate({ angle: 45 })
    }
    .margin(10)
  }
}


@Entry
@Component
struct Index {
  build() {
    Column() {
      //
      Mybook({ tittle: 200, bgcolor: '#ffc62424' })
     /* Mybook({ tittle: '二娃', bgcolor: '#681189d9' })
      Mybook({ tittle: '三娃', bgcolor: '#ff87a23a' })
      Mybook({ tittle: '四娃', bgcolor: '#a424c647' })
      Mybook({ tittle: '五娃', bgcolor: '#d0c67d24' })
      Mybook({ tittle: '六娃', bgcolor: '#7e24c64c' })
      Mybook({ tittle: '七娃', bgcolor: '#c97a24c6' })*/
    }
    .width('100%')
    .height('100%')
  }
}

this在自定义组件中的一些情况

在自定义组件的情况下的箭头在那个位置写this就属于谁 普通函数this 是谁调用, this指向谁!!

// 组件可以接收数据 、组件还可以接收逻辑-函数

@Component
struct MyButton {
  @State
  title: number = 100
  // 接收传递函数
  add: () => void = () => {
  }

  build() {
    Row() {
      Button(this.title.toString())
        .type(ButtonType.Normal)
        .borderRadius(3)


      Text()
        .width(10)
        .height(10)
        .backgroundColor("#007DFE")
        .translate({ x: -5 })
        .rotate({ angle: 45 })
    }
    .onClick(() => {
      this.add()
    })
  }
}

// A 父亲的title ++  正解 
// B 儿子的title ++
// C 报错
// D 什么都没有发生


@Entry
@Component
struct Index {
  @State
  title: number = 20

  build() {
    Column() {
      Text(`父组件的title数据 ${this.title}`)
      MyButton({
        title: 30, add: () => {
          this.title++
        }
      })


    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}
// 组件可以接收数据 、组件还可以接收逻辑-函数

@Component
struct MyButton {
  @State
  title: number = 100
  // 接收传递函数
  add: () => void = () => {
  }

  build() {
    Row() {
      Button(this.title.toString())
        .type(ButtonType.Normal)
        .borderRadius(3)


      Text()
        .width(10)
        .height(10)
        .backgroundColor("#007DFE")
        .translate({ x: -5 })
        .rotate({ angle: 45 })
    }
    .onClick(() => {
      this.add()
    })
  }
}
@Entry
@Component
struct Index {
  @State
  title: number = 20

  build() {
    Column() {
      Text(`父组件的title数据 ${this.title}`)
      // 父组件传递儿子 逻辑 - 普通函数    this.  没有代码提示
      // 谁使用逻辑 this指向谁
      MyButton({
        title: 30, add() {
          // 指向了儿子
          this.title++
        }
      })


    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

自定义组件可以添加的事件

import { promptAction } from '@kit.ArkUI'

@Component
struct inseid {
  build() {
    Button('完美世界')
      .width(150)
      .height(80)

  }
}
/*
 * .onCLick()支持
 * .onChange()不支持
 * .background()支持
 * .fontColor()不支持
 * */

@Entry
@Component
struct Index {
  build() {
    Column(){
      inseid()
        .onClick(()=>{
          promptAction.showToast({message:'你好'})
        })
    }
    .width('100%')
    .height('100%')
  }
}

构建函数 @BuilderParam

自定义函数可以外部传递UI

单个@BuilderParam

组件内有且仅有一个使用 @BuilderParam 装饰的属性,即可使用尾随闭包

@Component
struct MyButton {
  //定义默认的布局结构
  @Builder
  defaultBuilder() {
    Button("默认的按钮")
  }
    // 2利用@BuilderParam编写占位符
  @BuilderParam
  //名称:类型=函数-不要加小括号
  aaa: () => void = this.defaultBuilder

  build() {
    Column() {
      Text("===================")
      this.aaa()
      Text("===================")
        //占位符
    }
    .width(300)
    .height(300)
    .border({ width: 10 })
    .borderRadius(150)
  }
}


@Entry
@Component
struct Index {
  build() {
    //容器组件
    Column() {
      Button('123456')
      MyButton() {
        Button('出去')
          .type(ButtonType.Capsule)
      }
      MyButton(){
        Column(){
          Text('xxxxx')
          TextInput()
        }
      }
      MyButton(){
        Row(){
         Image($r('app.media.layered_image'))
          Text('xxx继续')
        }
      }
      MyButton(){
        Text('内容')
      }
    }
    .width('100%')
    .height('100%')
  }
}

多个@BuilderParam

子组件有多个BuilderParam,必须通过参数的方式来传入

@Component
struct MyNavBar {
  // 1 默认结构
  @Builder
  backBuilder() {
    Text("<--")
  }
  // 2 构建函数
  @BuilderParam
  leftBui: () => void = this.backBuilder
  @BuilderParam
  centerBui: () => void = this.backBuilder
  @BuilderParam
  rightBui: () => void = this.backBuilder

  build() {
    Row() {
      this.leftBui()
      this.centerBui()
      this.rightBui()

    }
    .width("100%")
    .justifyContent(FlexAlign.SpaceBetween)
    .backgroundColor(Color.White)
  }
}


@Entry
@Component
struct Index {
  @Builder
  leftBuiParent() {
    Text("返回")
      .fontSize(30)
  }

  @Builder
  centerBuiParent() {
    Text("首页")
      .fontSize(30)
  }

  @Builder
  rightBuiParent() {
    Text("菜单")
      .fontSize(30)
  }

  build() {
    Column() {
      // 多个 @BuilerParam  不能使用 单个@BuilderParam传递参数语法
      // 组件传递逻辑,传递函数思想
      MyNavBar({
        leftBui: this.leftBuiParent,
        centerBui: this.centerBuiParent,
        rightBui: this.rightBuiParent
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .backgroundColor("#ccc")
  }
}

@Prop

@Prop 可以装饰的变量可以和父组件建立单向的同步关系。

@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。

父向子传递数据:通过 调用子组件的时候 传递参数的方式

子向父传递数据:通过 父组件传递函数,子组件调用函数的方式实现

@Component
struct myinde {
//父组件如果修改数据,会一直同步
  @Prop
  num:number=0
  addNum:(n:number)=>void = () => {

  }
  build() {
    Column(){
      Button(`子组件${this.num}`)
        .backgroundColor('#333840')
        .onClick(()=>{
          this.addNum(5)
        })

    }
  }
}


@Entry
@Component
struct Index {
  @State
  num:number = 100

  addNum = (n:number) =>{
    this.num+=n
  }
  build() {
    Column(){
     Button(`父组件${this.num}`)

      myinde({num:this.num,addNum:this.addNum})
    }
    .width('100%')
    .height('100%')

  }
}

案例

基础差思路

  1. 只看小图片 + 大图片

    点击小图之后 大图才有显示

image.png

思路

  1. 数据设计

    1. 父组件定义两个数据

      1. 数组 存放 小图地址
      2. 大图地址 默认空
  2. 完成布局

    1. 遍历父组件数组 -> 渲染小子组件
  3. 考虑功能交互

    1. 。。。。。 子向父传递参数!!!
@Component
struct Myimage {
 imgSrc:string=''
  imgList: string[] = ["app.media.111", "app.media.2", "app.media.3", "app.media.4"]
  //3.1 定义回调函数
  setSrc:(bigSrc:string)=>void=()=>{
  }
  build() {
    Column({ space: 10 }) {
      ForEach(this.imgList,(item:string)=>{
      Image($r(item))
        .width(100)
        .height(60)
        .onClick(()=>{
          // this.imgSrc=item
          this.setSrc(item)//3.3 回调函数传参
        })
      })

    }
    .alignItems(HorizontalAlign.Start)
    .width(100)
  }
}


@Entry
@Component
struct Index {
  @State
  //大图路径
  bigSrc: string = ""
  //函数路径接受给自己 bigSrc
  setSrc = (bigSrc: string) => {
    this.bigSrc = bigSrc
  }
  build() {
    Column() {
      Row() {
        Myimage({imgSrc:this.bigSrc,setSrc:this.setSrc })//3.2调用
        Column() {
          //大图
          Image($r(this.bigSrc))
            .width(200)
            .height(120)

        }
        .backgroundColor(Color.Pink)
        .layoutWeight(1)
      }
      .backgroundColor(Color.Orange)

    }
    .width('100%')
    .height('100%')
  }
}