首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙HarmonyOS实战-ArkTS语言(基本语法)

  • 25-02-22 03:20
  • 4439
  • 10700
blog.csdn.net

 一、ArkTS语言基本语法

1.简介

HarmonyOS的ArkTS语言是一种基于TypeScript开发的语言,它专为HarmonyOS系统开发而设计。ArkTS语言结合了JavaScript的灵活性和TypeScript的严谨性,使得开发者能够快速、高效地开发出高质量的HarmonyOS应用程序。

ArkTS语言具有以下特点:

  1. 静态类型检查:开发者在编写代码时可以使用类型注解来进行类型检查,从而减少因类型错误而导致的bug。

  2. 异步/同步编程:ArkTS语言支持基于Promise和async/await的异步/同步编程方式,能够更好地处理异步操作。

  3. 内置模块:ArkTS语言内置了许多常用的模块,如文件系统、网络请求、图形渲染等,使得开发者不必自己编写这些模块。

  4. 兼容性:ArkTS语言使用TypeScript语法,可以与JavaScript代码无缝集成,并且可以编译成JavaScript代码来在其他平台上运行。

ArkTS语言基础类库是HarmonyOS系统上为应用开发者提供的常用基础能力,主要包含能力如下图所示:

在这里插入图片描述
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。

ArkTS和HTML的差别:
在这里插入图片描述
在这里插入图片描述

2.TypeScript的基础语法

TypeScript是一种由微软开发的JavaScript超集语言,它支持JavaScript的所有语法,但添加了一些新的特性和语法,使开发更加可靠和高效。TypeScript最大的特点是引入了静态类型,开发者可以在编译时发现类型错误,提高代码的可维护性和可读性。

TypeScript代码可以在编译时被转换成JavaScript代码,在浏览器和Node.js环境下都可以运行。虽然TypeScript相对于JavaScript来说更加复杂,但是它可以帮助开发者更好地组织和管理复杂的项目,特别是在团队协作中提高代码的质量和可维护性。

TypeScript基础知识包括基本类型、变量声明、函数、类、接口、泛型等。另外,TypeScript还支持模块化开发,可以使用ES模块规范或者CommonJS规范导入和导出模块。在实际项目开发中,TypeScript还可以结合工具链如Webpack、Babel进行编译、打包等操作。

在这里插入图片描述
除了上面提到的变量声明、函数定义、类定义、接口定义和枚举类型外,TypeScript还有一些基础语法需要掌握:

2.1 类型注解

TypeScript的静态类型检查是通过类型注解实现的。在声明变量或函数时,可以使用冒号加上类型注解,指定变量或函数的类型。例如:

  1. let name: string = "TypeScript";
  2. function add(a: number, b: number): number {
  3. return a + b;
  4. }

2.2 接口

TypeScript的接口是用来描述对象的形状的。可以定义对象需要包含哪些属性和方法,以及它们的类型。例如:

  1. interface Person {
  2. name: string;
  3. age: number;
  4. sayHello(): void;
  5. }
  6. let tom: Person = {
  7. name: "Tom",
  8. age: 18,
  9. sayHello: function() {
  10. console.log(`Hello, my name is ${this.name}!`);
  11. }
  12. };

2.3 泛型

TypeScript的泛型可以帮助我们编写更加灵活、可重用的代码。它允许在编写函数、类或接口时使用参数化类型,从而提高代码的通用性和可读性。例如:

  1. function identity<T>(arg: T): T {
  2. return arg;
  3. }
  4. let output = identity<string>("TypeScript");
  5. console.log(output); // 输出 TypeScript

2.4 类的继承

TypeScript的类可以继承其他类,从而实现代码的重用和扩展。通过关键字extends可以让一个类继承另一个类,并继承其属性和方法。例如:

  1. class Animal {
  2. name: string;
  3. constructor(name: string) {
  4. this.name = name;
  5. }
  6. move(distance: number = 0) {
  7. console.log(`${this.name} moved ${distance}m.`);
  8. }
  9. }
  10. class Dog extends Animal {
  11. bark() {
  12. console.log("Woof! Woof!");
  13. }
  14. }
  15. let dog = new Dog("Bobby");
  16. dog.move(10); // 输出 "Bobby moved 10m."
  17. dog.bark(); // 输出 "Woof! Woof!"

2.5 类的访问修饰符

TypeScript的类可以通过访问修饰符来控制类的属性和方法的访问权限。有三个访问修饰符可以使用:public、private和protected。默认情况下,都是public。

public:公共的,任何外部或内部都可以访问。

private:私有的,只有类的内部可以访问,外部无法访问。

protected:受保护的,只有类的内部和其子类可以访问,外部无法访问。

  1. class Person {
  2. protected name: string;
  3. constructor(name: string) {
  4. this.name = name;
  5. }
  6. protected sayHello() {
  7. console.log(`Hello, I'm ${this.name}.`);
  8. }
  9. }
  10. class Student extends Person {
  11. constructor(name: string) {
  12. super(name);
  13. }
  14. public sayHelloToTeacher(teacher: Person) {
  15. console.log(`Hello, ${teacher.name}, I'm ${this.name}.`);
  16. }
  17. }
  18. let tom = new Student("Tom");
  19. let bob = new Person("Bob");
  20. tom.sayHelloToTeacher(bob); // 输出 "Hello, Bob, I'm Tom."
  21. bob.sayHello(); // 报错:属性 'sayHello' 受保护,只能在类 'Person' 及其子类中访问。

以上只是举例一些TS的基础语法,TS内容远不止这些不懂的可以去学学TS。

3.ArkTS的基本组成

在这里插入图片描述

  • 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新。

  • UI描述:以声明式的方式来描述UI的结构,例如build()方法中的代码块。

  • 自定义组件:可复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Hello。

  • 系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,比如示例中的Column、Text、Divider、Button。

  • 属性方法:组件可以通过链式调用配置多项属性,如fontSize()、width()、height()、backgroundColor()等。

  • 事件方法:组件可以通过链式调用设置多个事件的响应逻辑,如跟随在Button后面的onClick()。
    系统组件、属性方法、事件方法具体使用可参考基于ArkTS的声明式开发范式。

除此之外,ArkTS扩展了多种语法范式来使开发更加便捷:

  • @Builder/@BuilderParam:特殊的封装UI描述的方法,细粒度的封装和复用UI描述。
  • @Extend/@Style:扩展内置组件和封装属性样式,更灵活地组合内置组件。
  • stateStyles:多态样式,可以依据组件的内部状态的不同,设置不同样式。

4.自定义组件

  1. @Component
  2. struct HelloComponent {
  3. @State message: string = 'Hello, World!';
  4. build() {
  5. // HelloComponent自定义组件组合系统组件Row和Text
  6. Row() {
  7. Text(this.message)
  8. .onClick(() => {
  9. // 状态变量message的改变驱动UI刷新,UI从'Hello, World!'刷新为'Hello, ArkUI!'
  10. this.message = 'Hello, ArkUI!';
  11. })
  12. }
  13. }
  14. }
  15. @Entry
  16. @Component
  17. struct ParentComponent {
  18. build() {
  19. Column() {
  20. Text('ArkUI message')
  21. HelloComponent({ message: 'Hello, World!' });
  22. Divider()
  23. HelloComponent({ message: '你好!' });
  24. }
  25. }
  26. }
  • struct:自定义组件基于struct实现,struct + 自定义组件名 +
    {…}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。

  • build()函数:build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。

  • @Entry:@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。@Entry可以接受一个可选的LocalStorage的参数。

4.1 build()函数规范

1、根节点唯一

  1. @Entry
  2. @Component
  3. struct MyComponent {
  4. build() {
  5. // 根节点唯一且必要,必须为容器组件
  6. Row() {
  7. ChildComponent()
  8. }
  9. }
  10. }
  11. @Component
  12. struct ChildComponent {
  13. build() {
  14. // 根节点唯一且必要,可为非容器组件
  15. Image('test.jpg')
  16. }
  17. }

2、不允许声明本地变量、打印、作用域

  1. build() {
  2. // 反例:不允许声明本地变量
  3. let a: number = 1;
  4. // 反例:不允许console.info
  5. console.info('print debug log');
  6. // 反例:不允许本地作用域
  7. {
  8. ...
  9. }
  10. }

3、不允许调用没有用@Builder装饰的方法,允许系统组件的参数是TS方法的返回值。

  1. @Component
  2. struct ParentComponent {
  3. doSomeCalculations() {
  4. }
  5. calcTextValue(): string {
  6. return 'Hello World';
  7. }
  8. @Builder doSomeRender() {
  9. Text(`Hello World`)
  10. }
  11. build() {
  12. Column() {
  13. // 反例:不能调用没有用@Builder装饰的方法
  14. this.doSomeCalculations();
  15. // 正例:可以调用
  16. this.doSomeRender();
  17. // 正例:参数可以为调用TS方法的返回值
  18. Text(this.calcTextValue())
  19. }
  20. }
  21. }

4、不允许switch和表达式

  1. build() {
  2. Column() {
  3. // 反例:不允许使用switch语法
  4. switch (expression) {
  5. case 1:
  6. Text('...')
  7. break;
  8. case 2:
  9. Image('...')
  10. break;
  11. default:
  12. Text('...')
  13. break;
  14. }
  15. // 反例:不允许使用表达式
  16. (this.aVar > 10) ? Text('...') : Image('...')
  17. }
  18. }

5.页面和自定义组件生命周期

在这里插入图片描述
页面生命周期,即被@Entry装饰的组件生命周期,提供以下生命周期接口:

  • onPageShow:页面每次显示时触发。
  • onPageHide:页面每次隐藏时触发一次。
  • onBackPress:当用户点击返回按钮时触发。

组件生命周期,即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:

  • aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
  • aboutToDisappear:在自定义组件即将析构销毁时执行。
  1. // Index.ets
  2. import router from '@ohos.router';
  3. @Entry
  4. @Component
  5. struct MyComponent {
  6. @State showChild: boolean = true;
  7. // 只有被@Entry装饰的组件才可以调用页面的生命周期
  8. onPageShow() {
  9. console.info('Index onPageShow');
  10. }
  11. // 只有被@Entry装饰的组件才可以调用页面的生命周期
  12. onPageHide() {
  13. console.info('Index onPageHide');
  14. }
  15. // 只有被@Entry装饰的组件才可以调用页面的生命周期
  16. onBackPress() {
  17. console.info('Index onBackPress');
  18. }
  19. // 组件生命周期
  20. aboutToAppear() {
  21. console.info('MyComponent aboutToAppear');
  22. }
  23. // 组件生命周期
  24. aboutToDisappear() {
  25. console.info('MyComponent aboutToDisappear');
  26. }
  27. build() {
  28. Column() {
  29. // this.showChild为true,创建Child子组件,执行Child aboutToAppear
  30. if (this.showChild) {
  31. Child()
  32. }
  33. // this.showChild为false,删除Child子组件,执行Child aboutToDisappear
  34. Button('create or delete Child').onClick(() => {
  35. this.showChild = false;
  36. })
  37. // push到Page2页面,执行onPageHide
  38. Button('push to next page')
  39. .onClick(() => {
  40. router.pushUrl({ url: 'pages/Page2' });
  41. })
  42. }
  43. }
  44. }
  45. @Component
  46. struct Child {
  47. @State title: string = 'Hello World';
  48. // 组件生命周期
  49. aboutToDisappear() {
  50. console.info('[lifeCycle] Child aboutToDisappear')
  51. }
  52. // 组件生命周期
  53. aboutToAppear() {
  54. console.info('[lifeCycle] Child aboutToAppear')
  55. }
  56. build() {
  57. Text(this.title).fontSize(50).onClick(() => {
  58. this.title = 'Hello ArkUI';
  59. })
  60. }
  61. }

6.装饰函数

6.1 @Builder装饰器

@Builder主要是定义页面UI

6.1.1 装饰指向

1、自定义组件内自定义构建函数

  1. @Builder MyBuilderFunction(){ ... }
  2. #使用
  3. this.MyBuilderFunction(){ ... }

2、MyGlobalBuilderFunction()

  1. @Builder function MyGlobalBuilderFunction(){ ... }
  2. #使用
  3. MyGlobalBuilderFunction()
6.1.2 参数传递

1、按引用传递参数

  1. @Builder function ABuilder($$: { paramA1: string }) {
  2. Row() {
  3. Text(`UseStateVarByReference: ${$$.paramA1} `)
  4. }
  5. }
  6. @Entry
  7. @Component
  8. struct Parent {
  9. @State label: string = 'Hello';
  10. build() {
  11. Column() {
  12. // 在Parent组件中调用ABuilder的时候,将this.label引用传递给ABuilder
  13. ABuilder({ paramA1: this.label })
  14. Button('Click me').onClick(() => {
  15. // 点击“Click me”后,UI从“Hello”刷新为“ArkUI”
  16. this.label = 'ArkUI';
  17. })
  18. }
  19. }
  20. }

2、按值传递参数

  1. @Builder function ABuilder(paramA1: string) {
  2. Row() {
  3. Text(`UseStateVarByValue: ${paramA1} `)
  4. }
  5. }
  6. @Entry
  7. @Component
  8. struct Parent {
  9. label: string = 'Hello';
  10. build() {
  11. Column() {
  12. ABuilder(this.label)
  13. }
  14. }
  15. }

6.2 @BuilderParam装饰器

@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。

6.2.1 装饰指向

1、本地初始化@BuilderParam

  1. @Builder function GlobalBuilder0() {}
  2. @Component
  3. struct Child {
  4. @Builder doNothingBuilder() {};
  5. @BuilderParam aBuilder0: () => void = this.doNothingBuilder;
  6. @BuilderParam aBuilder1: () => void = GlobalBuilder0;
  7. build(){}
  8. }

2、初始化子组件@BuilderParam

  1. @Component
  2. struct Child {
  3. @BuilderParam aBuilder0: () => void;
  4. build() {
  5. Column() {
  6. this.aBuilder0()
  7. }
  8. }
  9. }
  10. @Entry
  11. @Component
  12. struct Parent {
  13. @Builder componentBuilder() {
  14. Text(`Parent builder `)
  15. }
  16. build() {
  17. Column() {
  18. Child({ aBuilder0: this.componentBuilder })
  19. }
  20. }
  21. }

this都是器其本身,不会存在传递。

6.2.2 使用场景

1、参数化传递

  1. @Builder function GlobalBuilder1($$ : {label: string }) {
  2. Text($$.label)
  3. .width(400)
  4. .height(50)
  5. .backgroundColor(Color.Blue)
  6. }
  7. @Component
  8. struct Child {
  9. label: string = 'Child'
  10. // 无参数类,指向的componentBuilder也是无参数类型
  11. @BuilderParam aBuilder0: () => void;
  12. // 有参数类型,指向的GlobalBuilder1也是有参数类型的方法
  13. @BuilderParam aBuilder1: ($$ : { label : string}) => void;
  14. build() {
  15. Column() {
  16. this.aBuilder0()
  17. this.aBuilder1({label: 'global Builder label' } )
  18. }
  19. }
  20. }
  21. @Entry
  22. @Component
  23. struct Parent {
  24. label: string = 'Parent'
  25. @Builder componentBuilder() {
  26. Text(`${this.label}`)
  27. }
  28. build() {
  29. Column() {
  30. this.componentBuilder()
  31. Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 })
  32. }
  33. }
  34. }

2、尾随闭包

  1. // xxx.ets
  2. @Component
  3. struct CustomContainer {
  4. @Prop header: string;
  5. @BuilderParam closer: () => void
  6. build() {
  7. Column() {
  8. Text(this.header)
  9. .fontSize(30)
  10. this.closer()
  11. }
  12. }
  13. }
  14. @Builder function specificParam(label1: string, label2: string) {
  15. Column() {
  16. Text(label1)
  17. .fontSize(30)
  18. Text(label2)
  19. .fontSize(30)
  20. }
  21. }
  22. @Entry
  23. @Component
  24. struct CustomContainerUser {
  25. @State text: string = 'header';
  26. build() {
  27. Column() {
  28. // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包
  29. // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数
  30. CustomContainer({ header: this.text }) {
  31. Column() {
  32. specificParam('testA', 'testB')
  33. }.backgroundColor(Color.Yellow)
  34. .onClick(() => {
  35. this.text = 'changeHeader';
  36. })
  37. }
  38. }
  39. }
  40. }

6.3 @Styles装饰器

@Styles装饰器主要是定义公共样式

6.3.1 装饰指向

1、全局

  1. // 全局
  2. @Styles function functionName() { ... }
  3. // 在组件内
  4. @Component
  5. struct FancyUse {
  6. @Styles fancy() {
  7. .height(100)
  8. }
  9. }

2、组件内

  1. @Component
  2. struct FancyUse {
  3. @State heightValue: number = 100
  4. @Styles fancy() {
  5. .height(this.heightValue)
  6. .backgroundColor(Color.Yellow)
  7. .onClick(() => {
  8. this.heightValue = 200
  9. })
  10. }
  11. }
6.3.2 使用场景
  1. // 定义在全局的@Styles封装的样式
  2. @Styles function globalFancy () {
  3. .width(150)
  4. .height(100)
  5. .backgroundColor(Color.Pink)
  6. }
  7. @Entry
  8. @Component
  9. struct FancyUse {
  10. @State heightValue: number = 100
  11. // 定义在组件内的@Styles封装的样式
  12. @Styles fancy() {
  13. .width(200)
  14. .height(this.heightValue)
  15. .backgroundColor(Color.Yellow)
  16. .onClick(() => {
  17. this.heightValue = 200
  18. })
  19. }
  20. build() {
  21. Column({ space: 10 }) {
  22. // 使用全局的@Styles封装的样式
  23. Text('FancyA')
  24. .globalFancy ()
  25. .fontSize(30)
  26. // 使用组件内的@Styles封装的样式
  27. Text('FancyB')
  28. .fancy()
  29. .fontSize(30)
  30. }
  31. }
  32. }

6.4 @Extend装饰器

@Extend用于扩展原生组件样式,作用和@Styles差不多。

6.4.1 装饰指向

@Extend仅支持定义在全局,不支持在组件内部定义

1、@Extend支持封装指定的组件的私有属性和私有事件

  1. // @Extend(Text)可以支持Text的私有属性fontColor
  2. @Extend(Text) function fancy () {
  3. .fontColor(Color.Red)
  4. }
  5. // superFancyText可以调用预定义的fancy
  6. @Extend(Text) function superFancyText(size:number) {
  7. .fontSize(size)
  8. .fancy()
  9. }

2、@Extend装饰的方法支持参数

  1. // xxx.ets
  2. @Extend(Text) function fancy (fontSize: number) {
  3. .fontColor(Color.Red)
  4. .fontSize(fontSize)
  5. }
  6. @Entry
  7. @Component
  8. struct FancyUse {
  9. build() {
  10. Row({ space: 10 }) {
  11. Text('Fancy')
  12. .fancy(16)
  13. Text('Fancy')
  14. .fancy(24)
  15. }
  16. }
  17. }

3、@Extend装饰的方法的参数可以为function

  1. @Extend(Text) function makeMeClick(onClick: () => void) {
  2. .backgroundColor(Color.Blue)
  3. .onClick(onClick)
  4. }
  5. @Entry
  6. @Component
  7. struct FancyUse {
  8. @State label: string = 'Hello World';
  9. onClickHandler() {
  10. this.label = 'Hello ArkUI';
  11. }
  12. build() {
  13. Row({ space: 10 }) {
  14. Text(`${this.label}`)
  15. .makeMeClick(this.onClickHandler.bind(this))
  16. }
  17. }
  18. }

4、@Extend的参数可以为状态变量

  1. @Extend(Text) function fancy (fontSize: number) {
  2. .fontColor(Color.Red)
  3. .fontSize(fontSize)
  4. }
  5. @Entry
  6. @Component
  7. struct FancyUse {
  8. @State fontSizeValue: number = 20
  9. build() {
  10. Row({ space: 10 }) {
  11. Text('Fancy')
  12. .fancy(this.fontSizeValue)
  13. .onClick(() => {
  14. this.fontSizeValue = 30
  15. })
  16. }
  17. }
  18. }
☀️6.4.2 使用场景
  1. @Extend(Text) function fancyText(weightValue: number, color: Color) {
  2. .fontStyle(FontStyle.Italic)
  3. .fontWeight(weightValue)
  4. .backgroundColor(color)
  5. }
  6. @Entry
  7. @Component
  8. struct FancyUse {
  9. @State label: string = 'Hello World'
  10. build() {
  11. Row({ space: 10 }) {
  12. Text(`${this.label}`)
  13. .fancyText(100, Color.Blue)
  14. Text(`${this.label}`)
  15. .fancyText(200, Color.Pink)
  16. Text(`${this.label}`)
  17. .fancyText(300, Color.Orange)
  18. }.margin('20%')
  19. }
  20. }

7.多态样式

stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:

  • focused:获焦态
  • normal:正常态
  • pressed:按压态
  • disabled:不可用态

7.1 基本使用

  1. @Entry
  2. @Component
  3. struct CompWithInlineStateStyles {
  4. @State focusedColor: Color = Color.Red;
  5. normalColor: Color = Color.Green
  6. build() {
  7. Column() {
  8. Button('clickMe').height(100).width(100)
  9. .stateStyles({
  10. normal: {
  11. .backgroundColor(this.normalColor)
  12. },
  13. focused: {
  14. .backgroundColor(this.focusedColor)
  15. }
  16. })
  17. .onClick(() => {
  18. this.focusedColor = Color.Pink
  19. })
  20. .margin('30%')
  21. }
  22. }
  23. }

7.2 @Styles和stateStyles联合使用

  1. @Entry
  2. @Component
  3. struct MyComponent {
  4. @Styles normalStyle() {
  5. .backgroundColor(Color.Gray)
  6. }
  7. @Styles pressedStyle() {
  8. .backgroundColor(Color.Red)
  9. }
  10. build() {
  11. Column() {
  12. Text('Text1')
  13. .fontSize(50)
  14. .fontColor(Color.White)
  15. .stateStyles({
  16. normal: this.normalStyle,
  17. pressed: this.pressedStyle,
  18. })
  19. }
  20. }
  21. }

7.3 stateStyles里使用常规变量和状态变量

  1. @Entry
  2. @Component
  3. struct CompWithInlineStateStyles {
  4. @State focusedColor: Color = Color.Red;
  5. normalColor: Color = Color.Green
  6. build() {
  7. Button('clickMe').height(100).width(100)
  8. .stateStyles({
  9. normal: {
  10. .backgroundColor(this.normalColor)
  11. },
  12. focused: {
  13. .backgroundColor(this.focusedColor)
  14. }
  15. })
  16. .onClick(() => {
  17. this.focusedColor = Color.Pink
  18. })
  19. .margin('30%')
  20. }
  21. }

 ?写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取文中提到的学习资料,请点击→全套鸿蒙HarmonyOS学习资料
  • 或者关注小编后私信回复【666】也可获取资料哦~~

注:本文转载自blog.csdn.net的蜀道山QAQ的文章"https://blog.csdn.net/shudaoshanQAQ/article/details/135394734"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top