当前位置: 首页 > news >正文

HarmonyOS 组件样式@Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)

1. HarmonyOS @Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)

  @Styles装饰器:定义组件重用样式
  ;@Extend装饰器:定义扩展组件样式
  自定义扩展:AttributeModifier、AttributeUpdater

1.1. 区别

1.1.1. 对比

  声明式语法引入了@Styles和@Extend两个装饰器,可以解决部分复用的问题,但是存在以下受限场景:
  (1)@Styles和@Extend均是编译期处理,不支持跨文件的导出复用。
  (2)@Styles仅能支持通用属性、事件,不支持组件特有的属性。
  (3)@Styles虽然支持在多态样式下使用,但不支持传参,无法对外开放一些属性。
  (4)@Extend虽然能支持特定组件的私有属性、事件,但同样不支持跨文件导出复用。
  (5)@Styles、@Extend对于属性设置,无法支持业务逻辑编写,动态决定是否设置某些属性。只能通过三元表达式对所有可能设置的属性进行全量设置,设置大量属性时效率低下。
  (为了解决上述问题,ArkUI引入了AttributeModifier的机制,可以通过Modifier对象动态修改属性。能力对比如下:

项目@Styles@ExtendAttributeModifier
跨文件导出不支持不支持支持
通用属性设置支持支持支持
通用事件设置支持支持部分支持
组件特有属性设置不支持支持部分支持
组件特有事件设置不支持支持部分支持
参数传递不支持支持支持
多态样式支持不支持支持
业务逻辑不支持不支持支持

  可以看出,AttributeModifier的能力和灵活性更好,当前持续在构建全量的属性、事件设置能力。未来,AttributeModifier可以替代@Styles和@Extend几乎所有的能力,建议上述场景都使用AttributeModifier。

1.1.2. @Style 和 @Extend 是否支持export导出

  方舟UI框架(ArkUI)解答文档
  (1)@Styles或@Extend目前不支持export导出,后续这两个装饰器不会继续演进。
  (2)推荐开发者使用新的样式复用方法,通过attributeModifier属性动态的设置组件,通过自定义class继承对应基础组件的Modifier,在class中设置复用的属性,对应class也没有无法export的限制。但是attributeModifier的复用能力仍有缺陷,目前不支持事件手势,这两个能力已有需求跟踪。
在这里插入图片描述

1.2. @Styles装饰器:定义组件重用样式

  如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。
  @Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。
  说明:
  从API version 9开始,该装饰器支持在ArkTS卡片中使用。
  从API version 11开始,该装饰器支持在元服务中使用。

1.2.1. 装饰器使用说明

  (1)当前@Styles仅支持通用属性和通用事件。
  @Styles方法不支持参数,反例如下。

// 反例: @Styles不支持参数
@Styles function globalFancy (value: number) {.width(value)
}

  (2)@Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。
  说明
  只能在当前文件内使用,不支持export。
  如果想实现export功能,推荐使用AttributeModifier

// 全局
@Styles function functionName() { ... }// 在组件内
@Component
struct FancyUse {@Styles fancy() {.height(100)}
}

  (3)如果要实现跨文件操作的功能,可以参考使用动态属性设置。

// index.ets
import { MyButtonModifier } from './setAttribute'@Entry
@Component
struct attributeDemo {@State modifier: MyButtonModifier = new MyButtonModifier()build() {Row() {Column() {Button("Button").attributeModifier(this.modifier).onClick(() => {this.modifier.isDark = !this.modifier.isDark})}.width('100%')}.height('100%')}
}
// setAttribute.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {isDark: boolean = falseapplyNormalAttribute(instance: ButtonAttribute): void {if (this.isDark) {instance.backgroundColor(Color.Black)} else {instance.backgroundColor(Color.Red)}}
}

  (4)定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值,示例如下:

@Component
struct FancyUse {@State heightValue: number = 100@Styles fancy() {.height(this.heightValue).backgroundColor(Color.Yellow).onClick(() => {this.heightValue = 200})}
}

  (5)组件内@Styles的优先级高于全局@Styles。
  框架优先找当前组件内的@Styles,如果找不到,则会全局查找。

1.2.2. 使用场景

  以下示例中演示了组件内@Styles和全局@Styles的用法。

import { TitleBar } from '../../components/common/TitleBar'
import { router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'/*** @Styles可以定义在组件内、外*/
/*** 组件外* 在组件外定义时需带上function关键字*/
@Styles
function styleGlobal() {.backgroundColor(Color.Red).width(100).height(100)
}@Styles
function styleGlobal2() {// .backgroundColor(color).width(100).height(100)
}@Entry
@Component
struct StylePage {@State pageTitle: string = "网格列表"aboutToAppear() {try {this.pageTitle = (router.getParams() as RouterParams).title} catch (e) {}}/*** 组件内* 在组件外定义时不需要带function关键字*/@StylesstyleFancy() {.backgroundColor(Color.Blue).width(100).height(100)}build() {Column() {TitleBar({ pageTitle: $pageTitle })Text("组件外样式").styleGlobal().fontSize(30)Text("组件内样式").styleFancy().fontSize(30)//@Styles还可以在StateStyles属性内部使用,// 在组件处于不同的状态时赋予相应的属性。//在StateStyles内可以直接调用组件外定义的Styles,// 但需要通过this关键字调用组件内定义的Styles。Button() {Text("StateStyles")}.stateStyles({normal: {.width(180).height(180)},disabled: this.styleFancy,pressed: styleGlobal})}}
}

在这里插入图片描述

1.3. @Extend 扩展原生组件样式

  @Extend,用于扩展原生组件样式
  说明:
  从API version 9开始,该装饰器支持在ArkTS卡片中使用。
  从API version 11开始,该装饰器支持在元服务中使用。

1.3.1. 装饰器使用说明

1.3.1.1. 语法
@Extend(UIComponentName) function functionName { ... }
1.3.1.2. 使用规则

  (1)和@Styles不同,@Extend仅支持在全局定义,不支持在组件内部定义。
  说明
  只能在当前文件内使用,不支持export
  如果想实现export功能,推荐使用AttributeModifier
  (2)和@Styles不同,@Extend支持封装指定组件的私有属性、私有事件和自身定义的全局方法。

// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {.fontSize(size).fancy()
}

  (3)和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。

// xxx.ets
@Extend(Text) function fancy (fontSize: number) {.fontColor(Color.Red).fontSize(fontSize)
}@Entry
@Component
struct FancyUse {build() {Row({ space: 10 }) {Text('Fancy').fancy(16)Text('Fancy').fancy(24)}}
}

  (4)@Extend装饰的方法的参数可以为function,作为Event事件的句柄。

@Extend(Text) function makeMeClick(onClick: () => void) {.backgroundColor(Color.Blue).onClick(onClick)
}
@Entry
@Component
struct FancyUse {@State label: string = 'Hello World';onClickHandler() {this.label = 'Hello ArkUI';}build() {Row({ space: 10 }) {Text(`${this.label}`).makeMeClick(() => {this.onClickHandler()})}}
}

  (5)@Extend的参数可以为状态变量,当状态变量改变时,UI可以正常的被刷新渲染。

@Extend(Text) function fancy (fontSize: number) {.fontColor(Color.Red).fontSize(fontSize)
}@Entry
@Component
struct FancyUse {@State fontSizeValue: number = 20build() {Row({ space: 10 }) {Text('Fancy').fancy(this.fontSizeValue).onClick(() => {this.fontSizeValue = 30})}}
}

1.3.2. 使用场景

  通过@Extend组合样式后,使得代码更加简洁,增强可读性。

import { router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'
import { TitleBar } from '../../components/common/TitleBar'@Extend(Text)
function extendText() {.fontSize(15).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).margin({top: 20,right: 20,bottom: 20,left: 20}).padding(20).border({width: {left: 1,right: 1,top: 1,bottom: 1},color: {left: Color.Blue,right: Color.Blue,top: Color.Red,bottom: $r('app.color.primary_font_content')},radius: {topLeft: 0,topRight: 0,bottomLeft: 0,bottomRight: 0},style: {left: BorderStyle.Dotted,right: BorderStyle.Dotted,top: BorderStyle.Solid,bottom: BorderStyle.Solid}})
}// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text)
function fancy() {.fontColor(Color.Red)
}// superFancyText可以调用预定义的fancy
@Extend(Text)
function superFancyText(size: number) {.fontSize(size).fancy()
}@Extend(Text)
function extendTextLine(fontSize: number) {.fontSize(fontSize).fontColor($r('app.color.primary_font_title')).maxLines(1).margin({ top: 20 })
}@Entry
@Component
struct ExtendPage {@State pageTitle: string = "Extend"aboutToAppear() {try {this.pageTitle = (router.getParams() as RouterParams).title} catch (e) {}}build() {Column() {TitleBar({ pageTitle: $pageTitle })Text('全局样式').extendText()Text('私有事件和自身定义的全局方法').superFancyText(20)Text('@Extend装饰传递参数').extendTextLine(20)}}
}

在这里插入图片描述

1.4. AttributeModifier

  声明式语法引入了@Styles和@Extend两个装饰器,可以解决部分复用的问题,但是存在以下受限场景,为此,ArkUI引入了AttributeModifier的机制,可以通过Modifier对象动态修改属性。AttributeModifier的能力和灵活性更好,当前持续在构建全量的属性、事件设置能力。未来,AttributeModifier可以替代@Styles和@Extend几乎所有的能力,建议上述场景都使用AttributeModifier。

1.4.1.接口定义

declare interface AttributeModifier<T> {applyNormalAttribute?(instance: T): void;applyPressedAttribute?(instance: T): void;applyFocusedAttribute?(instance: T): void;applyDisabledAttribute?(instance: T): void;applySelectedAttribute?(instance: T): void;}

  AttributeModifier是一个接口,需要开发者实现ApplyXxxAttribute的方法。Xxx表示多态的场景,支持默认态、按压态、焦点态、禁用态、选择态。其中,T是组件的属性类型,开发者可以在回调中获取到属性对象,通过该对象设置属性。

declare class CommonMethod<T> {attributeModifier(modifier: AttributeModifier<T>): T;
}
}

  在组件的通用方法上,增加了attributeModifier传入自定义的Modifier。由于组件在实例化时会明确T的类型,所以调用该方法时,T必须是组件对应的Attribute类型,或者是CommonAttribute。

1.4.2. 行为规格

  (1)组件通用方法attributeModifier支持传入一个实现AttributeModifier接口的实例,T必须是组件对应的Attribute类型,或者是CommonAttribute。
  (2)在组件首次初始化或者关联的状态变量发生变化时,如果传入的实例实现了对应接口,会触发applyNormalAttribute。
  (3)回调applyNormalAttribute时,会传入组件属性对象,通过该对象可以设置当前组件的属性/事件。
暂未支持的属性/事件,执行时会抛异常。
  (4)属性变化触发ApplyXxxAttribute函数时,该组件之前已设置的属性,在本次变化后未设置的属性会恢复为属性的默认值。
  (5)可以通过该接口使用多态样式的功能,例如如果需要在组件进入按压态时设置某些属性,就可以通过自定义实现applyPressedAttribute方法完成。
  (6)一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性,遵循属性覆盖原则,即后设置的属性生效。
  (7)一个Modifier实例对象可以在多个组件上使用。
  (8)一个组件上多次使用applyNormalAttribute设置不同的Modifier实例,每次状态变量刷新均会按顺序执行这些实例的方法属性设置,同样遵循属性覆盖原则。

1.4.3. 属性设置与修改

  AttributeModifier可以分离UI与样式,支持参数传递及业务逻辑编写,并且通过状态变量触发刷新。

// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {// 可以实现一个Modifier,定义私有的成员变量,外部可动态修改isDark: boolean = false// 通过构造函数,创建时传参constructor(dark?: boolean) {this.isDark = dark ? dark : false}applyNormalAttribute(instance: ButtonAttribute): void {// instance为Button的属性对象,可以通过instance对象对属性进行修改if (this.isDark) { // 支持业务逻辑的编写// 属性变化触发apply函数时,变化前已设置并且变化后未设置的属性会恢复为默认值instance.backgroundColor(Color.Black)} else {// 支持属性的链式调用instance.backgroundColor(Color.Red).borderColor(Color.Black).borderWidth(2)}}
}
// demo.ets
import { MyButtonModifier } from './button_modifier'@Entry
@Component
struct attributeDemo {// 支持用状态装饰器修饰,行为和普通的对象一致@State modifier: MyButtonModifier = new MyButtonModifier(true);build() {Row() {Column() {Button("Button").attributeModifier(this.modifier).onClick(() => {// 对象的一层属性被修改时,会触发UI刷新,重新执行applyNormalAttributethis.modifier.isDark = !this.modifier.isDark})}.width('100%')}.height('100%')}
}

  一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性,遵循属性覆盖原则,即后设置的属性生效。

// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {isDark: boolean = falseconstructor(dark?: boolean) {this.isDark = dark ? dark : false}applyNormalAttribute(instance: ButtonAttribute): void {if (this.isDark) {instance.backgroundColor(Color.Black)} else {instance.backgroundColor(Color.Red).borderColor(Color.Black).borderWidth(2)}}
}
// demo.ets
import { MyButtonModifier } from './button_modifier';@Entry
@Component
struct attributeDemo {@State modifier: MyButtonModifier = new MyButtonModifier(true);build() {Row() {Column() {// 先设置属性,后设置modifier,按钮颜色会跟随modifier的值改变Button("Button").backgroundColor(Color.Blue).attributeModifier(this.modifier).onClick(() => {this.modifier.isDark = !this.modifier.isDark})}.width('100%')}.height('100%')}
}

  一个组件上多次使用applyNormalAttribute设置不同的Modifier实例,每次状态变量刷新均会按顺序执行这些实例的方法属性设置,遵循属性覆盖原则,即后设置的属性生效。

// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {isDark: boolean = falseconstructor(dark?: boolean) {this.isDark = dark ? dark : false}applyNormalAttribute(instance: ButtonAttribute): void {if (this.isDark) {instance.backgroundColor(Color.Black).width(200)} else {instance.backgroundColor(Color.Red).width(100)}}
}
// button_modifier2.ets
export class MyButtonModifier2 implements AttributeModifier<ButtonAttribute> {isDark2: boolean = falseconstructor(dark?: boolean) {this.isDark2 = dark ? dark : false}applyNormalAttribute(instance: ButtonAttribute): void {if (this.isDark2) {instance.backgroundColor('#2787D9')} else {instance.backgroundColor('#707070')}}
}
// demo.ets
import { MyButtonModifier } from './button_modifier';
import { MyButtonModifier2 } from './button_modifier2';@Entry
@Component
struct attributeDemo {@State modifier: MyButtonModifier = new MyButtonModifier(true);@State modifier2: MyButtonModifier2 = new MyButtonModifier2(true);build() {Row() {Column() {Button("Button").attributeModifier(this.modifier).attributeModifier(this.modifier2).onClick(() => {this.modifier.isDark = !this.modifier.isDarkthis.modifier2.isDark2 = !this.modifier2.isDark2})}.width('100%')}.height('100%')}
}

1.4.4. 设置多态样式、事件

  使用AttributeModifier设置多态样式、事件,实现事件逻辑的复用,支持默认态、按压态、焦点态、禁用态、选择态。例如如果需要在组件进入按压态时设置某些属性,就可以通过自定义实现applyPressedAttribute方法完成。

// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {applyNormalAttribute(instance: ButtonAttribute): void {// instance为Button的属性对象,设置正常状态下属性值instance.backgroundColor(Color.Red).borderColor(Color.Black).borderWidth(2)}applyPressedAttribute(instance: ButtonAttribute): void {// instance为Button的属性对象,设置按压状态下属性值instance.backgroundColor(Color.Green).borderColor(Color.Orange).borderWidth(5)}
}
// demo.ets
import { MyButtonModifier } from './button_modifier'@Entry
@Component
struct attributeDemo {@State modifier: MyButtonModifier = new MyButtonModifier();build() {Row() {Column() {Button("Button").attributeModifier(this.modifier)}.width('100%')}.height('100%')}
}

1.4.5. 示例

import { CommonModifier, router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'
import { TitleBar } from '../../components/common/TitleBar'class MyButtonModifier implements AttributeModifier<ButtonAttribute> {isDark: boolean = false// applyNormalAttribute(instance: ButtonAttribute): void {//   if (this.isDark) {//     instance.backgroundColor(Color.Black)//   } else {//     instance.backgroundColor(Color.Red)//   }// }/*** 组件普通状态时的样式* @param instance*/applyNormalAttribute(instance: ButtonAttribute): void {instance.backgroundColor(Color.Black)}/*** 组件按压状态的样式* @param instance*/applyPressedAttribute(instance: ButtonAttribute): void {instance.backgroundColor(Color.Red)}/*** 组件禁用状态的样式* @param instance*/applyDisabledAttribute(instance: ButtonAttribute): void {}/*** 组件选中状态的样式* @param instance*/applySelectedAttribute(instance: ButtonAttribute): void {}
}class MyModifier extends CommonModifier {applyNormalAttribute(instance: CommonAttribute): void {super.applyNormalAttribute?.(instance);}public setGroup1(): void {this.borderStyle(BorderStyle.Dotted)this.borderWidth(8)}public setGroup2(): void {this.borderStyle(BorderStyle.Dashed)this.borderWidth(8)}
}@Component
struct MyImage1 {@Link modifier: CommonModifierbuild() {Image($r("app.media.icon_main_apply_normal")).attributeModifier(this.modifier as MyModifier)}
}/*** 设置自定义Modifier给一个组件,该组件对应属性生效。* 自定义Modifier属性值变化,组件对应属性也会变化。自定义Modifier类型为基类,* 构造的对象为子类对象,使用时要通过as进行类型断言为子类。* 一个自定义Modifier设置给两个组件,Modifier属性变化的时候对两个组件同时生效。* 一个Modifier设置了属性A和属性B,再设置属性C和属性D,4个属性同时在组件上生效。* 自定义Modifier不支持@State标注的状态数据的变化感知,见示例2。* 多次通过attributeModifier设置属性时,生效的属性为所有属性的并集,相同属性按照设置顺序生效。*/
@Entry
@Component
struct AttributeModifierPage {@State pageTitle: string = "自定义样式"@State modifier: MyButtonModifier = new MyButtonModifier()@State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10)index: number = 0;aboutToAppear() {try {this.pageTitle = (router.getParams() as RouterParams).title} catch (e) {}}build() {Column() {TitleBar({ pageTitle: $pageTitle })Column() {// Button("Button")//   .attributeModifier(this.modifier)//   .onClick(() => {//     this.modifier.isDark = !this.modifier.isDark//   })Button("Button").attributeModifier(this.modifier)Button($r("app.string.EntryAbility_label")).margin(10).onClick(() => {console.log("Modifier", "onClick")this.index++;if (this.index % 2 === 1) {(this.myModifier as MyModifier).setGroup1()console.log("Modifier", "setGroup1")} else {(this.myModifier as MyModifier).setGroup2()console.log("Modifier", "setGroup2")}})MyImage1({ modifier: this.myModifier })}.width('100%')}.height('100%')}
}

在这里插入图片描述

1.5. AttributeUpdater

1.5.1. 概述

  大量属性频繁更新时,如果使用状态变量,会导致前端状态管理计算量太大,并需要对单个组件进行全量的属性更新。虽然可以通过AttributeModifier的机制按需更新,但是前端还是默认会有一些diff和reset的策略。
  为此引入了AttributeUpdater的能力,它是一个特殊的AttributeModifier,除了继承AttributeModifier的能力,还提供了获取属性对象的能力。通过属性对象可以不经过状态变量,直接更新对应属性。使用AttributeUpdater,开发者可实现自定义的更新策略,进一步提高属性更新的性能。但是由于该能力比较灵活,无法限制“单一数据源”的规则,同时和状态变量更新相同属性时,存在相互覆盖的情况,需要开发者自己保障属性设置的合理性。

1.5.2. 接口定义

export declare class AttributeUpdater<T, C = Initializer<T>> implements AttributeModifier<T> {applyNormalAttribute?(instance: T): void;initializeModifier(instance: T): void;get attribute(): T | undefined;updateConstructorParams: C;
}

  AttributeUpdater实现了AttributeModifier接口,额外提供了initializeModifier,可以对组件的属性进行初始化,并且通过attribute属性方法,获取到属性对象,通过该对象直接更新对应组件的属性。另外也可以直接通过updateConstructorParams更新组件的构造参数。

1.5.3. 行为规格

  (1)开发者可以实现一个AttributeUpdater的类,并通过组件的AttributeModifier设置,首次绑定时会触发initializeModifier方法,进行属性的初始化,后续其它的生命周期和AttributeModifier保持一致。
  (2)组件初始化完成之后,可以通过AttributeUpdater实例的attribute属性方法,获取到属性对象,否则为undefined。
  (3)通过attribute属性对象直接修改属性,会将最新设置的属性记录在当前对象中,并立即触发组件属性的更新。
  (4)如果将AttributeUpdater实例标记为状态变量进行修改,或者通过其它状态变量更新对应组件的属性,会触发applyNormalAttribute的流程,如果开发者没有覆写该逻辑,默认会将属性对象记录的所有属性,批量进行一次更新。
  (5)如果开发者复写applyNormalAttribute的逻辑,并且不调用super的该方法,将会失去获取attribute属性对象的能力,不会调用initializeModifier方法。
  (6)一个AttributeUpdater对象只能同时关联一个组件,否则只会有一个组件生效属性设置。

1.5.4. 通过modifier直接修改属性

  组件初始化完成之后,可以通过AttributeUpdater实例的attribute属性方法,获取到属性对象,通过属性对象直接修改属性,会立即触发组件属性的更新。

import { AttributeUpdater } from '@ohos.arkui.modifier'class MyButtonModifier extends AttributeUpdater<ButtonAttribute> {initializeModifier(instance: ButtonAttribute): void {instance.backgroundColor('#2787D9').width('50%').height(30)}
}@Entry
@Component
struct updaterDemo {modifier: MyButtonModifier = new MyButtonModifier()build() {Row() {Column() {Button("Button").attributeModifier(this.modifier).onClick(() => {this.modifier.attribute?.backgroundColor('#17A98D').width('30%')})}.width('100%')}.height('100%')}
}

1.5.4. 通过modifier更新组件的构造参数

  可以直接通过AttributeUpdater实例的updateConstructorParams方法,更新组件的构造参数。

import { AttributeUpdater } from '@ohos.arkui.modifier'class MyTextModifier extends AttributeUpdater<TextAttribute, TextInterface> {initializeModifier(instance: TextAttribute): void {}
}@Entry
@Component
struct updaterDemo {modifier: MyTextModifier = new MyTextModifier()build() {Row() {Column() {Text("Text").attributeModifier(this.modifier).fontColor(Color.White).fontSize(14).border({ width: 1 }).textAlign(TextAlign.Center).lineHeight(20).width(200).height(50).backgroundColor('#2787D9').onClick(() => {this.modifier.updateConstructorParams('Update');})}.width('100%')}.height('100%')}
}

相关文章:

HarmonyOS 组件样式@Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)

1. HarmonyOS Style 、 Extend、自定义扩展&#xff08;AttributeModifier、AttributeUpdater&#xff09; Styles装饰器&#xff1a;定义组件重用样式   ;Extend装饰器&#xff1a;定义扩展组件样式   自定义扩展&#xff1a;AttributeModifier、AttributeUpdater 1.1. 区…...

信息安全工程师(73)网络安全风险评估过程

一、确定评估目标 此阶段需要明确评估的范围、目标和要求。评估目标通常包括特定的网络系统、信息系统或网络基础设施&#xff0c;评估范围可能涉及整个组织或仅特定部门。明确评估要求有助于确保评估过程的针对性和有效性。 二、收集信息 在评估开始之前&#xff0c;需要对目标…...

在MacOS玩RPG游戏 - RPGViewerPlus

背景知识 由于我一直使用Mac电脑&#xff0c;所以一直对Mac如何玩RPGMV/RPGMZ游戏的方式有进一步的想法。 网上能给出的方案都是自行启动一个HTTP服务进行&#xff0c;进行服务加载。这个方法有效&#xff0c;但兼容性较差。涉及到自定义功能模块的游戏&#xff0c;都会有报错…...

2024.10.27 直接插入排序 非递归后序遍历(复杂版)

直接插入排序 思路&#xff1a;用temp变量存放需要插入前面有序序列的变量&#xff0c;然后用里面的那个for循环寻找到需要插入的位置。 额外注意的点&#xff1a;arr[j1]temp;这个是因为内置循环每次出来之后所指向的位置是我们要插入的位置的前一个&#xff08;-1或者插入…...

Ubuntu 22.04系统启动时自动运行ROS2节点

在 Ubuntu 启动时自动运行 ROS2 节点的方法 环境&#xff1a;Ubuntu 系统&#xff0c;ROS2 Humble&#xff0c;使用系统自带的 启动应用程序 目标&#xff1a;在系统启动时自动运行指定的 ROS2 节点 效果展示 系统启动后&#xff0c;自动运行小乌龟节点和键盘控制节点。 实践…...

张三进阶之路 | 基于Spring AOP的Log收集

前情提要 &#x1f4cc; 张三对于公司的日志处理系统不满意&#xff0c;认为其性能不佳且功能有限。为了展示自己的能力和技术实力&#xff0c;他决定利用Spring AOP&#xff08;面向切面编程&#xff09;开发一个更高效的日志处理系统&#xff0c;并将其存储在Redis中。 首先…...

ubuntu新装ubuntu,重启黑屏

现象&#xff1a;双系统电脑向移动硬盘安装Ubuntu系统后&#xff0c;重启黑屏并显示Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists possible device or file completions. 又拔下无法启…...

太极安全监控系统0.8

完善后的代码及功能详细介绍 完善后的代码 python import os import sys import subprocess import re import datetime import threading import tkinter as tk from tkinter import messagebox, simpledialog, ttk import scapy.all as scapy import whois import numpy as …...

E-清楚姐姐的布告规划【01背包】

就当一个01背包写就行&#xff0c;只不过需要保证不交叉&#xff0c;w[i]覆盖i点&#xff0c;用一个if来判断即可 #include<bits/stdc.h> #define int long long using namespace std; int w[5005]; int f[5005]; int t,n,m; signed main() {cin>>t;while(t--){…...

哪款宠物空气净化器噪音低?希喂、美的、安德迈测评分享

今年双11&#xff0c;宠物空气净化器到底应该如何选&#xff1f;在所有的家电品类里&#xff0c;宠物空气净化器算是比较特殊的那个&#xff0c;产品迭代太快&#xff0c;我们把今年双11在售的各大主流品牌的宠物空气净化器统一汇总整理&#xff0c;发现基本一多半都是24年下半…...

2024年10月23日第一部分

1.马小民要不要承担责任 2.主动 我就是那种平常沉默寡言孤僻内向自卑又宅又无趣&#xff0c;感觉不管在哪里都是比较边缘不合群的人。6月份遇到一个女生&#xff0c;还是人家主动加的我&#xff0c;断断续续聊了一个月就没下文了&#xff0c;可能我没谈过恋爱吧&#xff0c;快…...

医院信息化与智能化系统(9)

医院信息化与智能化系统(9) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…...

逻辑回归与神经网络

从逻辑回归开始学习神经网络 神经网络直观上解释&#xff0c;就是由许多相互连接的圆圈组成的网络模型&#xff1a; 而逻辑回归可以看作是这个网络中的一个圆圈&#xff1a; 圆圈被称为神经元&#xff0c;整个网络被称为神经网络。 本节的任务是我们究竟如何理解具体的一个神…...

隨筆 20241024 Kafka 数据格式解析:批次头与数据体

Kafka作为分布式流处理平台&#xff0c;以其高吞吐量、可扩展性和强大的数据传输能力&#xff0c;成为了现代大数据和实时处理的核心组件之一。在Kafka中&#xff0c;数据的存储和传输遵循一种高效的结构化格式&#xff0c;主要由 批次头&#xff08;Batch Header&#xff09;和…...

【WiFi7】 支持wifi7的手机

数据来源 Smartphones with WiFi 7 - list of all latest phones 2024 Motorola Moto X50 Ultra 6.7" 1220x2712 Snapdragon 8s Gen 3 16GB RAM 1024 GB 4500 mAh a/b/g/n/ac/6e/7 Sony Xperia 1 VI 6.5" 1080x2340 Snapdragon 8 Gen 3 12GB RAM 512 G…...

LabVIEW偏振调制激光高精度测距系统

在航空航天、汽车制造、桥梁建筑等先进制造领域&#xff0c;许多大型零件的装配精度要求越来越高&#xff0c;传统的测距方法在面对大尺寸、高精度测量时&#xff0c;难以满足工业应用的要求。绝对测距技术在大尺度测量上往往会因受环境影响大、测距精度低而无法满足需求。基于…...

Python Pandas 数据分析的得力工具:简介

Python Pandas 数据分析的得力工具&#xff1a;简介 在如今的大数据与人工智能时代&#xff0c;数据的收集和处理能力变得至关重要。无论是在科学研究、商业分析还是人工智能领域&#xff0c;如何快速、高效地分析和处理数据都是不可忽视的课题。在众多的数据分析工具中&#…...

Llama 3.2-Vision 多模态大模型本地运行教程

Ollama 刚刚放出了对 Llama 3.2-Vision 的支持&#xff01;这让人想起了新游戏发布带来的兴奋感——我期待着探索 Ollama 对 Llama 3.2-Vision 的支持。该模型不仅在自然语言理解方面表现出色&#xff0c;而且可以无缝处理图像&#xff0c;最好的部分是什么&#xff1f;它是免费…...

iOS 18.2 可让欧盟用户删除App Store、Safari、信息、相机和照片应用

升级到 iOS 18.2 之后&#xff0c;欧盟的 iPhone 用户可以完全删除一些核心应用程序&#xff0c;包括 App Store、Safari、信息、相机和 Photos 。苹果在 8 月份表示&#xff0c;计划对其在欧盟的数字市场法案合规性进行更多修改&#xff0c;其中一项更新包括欧盟用户删除系统应…...

照片怎么转换成pdf?盘点6种图片转pdf格式有效方法,直击要点!

照片怎么转换成pdf&#xff1f;在日常生活和工作中&#xff0c;我们难免会碰到需要将照片以pdf格式保存的情况&#xff0c;以便于更好的整理、分享或打印。虽然jpg格式的图片因其体积小而方便分享&#xff0c;但有时我们也希望将这些图片转换成pdf格式&#xff0c;以便于创建专…...

【Qt】Windows下Qt连接DM数据库

环境信息&#xff1a;W11 Qt5.12及以上 dm8 QODBC达梦 Windows环境创建ODBC数据源 使用 ODBC 方法访问 DM 数据库服务器之前&#xff0c;必须先配置 ODBC 数据源 在控制面板Windows工具中显示ODBC数据源管理器 ODBC数据源管理器标签 用户 DSN&#xff1a;添加、删除或配置本…...

2024 你还不会微前端吗 (上) — 从巨石应用到微应用

前言 微前端系列分为 上/下 两篇&#xff0c;本文为 上篇 主要还是了解微前端的由来、概念、作用等&#xff0c;以及基于已有的微前端框架进行实践&#xff0c;并了解微前端的核心功能所在&#xff0c;而在 下篇 中主要就是通过自定义实现一个微前端框架来加深理解。 微前端是…...

WPF+MVVM案例实战(三)- 动态数字卡片效果实现

1、创建项目 打开 VS2022 &#xff0c;新建项目 Wpf_Examples&#xff0c;创建各层级文件夹&#xff0c;安装 CommunityToolkit.Mvvm 和 Microsoft.Extensions.DependencyInjectio NuGet包,完成MVVM框架搭建。搭建完成后项目层次如下图所示&#xff1a; 这里如何实现 MVVM 框…...

#网络安全#渗透测试# 渗透测试应用

网络安全渗透测试是一种重要的安全评估方法&#xff0c;用于发现和评估网络系统中的安全漏洞。在进行渗透测试时&#xff0c;需要注意以下几个关键点&#xff1a; 法律和道德考量 获得授权&#xff1a;在进行渗透测试之前&#xff0c;必须获得目标系统的正式授权。未经授权的测…...

MicroServer Gen8再玩 OCP万兆光口+IT直通之二

这个接上一篇&#xff0c;来个简单测试。 一、测试环境 PC端&#xff1a;Win10&#xff0c;网卡&#xff1a;万兆光纤&#xff08;做都做了&#xff0c;都给接上&#xff09;&#xff0c;硬盘使用N年的三星SSD 840 交换机&#xff1a;磊科GS10&#xff0c;带两个万兆口 Gen…...

【JAVA面试题】Java和C++主要区别有哪些?各有哪些优缺点?

文章目录 强烈推荐前言区别&#xff1a;1. 语法和编程风格2.内存管理3.平台独立性4.性能5.指针和引用6.多线程7.使用场景 Java 的优缺点优点&#xff1a;缺点&#xff1a; C 的优缺点优点&#xff1a;缺点&#xff1a; 总结专栏集锦 强烈推荐 前些天发现了一个巨牛的人工智能学…...

保姆级教程!!教你通过【Pycharm远程】连接服务器运行项目代码

小罗碎碎念 这篇文章主要解决一个问题——我有服务器&#xff0c;但是不知道怎么拿来写代码&#xff0c;跑深度学习项目。确实&#xff0c;玩深度学习的成本比较高&#xff0c;无论是前期的学习成本&#xff0c;还是你需要具备的硬件成本&#xff0c;都是拦路虎。小罗没有办法…...

JMeter详细介绍和相关概念

JMeter是一款开源的、强大的、用于进行性能测试和功能测试的Java应用程序。 本篇承接上一篇 JMeter快速入门示例 &#xff0c; 对该篇中出现的相关概念进行详细介绍。 JMeter测试计划 测试计划名称和注释&#xff1a;整个测试脚本保存的名称&#xff0c;以及对该测试计划的注…...

如何使用Git

简介 一.git简介 Git是一个分布式版本控制工具,通常用来对软件开发过程中的源代码文件进行管理.通过Git仓库来存储和管理这些文件,Git仓库分两种: 本地仓库:开发人员自己电脑上的Git仓库远程仓库:远程服务器上的Git仓库 commit:提交,将本地文件和版本信息保存到本地仓库 p…...

Redis 哨兵 问题

前言 相关系列 《Redis & 目录》&#xff08;持续更新&#xff09;《Redis & 哨兵 & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Redis & 哨兵 & 总结》&#xff08;学习总结/最新最准/持续更新&#xff09;《Redis & 哨兵…...

word wordpress/权威发布

数据库的入侵防范上一篇我们分析了对弱口令或默认用户名/口令的破解&#xff0c;这一篇我们来分析第二种方法手段&#xff0c;它就是特权的提升。特权提升&#xff1a;  有几种内部人员攻击的方法可以导致恶意的用户占有超过其应该具有的系统特权。而且外部的攻击者有时通过破…...

poi player wordpress/怎样打小广告最有效

9月22日消息&#xff0c;据国外媒体报道&#xff0c;日前微软开始通过发布补丁清理关于Windows 10的免费升级应用。 此前微软一直通过弹窗提醒要求Windows 7以及Windows 8用户免费升级至最新操作系统Windows 10。随着7月29日免费升级的到期&#xff0c;拖了近两个月后&#xff…...

可以做网站的域名后缀/电商网站建设开发

所有的php文件放到同一个目录下 ../Trie/ ├── CharMap.php ├── Map.php ├── StdMap.php ├── Trie.php ├── TrieNode.php ├── index.php ├── test.php~ └── words.txt * TrieNode.php <?php /*** Class TrieNode* 字典树是利用字符串的公…...

百度站长工具网站验证/自己怎样推广呢

软考体型分值分配...

做设计的地图网站/网站怎样优化文章关键词

ZMQ (以下 ZeroMQ 简称 ZMQ)是一个简单好用的传输层&#xff0c;像框架一样的一个 socket library&#xff0c;他使得 Socket 编程更加简单、简洁和性能更高。是一个消息处理队列库&#xff0c;可在多个线程、内核和主机盒之间弹性伸缩。ZMQ 的明确目标是“成为标准网络协议栈的…...

南宁建设网站制作/关键词挖掘

设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行&#xff0c;每行分别先给出多项式非零项的个数&#xff0c;再以指数递降方式输入一个多项式非零项系数和指数&#xff08;绝对值均为不超过1000的整数&#xff09;。数字间以空格分隔。 输出格式: 输出分2行&a…...