鸿蒙OS开发教学:【编程之重器-装饰器】

HarmonyOS 有19种装饰器

必须【2】

绘制一个页面,这两个肯定会用到

  1. @Entry
  2. @Component

可选【17】

  1. @State
  2. @Prop
  3. @Link
  4. @ObjectLink
  5. @Watch
  6. @Styles
  7. @StorageProp
  8. @StorageLink
  9. @Provide
  10. @Consume
  11. @Observed
  12. @Builder
  13. @BuilderParam
  14. @LocalStorageProp
  15. @LocalStorageLink
  16. @Extend
  17. @Concurrent

如果你有一定编程基础,应该在你所熟悉的语言领域已见过这种形式。

@format("Hello, %s")
helloWorld: string;
@Deprecated    
private static void helloWord(){        System.out.println("这个方法已经不推荐使用");    
}
@ParamMetadata("ClassThree", 5)
class HelloWorld {int timeYear;
}
@RestController
public class HelloWorldController {
}
@interface HelloWorldObject : NSObject {
}

装饰器

鸿蒙OS开发更多内容↓点击HarmonyOS与OpenHarmony技术
鸿蒙技术文档开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。

@Entry @Component

@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State message: string = 'Hello World'build() {    Row() {      Column() {        Text(this.message)          .fontSize(50)          .fontWeight(FontWeight.Bold)      }.width('100%')    }.height('100%')  }}}

@State

组件内状态更新(即,变量内容发生变化,组件自动刷新)

@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {  @State message: string = 'Hello World'  build() {        Row() {              Column() {                    Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)Button('更新this.message内容').onClick( ()=>{ this.message = 'HarmonyOS'})}.width('100%')}.height('100%')  }
}

@Link

父组件与子组件双向同步数据(即,父组件和子组件都可以更新父组件已关联的数据)

NOTE:  子组件中的 @Link 变量,不能初始化。

import { TestChild } from './TestChild'
@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State message: string = '混沌'build() {Row() {// 父组件Column( {space : 20} ) {Text(this.message).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.message = 'Hello Word'})// 子组件TestChild({m: $message})}.width('100%')}.height('100%')   }
}
@Component
export struct  TestChild{  @Link m: string  private childCount: number = 0build(){    Button('Child 更新文字内容')      .onClick( ()=>{        this.m = 'HarmonyOS - Child' + (this.childCount++)      })  }
}

@Prop

父组件与子组件单向同步数据(即,父组件可以同步数据至子组件,子组件无法同步数据到父组件)

NOTE: 父组件的更新指的是其内容相比之前状态发生了变化,如下代码中,如果将count 字段内容不赋值给 message, 则子组件仅仅会更新一次内容

import { TestChild } from './TestChild'@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State message: string = '混沌'count: number = 0build() {Row() {Column( {space : 20} ) {Text(this.message).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.message = 'Hello Word ' + this.count++})TestChild({m: this.message})}.width('100%')}.height('100%')}
}
@Component
export struct TestChild{@Prop m: stringprivate childCount: number = 0build(){Column( {space:20} ){Text(this.m).fontSize(30)Button('TestChild 更新文字内容').onClick( ()=>{this.m = 'HarmonyOS - Child' + (this.childCount++)})}.backgroundColor(Color.Pink)}
}

@Provide @Consume

父组件与子组件的子组件(官方叫法:后代组件)双向向同步数据(即,父组件与后代组件可以相互操作 @Provide 修饰的数据)

NOTE:@Provide 与 @Consume声明的变量名必须一致

import {TestChild } from './TestChild'
@Entry //这是一个页面
@Component // 页面中有一个视图容器,即根布局 Row()
struct Index {@Provide msg: string = '混沌'count: number = 0build(){Row(){Column( {space : 20} ) {Text(this.msg).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.msg = 'Hello World ' + (this.count++)})TestChild()}.width('100%')}.height('100%')}
}

TestChild 嵌套 TestChild2, TestChild2嵌套TestChild3

@Component
export struct TestChild{build(){TestChild2(){.width('100%').backgroundColor(Color.Red).align(Alignment.Center)}}
}@Component
export struct TestChild2{build(){TestChild3()}
}@Component
export struct TestChild3{@Consume msg: stringcount: number = 0build(){Column(){Text(this.msg).fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.msg = 'HarmonyOS - Child' + (this.count++)}) }.backgroundColor(Color.Pink)}
}

@Observed @ObjectLink

父组件与嵌套对象或数组进行双向向同步数据

说明

实际业务研发中,我们封装好多类(与 @Component 修饰的组件无关),这个时候,如果要让父组件 和 嵌套对象进行数据同步,前边所介绍的所有装饰器是无法做到的。

NOTE

1. 子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定 

2. 单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用初始状态

NOTE:

这次你会发现 点击“Parent 更新文字内容”,父组件文字没有发生变化,原因是因为有3级嵌套类如何破解?

“子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定”

// 引起此问题初始化代码
@State b: ClassB = new ClassB(new ClassA(0));
// 修改
@State a: ClassA = new ClassA(0)
@State b: ClassB = new ClassB(a)
import {ClassA, ClassB, TestChild } from './TestChild'
@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State b: ClassB = new ClassB(new ClassA(0));build() {Row() {Column( {space : 20} ) {Text(this.b.a.c + '').fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.b.a.c += 1;})TestChild({a: this.b.a})}.width('100%')}.height('100%')}
}
@Component
export struct TestChild {@ObjectLink a: ClassA;build(){Column(){Text(this.a.c + '').fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.a.c += 1;} )}.backgroundColor(Color.Pink)}}      @Observed
export class ClassA {public c: number;constructor(c: number) {this.c = c;}}export class ClassB {public a: ClassA;constructor(a: ClassA) {this.a = a;}
}

@Watch

关注某个变量状态发生变化

NOTE:监听的这个变量不要放在回调方法中,让其发生二次变化,容易导致死循环

import {ClassA, ClassB, TestChild } from './TestChild'@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State msg: string = '混沌'@State index: number = 0;build(){Row(){Column( {space : 20} ) {Text(this.msg + ' ' + this.index).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.index++})TestChild({count: this.index})}.width('100%')}.height('100%')}   
}

NOTE:使用 @Prop 修饰的原因:感知父组件改变 count 值

@Component
export struct  TestChild{@Prop @Watch('onCountUpdated') count: number;@State total: number = 0;// @Watch 回调onCountUpdated(propName: string): void {this.total += 1;}build(){Column(){Text('HarmonyOS - Child' + this.total).fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.backgroundColor(Color.Pink)}}

@LocalStorageLink @LocalStorageProp

LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility内,页面间共享状态

LocalStorage在场景使用过程中包含了两个装饰器,即@LocalStorageLink 和 @LocalStorageProp

import { TestChild } from './TestChild';// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build(){Row(){Column( {space : 20} ){Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.count++})TestChild()   }.width('100%')}.height('100%')}}
@Component
export struct TestChild {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build() {Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})  }.width('100%').backgroundColor(Color.Pink)}}

总结,本例展示了:

  • 使用构造函数创建LocalStorage实例storage
  • 使用@Entry装饰器将storage添加到 Index 顶层组件中
  • @LocalStorageLink绑定LocalStorage对给定的属性,建立双向数据同步
import { TestChild } from './TestChild';// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageProp('PropA') count: number = 1;build() {Row() {Column( {space : 20} ) {Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.count++})TestChild() }.width('100%')}.height('100%')}
}
let storage = LocalStorage.GetShared()@Component
export struct TestChild{// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build() {Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.width('100%').backgroundColor(Color.Pink)}}

总结

@LocalStorageLink(key)是和LocalStorage中key对应的属性建立双向数据同步:

  1. 本地修改发生,该修改会被写回LocalStorage中;
  2. LocalStorage中的修改发生后,该修改会被同步到所有绑定LocalStorage对应key的属性上,包括单向(@LocalStorageProp和通过prop创建的单向绑定变量)、双向(@LocalStorageLink和通过link创建的双向绑定变量)变量。

这个例子中TestChild组件使用了@LocalStorageLInk, 当其值发生变化时,会同时影响到父布局使用到 @LocalStorageProp 装饰器的变量值,即 子组件的变量通过LocalStorage可以影响到相应的父组件变量值,但父组件的相关变量值是无法影响到子组件的变量值

@StorageLink @StorageProp

AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。

AppStorage在场景使用过程中包含了两个装饰器,即@StorageLink 和 @StorageProp

和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”,持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转,才可以和UI交互。

NOTE:   AppStorage 和 LocalStorage是互不影响的

import { TestChild } from './TestChild';
AppStorage.SetOrCreate('PropA', 47);// 创建新实例并使用给定对象初始化
let storage = new LocalStorage();// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@StorageLink('PropA') count: number = 1;@LocalStorageLink('PropA') countL: number = 1;build() {Row(){Column( {space : 20} ) {Text('AppStorage ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('更新AppStorage内容').onClick( ()=>{this.count++})Text('LocalStorage ' + this.countL).fontSize(30).fontWeight(FontWeight.Bold)Button('更新LocalStorage内容').onClick( ()=>{this.countL++})TestChild() }.width('100%')}.height('100%')}
}
@Component
export struct TestChild {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@StorageLink('PropA') count: number = 1;build(){Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.width('100%').backgroundColor(Color.Pink)}}

@Builder

@Builder 用于UI元素复用,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用

总结
值引用方式,可以感知父组件的状态变化
值传递方式,无法感知父组件的状态变化

@Entry
@Component
struct Index {@State count: number = 1;@Builder BuilderOne($$: { paramA1: number }) {Column() {Text(`组件1值引用: ${$$.paramA1} `).fontSize(20)}.width('100%').backgroundColor(Color.Pink)}@Builder BuilderTwo(paramA1: number) {Column() {Text(`组件2值传递: ${paramA1} `).fontSize(20)}.width('100%').backgroundColor(Color.Pink)}build() {Row() {Column({ space: 20 }) {Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('更新').onClick(() => {this.count++})this.BuilderOne({ paramA1: this.count })this.BuilderTwo(this.count)}.width('100%')}.height('100%')}
}

@BuilderParam

当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

import Prompt from '@system.prompt';
import { TestChild } from './TestChild';@Entry
@Component
struct Index {@Builder BuilderOne() {TestChild( {msg: 'BuilderOne 视图'} ) {Text('1').fontColor(Color.Red)}}@Builder BuilderTwo() {Stack(){TestChild( {msg: 'BuilderTwo 视图'} ) {Text('1').fontColor(Color.Red)Text('2').fontColor(Color.Red)}}.onClick( () => {Prompt.showToast({message: '点了 BuilderTwo'})})}@BuilderParam aBuilder0: () => void = this.BuilderOne@BuilderParam aBuilder1: () => void = this.BuilderTwobuild(){Column({ space: 20 }) {this.aBuilder0()this.aBuilder1()TestChild( {msg: '中国'} ) {Text('1').fontColor(Color.Red)})}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}
@Component
export struct TestChild {msg: string@BuilderParam aB0: () => {}build(){Column( {space : 20} ) {this.aB0()Text('TestChild上下有 '+ this.msg).fontSize(20).fontWeight(FontWeight.Bold)this.aB0()  }.width('100%').backgroundColor(Color.Pink)}}

总结

  1. @BuilderParam 既可以指向一个对象, 也可以指向@Builder修饰的方法
  2. 关于子组件占位出现两个的问题,应该是系统原因
  3. 带占位的自定义视图是没法响应onClick事件的,所以在本示例种,将子组件外边再添加了一个容器组件,用来进行点击事件响应

@Styles

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

import Prompt from '@system.prompt';@Entry
@Component
struct Index {//仅支持公共属性@Styles fancy() {.width(200).height(300).backgroundColor(Color.Pink).onClick(() => {Prompt.showToast({message: 'I am fancy'})})}build() {Column({ space: 20 }) {Text('Styles').textAlign(TextAlign.Center).fancy()}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}

总结

  1. @Styles 当前仅支持通用属性
  2. @Styles 修饰的方法不支持参数
  3. 引用@Styles 修饰的方法时,建议放在最后,比如:Text().fancy().textAlign(....)  应该变为 Text().textAlign(....) .fancy()

@Extend

用于扩展原生组件样式

注意

1. 原生指的ArkTS写的组件

  1. 扩展,不是新定义增加不存在的属性
import Prompt from '@system.prompt';//仅支持公共属性
@Styles function fancy() {.width(200).height(300).backgroundColor(Color.Pink).onClick(() => {Prompt.showToast({message: 'I am fancy'})})
}@Extend(Text) function superFancy(size:number, onClick?: () => void) {.fontSize(size).textAlign(TextAlign.Center).fancy().onClick(onClick)
}@Entry
@Component
struct Index {onClickHandler() {Prompt.showToast({message: 'fancy出去了'})}build(){Column({ space: 20 }) {Text('Styles').superFancy(30, this.onClickHandler.bind(this))}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}

总结

  1. @Extend 在 @Styles基础上,增加了传参特性
  2. @Extend 必须定义为全局
  3. 支持封装指定的组件的私有属性和私有事件和预定义相同组件的@Extend的方法

@Concurrent

在使用TaskPool时,执行的并发函数需要使用该装饰器修饰,否则无法通过相关校验。

import taskpool from '@ohos.taskpool';@Concurrent
function add(num1: number, num2: number): number {return num1 + num2;
}async function ConcurrentFunc(): Promise<void> {try {let task: taskpool.Task = new taskpool.Task(add, 1, 2);console.info("taskpool res is: " + await taskpool.execute(task));}catch (e) {}
}@Entry
@Component
struct Index {@State message: string = 'Hello World'build(){Row(){Column(){Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {ConcurrentFunc();})}.width('100%')}.height('100%')}
}

搜狗高速浏览器截图20240326151450.png

结尾

到此我们已学完所有的装饰器用法,灵活使用装饰器,全凭官方指导文档是不够的,它仅仅提供了一种最小化的场景使用模型,到了具体业务实现场景中,非常容易犯糊涂蒙圈。可以前往参考这个鸿蒙技术文档qr23.cn/AKFP8k。

个人感觉@BuilderParam和 @ObjectLink理解起来还是有点费劲。

鸿蒙最值得程序员入行

为什么这么说?市场是决定人力需求的,数据说话最管用:

1、鸿蒙其全栈自研,头部大厂商都陆续加入合作开发鸿蒙原生应用——人才需求上涨

2、鸿蒙作为新系统、新技术,而现在市面上技术人才少——高薪招聘开启

3、鸿蒙1+8+N生态,不仅只有应用开发;还有车载、数码、智能家居、家电等——就业范围广

4、纯血鸿蒙,目前没有多少人熟悉。都处于0基础同一起跑线——无行业内卷

开发者最需要什么?岗位多、薪资高、不内卷、行业竞争低。而当下的鸿蒙恰恰符合要求。

那么这么好的鸿蒙岗位,应聘要求都很高吧?其实不然鸿蒙作为新出的独立系统,其源头上大家都处于同一水平线上,一开始的技术要求都不会很高,毕竟面试官也是刚起步学习。招聘要求示例:

从信息看出,几乎应职要求是对标有开发经验的人群。可以说鸿蒙对开发者非常友好,尽管上面没提鸿蒙要求,但是面试都会筛选具有鸿蒙开发技能的人。我们程序员都知道学习开发技术,最先是从语言学起,鸿蒙语言有TS、ArkTS等语法,那么除了这些基础知识之外,其核心技术点有那些呢?下面就用一张整理出的鸿蒙学习路线图表示:

从上面的OpenHarmony技术梳理来看,鸿蒙的学习内容也是很多的。现在全网的鸿蒙学习文档也是非常的少,下面推荐一些:完整内容可在头像页保存,或这qr23.cn/AKFP8k甲助力

内容包含:《鸿蒙NEXT星河版开发学习文档》

  • ArkTS
  • 声明式ArkUI
  • 多媒体
  • 通信问题
  • 系统移植
  • 系统裁剪
  • FW层的原理
  • 各种开发调试工具
  • 智能设备开发
  • 分布式开发等等。

这些就是对往后开发者的分享,希望大家多多点赞关注喔!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

141.环形链表 142.环形链表II

给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;索…

你管这破玩意叫网络

你是一台电脑&#xff0c;你的名字叫 A 很久很久之前&#xff0c;你不与任何其他电脑相连接&#xff0c;孤苦伶仃。 直到有一天&#xff0c;你希望与另一台电脑 B 建立通信&#xff0c;于是你们各开了一个网口&#xff0c;用一根网线连接了起来。 用一根网线连接起来怎么就能…

R语言赋值符号<-、=、->、<<-、->>的使用与区别

R语言的赋值符号有&#xff1c;-、、-&#xff1e;、&#xff1c;&#xff1c;-、-&#xff1e;&#xff1e;六种&#xff0c;它们的使用与区别如下: <-’&#xff1a;最常用的赋值符号。它将右侧表达式的值赋给左侧的变量&#xff0c;像一个向左的箭头。例如&#xff0c;x …

ethers.js:sign(签名)

Signers 在ethers中Signer是以太坊账户的抽象&#xff0c;可以用来签名消息和交易&#xff0c;如将签名的交易发送到以太坊网络以执行状态更改的操作。 npm install ethers5.4.0// 引入 import { ethers } from ethers签名 this.provider new ethers.providers.Web3Provider(…

<QT基础(4)>QLabel使用笔记

Label 前面的文章里面把QLabel批量引入ScrollArea作为预览窗口&#xff0c;这篇把图像填充到QLable的PixelMap展示指定图像。 参数设置 设置QLabel的大小格式 QWidget* widget new QWidget; widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); widget->…

Go打造REST Server【二】:用路由的三方库来实现

前言 在之前的文章中&#xff0c;我们用Go的标准库来实现了服务器&#xff0c;JSON渲染重构为辅助函数&#xff0c;使特定的路由处理程序相当简洁。 我们剩下的问题是路径路由逻辑&#xff0c;这是所有编写无依赖HTTP服务器的人都会遇到的问题&#xff0c;除非服务器只处理一到…

数据结构进阶篇 之 【二叉树链序存储】的整体实现讲解

封建迷信我嗤之以鼻&#xff0c;财神殿前我长跪不起 一、二叉树链式结构的实现 1.二叉树的创建 1.1 手动创建 1.2 前序递归创建 2.二叉树的遍历 2.1 前序&#xff0c;中序以及后序遍历概念 2.2 层序遍历概念 2.3 前序打印实现 2.4 中序打印实现 2.4 后序打印实现 2.…

HTTP(1)

目录 一、认识HTTP协议 理解 应用层协议 二、fiddler的安装以及介绍 1、fiddler的安装 2、fiddler的介绍 三、HTTP 报文格式 1、http的请求 2、http的响应 五、认识URL 六、关于URL encode 一、认识HTTP协议 HTTP 全称为&#xff1a;“超文本传输协议”&#xff0c;是…

鸿蒙开发之了解ArkTS

鸿蒙开发者官网 &#xff1a; https://developer.huawei.com/consumer/cn/ 开发鸿蒙要用的软件是 DevEco Studio ArkTS建立在JS和TS的基础之上&#xff0c;扩展了声明式UI开发范式和状态管理&#xff0c;提供更简洁和自然的开发方式。 ArkTS引入了渲染引擎的增强&#xff0c…

【机器学习300问】56、什么是自编码器?

一、什么是自编码器&#xff1f; 自编码器&#xff08;Autoencoder&#xff0c;AE&#xff09;本质是一种特殊的神经网络架构。主要用于无监督学习和特征学习任务。它的目标是通过编码然后解码的过程&#xff0c;学会重构其输入数据&#xff0c;试图还原其原始输入的。 当时我学…

信息安全之网络安全防护

先来看看计算机网络通信面临的威胁&#xff1a; 截获——从网络上窃听他人的通信内容中断——有意中断他人在网络上的通信篡改——故意篡改网络上传送的报文伪造——伪造信息在网络上传送 截获信息的攻击称为被动攻击&#xff0c;而更改信息和拒绝用户使用资源的攻击称为主动…

AI智能分析网关智慧食安监管系统方案

3.15晚会刚过不久&#xff0c;淀粉肠的“屈辱”终于得以洗清&#xff0c;但某些品牌奶茶、梅菜扣肉、预制菜等等&#xff0c;生产过程仍是触目惊心。如何提升食品安全管理水平&#xff0c;保障食品从生产到消费环节的质量和安全&#xff1f;TSINGSEE青犀智利用智能分析网关V4Ea…

旺店通·旗舰奇门与金蝶云星空对接集成销售出库单查询连通销售出库新增(WDT 线下销售出库单对接(关联)-ok-不适用)

旺店通旗舰奇门与金蝶云星空对接集成销售出库单查询连通销售出库新增(WDT 线下销售出库单对接&#xff08;关联&#xff09;-ok-不适用) 源系统:旺店通旗舰奇门 慧策最先以旺店通ERP切入商家核心管理痛点——订单管理&#xff0c;之后围绕电商经营管理中的核心管理诉求&#xf…

Nginx(Docker 安装的nginx)配置域名SSL证书

1.首先确保Linux环境上已经安装了docker&#xff08;可参考Linux安装Docker-CSDN博客&#xff09; 2.通过docker 安装nginx&#xff08;可参考Linux 环境安装Nginx—源码和Dokcer两种安装方式-CSDN博客&#xff09; 3.安装SSL证书 3.1 在宿主机中创建证书目录并上传证书&…

使用Docker Compose一键部署前后端分离项目(图文保姆级教程)

一、安装Docker和docker Compose 1.Docker安装 //下载containerd.io包 yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm //安装依赖项 yum install -y yum-utils device-mapper-persistent-data l…

OpenGL的MVP矩阵理解

OpenGL的MVP矩阵理解 右手坐标系 右手坐标系与左手坐标系都是三维笛卡尔坐标系&#xff0c;他们唯一的不同在于z轴的方向&#xff0c;如下图&#xff0c;左边是左手坐标系&#xff0c;右边是右手坐标系 OpenGL中一般用的是右手坐标系 1.模型坐标系&#xff08;Local Space&…

软件设计师:10-面向对象

一、面向对象 二、对象和消息 属性&#xff1a;也叫成员变量、状态 消息&#xff1a;对象名.方法名&#xff08;传入你想要传递的参数&#xff09; 三、方法重载 方法名相同&#xff08;同名&#xff09;&#xff0c;但是参数个数或者参数类型不同叫方法重载 四、封装…

SpringBoot+Prometheus+Grafana实现应用监控和报警

一、背景 SpringBoot的应用监控方案比较多&#xff0c;SpringBootPrometheusGrafana是目前比较常用的方案之一。它们三者之间的关系大概如下图&#xff1a; 关系图 二、开发SpringBoot应用 首先&#xff0c;创建一个SpringBoot项目&#xff0c;pom文件如下&#xff1a; <…

分布式数据库技术的演进和发展方向

前言 这些年大家都在谈分布式数据库&#xff0c;各大企业也纷纷开始做数据库的分布式改造。那么&#xff0c;所谓的分布式数据库到底是什么&#xff1f;采用什么架构&#xff1f;优势在哪&#xff1f;为什么越来越多企业选择它&#xff1f;分布式数据库技术会向什么方向发展&a…

C/C++ 内存管理

1、C/C内存分布 首先我们来了解在一个程序中&#xff0c;代码主要存储在哪些地方&#xff1b; 1.栈&#xff1a;又叫堆栈&#xff0c;其中一般存储非静态局部变量、函数参数、返回值等&#xff0c;栈的增长是向下的。 2.内存映射段&#xff1a;是高效的 I/O 映射方式&#xff0…