【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理

【HarmonyOS】HarmonyOS NEXT学习日记:五、交互与状态管理

在之前我们已经学习了页面布局相关的知识,绘制静态页面已经问题不大。那么今天来学习一下如何让页面动起来、并且结合所学完成一个代码实例。

交互

如果是为移动端开发应用,那么交互上用的最多的就是触屏事件。当然ArkUI也提供了键鼠事件、焦点事件、拖拽事件等。不过我认为用到的时候再看文档就行,事件这个东西一通百通,所以这里只介绍几个常用的事件。

onClick

点击事件是指通过手指或手写笔做出一次完整的按下和抬起动作。当发生点击事件时,会触发以下回调函数

用法:onClick(event: (event?: ClickEvent) => void)

event参数提供点击事件相对于窗口或组件的坐标位置,以及发生点击的事件源

我们写一个示例,点击按钮操作一个数字

  @State num: number = 0

  build() {
    Column({space: 10}){
      Text(`数字:${this.num}`)
      Button('数字+1').onClick(()=>{
        this.num++
      })
      Button('数字-1').onClick(()=>{
        this.num--
      })
    }
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    }

在这里插入图片描述
点击数字+1按钮则数字变大1
在这里插入图片描述

触摸事件

当手指或手写笔在组件上触碰时,会触发不同动作所对应的事件响应,包括按下(Down)、滑动(Move)、抬起(Up)事件

用法:onTouch(event: (event?: TouchEvent) => void)

  • event.type为TouchType.Down:表示手指按下。
  • event.type为TouchType.Up:表示手指抬起。
  • event.type为TouchType.Move:表示手指按住移动。
@State eventType: string = ''

  build() {
    Column({space: 10}){
      Text(`eventType:${this.eventType}`)
      Button('触摸我').onTouch((event) => {
        if(event) {
          if (event.type === TouchType.Down) {
            this.eventType = 'Down';
          }
          if (event.type === TouchType.Up) {
            this.eventType = 'Up';
          }
          if (event.type === TouchType.Move) {
            this.eventType = 'Move';
          }
        }
      })
    }
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    }

在这里插入图片描述
手在按钮上按下时
在这里插入图片描述
手在按钮上移动时
在这里插入图片描述
手松开按钮后
在这里插入图片描述

状态管理

但如果希望构建一个动态的、有交互的界面,就需要引入“状态”的概念。
事实上之前我们已经多次用到了这个概念,点击按钮改变一个字符串并让他展示在页面上,这个字符串就是一个状态。

即:点击交互触发了文本状态变更,状态变更引起了UI渲染

我们将写组件时用到的变量分为以下两种

  • 普通变量:只能在初始化时渲染,后续将不会再刷新。
  • 状态变量:需要装饰器装饰,改变会引起 UI 的渲染刷新 (必须设置类型 和初始值)

不论是哪种变量,只要是定义在组件内,在使用的时候,都需要通过 this 访问。


@Entry
@Component
struct Index {
  @State str1: string = 'str1'
  str2: string = 'str2'

  build() {
    Column() {
      Text(this.str1)
      Text(this.str2)
    }
  }
}

实践-购物车

结合前面学的布局知识,和今天的交互、状态管理实现一个移动端商城的购物车。可以点击商品的+、-来为购物车添加商品。

interface Commodity {
  img: Resource,
  name: string,
  introduce: string,
  oldPrice: number,
  price: number,
  num: number,
}

@Entry
@Component
struct Index {
  @State Dog:Commodity={
    img: $r('app.media.test2'), // 商品图片资源
    name: '狗头', // 商品名称
    introduce: '这是一个滑稽的狗头', // 商品介绍
    oldPrice: 99, // 商品原价
    price: 9.9, // 商品现价
    num: 0, // 商品数量
  }

  build() {
    Column() {
      // 滚动视图
      Scroll(){
        Row(){
          // 商品图片
          Image(this.Dog.img)
            .size({
              width: 120,
              height: 80
            })
            .borderRadius(10)
            .margin({
              right: 10
            })
          
          // 商品信息列
          Column(){
            // 商品名称
            Row(){
              Text(this.Dog.name)
                .fontSize(18)
                .fontColor('#333')
            }
            // 商品介绍
            Row(){
              Text(this.Dog.introduce)
                .fontSize(16)
                .fontColor('#aaa')
                .lineHeight(30)
            }
            // 商品价格与操作
            Row(){
              Text(`${this.Dog.price}`)
                .fontSize(22)
                .fontWeight(FontWeight.Bold)
                .fontColor(Color.Red)
              
              Text(`${this.Dog.oldPrice}`)
                .fontSize(18)
                .fontColor('#999')
                .margin({left: 10})
                .decoration({
                  type: TextDecorationType.LineThrough
                })
              
              // 增加商品数量按钮
              Text('+')
                .width(15)
                .height(20)
                .margin({
                  left:30
                })
                .border({
                  width: 1,
                  color: '#aaa',
                  style: BorderStyle.Solid,
                  radius: {
                    topLeft:3,
                    bottomLeft:3
                  }
                })
                .fontColor('#333')
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .textAlign(TextAlign.Center)
                .onClick(()=>{
                  this.Dog.num++
                })
              
              // 显示商品数量
              Text(this.Dog.num+'')
                .height(20)
                .border({
                  width: 1,
                  color: '#aaa',
                  style: BorderStyle.Solid,
                })
                .padding({
                  left: 5,
                  right: 5
                })
              
              // 减少商品数量按钮
              Text('-')
                .width(15)
                .height(20)
                .border({
                  width: 1,
                  color: '#aaa',
                  style: BorderStyle.Solid,
                  radius: {
                    topRight:3,
                    bottomRight:3
                  }
                })
                .fontColor('#333')
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .textAlign(TextAlign.Center)
                .onClick(()=>{
                  if(this.Dog.num >= 1)
                    this.Dog.num--
                })
            }
          }
          .alignItems(HorizontalAlign.Start)
          .layoutWeight(1) // 设置列布局的权重
        }
        .alignItems(VerticalAlign.Top)
        .width('100%')
        .backgroundColor('#ddd')
        .padding(20)
      }
      .backgroundColor('#eee')
      .align(Alignment.Top)
      .layoutWeight(1) // 设置滚动视图的布局权重
      
      // 底部结算栏
      Row(){
        Column(){
          // 选购数量与总价
          Row(){
            Text(`已选${this.Dog.num}}件,`)
              .fontColor('#666')
            Text('合计:')
            Text(`${this.Dog.num * this.Dog.price}`)
              .fontColor(Color.Red)
          }
          // 显示优惠金额
          Row(){
            Text(`共减¥${(this.Dog.oldPrice - this.Dog.price) * this.Dog.num}`)
              .fontSize(14)
              .lineHeight(18)
              .fontColor(Color.Red)
          }
        }
        .alignItems(HorizontalAlign.End)
        .layoutWeight(1)
        
        // 结算按钮
        Button('结算外卖')
          .margin({
            left: 20
          })
      }
      .height(100)
      .padding(20)
      .backgroundColor(Color.White)
      .width('100%')
    }
  }
}

在这里插入图片描述
点击加号可以添加货物
在这里插入图片描述

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值