@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('请求接口')
})
}
}
欢迎加入课程班级,考取鸿蒙认证: