OpenHarmony ArkUI 实战开发—ETS 装饰器解读

news2024/11/24 16:01:49

前言

最近利用空闲时间在学习华为方舟开发框架(简称:ArkUI)的ets开发,发现在ets语言中装饰器的有着非常重要的作用,在写每一个自定义组件时都需要用到它,看到装饰器这个字眼,想起之前学过的设计模式里的装饰器模式(允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装),ets中的装饰器的作用就是类似这样的。华为官网中对装饰器的介绍也比较详细,参照官网的讲解,自己对其进行了汇总,方便后续理解与查阅。

装饰器

1、@Component

装饰内容为struct,@Component装饰的struct表示该结构体具有组件化能力,能够成为一个独立的组件,这种组件就是自定义组件

  • 所有的UI都是由组件构成,组件的数据结构为struct
  • 自定义组件可以调用其他自定义组件和内置组件
  • 自定义组件内部必须实现build方法来描述UI结构
  • 禁止自定义构造函数

@Component

struct MyComponent {

    build() {

        Column() {

            Text('my component')

                .fontColor(Color.Red)

        }.alignItems(HorizontalAlign.Center)

    }

}



@Component

struct ParentComponent {

    build() {

        Column() {

            MyComponent()

            Text('we use component')

                .fontSize(20)

        }

    }

}

2、@Entry

装饰内容为struct,用@Entry装饰的自定义组件用作页面的默认入口组件,加载页面时,将首先创建并呈现@Entry装饰的自定义组件。

  • 在单个源文件中,最多可以使用@Entry装饰一个自定义组件。即一个页面有且仅有一个@Entry
// 只会渲染加载出 MyComponent 组件,显示hello world

@Entry

@Component

struct MyComponent {

    build() {

        Column() {

            Text('hello world')

                .fontColor(Color.Red)

        }

    }

}



@Component

struct HideComponent {

    build() {

        Column() {

            Text('goodbye')

                .fontColor(Color.Blue)

        }

    }

}

3、@Preview

装饰内容为struct,用@Preview装饰的自定义组件可以在DevEco Studio的预览器上进行预览。

  • 单组件预览,仅预览被@Preview装饰的自定义组件

  • 在单个源文件中,最多可以使用10个**@Preview**装饰一个自定义组件

多个组件预览

4、@Builder

装饰内容为方法, @Builder装饰的方法用于定义组件的声明式UI描述,在一个自定义组件内快速生成多个布局内容。


@Entry

@Component

struct CompA {

  @State message: string = 'Builder演示'

  @State isA: boolean = false

  @State isB: boolean = false

  @Builder myBuilder(str: string, state: boolean, click: () => void) {

    Row() {

      Text(str + ":" + state)

        .fontSize(24).margin({ right: 20 })



      Button('开关').fontSize(24).onClick(() => {

        click()

      })

    }.margin({bottom: 5})

  }

  @Builder myCheckBox() {

    Row() {

      Checkbox({name: 'checkbox1',  group: 'checkboxGroup'})

        .select(true)

        .selectedColor(0xed6f21)

        .onChange((value: boolean) => {

          console.info('Checkbox1 change is'+ value)

        })

      Checkbox({name: 'checkbox2',  group: 'checkboxGroup'})

        .select(false)

        .selectedColor(0x39a2db)

        .onChange((value: boolean) => {

          console.info('Checkbox2 change is'+ value)

        })

    }

  }



  build() {

    Row() {

      Column() {

        Text(this.message)

          .fontSize(24)

          .fontWeight(FontWeight.Bold).margin({ bottom: 20 })



        this.myBuilder('A', this.isA, () => {

          this.isA = !this.isA

        })



        this.myBuilder('B', this.isB, () => {

          this.isB = !this.isB

        })

        this.myCheckBox()

      }

      .width('100%')

    }

    .height('100%')

  }

}

5、@Extend

装饰内容为方法,@Extend装饰器将新的属性函数添加到内置组件上,如Text、Column、Button等。

  • 通过@Extend装饰器可以快速定义并复用组件的自定义样式,即对内置组件进行封装,增强复用性

  • @Extend装饰器不能用在自定义组件struct定义框内。


  //给内置组件Text添加属性函数font 用于同时设置 字号,字体颜色,粗细

  @Extend(Text) function font (size: number, color: ResourceColor, weight: FontWeight) {

    .fontSize(size)

    .fontColor(color)

    .fontWeight(weight)

  }

  @Component

  @Entry

  struct Index {

    @State message: string = 'Hello World'

    build() {

      Row() {

        Column() {

          // 后面设置的样式会覆盖前面的,这里的最终字号为50

          Text(this.message)

            // 调用新增的属性函数 font

            .font(30, Color.Blue, FontWeight.Bold)

            .fontSize(50)

        }

        .width('100%')

      }

      .height('100%')

    }

  }

6、@CustomDialog

@CustomDialog装饰器用于装饰自定义弹窗

@CustomDialog

struct CustomDialogExample {

  controller: CustomDialogController

  cancel: () => void

  confirm: () => void



  build() {

    Column() {

      Text('自定义弹框标题').fontSize(20).margin({ top: 10, bottom: 10 })

      Text('这是自定义弹框内容,确定选择吗?').fontSize(16).margin({ bottom: 10 })

      Flex({ justifyContent: FlexAlign.SpaceAround }) {

        Button('取消')

          .onClick(() => {

            this.controller.close()

            this.cancel()

          }).backgroundColor(0xffffff).fontColor(Color.Black)

        Button('确定')

          .onClick(() => {

            this.controller.close()

            this.confirm()

          }).backgroundColor(0xffffff).fontColor(Color.Red)

      }.margin({ bottom: 10 })

    }

  }

}



@Entry

@Component

struct CustomDialogUser {

  @State textValue: string = ''

  dialogController: CustomDialogController = new CustomDialogController({

    builder: CustomDialogExample({ cancel: this.onCancel.bind(this), confirm: this.onAccept.bind(this)}),

    cancel: this.existApp,

    autoCancel: true

  })



  onCancel() {

    this.textValue = '点击了取消'

  }

  onAccept() {

    this.textValue = '点击了确定'

  }

  existApp() {

    this.textValue = '点击了空白区域'

  }



  build() {

    Column() {

      Text(this.textValue)

        .fontSize(30).margin({bottom: 20})

      Button('打开自定义弹框')

        .onClick(() => {

          this.dialogController.open()

        }).fontSize(30)

    }.width('100%').margin({ top: 20 })

  }

}

7、@BuilderParam

这是API8 提供的一个新的装饰器,@BuilderParam装饰器用于修饰自定义组件内函数类型的属性(例如:@BuilderParam content: () => any;)

  • @BuilderParam 是一个属性装饰器

  • 初始化自定义组件时被@BuilderParam修饰的属性必须赋值。

  • 可以在局部样式相同,局部样式不同时复用

  • 类似于slot插槽一样,能在自定义组件中插入对应的UI结构

  • 如果既有参数初始化组件和尾随闭包初始化组件,尾随闭包初始化组件优先级更高

参数初始化组件

通过参数初始化组件时,将@Builder装饰的方法赋值给@BuilderParam修饰的属性,并在自定义组件内调用content属性值。对@BuilderParam修饰的属性进行赋值时不带参数(如:content: this.specificParam),则此属性的类型需定义成无返回值的函数(如:@BuilderParam content: () => void)。若带参数(如:callContent: this.specificParam1(“111”)),则此属性的类型需定义成any(如:@BuilderParam callContent: any;)。

@Component

struct CustomContainer {

  header: string = "";

  @BuilderParam noParam: () => void;

  @BuilderParam withParam: any;

  footer: string = "";

  build() {

    Column() {

      Text(this.header)

        .fontSize(50)

      this.noParam()

      this.withParam()

      Text(this.footer)

        .fontSize(50)

    }

  }

}

@Entry

@Component

struct CustomContainerUser {

  @Builder specificNoParam() {

    Column() {

      Text("noParam").fontSize(50)

    }

  }

  @Builder SpecificWithParam(label: string) {

    Column() {

      Text(label).fontSize(50)

    }

  }



  build() {

    Column() {

      CustomContainer({

        header: "Header",

        noParam: this.specificNoParam,

        withParam: this.SpecificWithParam("WithParam"),

        footer: "Footer",

      })

    }

  }

}

参数初始化组件

在自定义组件中使用@BuilderParam修饰的属性接收尾随闭包(在初始化自定义组件时,组件名称紧跟一个大括号“{}”形成尾随闭包场景(CustomComponent(){})。开发者可把尾随闭包看做一个容器,向其填充内容,如在闭包内增加组件({Column(){Text(“content”)}),闭包内语法规范与build一致。此场景下自定义组件内有且仅有一个使用@BuilderParam修饰的属性。注意:一个组件内只允许有一个@BuilderParam装饰器

@Component

struct CustomContainer {

  header: string = "";

  @BuilderParam closer: () => void;

  build() {

    Column() {

      Text(this.header)

        .fontSize(50)

      this.closer()

    }

  }

}

@Builder function specificParam(label1: string, label2: string) {

  Column() {

    Text(label1)

      .fontSize(50)

    Text(label2)

      .fontSize(50)

  }

}

@Builder function specificNoParam() {

  Column() {

    Text('88888')

      .fontSize(50)

    Text('999999')

      .fontSize(50)

  }

}

@Entry

@Component

struct CustomContainerUser {

  @State text: string = "header"

  build() {

    Column() {

      CustomContainer({

        header: this.text,

        closer: specificNoParam

      })

      {

        Column(){

          specificParam("111", "22")

        }.onClick(()=>{

          this.text = "changeHeader"

        })

      }

    }

  }

}

8、@Styles

这是API8 提供的一个新的装饰器,我们知道@Extend装饰器不能写在组件内,但@Styles却能够定义在组件内。

@Styles和@Extend一样,也是提供方法将新的属性函数添加到内置组件。

有几个注意的点:

  • @Styles装饰的方法不能带参数

  • @Styles装饰的方法可以有多个

  • 后面执行的属性函数优先级最高

  • 当前@Styles仅支持通用属性

  • @Styles可以定义在组件内或组件外,在组件外定义时需带上function关键字,组件内定义时不需要

// 定义在组件外的 需要带function

@Styles function globalFancy() {

  .backgroundColor(Color.Red)

}



@Entry

@Component

struct FancyUse {

   // 定义在组件内的 不需要带function

  @Styles componentFancy() {

    .backgroundColor(Color.Blue)

  }

  build() {

    Column({ space: 10 }) {

      Text("Fancy")

        // 调用属性新增的函数

        .globalFancy()

        .width(100)

        .height(100)

        .fontSize(30)

      Text("Fancy")

        // 调用属性新增的函数

        .componentFancy()

        .width(100)

        .height(100)

        .fontSize(30)

    }

  }

}

9、@State

@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新

  • 支持多种类型:允许class、number、boolean、string强类型的按值和按引用类型。允许这些强类型构成的数组,即Array、Array、Array、Array。不允许object和any。

  • 支持多实例:组件不同实例的内部状态数据独立。

  • 内部私有:标记为@State的属性是私有变量,只能在组件内访问。

  • 需要本地初始化:必须为所有@State变量分配初始值,将变量保持未初始化可能导致框架行为未定义。

  • 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态属性的初始值。

简单类型的状态属性示例


@Entry

@Component

struct StateDemo {

  @State count: number =0

  private toggleClick() {

    this.count += 1

  }

  build() {

    Column() {

      Button() {

        Text(`click times: ${this.count}`)

          .fontSize(20).padding(10)

      }.onClick(this.toggleClick.bind(this))

    }.margin(30)

  }

}

复杂类型的状态变量示例


// 自定义Model类

class Model {

  value: string

  constructor(value: string) {

    this.value = value

  }

}



@Entry

@Component

struct EntryComponent {

  build() {

    Column() {

      // 创建MyComponent实例时通过变量名给组件内的变量进行初始化 2个组件实例的内部状态互不影响

      MyComponent({count: 1, increaseBy: 2})

      MyComponent({title: {value: 'Hello, World 2'}, count: 7})

    }.margin(20)

  }

}



@Component

struct MyComponent {

  @State title: Model = {value: 'Hello World'}

  @State count: number = 0

  private toggle: string = 'Hello World'

  private increaseBy: number = 1



  build() {

    Column() {

      Text(`${this.title.value}`).fontSize(30)

      Button() {

        Text(`点击修改title`).fontSize(20).fontColor(Color.White).padding({left: 10, right: 10})

      }.onClick(() => {

        this.title.value = (this.toggle == this.title.value) ? 'Hello World' : 'Hello UI'

      }).margin({top: 10, bottom: 10})



      Button() {

        Text(`添加增加 count=${this.count}`).fontSize(20).fontColor(Color.White).padding({left: 10, right: 10})

      }.onClick(() => {

        this.count += this.increaseBy

      })

    }.margin(16)

  }

}

10、@Prop

@Prop用于修饰基本数据类型,修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,更新当前组件的UI。

@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。类似于vue中的父子组件传值prop, 只是vue中的prop传递的属性值在子组件中不允许修改。

@Prop状态数据具有以下特征:

  • 支持简单类型:仅支持number、string、boolean简单类型;

  • 私有:仅在组件内访问;

  • 支持多个实例:一个组件中可以定义多个标有@Prop的属性;

  • 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。


@Entry

@Component

struct ParentComponent {

  @State countDownStartValue: number = 10 // 10 Nuggets default start value in a Game

  build() {

    Column() {

      Text(`这是子组件中显示的信息 count: ${this.countDownStartValue}`)

      Button() {

        Text('数字+1')

      }.onClick(() => {

        this.countDownStartValue += 1

      })

      Button() {

        Text('数字-1')

      }.onClick(() => {

        this.countDownStartValue -= 1

      })

      // 创建子组件时,必须在构造函数参数中提供其@Prop变量的初始值,同时初始化常规变量CostOfOneAttump(非Prop)

      CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2})

    }

  }

}



@Component

struct CountDownComponent {

  @Prop count: number

  private costOfOneAttempt: number



  build() {

    Column() {

      if (this.count > 0) {

        Text(`这是子组件中显示的信息 count: ${this.count}`)

      } else {

        Text('Game over!')

      }



      Button() {

        Text('Try again')

      }.onClick(() => {

        this.count -= this.costOfOneAttempt

      })

    }

  }

}

11、@Link

@Link用于修饰基本数据类型,类,数组,父子组件之间的双向数据绑定,父组件的内部状态数据作为数据源,任何一方所做的修改都会反映给另一方。

@Link装饰的变量可以和父组件的@State变量建立双向数据绑定:

  • 支持多种类型:@Link变量的值与@State变量的类型相同,即class、number、string、boolean或这些类型的数组;

  • 私有:仅在组件内访问;

  • 单个数据源:初始化@Link变量的父组件的变量必须是@State变量;

  • 双向通信:子组件对@Link变量的更改将同步修改父组件的@State变量;

  • 创建自定义组件时需要将变量的引用传递给@Link变量,在创建组件的新实例时,必须使用命名参数初始化所有@Link变量。@Link变量可以使用@State变量或@Link变量的引用进行初始化,@State变量可以通过’$'操作符创建引用。

  • @Link变量不能在组件内部进行初始化。

  @Entry

  @Component

  struct Player {

    @State isPlaying: boolean = false

    build() {

      Column() {

        PlayButton({buttonPlaying: $isPlaying})

        Text(`Player is ${this.isPlaying? '':'not'} playing`)

        Button() {

          Text(this.isPlaying? 'parent play' : 'parent pause')

        }.onClick(() => {

          this.isPlaying = !this.isPlaying

        })

      }

    }

  }

  @Component

  struct PlayButton {

    @Link buttonPlaying: boolean

    build() {

      Column() {

        Button() {

          Text(this.buttonPlaying? 'child play' : 'child pause')

        }.onClick(() => {

          this.buttonPlaying = !this.buttonPlaying

        })

      }

    }

  }

12、@Observed 和 @ObjectLink

由于 @State无法监听到类嵌套类的属性,@ObjectLink可以监听到类嵌套@Observed修饰的类的属性

@Observed

用于修饰类,表示该类中的数据变更被UI页面管理。

@ObjectLink

  • 用于修饰变量,并且不可以初始化

  • 不能用在@entry修饰的组件中

  • 装饰的变量类型必须为类(class type),并且该类要被@Observed装饰器所装饰。

  • @ObjectLink装饰的变量是不可变的(immutable)。

- 属性的改动是被允许的,当改动发生时,如果同一个对象被多个@ObjectLink变量所引用,那么所有拥有这些变量的自定义组件都会被通知去重新渲染。

  • @ObjectLink装饰的变量不可设置默认值。

- 必须让父组件中有一个由@State、@Link、@StorageLink、@Provide或@Consume所装饰变量参与的TS表达式进行初始化。

  • @ObjectLink装饰的变量是私有变量,只能在组件内访问。

@Observed class ClassA {

  public numA: number

  public classB: ClassB



  constructor(cValue: ClassB, aValue: number = 0) {

    this.classB = cValue;

    this.numA = aValue;

  }

}



@Observed

class ClassB {

  public numB: number



  constructor(aValue: number = 0) {

    this.numB = aValue;

  }

}



@Entry

@Component

struct Observer_page {

  @State classA: ClassA = new ClassA(new ClassB());



  build() {

    Column() {



      Text('父组件').fontSize(24).margin({ top: 20 })

      Text(`ClassA的numA值:${this.classA.numA}`)

        .fontSize(20)

        .fontWeight(FontWeight.Bold)

        .onClick(() => {

          this.classA.numA += 1

        })



      Text('父组件不会刷新').fontSize(16).margin({ top: 20 })  .fontColor('#FF0000')

      Text(`ClassB的numB值:${this.classA.classB.numB}`)

        .fontSize(20)

        .fontWeight(FontWeight.Bold)

        .onClick(() => {

          // 修改值,只会导致 @ObjectLink 装饰的变量所在的组件被刷新,当前组件不会刷新

          this.classA.classB.numB += 1

        })



      Text('子组件').fontSize(24).margin({ top: 20 })



      Observer_page2({ classB: this.classA.classB })

    }

    .width('100%')

    .height('100%')

  }

}



@Component

struct Observer_page2 {

  @ObjectLink  classB: ClassB



  build() {

    Column() {

      Text('子组件被刷新').fontSize(16).margin({ top: 20 })  .fontColor('#FF0000')



      Text(`ClassB的numB值:${this.classB.numB}`)

        .fontSize(20)

        .fontWeight(FontWeight.Bold)

        .onClick(() => {

          // 修改值,只会导致 @ObjectLink 装饰的变量所在的组件被刷新

          this.classB.numB += 1

        })



    }.width('100%')

    .height('100%')

  }

}

13、@Consume和@Provide

都用于修饰基本数据类型,类,数组,Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。Consume在感知到Provide数据的更新后,会触发当前view的重新渲染。

表1 @Provide

装饰器参数: 是一个string类型的常量,用于给装饰的变量起别名。如果规定别名,则提供对应别名的数据更新。如果没有,则使用变量名作为别名。推荐使用@Provide(“alias”)这种形式。
同步机制|:@Provide的变量类似@state,可以修改对应变量进行页面重新渲染。也可以修改@Consume装饰的变量,反向修改@State变量。
初始值:必须制定初始值。
页面重渲染场景: 触发页面渲染的修改:- 基础类型(boolean,string,number)变量的改变;- @Observed class类型变量及其属性的修改;- 添加,删除,更新数组中的元素。

表2 @Consume

初始值 : 不可设置默认值。

其他属性说明与Provide一致。


@Entry

@Component

struct CompA {

  @Provide("reviewVote") reviewVotes : number = 0;



  build() {

    Column() {

      CompB()

      Button() {

        Text(`${this.reviewVotes}`)

          .fontSize(30)

      }.width(100)

      .onClick(() => {

        this.reviewVotes += 1;

      })

    }

  }

}



@Component

struct CompB {

  build() {

    Column() {

      CompC()

    }

  }

}



@Component

struct CompC {

  @Consume("reviewVote") reviewVotes : number;

  build() {

    Column() {

      Button() {

        Text(`${this.reviewVotes}`)

          .fontSize(30)

      }.width(100).margin(20)

      .onClick(() => {

        this.reviewVotes += 1;

      })

    }

  }

}

14、@StorageProp和@StorageLink

如何将组件变量与AppStorage同步,主要提供@StorageLink和@StorageProp装饰器

@StorageLink装饰器

组件通过使用@StorageLink(key)装饰的状态变量,与AppStorage建立双向数据绑定,key为AppStorage中的属性键值。当创建包含@StorageLink的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。在UI组件中对@StorageLink的状态变量所做的更改将同步到AppStorage,并从AppStorage同步到任何其他绑定实例中。类似于@Link装饰器。

@StorageProp装饰器

组件通过使用@StorageProp(key)装饰的状态变量,将与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StoageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中的属性值的更改会导致绑定的UI组件进行状态更新。类似于@Prop装饰器。


let varA = AppStorage.Link('varA')

let envLang = AppStorage.Prop('languageCode')



@Entry

@Component

struct ComponentA {

  @StorageLink('varA') varA: number = 2

  @StorageProp('languageCode') lang: string = 'en'

  private label: string = 'count'



  aboutToAppear() {

    this.label = (this.lang === 'zh') ? '数' : 'Count'

  }



  build() {

    Row({ space: 20 }) {



      Button(`${this.label}: ${this.varA}`)

        .onClick(() => {

          AppStorage.Set<number>('varA', AppStorage.Get<number>('varA') + 1)

        })

      Button(`lang: ${this.lang}`)

        .onClick(() => {

          if (this.lang === 'zh') {

            AppStorage.Set<string>('languageCode', 'en')

          } else {

            AppStorage.Set<string>('languageCode', 'zh')

          }

          this.label = (this.lang === 'zh') ? '数' : 'Count'

        })

    }

  }

}

16、@Watch

用于修饰 被@State, @Prop, @Link, @ObjectLink,@Provide, @Consume, @StorageProp, @StorageLink中任意一个装饰的变量,@Watch用于监听状态变量的变化,应用可以注册回调方法。

@Watch用于监听状态变量的变化,语法结构为:

@State @Watch("onChanged") count : number = 0

如上给状态变量增加一个@Watch装饰器,通过@Watch注册一个回调方法onChanged, 当状态变量count被改变时, 触发onChanged回调。


@Entry

@Component

struct CompWatch {

  @State @Watch("onBasketUpdated") shopBasket : Array<number> = [ 7, 12, 47, 3 ];

  @State totalPurchase : number = 0;



  updateTotal() : number {

    let sum = 0;

    this.shopBasket.forEach((i) => { sum += i; });

    // 计算新的购物篮总价值,如果超过100RMB,则适用折扣

    this.totalPurchase = (sum < 100) ? sum : 0.9 * sum;

    return this.totalPurchase;

  }



  // @Watch cb

  onBasketUpdated(propName: string) : void {

    this.updateTotal();

  }



  build() {

    Column() {

      Button("add to basket").onClick(() => { this.shopBasket.push(Math.round(100 * Math.random())) })

      Text(`${this.totalPurchase}`)

        .fontSize(30)

    }

  }

}

总结

ets中装饰器的作用非常重要,需要在项目中多实践才能更好的熟练应用,理解其中的原理和作用。

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://gitee.com/MNxiaona/733GH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1626483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

偏见将如何扼杀你的人工智能/机器学习策略以及如何应对

任何类型的模型中的“偏差”都描述了模型对提示或输入数据的响应不准确的情况&#xff0c;因为它没有接受足够的高质量、多样化的数据训练来提供准确的响应。一个例子是 苹果的面部识别手机解锁功能对于肤色较深的人来说失败率明显高于肤色较浅的人。 该模型没有接受过足够多的…

分享8款安全监控/日志记录工具

安全监控工具的作用是实时监控和分析系统的安全状态&#xff0c;而日志记录工具的作用主要是记录系统的运行过程及异常信息。 关于安全监控工具&#xff0c;它通过对计算机系统、网络、应用程序和数据进行实时监控和分析&#xff0c;帮助发现和防止安全威胁和攻击。这种监控不…

2024全网最火的接口自动化测试,一看就会

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

2024信息系统、信号处理与通信技术国际会议(ICISPCT2024)

2024信息系统、信号处理与通信技术国际会议&#xff08;ICISPCT2024) 会议简介 2024国际信息系统、信号处理与通信技术大会&#xff08;ICISPCT2024&#xff09;将在青岛隆重开幕。本次会议旨在汇聚全球信息系统、信号处理和通信技术领域的专家学者&#xff0c;共同探索行业…

全网最全的接口测试教程

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 其实我觉得接口测试很简单&#xff0c;比一般的功能测试还简单&…

组合模式【结构型模式C++】

1.概述 组合模式又叫部分整体模式属于结构型模式&#xff0c;是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次。 2.结构 组件&#xff08;Component&#xff09;:定义了组合中所有对象的通用接口&#xff0c…

信号的调幅(AM)、调频(FM)与调相(PM)对频谱结构的影响(找找复刻电赛D题的伙伴)

0.目录 &#xff08;1&#xff09;调制与解调的基本概念 &#xff08;2&#xff09;调幅对频谱结构的影响 &#xff08;3&#xff09;调频信号幅值变化对频谱结构的影响 &#xff08;4&#xff09;调频信号频率变化对频谱结构的影响 &#xff08;5&#xff09;调幅调频信号…

Java Web 网页设计(3)

3.servlet JavaWeb——Servlet&#xff08;全网最详细教程包括Servlet源码分析&#xff09;-CSDN博客 servlet java不支持 只有Tomcat支持 使用时添加一下 servlet中最常用的两个&#xff08;固定&#xff09;方法&#xff1a; 下面我们创建一个servlet类 package com.oracle…

PE文件(三)节表

节表引入 PE文件的结构是由DOS头PE标记标准PE头可选PE头节表多个节构成的&#xff0c;如下便是一个pe文件结构图&#xff0c;它的每一段都可以被称作节 图中这么多的节在硬盘上和内存中的存储位置都由节表去管理和记录&#xff0c;而不是随意的存储。 节表相当于是一个对各个…

论文解读:Label Hallucination for Few-Shot Classification

文章汇总 动机 本文的一个思想就是&#xff1a;尽管新类的标签并不能“恰如其分”地表示基数据集中的样本&#xff0c;但是很多基数据集的样本会包含与新类中相似的对象&#xff0c;例如&#xff0c;基数据集中的老虎和新类中的猫有相似的特征&#xff0c;那么就有60%的概率将…

补充centos7软件包的方式/编译安装源码包软件/企业案例/linux进程管理/企业管理进程系列命令(企业经验)--8820字详谈

cenros7软件包的安装方式 软件包分类安装方式优缺点rpm包软件开发商编译打包&#xff0c;安装简单&#xff0c;快速软件版本可能偏低&#xff0c;安装路径是固定好的源码包自己手动编译安装并且复杂软件爸爸随意选&#xff0c;可以定制安装路径二进制包解压就可以使用不能进行…

new String和直接赋值的一些问题

分析1 我们先看以下代码&#xff1a; String str1 "abc"; // 在常量池中String str2 new String("abc"); // 在堆上System.out.println(str1 str2)以上结果的输出是什么&#xff1f; 输出&#xff1a;false 前置知识&#xff1a; 在JVM中&#xff0c…

PTA 天梯赛 L1-010 比较大小【C++】 L1-011 A-B 【C++ vector动态数组】【Python 字符串replace函数】

L1-010 比较大小 判断顺序很重要 #include<iostream> using namespace std; int main() {int a, b, c;cin >> a >> b >> c;int temp;if (a > b) {temp a;a b;b temp;}if (a > c) {temp a;a c;c temp;}if (b > c) {temp b;b c;c te…

从零开始的软件测试学习之旅(二)测试方法及禅道使用篇

测试方法bug统计以及禅道使用 按是否要运行程序进行划分测试方法测试计划和测试方案测试方案包含:测试用例设计方法一.等价类划分法二.边界值法三.判定表法四.因果图: 输入条件或输入条件组合较多,组合使用判定表与因果图五.正交法:基于数学概率学,设计最经济的实验路径六.场景…

Vue面试经验

Vue部分 Vue编译时声明周期的执行顺序 Vue中父子组件渲染顺序&#xff08;同步引入子组件&#xff1a;import Son from ‘/components/son’ &#xff09; 父子组件编译时的生命周期执行顺序 这里修改data数据时也修改了dom&#xff0c;如过知识通过按钮对数据进行操作&…

Veeam配置备份oracle实例

Veeam是一家专门提供数据管理和数据保护解决方案的软件公司。他们的产品主要包括备份、复制和虚拟化管理等功能&#xff0c;旨在帮助企业保护其数据、应用程序和系统&#xff1b;NBU&#xff0c;COMMVALT&#xff0c;Veeam 国际三大知名备份软件厂商。本文介绍使用Veaam 备份Li…

数据结构——二叉树的操作 (层序遍历)(C++实现)

数据结构——二叉树的操作&#xff08;2&#xff09;&#xff08;C实现&#xff09; 统计叶子结点个数统计结点个数层序遍历非递归方式递归方式 我们今天接着来看二叉树的操作&#xff0c;如果还没有看过上一篇的可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/a…

ezplot--Matlab学习

目录 一、代码 二、效果 ​编辑 三、ezplot讲解 四、如何自定义一个函数 一、代码 clc; clear; t0:32; x4(t) cos(2*pi*t/4).*sin(2*pi*t/4); x8(t) cos(2*pi*t/8).*sin(2*pi*t/8); x16(t) cos(2*pi*t/16).*sin(2*pi*t/16); subplot(3,1,1) ezplot(x4,[0,32]); subplot…

怎样选购内衣洗衣机?2024年5款最新推荐机型种草

随着科技的不断发展&#xff0c;内衣洗衣机成为了家家户户必备的小家电之一&#xff0c;为我们的生活带来了极大的便利。但面对市场上众多的内衣洗衣机品牌&#xff0c;如何选择一款质量好的内衣洗衣机呢&#xff1f;本文将为您推荐5款最新的内衣洗衣机品牌&#xff0c;从而帮助…

冯唐成事心法笔记 —— 知人

系列文章目录 冯唐成事心法笔记 —— 知己 冯唐成事心法笔记 —— 知人 冯唐成事心法笔记 —— 知世 冯唐成事心法笔记 —— 知智慧 文章目录 系列文章目录PART 2 知人 人人都该懂战略人人都该懂战略第一&#xff0c;什么是战略第二&#xff0c;为什么要做战略第三&#xff0…