【Harmony OS 4.0】从零开始,快速上手

news2024/11/14 15:35:15

2019年8月份Harmony OS 1.0,
2020年9月份Harmony OS 2.0
2022年7月份Harmony OS 3.0
2023年3月份Harmony OS 4.0,不兼容 android app

1. 快速上手

1.1 下载并安装 DevEco Studio

1.2 创建项目并初始化

  1. 项目 build init 时报错:request to http://registry.cnpmjs.org/pnpm failed, reason: getaddrinfo ENOTFOUND registry.cnpmjs.org
  2. 运行 npm install -g cnpm --registry=https://registry.npm.taobao.org,仍报错:request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired. 显示证书过期。使用的是老版本的淘宝镜像,淘宝不在维护.
  3. 设置淘宝最新的镜像源. 运行 npm install -g cnpm --registry=https://registry.npmmirror.com. 成功

1.3 创建模拟器

  1. 创建模拟器前需要先申请参加模拟器Beta活动.
  2. 若提示该账号没有权限,请先点击“Submit the application form”完成权限申请.

1.4 了解项目目录:工程级目录 / 模块级目录

  1. 通过修改下面俩个文件路径设置模拟器打开的主页面
    1.1 src/main/ets/entryability/entryability.ts ⇒ windowStage.loadContent(‘test_pages/test2’)
    1.2 resources/base/profile/main_pages.json ⇒ { “src”: [‘test_pages/test2’] },配置router路径

1.5 DevEco Studio 配置 TypeScript

  1. 安装 Nodejs,配置 Nodejs 的环境变量
  2. 安装 typescript,npm install -g typescript,tsc -v 查看版本号
  3. 编译 .ts 文件的命令:tsc 文件名
    编译 .js 文件的命令:node 文件名

2. TypeScript 快速入门

2.1 掌握 ts 常用基本类型

// 1. boolean 类型
let isOff = true
let isOn = false

// 2. 数字类型
let a: Number/number = 2

// 3. 字符串类型
let aStr:string = "hello"

// 4. 俩种数组类型
let arr1:number[] = [1, 3, 5]
let arr2: Array<string> = ["hello", "world"]

// 4.1 回顾splice用法,改变原数组,返回修改后的数组
let arr3 = [1, 3, 5, 7]
arr3.splice(2, 0, 3) // 把值3添加到下标2的地方
console.log(arr3) // [1, 3, 3, 5, 7]
arr3.splice(4, 1) // 删除下标4的值
console.log(arr3) // [1, 3, 3, 5]

// 5. 定义一个元组类型  ==>  允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let arr4: [string, number]
arr4 = ['hello', 100]
arr4 = [100, 'hello'] // error demo
arr4 = ['hello', 100, 200] // error demo

// 6. 定义枚举 enum  ==>  是对javascript标准数据类型的一个补充,可以为一组数值赋予友好的名字。
enum Color { red, green, blue }
let c: Color = Color.green

// 7. 定义未知类型 any/Unknown  ==>  不清楚类型的变量,不希望类型检查器对这些值进行检查,直接通过编译阶段的检查。
let noSure: unknown/any
noSure = 4 // 这里4可以是任意值

// 8. viod  ==>  函数没有返回值
function myfunc(): void {
	// 这里不能有return
}

// 9. Null  ==> 空值,没有给它分配内存,内存中没有变量;
//    undefined  ==> 未定义的变量,有这个变量,但是没有定义

// 10. 联合类型
let a: string | number
a = 'hello'
a = 100

2.2 掌握条件语句

// 1. if
// 2. if...else 
// 3. if...else if...else 
// 4. switch...case,用来做多条件的等于判断
let gender: string = 'mail'
switch (gender) {
	case 'mail': {
		console.log('男')
		break; // 满足条件就终止判断
	}
	case 'femail': {
		console.log('女')
		break;
	}
	default: { // 上面所有case条件都不满足,就会进入default
		console.log('不能确定性别')
		break;
	}
}

2.3 掌握循环语句

// 1. 
let i: numebr;
for(i = 1;i <= 10;i++) {
	console.log(i)
}

// 2. 只能针对集合或者是列表
let j: any
// let j: unkonwn
let nums: Array<number> = [12, 23, 56, 32]
for (j in nums) {
	console.log(nums[j])
}

2.4 掌握函数

// 1. 有名函数
function add(x: number, y: number): void{}
add(10, 20)

// 2. 匿名函数
let add_Func = function(x: number, y: number): number{
	return x + y
}
add_Func(10, 20)

// 3. 可选参数的函数
function fn(x: number, name?: string) :void {}
fn(10)

// 4. 剩余参数 ==> 个数不限的可选参数
function fn(x: number, ...other: Array<any>) :void {}
fn(10, 'hello', 30)

// 5. 箭头函数  ==>  定义匿名函数的简写语法
let fn = (x: number, y: number) => {}

2.5 掌握类对象 ==> public(公共的,在任何地方都一用),private(私有的,只能在类里面用), protected(在一个包里面可以用)

2.5.1 在 ArkTs 中,private 好处是类对象外的代码无法访问到,不允许别人在类外面随意改动它
2.5.2 在 ArkTs 中,private 必须本地初始化。

// 1. 定义一个Person类
class Person {
	// 私有属性
	private name: string
	private age: number
	// 定义构造函数
	constructor(name: string, age: number){
		this.name = name
		this.age = age
	}
	// 公共成员函数
	public getPersonInfo() :string {
		return 	`我的名字是${this.name},年龄是${this.age}`
	}
}
let p = new Person('张三'18)
p.getPersonInfo()

// 2. 继承 extends
// 定义一个Employee类继承Person
class Employee extends Person {
	private department: string;
	constructor(name: string, age: number, department: string){
		// 调用父类的构造函数
		super(name, age)
		this.department = department
	}
	public getEmployeeInfo() :string {
		return this.getPersonInfo() + `,我的工作部门是${this.department}`
	}
}
let emp = new Employee('王五', 26, '行政部')
emp.getEmployeeInfo()
emp.getPersonInfo()

2.6 掌握可迭代对象 ==> 当一个对象实现了 Symbol.iterator 属性时,它是可迭代的。一些内置的类型如 Array, Map, Set, String, Int32Array, Uint32Array 等都具有可迭代性。(可以通过for…of循环遍历的对象)

迭代器都是可迭代对象
可迭代对象是迭代器的一个子集

// 1. for..of 语句,针对可迭代对象才能使用,i 代表其中元素,不指下标。
let str: string = 'sdfs'
for(let i of str) {
	console.log(i) // s d f s
}

// 2. map类型,每个元素都是由俩个组成:key,value
let map1 = new Map<string, number>()
map1.set('a', 111)
map1.set('b', 222)
map1.set('c', 333)
for(let j of map1) {
	console.log(j) // ['a', 111] ['b', 222] ['c', 333]
	console.log(j[1]) // 111 222 333
}

2.7 模块 ==> 前端模块化

3. ArkTs/ArkUI

  1. 继承 TS 的所有特性,是 TS 的超集。
  2. ArkUI 是一套构建分布式应用界面的声明式UI开发框架,只能使用表达式。组件中不需要renturn。
  3. 装饰器:
    3.1 @Entry:标识这是个入口组件,且表示是一个独立page页面,通过router进行跳转。
    3.2 @Component:自定义组件,可进行页面渲染。
    3.3 struct TextExample{}:定义名为TextExample的结构体,代表这个组件
    3.4 build() {}:定义build方法构建UI,类似ReactNative中的render方法,生成节点树实例。
  4. 自定义组件:
  5. 容器组件均支持子组件配置,可以实现相对复杂的多级嵌套。
    Column, Row, Flex, Stack, Grid, List 等组件都是容器组件
  6. 如果组件支持子组件配置,则需在尾随闭包 “{…}” 中为组件添加子组件的UI描述
  7. UI描述:
  8. 系统组件:由ArkUI直接提供的组件。
  9. 自定义组件:由开发者定义的组件。
  10. 属性方法:
  11. 事件方法:

3.1 配置组件的事件方法

事件方法以 “.” 链式调用的方式配置系统组件支持的事件,建议每个事件方法单独写一行。

// 1. 使用箭头函数配置组件的事件方法
Button('Click me')
	.onClick(() => {})

// 2. 使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数题中的this指向当前组件
Button('add counter')
	.onClick(function(){}.bind(this))

// 3. 使用组件的成员函数配置组件的事件方法,⚠️组件的成员函数只能在事件方法上面定义
myClickHandler(): void {}
Button('add counter')
	.onClick(this.myClickHandler.bind(this))

3.2 类型定义

3.2.1 Resource 资源引用类型

// @Builder 自定义构建函数时,用 :Resource 表示资源引用类型
@Builder function CreateIcon (icon: Resource): void {
  Column() {
    Image(icon).width(28).height(28).objectFit(ImageFit.Contain).margin(10)
  }
}

3.2.2 Length 长度类型,用于描述尺寸单位

@Prop widthValue: Length = 0

3.2.3 ResourceStr 字符串类型,用于描述字符串入参可以使用的类型
3.2.4 Padding 内边距类型,用于描述组件不同方向的内边距
3.2.5 Margin

4. 容器组件

4.1 Column

  1. 是沿垂直方向布局容器
  2. 支持很多通用属性,如alignItems,justifyContent,width,height,border等
// 常用属性
Column({space: 5}){} // 创建一个column容器组件,设置子元素间的垂直间距为5,纵向布局元素垂直方向间距为5.
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Center)

4.2 Row

  1. 是沿水平方向布局容器
  2. 支持很多通用属性,如alignItems,justifyContent,width,height,border等
// 常用属性
Row({space: 5}){} // 横向布局元素间距
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Start)

4.3 List

  1. onReachEnd 事件:列表到底末尾位置时触发。
    List边缘效果为弹簧效果时,划动经过末尾位置时触发一次,回弹回末尾位置时再触发一次。

5. 基础组件

5.1 Text

  1. Text 组件是可以显示一段文本的组件。
// 常用属性:
.textAlign(TextAlign.Center)
.fontSize(14)
.fontColor()
.textOverflow({overflow: TextOverflow.Ellipsis}) // 设置文本溢出方式为省略号
.maxLines(1) // 设置最大行数为1
.border({width: 1})
.lineHeight(15) // 设置行高为20
.padding(10)

5.2 Image

// 引入项目本地 resources/base/media 路径下的图片
Image($r('app.media.ic_default'))

// @Builder 自定义构建函数时,用 :Resource 表示资源引用类型
@Builder function CreateIcon (icon: Resource): void {
  Column() {
    Image(icon).width(28).height(28).objectFit(ImageFit.Contain).margin(10)
  }
}

5.3 ScrollBar

  1. 滚动条组件ScrollBar,用于配合可滚动组件使用,如List、Grid、Scroll

6. @Component 自定义组件

  1. @Component 装饰的UI单元,可以组合多个系统组件实现UI的复用。
  2. 由开发者定义的称为自定义组件
  3. 具有以下特点
    3.1 可组合:允许开发者组合使用系统组件,及其属性和方法。
    3.2 可重用:可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
    3.3 数据驱动UI更新,通过状态变量的改变,来驱动UI的刷新。

6.1 自定义组件通用样式

@Component
struct 自定义组件名 {
	build() {}
}

6.2 实现并引用自定义组件

// 自定义子组件
@Component
struct MyHelloComponent {
  @State username: string = '🧚‍'
  build(){
    Column() {
      Text(`hello ${this.username}`)
        .fontSize(16)
        .fontColor(Color.Grey)
        .height(15)
        .onClick(() => {
          this.username = '七喜'
        })
    }
  }
}
// 父组件
@Entry
@Component
struct UITest3 {
  build() {
    Column({space: 10}) {
      Text('主界面')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.Black)
      MyHelloComponent({username: 'world'}) // 引用自定义组件
      Divider()
      MyHelloComponent({username: 'SZ'}) // 引用自定义组件
    }
  }
}

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

  1. 自定义组件:@Component 装饰的UI单元,可以组合多个系统组件实现UI的复用。
    组件生命周期,即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:
    1.1 aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
    1.1 aboutToDisappear:在自定义组件即将析构销毁时执行。
  2. 页面:即应用的UI页面。可以由一个或多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。
    只有被@Entry装饰的组件才可以调用页面的生命周期。页面生命周期,即被@Entry装饰的组件生命周期,提供以下生命周期接口:
    2.1 onPageShow:页面每次显示时触发。
    2.2 onPageHide:页面每次隐藏时触发一次。
    2.3 onBackPress:当用户点击返回按钮时触发。
  3. 流程图如下
    在这里插入图片描述

7.1 入口组件(页面)嵌套自定义组件的生命周期流程

  1. 页面组件aboutToAppear —> 自定义组件aboutToAppear —> 页面组件onPageShow(在页面组件点击删除自定义组件) --> 自定义组件aboutToDisappear
  2. 在页面组件跳转到另一个页面组件,页面组件onPageHide
  3. 在页面组件返回手机主屏,页面组件aboutToDisappear

8. @Builder 自定义构建函数

8.1 自定义组件内自定义构建函数

// 1. 定义语法
@Builder MyBuilderFunction() {}

// 2. 使用语法
this.MyBuilderFunction() {}

8.2 全局自定义构建函数

// 1. 定义语法
@Builder function MyGlobalBuilderFunction() {}

// 2. 使用语法
MyGlobalBuilderFunction() {}

8.3 参数传递规则

  1. 按引用传递参数
  2. 按值传递参数
    2.1 当传递的参数为状态变量时,状态变量的改变不会引起@Builder方法内的UI刷新。所以当使用状态变量的时候,推荐使用按引用传递
// 按引用传递参数
class obj {
  username: string = ''
}
@Builder function MyBuilder($$: obj) { // 参数需要直接传入对象字面量才会按引用传递该参数,其余传递方式均为按值传递。
  Column() {
    Text(`hello ${$$.username}`)
      .fontSize(18)
      .fontColor(Color.Grey)
  }
}

@Entry
@Component
struct UITest4 {
  @State person_name: string = '花花' // 当传递的参数为状态变量时,状态变量的改变才会引起@Builder方法内的UI刷新
  build() {
    Column() {
      MyBuilder({username: this.person_name})
      Button('点击修改')
        .margin({top: 8})
        .onClick(() => {
          this.person_name = '七喜'
        })
    }
  }
}

9. 状态管理

  1. 状态变量:被状态装饰器(@State) 装饰的变量叫状态变量,状态变量值的改变会引起UI的渲染更新。@State count: number = 0
  2. 常规变量:没有被状态装饰器修饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的渲染更新。private/public increaseBy: number = 1
  3. 数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。
  4. 命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段
  5. 从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。子组件初始化的默认值在有父组件传值的情况下,会被覆盖。
  6. 初始化子组件:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量
  7. 本地初始化:在变量声明的时候赋值,作为变量的默认值。

9.1 @State装饰器 - 组件内状态 - 必须本地初始化

  1. 与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化
  2. 与子组件中的@Prop,@Link、@ObjectLink装饰变量之间建立双向数据同步。
// 自定义类型
class Person {
  public name: string
  public age: number

  constructor(xName: string, xAge: number) {
    this.name = xName
    this.age = xAge
  }
}
// 自定义子组件
@Component
struct MyChild {
  @State person: Person = new Person('魔鬼', 18) // 指定自定义类型,初始化值
  private increase: number = 1

  build() {
    Column({space: 3}) {
      Text(`${this.person.name}、年龄${this.person.age}`).fontSize(18).fontWeight(500).height(60)
      Divider()
      Button(`修改姓名`).onClick(() => {
        this.person.name = this.person.name ===  '魔鬼' ? '天使': '魔鬼'
      })
        .width(200)
        .height(60)
      Button('修改年龄').onClick(() => {
        this.person.age += this.increase
      })
        .width(200)
        .height(60)
    }
      // .backgroundColor('#CCBBFF')
  }
}
// 父组件
@Entry
@Component
struct UITest5 {
  build() {
    Column({space: 30}) {
      MyChild({person: new Person('天使', 2), increase: 1})
      MyChild({increase: 2})
      MyChild()
    }
  }
}

9.2 @Prop装饰器 - 父子单向同步 - 允许本地初始化

  1. @Prop装饰变量时会进行深拷贝,在拷贝的过程中除了基本类型、Map、Set、Date、Array外,都会丢失类型。
  2. @Prop装饰器不能在@Entry装饰的自定义组件中使用。
  3. 被装饰变量的初始值,允许本地初始化。
// @Prop装饰器 - 父子单向同步
// 子组件
@Component
struct MyChild {
  @Prop age: number = 9 // 被装饰变量的初始值,允许本地初始化。当没有初始值时,页面显示undefined
  private increase: number = 1
  build() {
    Column(){
      if (this.age >= 18) {
        Text(`子组件年龄${this.age}`).height(60)
      } else {
        Text(`未成年${this.age}`).height(60)
      }
      Button('减少子组件年龄').onClick(() => {
        this.age -= this.increase
      })
    }
  }
}
// 父组件
@Entry
@Component
struct UITest6{
  @State init_age: number = 14
  build() {
    Column() {
      Text(`父组件年龄${this.init_age}`).height(60)
      Button('增加父组件年龄').onClick(() => {
        this.init_age += 1
      })
      Divider()
      MyChild({age: this.init_age, increase: 2})
      Divider()
      MyChild()
    }
  }
}

9.3 @Link装饰器 - 父子双向同步 - 禁止本地初始化

  1. 父组件中@State, @StorageLink和@Link 和 子组件@Link可以建立双向数据同步。
  2. 被装饰变量的初始值,禁止本地初始化。

下面代码展示了class类对象类型、简单类型,俩种父子双向数据同步示例。

// @Link装饰器 - 父子双向同步。class类对象类型和简单类型俩种父子双向同步
// 自定义class类对象类型
class ButtonState {
  value: string
  width: number

  constructor(value: string, width: number) {
    this.value = value
    this.width = width
  }
}
// 一号子组件 - class类对象类型
@Component
struct MyChildButton01 {
  // class类对象类型
  @Link buttonState: ButtonState

  build() {
    Column() {
      Button(`${this.buttonState.value}${this.buttonState.width}`)
        .width(this.buttonState.width)
        .height(50)
        .backgroundColor('#B088FF')
        .fontColor('#FFFFFF,90%')
        .onClick(() => {
          if (this.buttonState.width < 400) {
            this.buttonState.width += 50
          } else {
            this.buttonState = new ButtonState('一号本地', 100)
          }
        })
    }
  }
}
// 二号子组件 - 简单类型
@Component
struct MyChildButton02 {
  // 简单类型
  @Link buttonValue: string
  @Link buttonWidth: number

  build() {
    Column() {
      Button(`${this.buttonValue}${this.buttonWidth}`)
        .width(this.buttonWidth)
        .height(50)
        .backgroundColor('#FF7744')
        .fontColor('#FFFFFF,90%')
        .onClick(() => {
          this.buttonValue = this.buttonWidth < 400 ? this.buttonValue : '二号本地'
          this.buttonWidth = this.buttonWidth < 400 ? this.buttonWidth + 50 : 100
        })
    }
  }
}
// 父组件
@Entry
@Component
struct UITest6 {
  // class类对象类型
  @State parentButton: ButtonState = new ButtonState('一号子级', 100)
  // 简单类型
  @State parentValue: string = '二号子级'
  @State parentWidth: number = 100

  build() {
    Column({space: 10}) {
      Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
        // class类对象类型从父组件@State向子组件@Link数据同步
        Button(`父组件中修改${this.parentButton.value}${this.parentButton.width}`).onClick(() => {
          this.parentButton.width = this.parentButton.width < 400 ? this.parentButton.width + 50 : 100
        })
        // 简单类型从父组件@State向子组件@Link数据同步
        Button(`父组件中修改${this.parentValue}${this.parentWidth}`).onClick(() => {
          this.parentWidth = this.parentWidth < 400 ? this.parentWidth + 50 : 100
        })
        // class类对象类型初始化@Link
        MyChildButton01({ buttonState: $parentButton })
        // 简单类型初始化@Link
        MyChildButton02({ buttonValue: $parentValue, buttonWidth: $parentWidth })
      }
    }
  }
}

10. if/else 条件渲染

  1. 渲染控制的能力
  2. 修改条件分支的时候,会把原来的条件分支组件先删除,再重新创建一个条件分支组件。
// if/else 条件渲染
// 子组件
@Component
struct MyChild {
  @Link count: number // @Link装饰器 - 父子双向同步 - 禁止本地初始化
  @Prop label: string // @Prop装饰器 - 父子单向同步 - 允许本地初始化

  build() {
    Row() {
      Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
        Text(`${this.label}`)
        Button(`计数器${this.count}`).onClick(() => {
          this.count += 1
        })
      }
      // .backgroundColor('#B94FFF')
    }
  }
}
// 父组件
@Entry
@Component
struct UITest6 {
  @State flag: boolean = true // @State装饰器 - 组件内状态 - 必须本地初始化
  @State parentCount: number = 0

  build() {
    Column() {
      if (this.flag) {
        MyChild({ count: $parentCount, label: '真真' })
      } else {
        MyChild({ count: $parentCount, label: '假假' })
      }
      Button(`是否真假:${this.flag}`).onClick(() => {
        this.flag = !this.flag
      }).margin(10)
    }
  }
}

11. ForEach 循环渲染

  1. ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。
    例如,ListItem组件要求ForEach的父容器组件必须为List组件。
  2. 数组类型数据
  3. 接受三个参数
  4. 和 if…else 不一样,会做二次渲染,可以做到单独修改某一个值。
// ForEach 循环渲染
// 子组件
@Component
struct MyChild {
  @Prop label: string

  build() {
    Column() {
      Text(this.label).fontSize(24).fontColor("#9955FF")
    }
  }
}
// 父组件
@Entry
@Component
struct UITest7 {
  @State my_array: Array<string> = ['one', 'two', 'three']

  build() {
    Column({space: 15}) {
      ForEach(this.my_array, (item: string, index: number) => { // ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用。
        MyChild({label: item}) // 且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。
      })
      Button('修改two').onClick(() => {
        this.my_array[1] = 'new_two' // 和 if..else 不一样,会做二次渲染,可以做到单独修改某一个值。
      })
    }
    .justifyContent(FlexAlign.Center)
    .height("100%")
    .width('100%')
  }
}

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

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

相关文章

产业经济大脑建设方案(三)

为了加速产业经济的智能化转型&#xff0c;我们建议建立一个全面集成的产业经济大脑系统&#xff0c;该系统结合人工智能、大数据分析和云计算技术&#xff0c;构建数据驱动的决策支持平台。该平台将实时采集和处理产业链各环节的数据&#xff0c;利用智能算法进行深度分析和预…

【C++】C++11新增特性

目录 C11简介&#xff1a; 1、统一的列表初始化&#xff1a; std::initializer_list 2、自动类型推导&#xff1a; auto&#xff1a; decltype&#xff1a; 3、final 和 override final&#xff1a; override&#xff1a; 4、默认成员函数控制&#xff1a; 显示缺省…

网络安全简介(入门篇)

目录 前言 一、什么是网络安全&#xff1f; 二、网络安全的重要性 1、保护数据安全和隐私 2、防止服务中断和数据丢失 3、防止经济损失和法律责任 4、维护公共安全和国家安全 5、提升技术发展和创新 三、网络安全等级保护 1、第一级&#xff08;自主保护级&#xff0…

Java基础-Windows开发环境下Java8和OpenJDK17的自由切换

一、Java语言介绍 Java是一种广泛使用的编程语言和计算平台&#xff0c;具有平台无关性、稳定性和强大的生态系统。随着时间的推移&#xff0c;Java不断演进&#xff0c;推出了多个版本&#xff0c;每个版本都带来了新的功能和性能改进。 1. Java主流版本 Java的主流版本包括…

【排序篇】快速排序的非递归实现与归并排序的实现

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 文章目录 1 快速排序非递归2. 归并排序3.排序算法复杂度及稳定性分析 1 快速排序非递归 利…

Leetcode面试经典150题-14.最长公共前缀

解法都在代码里&#xff0c;不懂就留言或者私信 这个题比较简单&#xff0c;基本上是笔试的第一第二题 class Solution {/**最长公共前缀这种问题个人感觉最重要的是剪枝我理解可以先按照字符串的长度排个序&#xff0c;然后把第一个字符串的长度作为暂时的最长公共前缀的长度…

分享一个基于python爬虫的“今日头条”新闻数据分析可视化系统(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

【装修】出租屋改造计划,米家IoT全屋智能家居方案 投影仪与家庭ktv游戏影院方案

【装修】出租屋改造计划&#xff0c;米家IoT全屋智能家居方案 & 投影仪与家庭ktv游戏影院方案 文章目录 1、目标效果 & 预算2、网络&#xff1a;路由 & 中枢网关方案3、卧室&#xff1a;灯光系列 & 环境系列4、米家&#xff1a;其他房间&#xff08;暂不装&…

C++ 内存布局 - Part2: 从内存布局角度看类型转换 static_cast, dynamic_cast, reinterpret_cast

0. 总论 开门见山&#xff0c;先把结论写在这里&#xff1a; 1&#xff09;static_cast 在做基类指针和派生类指针之间的转换时&#xff0c;会根据编译时的静态偏移操作指针&#xff0c;但是没有运行期的类型安全检查&#xff0c;程序员需要自己确保类型的正确性&#xff0c;…

ollama轻松部署本地GraphRAG(避雷篇)

本篇文章主要介绍如何使用ollama本地部署微软的Graph RAG&#xff0c;&#xff0c;Graph RAG成为RAG一种新范式&#xff0c;对于全局总结性问题表现突出&#xff0c;当开始的技术路线是Qwen2vllmfastchat本地部署Grapg RAG&#xff0c;但是embedding 的openai服务怎么都跑不起来…

完整搭建windows下mysql8.0源码编译调试环境!

背景&#xff1a; 前段时间一直在看mysql相关的博客&#xff0c;所以对源码起了浓厚的兴趣&#xff0c;所以尝试通过vmware和vscode在windosw环境中搭建一套编译调试的环境~ 看了一下网上的搭建教程基本杂乱无章&#xff0c;想要从零跟着搭建出一个完善的调试环境也不是易事&…

redis I/O复用机制

I/O复用模型 传统阻塞I/O模型 串行化处理&#xff0c;就是要等&#xff0c;假如进行到accept操作&#xff0c;cpu需要等待客户端发送的数据到tcp接收缓冲区才能进行read操作&#xff0c;而在此期间cpu不能执行任何操作。 I/O复用 用一个进程监听大量连接&#xff0c;当某个连…

国产大模型领域跳槽:收入潜力解析

夏尽秋来&#xff0c;2024年国产大模型看似喧闹已止&#xff0c;进入稳定竞争期。 作为一种新的IT解决方案&#xff0c;国产大模型一出生便伴随着激烈竞争。 外有GPT4&#xff0c;内有多家公司角逐“中国版ChatGPT”。 据我所知&#xff0c;就国内某家头部大模型创业公司的收…

0817(持久层框架:JDBC,MyBatis)

三层架构&#xff08;表现层&#xff0c;业务层&#xff0c;持久层&#xff09; java中框架的概述&#xff08;表现层、业务层、持久层的关系&#xff09;_控制层业务层持久层的关系-CSDN博客 框架&#xff1a;框架一般处在低层应用平台&#xff08;如J2EE&#xff09;和高层…

利用keepalived达成服务高可用

官方网站Keepalived for Linux 1.keepalived简介 vrrp 协议的软件实现&#xff0c;原生设计目的为了 高可用 ipvs 服务 功能&#xff1a; 基于 vrrp 协议完成地址流动 为 vip 地址所在的节点生成 ipvs 规则 ( 在配置文件中预先定义 ) 为 ipvs 集群的各 RS 做健康状态检测 …

【Linux网络】NAT技术

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 引言 随着互联网的飞速发展&#xff0c;IP地址资源日益紧张&#xff0c;这促使了NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;技术的诞生与发展。NAT技术不仅解决了IPv4…

webshell免杀--免杀入门

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理webshell免杀的一些基础思路 入门级&#xff0c;不是很深入&#xff0c;主要是整理相关概念 免杀对象 1.各类杀毒软件 类似360&#xff0c;火绒等&#xff0c;查杀己方webshell的软件。 2.各类流量…

计算机网络系统速成

Http与Https Http与Https是两种重要的网络通信协议&#xff0c;它们在Web通信中扮演着关键角色。以下是对Http与Https的详细解析&#xff1a; 一、Http&#xff08;超文本传输协议&#xff09; 1. 定义与功能 定义&#xff1a;Http&#xff08;HyperText Transfer Protocol…

打卡学习Python爬虫第三天|电影天堂案例

一、明确需求 目标&#xff1a;爬取最新更新的电影的豆瓣链接 观察网页和页面源代码&#xff0c;每部电影都有一个超链接去到子页面&#xff0c;我们需要的内容在子页面&#xff0c;如果我们一个一个子页面的去爬取会比较麻烦&#xff0c;可以尝试先通过首页爬取子页面的超链…

指针初阶(指针类型转换的使用、指针数组)

一.指针基础 0.指针的大小 指针指向的是一块地址&#xff0c;所以指针存储的是地址&#xff0c;例如在32位系统中。定义了一个int32_t类型的变量。使用int32_t *定义一个指针&#xff0c;使其指向该变量。 设该变量存储在地址为00000000000000000000000000000001&#xff08;3…