HarmonyOS应用开发-样式复用多态

@Styles

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-style-0000001473856690-V2

如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。

@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。用于快速定义并复用自定义样式

  • 局部定义
复制代码
// 全局
@Styles function functionNameStyle() { 
  .width(150)
  .height(100)
  .backgroundColor(Color.Red)
}
​
@Entry
@Component
sturt Index {
  // 组件内
  @Styles functionNameStyle() { ... }
​
  build() {
    Text('Text')
      .functionNameStyle()
  }
}
  • demo
复制代码
@Entry
@Component
struct Index {
​
  @Styles iptStyle() {
    .width('80%')
    .height(50)
    .backgroundColor(Color.White)
    .border({ width: 1, color: Color.Gray })
    .margin({top:20,bottom: 20})
  }
​
  build() {
    Column() {
      TextInput({placeholder:'请输入手机号'})
        .iptStyle()
​
      TextInput({placeholder:'请输入验证码'})
        .iptStyle()
    }
  }
}
  • 案例
复制代码
// function 函数名() {}
// @Styles function 函数名Style() {}
// @Styles function iptStyle() {
//   .width('90%').height(50).backgroundColor('#fff')
//   .border({
//     width:{bottom:2},
//     color: '#e5e5e5'
//   })
//   .margin({top:20})
//   .borderRadius(0)
// }
​
@Entry
@Component
struct Index {
​
  @Styles iptStyle() {
    .width('90%').height(50).backgroundColor('#fff')
    .border({
      width:{bottom:2},
      color: '#e5e5e5'
    })
    .margin({top:20})
    .borderRadius(0)
  }
​
  build() {
    Column(){
      TextInput({placeholder:'请输入手机号'}).iptStyle()
      TextInput({placeholder:'请输入验证码'}).iptStyle()
    }
  }
}

@Extend

@Extend 用于扩展原生组件样式,通过传参提供更灵活的样式复用

  • 仅支持全局

  • 支持传参,传递状态自动同步,也可以传递回调函数

复制代码
// 全局  原生组件                     参数
//  ↓     ↓                          ↓ 
@Extend(Text) function 属性名字(data: number) { 
  .width(data)
}
  • demo1
复制代码
// @Styles function iptStyle() {
@Extend(TextInput) function iptStyle(width:number=80) {
  // .width('80%')
  .width(`${width}%`)
  .backgroundColor('#fff')
  .border({
    width: 1,
    color: '#ccc',
    style: BorderStyle.Solid
  })
  .margin({top:20,bottom:20})
}
​
@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('登录页')
​
      TextInput({placeholder:'请输入用户名'})
        .iptStyle()
        // .width('100%')  不推荐, 后者覆盖前者
​
      Row() {
        TextInput({placeholder:'验证码'})
          .iptStyle(40)
        Button('获取验证码')
      }
​
    }
  }
}
  • demo2
复制代码
@Extend(TextInput) function iptStyle(cb: (data:string) => void,w:number=80) {
  .width(`${w}%`)
  .height(50)
  .backgroundColor(Color.White)
  .border({ width: 1, color: Color.Gray })
  .margin({top:20,bottom: 20})
  .onChange(cb)
}
​
@Entry
@Component
struct Index {
  @State mobile:string = ''
  @State code:string = ''
​
  @State w:number = 40
  build() {
    Column() {
      Text(`手机号:${this.mobile}`)
      Text(`验证码:${this.code}`)
​
      TextInput({placeholder:'请输入手机号'})
        .iptStyle((data:string) => {
          this.mobile = data
        })
​
      TextInput({placeholder:'请输入验证码'})
        .iptStyle((data:string) => {
          this.code = data
        },40)
​
      TextInput({placeholder:'点击变成'})
        .iptStyle((data:string) => {
          this.code = data
        },this.w)
        .onClick(() =>{
          this.w=90
        })
        .onBlur(() => {
          this.w =40
        })
    }
  }
}

多态

stateStyles() 可以依据组件的内部状态的不同,快速设置不同样式。

  • normal:正常态。

  • pressed:按压态。

  • focused:获焦态。 DevEco5 有bug@24.6

  • disabled:不可用态。

复制代码
@Entry
@Component
struct Index {
​
  @State disabled:boolean = false // true 禁用, false没有禁用 启用
​
  build() {
    Column() {
      Text('通过Text内置组件模拟实现Button效果').fontSize(20)
​
      // TextInput({placeholder:'hello'})
      //   .stateStyles({ // input打开后默认第一个自动获取焦点
      //     focused: {
      //       .backgroundColor('red')
      //     }
      //   })
      //
      // TextInput({placeholder:'hello'})
      //   .stateStyles({ // 第二个得自己点
      //     focused: {
      //       .backgroundColor('red')
      //     }
      //   })
​
      Text('删除')
        .width(100).height(50)
        .fontColor('#fff')
        // .backgroundColor('#000')
        .borderRadius(25)
        .textAlign(TextAlign.Center)
        .focusable(true) // 获取焦点,切记页面不能有默认获取焦点组件否相互影响
        // .enabled(false)  // 是否激活状态: true-启动,false禁用  应该灰色  这哥们比较矫情需要点击修改状态才可以禁用  类似于获取短信验证码 不是立马禁用而是操作后
        .enabled(!this.disabled)
        .stateStyles({
          normal: {
            .backgroundColor('red')
          },
          pressed: {
            .backgroundColor('#000')
          },
          // focused: {
          //   .backgroundColor('blue')
          // },
          disabled: {
            .backgroundColor('#ccc')
          }
        })
​
​
      Text(`当前状态:${this.disabled}-${this.disabled?'已禁用':'正常'}`)
      // disabled为真代表禁用了, 咱们点击按钮让他启用
      Button(this.disabled?'启用':'禁用').onClick(() => this.disabled = !this.disabled)
    }
      .padding(30)
  }
}
  • 获取短信
复制代码
@Entry
@Component
struct Index {
  // 准备 完成布局  包括禁用效果 等等之类的
  // 1 声明响应式数据
  // content=获取验证码、time=60 学习咱们用10、timer定时器 后期清楚、 disabled 是否禁用
  // 并且视图使用
  // 2 绑定点击事件
  // 4 事件处理函数中
  // - 4.1 过滤   手机号过滤、避免重复点击
  // - 4.2 立马-1 并同步页面
  // - 4.3 每隔1秒-1    并且判断   time<=1  =》先清空定时器,接着响应式数据还原,最后终止代码执行
  // - 4.4 发送服务器请求  让服务器发送短信验证码
​
  @State content:string = '获取验证码'
  @State isEnabled:boolean = true
​
  private time:number = 10
  private timer:number = 0
​
  build() {
    Text(this.content)
      .fontSize(40)
      .fontColor(this.isEnabled?Color.White:'#ccc')
      // .fontColor('#ccc')
      .borderRadius(30)
      .padding(20)
      // 是否可交互   true-可以 没有禁用, false-不可以  也就禁用了
      .enabled(this.isEnabled)
      .stateStyles({
        normal: {
          .backgroundColor(Color.Black)
        },
        disabled: {
          .backgroundColor(Color.Gray)
        },
      })
      .onClick(() => {
        // - 4.1 过滤   手机号过滤、避免重复点击
        if (!this.isEnabled) return
        // - 4.2 立马-1 并同步页面
        this.isEnabled = false
        this.time--
        this.content = `剩余${this.time}s`
        // - 4.3 每隔1秒-1    并且判断   time<=1  =》先清空定时器,接着响应式数据还原,最后终止代码执行
        this.timer = setInterval(() => { // 返回number 第一次1 第二次2 唯一的
          if (this.time<=1) {
            clearInterval(this.timer)
            this.content = '获取验证码'
            this.isEnabled = true
            this.time = 10
            this.timer = 0
            return
          }
          this.time--
          this.content = `剩余${this.time}s`
        }, 1000)
        // - 4.4 发送服务器请求  让服务器发送短信验证码
        console.log('请求接口')
      })
  }
}

欢迎加入课程班级,考取鸿蒙认证:

https://developer.huawei.com/consumer/cn/training/classDetail/d43582bb30b34f548c16c127cb3be104?type=1?ha_source=hmosclass\&ha_sourceId=89000248

相关推荐
天聚数行6 小时前
华为鸿蒙系统(HarmonyOS)调用天聚数行 API 教程
华为·php·harmonyos·tianapi·天聚数行
BlackWolfSky7 小时前
鸿蒙加解密
华为·harmonyos
融云7 小时前
融云 4 款 SDK 首批通过 GIIC 鸿蒙生态评测
华为·harmonyos
讯方洋哥7 小时前
HarmonyOS应用开发—页面路由
华为·harmonyos
鸿蒙开发工程师—阿辉8 小时前
HarmonyOS 5 高效使用命令:HDC 基本使用
华为·harmonyos
梧桐ty8 小时前
鸿蒙 + Flutter:构建万物互联时代的跨平台应用新范式
flutter·华为·harmonyos
梧桐ty10 小时前
鸿蒙 + Flutter:破解“多端适配”困局,打造万物互联时代的高效开发范式
flutter·华为·harmonyos
Python私教10 小时前
鸿蒙应用的测试和调试完全指南:从单元测试到性能分析
华为·单元测试·harmonyos
Archilect10 小时前
终点、光圈与 Lottie 生命周期:复杂关闭动效的「收尾工程」
harmonyos