【鸿蒙 HarmonyOS 4.0】TypeScript开发语言

一、背景

HarmonyOS 应用的主要开发语言是 ArkTS,它由 TypeScript(简称TS)扩展而来,在继承TypeScript语法的基础上进行了一系列优化,使开发者能够以更简洁、更自然的方式开发应用。值得注意的是,TypeScript 本身也是由另一门语言 JavaScript 扩展而来。因此三者的关系如下图所示

二、TypeScript

2.1、运行环境

2.1.1、线上Playground

TypeScript提供了一个线上的 Playground 供练习使用,地址为TypeScript: 演练场 - 一个用于 TypeScript 和 JavaScript 的在线编辑器。

2.1.2、本地运行环境 

2.1.2.1、采用的是VSCode 编辑器
2.1.2.2、前提条件

1、安装插件:Code Runner:它提供了简便的代码执行功能,支持多种编程语言,使开发者能够快速运行和调试代码片段。


2、安装Node.js并配置Path环境变量

说明:我已经安装了Node.js,便不重复安装了

为了方便在终端执行Node.js相关的命令,我们需要将Node.js的安装目录加入到Path环境变量下

步骤1:首先在DevEco Studio的设置界面查看Node.js的安装目录

步骤2:然后打开环境变量配置面板,按下 Win+,唤起运行窗口,之后运行命令 sysdm.cpl 

步骤3:点击高级选项卡,并点击环境变量

步骤4:在系统变量中选中 Path ,并点击编辑

步骤5:点击新建,并填入Node.js的安装目录,完成后点击确定


3、安装ts-node

这是一个 TypeScript 的运行环境,它允许我们直接运行 TypeScript 代码。ts-node的安装和运行依赖于Node.js环境,已经安装了Node.js

npm install -g ts-node

在终端中输入node -v 和ts-node -v后出现各自版本,说明这两个已经安装成功了,如下:

注:完成后需要重新启动VSCode,另其重新加载环境变量和相关依赖。

2.1.2.3、编写程序并运行

首先在合适的位置创建一个工程目录,例如C:\Users\......\hello-ts,然后使用VSCode打开目录,创建ts文件,并编写Typescript代码运行

问题:运行ts时出现以下错误,百度后发现是由于 ts-node 版本升级导致的兼容性问题

解决:需要在项目中安装  @types/node 

npm install --save-dev @types/node

效果: 安装  @types/node 后,再运行就能够正常打印日志了

2.2、声明

2.2.1、变量声明

2.2.2、常量声明

 let用于声明变量,而const用于声明常量,两者的区别是变量在赋值后可以修改,而常量在赋值后便不能再修改。

const b:number = 200;

2.2.3、类型推断 

如果一个变量或常量的声明包含了初始值,TS 便可以根据初始值进行类型推断,此时我们就可以不显式指定其类型,例如

let c = 60;
console.log(typeof c); //number

2.3、常用数据类型 

2.3.1、number

number表示数字,包括整数和浮点数,例如: 100-332.5-3.9

let a :number = 100
let b :number = -33
let c :number = 2.5
let d :number = -3.9

2.3.2、string 

string表示字符串,例如: 你好hello

let a:string = '你好'
let b:string = 'hello'

 2.3.3、boolean

boolean表示布尔值,可选值为:truefalse

let isOpen:boolean = true
let isDone:boolean = false

 2.3.4、数组

数组类型定义由两部分组成,元素类型[],例如number[]表示数字数组,string[]表示字符串数组,数组类型的变量可由数组字面量——[item1,item2,item3]进行初始化。

let a: number[] = []
let b: string[] = ['你好', 'hello']

2.3.5、对象 

在TS中,对象(object)是一种一系列由属性名称属性值组成的数据结构,例如姓名:'张三', 年龄:10, 性别:'男'。对象类型的声明需要包含所有属性的名称类型,例如{name: string, age: number, gender: string},对象类型的变量可以通过对象字面量——{name:'张三', age:10, gender:'男'}进行初始化。

let person: {name:string, age:number, gender:string} = {name:'张三', age:10, gender:'男'};

2.4、函数 

2.4.1、函数声明语法

声明函数的基础语法如下

2.4.2、参数

2.4.2.1、特殊语法

①可选参数

可选参数通过参数名后的?进行标识,如以下案例中的gender?参数。

function getPersonInfo(name: string, age: number, gender?: string): string {if (gender === undefined) {gender = '未知'}return `name:${name},age:${age},gender:${gender}`;
}let p1 = getPersonInfo('zhagnsan', 10, '男')
let p2 = getPersonInfo('lisi', 15);
console.log(p1);
console.log(p2);

注:调用函数时,未传递可选参数,则该参数的值为undefined

②默认参数

可在函数的参数列表为参数指定默认值,如以下案例中的gender: string='未知'参数。

function getPersonInfo(name: string, age: number, gender: string='未知'): string {return `name:${name},age:${age},gender:${gender}`;
}let p1 = getPersonInfo('zhagnsan', 10, '男')
let p2 = getPersonInfo('lisi', 15);
console.log(p1);
console.log(p2);
2.4.2.2、 特殊类型

①联合类型

一个函数可能用于处理不同类型的值,这种情况可以使用联合类型,例如以下案例中的message: number | string

function printNumberOrString(message: number | string) {console.log(message)
}printNumberOrString('a')
printNumberOrString(1)

②任意类型

 若函数需要处理任意类型的值,则可以使用any类型,例如以下案例中的message: any

function print(message:any) {console.log(message)
}print('a')
print(1)
print(true)

2.4.3、 返回值

2.4.3.1、特殊类型

若函数没有返回值,则可以使用void作为返回值类型,其含义为空。

function test(): void {console.log('hello');
}
2.4.3.2、类型推断

函数的返回值类型可根据函数内容推断出来,因此可以省略不写。

function test() {console.log('hello');
}function sum(a: number, b: number) {return a + b;
}

2.4.4、函数声明特殊语法

①匿名函数

匿名函数的语法结构简洁,特别适用于简单且仅需一次性使用的场景。

let numbers: number[] = [1, 2, 3, 4, 5]
numbers.forEach(function (number) {console.log(number);
})

注意:匿名函数能够根据上下文推断出参数类型,因此参数类型可以省略。

②箭头函数

匿名函数的语法还可以进一步的简化,只保留参数列表和函数体两个核心部分,两者用=>符号连接。

let numbers: number[] = [1, 2, 3, 4, 5]
numbers.forEach((num) => { console.log(num) })

2.5、类

2.5.1、类介绍

类(class)是面向对象编程语言中的一个重要概念。

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,其核心理念在于将程序中的数据与操作数据的方法有机地组织成对象,从而使程序结构更加模块化和易于理解。通过对象之间的协同合作,实现更为复杂的程序功能。

类(class)是对象的蓝图或模板,它定义了对象的属性(数据)和行为(方法)。通过类可以创建多个具有相似结构和行为的对象。例如定义一个 Person类,其对象可以有张三李四等等。

2.5.2、语法说明

2.5.2.1、类的定义

class Person {id: number;name: string;age: number = 18;constructor(id: number, name: string) {this.id = id;this.name = name;}introduce(): string {return `hello,I am ${this.name},and I am ${this.age} years old`}
}
2.5.2.2、对象创建

①语法

创建对象的关键字为new,具体语法如下

let person = new Person(1,'zhangsan');

②对象属性的访问

console.log(person.name); //读person.name = 'lisi'; //写console.log(person.name);

③对象方法的调用

对象创建后,便可通过对象调用类中声明的方法,如下

let intro = person.introduce();
console.log(intro);
2.5.2.3、静态成员

Typescript 中的类中可以包含静态成员(静态属性和静态方法),静态成员隶属于类本身,而不属于某个对象实例。静态成员通用用于定义一些常量,或者工具方法。

①声明静态成员

定义静态成员需要使用static关键字。

class Constants{static count:number=1;
}class Utils{static toLowerCase(str:string){return str.toLowerCase();}
}console.log(Constants.count);
console.log(Utils.toLowerCase('Hello World'));

②使用静态成员

静态成员无需通过对象实例访问,直接通过类本身访问即可。

console.log(Constants.count);
console.log(Utils.toLowerCase('Hello World'));

2.5.3、继承

继承是面向对象编程中的重要机制,允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。子类可以直接使用父类的特性,并根据需要添加新的特性或覆盖现有的特性。这种机制赋予面向对象程序良好的扩展性。

class Student extends Person {classNumber: string;constructor(id: number, name: string, classNumber: string) {super(id, name);this.classNumber = classNumber;}introduce(): string {return super.introduce()+`, and I am a student`;}
}let student = new Student(1,'xiaoming','三年二班');
console.log(student.introduce());

注意:

  • 类的继承需要使用关键字extends
  • 子类构造器中需使用super()调用父类构造器对继承自父类的属性进行初始化。
  • 在子类中可以使用this关键字访问继承自父类的属性和方法。
  • 在子类中可以使用super关键字访问父类定义的方法。

2.5.4、访问修饰符

访问修饰符(Access Modifiers)用于控制类成员(属性、方法等)的可访问性。TypeScript提供了三种访问修饰符,分别是privateprotectedpublic

class Person {private id: number;protected name: string;public age: number;constructor(id: number, name: string, age: number) {this.id = id;this.name = name;this.age = age;}
}class Student extends Person {}

说明:

  • private 修饰的属性或方法是私有的,只能在声明它的类中的被访问。
  • protected 修饰的属性或方法是受保护的,只能在声明它的类和其子类中被访问。
  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的。

2.6、接口

2.6.1、接口介绍

接口(interface)是面向对象编程中的另一个重要概念。接口通常会作为一种契约或规范让类(class)去遵守,确保类实现某些特定的行为或功能。

2.6.2、语法说明

①接口定义

接口使用interface关键字定义,通常情况下,接口中只会包含属性和方法的声明,而不包含具体的实现细节,具体的细节由其实现类完成。

interface Person {id: number;name: string;age: number;introduce(): void;
}

②接口实现

接口的实现需要用到implements关键字,实现类中,需要包含接口属性的赋值逻辑,以及接口方法的实现逻辑。

class Student implements Person {id: number;name: string;age: number;constructor(id: number, name: string, age: number) {this.id = id;this.name = name;this.age = age;}introduce(): void {console.log('Hello,I am a student');}
}

2.6.3、多态

多态是面相对象编程中的一个重要概念,它可以使同一类型的对象具有不同的行为。下面我们通过一个具体的案例来体会多态这一概念

首先,再创建一个Person接口的实现类Teacher,如下

class Teacher implements Person {id: number;name: string;age: number;constructor(id: number, name: string, age: number) {this.id = id;this.name = name;this.age = age;}introduce(): void {console.log('Hello,I am a teacher');}
}

然后分别创建一个Student对象和一个Teacher对象,注意两个对象的类型均可以设置Person,如下

let p1: Person = new Student(1, 'zhangsan', 17);
let p2: Person = new Teacher(2, 'lisi', 35);

最后分别调用p1p2introduce()方法,你会发现,同样是Person类型的两个对象,调用同一个introduce()方法时,表现出了不同的行为,这就是多态

p1.introduce();//Hello,I am a student
p2.introduce();//Hello,I am a teacher

2.6.4、接口的作用

在传统的面向对象编程的场景中,接口主要用于设计和组织代码,使代码更加容易扩展和维护。

假如现在需要实现一个订单支付系统,按照面向对象编程的习惯,首先需要定义一个订单类(Order),如下

class Order {totalAmount: number;constructor(totalAmount: number) {this.totalAmount = totalAmount;}pay() {console.log(`AliPay:${this.totalAmount}`);}
}

很容易预想到,这个系统将来可能需要支持其他的支付方式,为了方便代码支持新的支付方式,我们可以对代码进行如下改造。

首先定义一个支付策略的接口,接口中声明一个pay方法,用来规范实现类必须实现支付逻辑。

interface PaymentStrategy {pay(amount: number): void;
}

然后在订单类中增加一个PaymentStrategy的属性,并且在订单类中的pay方法中调用PaymentStrategypay方法,如下

class Order {totalAmount: number;paymentStrategy: PaymentStrategy;constructor(totalAmount: number, paymentStrategy: PaymentStrategy) {this.totalAmount = totalAmount;this.paymentStrategy = paymentStrategy;}pay() {this.paymentStrategy.pay(this.totalAmount);}
}

这样改造完之后,就可以很容易的在不改变现有代码的情况下,支持新的支付方式了。

比如现在需要支持AliPay,那我们就可以创建AliPay这个类(class)并实现(implement)PaymentStrategy这个接口,如下

class AliPay implements PaymentStrategy {pay(amount: number): void {console.log(`AliPay:${amount}`);}
}

这样一来,之后创建的订单就可以使用AliPay这个支付方式了。

let order = new Order(1000,new AliPay());
order.pay();

2.6.5、TS中接口的特殊性

TypeScript 中的接口是一个非常灵活的概念,除了用作类的规范之外,也常用于直接描述对象的类型,例如,现有一个变量的定义如下

let person: {name:string, age:number, gender:string} = {name:'张三', age:10, gender:'男'};

可以看到变量的值为一个一般对象,变量的类型为{name:string, age:number, gender:string},此时就可以声明一个接口来描述该对象的类型,如下

interface Person {name: string;age: number;gender: string;
}let person: Person = {name:'张三', age:10, gender:'男'};

2.7、枚举

2.7.1、枚举介绍

枚举(Enumeration)是编程语言中常见的一种数据类型,其主要功能是定义一组有限的选项,例如,方向(上、下、左、右)或季节(春、夏、秋、冬)等概念都可以使用枚举类型定义。

2.7.2、语法说明

①枚举定义

枚举的定义需使用enum关键字,如下

enum Season {SPRING,SUMMER,AUTUMN,WINTER
}

②枚举使用

枚举的使用记住两个原则即可

  • 枚举值的访问

像访问对象属性一样访问枚举值,例如Season.SPRING

  • 枚举值的类型

枚举值的类型为enum的名称,例如Season.SPRINGSeason.SUMMER等值的类型都是Season

let spring:Season = Season.SPRING;

③使用场景

现需要编写一个函数move,其功能是根据输入的方向(上、下、左、右)进行移动,此时就可以先使用枚举定义好所有可能的输入选项,如下

enum Direction {UP,BOTTOM,LEFT,RIGHT
}

move函数的实现如下

function move(direction: Direction) {if(direction===Direction.UP){console.log('向上移动');}else if(direction===Direction.BOTTOM){console.log('向下移动');}else if(direction===Direction.LEFT){console.log('向左移动');}else{console.log('向右移动');}
}move(Direction.UP);

2.7.3、赋值

在TypeScript 中,枚举实际上是一个对象,而每个枚举值都是该对象的一个属性,并且每个属性都有具体的值,属性值只支持两种类型——数字或字符串。

默认情况下,每个属性的值都是数字,并且从 0 开始递增,例如上述案例中的Direction枚举中,Direction.UP的值为0Direction.BOTTOM的值为1,依次类推,具体如下

console.log(Direction.UP) //0
console.log(Direction.BOTTOM) //1
console.log(Direction.LEFT) //2
console.log(Direction.RIGHT) //3

除了使用默认的数字作为属性的值,我们还能手动为每个属性赋值,例如

enum Direction {UP = 1,BOTTOM = 2,LEFT = 3,RIGHT = 4
}console.log(Direction.UP) //1
console.log(Direction.BOTTOM) //2
console.log(Direction.LEFT) //3
console.log(Direction.RIGHT) //4

再例如

enum Direction {UP = 'up',BOTTOM = 'bottom',LEFT = 'left',RIGHT = 'right'
}console.log(Direction.UP) //up
console.log(Direction.BOTTOM) //bottom
console.log(Direction.LEFT) //left
console.log(Direction.RIGHT) //right

通过为枚举属性赋值,可以赋予枚举属性一些更有意义的信息,例如以下枚举

enum Color {Red = 0xFF0000,Green = 0x00FF00,Blue = 0x0000FF
}enum FontSize {Small = 12,Medium = 16,Large = 20,ExtraLarge = 24
}

2.8、模块化

2.8.1、模块化介绍

模块化是指将复杂的程序拆解为多个独立的文件单元,每个文件被称为一个模块。在 TypeScript 中,默认情况下,每个模块都拥有自己的作用域,这意味着在一个模块中声明的任何内容(如变量、函数、类等)在该模块外部是不可见的。为了在一个模块中使用其他模块的内容,必须对这些内容进行导入导出

2.8.2、语法说明

①导出

导出须使用export关键字,语法如下

export function hello() {console.log('hello module A');
}export const str = 'hello world';const num = 1;

②导入

导入须使用import关键字,语法如下

import { hello, str } from './moduleA';hello();
console.log(str);

2.8.3、避免命名冲突

若多个模块中具有命名相同的变量、函数等内容,将这些内容导入到同一模块下就会出现命名冲突。例如,在上述案例的基础上,又增加了一个 moduleC,内容如下

export function hello() {console.log('hello module C');
}export const str = 'module C';

moduleB 同时引入 moduleA 和 moduleC 的内容,如下,显然就会出命名冲突

import { hello, str } from "./moduleA";
import { hello, str } from "./moduleC";hello() //?
console.log(str); //?

①导入重命名

import { hello as helloFromA, str as strFromA } from "./moduleA";
import { hello as helloFromC, str as strFromC } from "./moduleC";helloFromA();
console.log(strFromA);helloFromC();
console.log(strFromC);

②创建模块对象

上述导入重命名的方式能够很好的解决命名冲突的问题,但是当冲突内容较多时,这种写法会比较冗长。除了导入重命名外,还可以将某个模块的内容统一导入到一个模块对象上,这样就能简洁有效的解决命名冲突的问题了,具体语法如下

import * as A from "./moduleA";
import * as C from "./moduleC";A.hello();
console.log(A.str);C.hello();
console.log(C.str);

2.8.4、默认导入导出

①默认导出

默认导出允许一个模块指定一个(最多一个)默认的导出项,语法如下

export default function hello(){console.log('moduleA');
}

②默认导入

由于每个模块最多有一个默认导出,因此默认导入无需关注导入项的原始名称,并且无需使用{}

import helloFromA from "./moduleA";

由于默认导入时无需关注导入项的名称,所以默认导出支持匿名内容,比如匿名函数,语法如下 

export default function () {console.log('moduleB');
}

最后:👏👏😊😊😊👍👍 

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

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

相关文章

Python:Keyboard Interrupt - 当代码遇到“Ctrl+C“时发生了什么?

Python:Keyboard Interrupt - 当代码遇到"CtrlC"时发生了什么? 🌈 个人主页:高斯小哥 🔥 高质量专栏:【Matplotlib之旅:零基础精通数据可视化】 💡 创作高质量博文&#x…

Web服务器集群: kylin 部署 Halo博客系统

目录 一、实验 1.环境 2. kylin 部署mysql数据库 3. kylin 构建Java运行环境 4. 创建博客使用的数据库 5. kylin 部署 halo博客系统 6. kylin 部署nginx 7. kylin 使用 SSL证书基于https访问部署的博客系统 二、问题 1.mysql安装报错 2.查看mysql数据库报错 3.syste…

【SQL注入】靶场SQLI DUMB SERIES-24通过二次注入重置用户密码

先使用已知信息admin/admin登录进去查下题,发现可以修改密码 猜测可能存在的SQL语句:UPDATE user SET password新密码 WHERE user用户名 and password旧密码 假设我们知道有个admin用户,但是不知道其密码,如何可以将其密码重置&…

杂题——1097: 蛇行矩阵

题目描述 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。 输入格式 本题有多组数据,每组数据由一个正整数N组成。(N不大于100) 输出格式 对于每一组数据,输出一个N行的蛇形矩阵。两组输出之间不要额外的空行。矩阵三角…

如何在群辉7.2中使用Docker搭建容器魔方服务并远程访问【内网穿透】

文章目录 1. 拉取容器魔方镜像2. 运行容器魔方3. 本地访问容器魔方4. 群辉安装Cpolar5. 配置容器魔方远程地址6. 远程访问测试7. 固定公网地址 本文主要介绍如何在群辉7.2版本中使用Docker安装容器魔方,并结合Cpolar内网穿透工具实现远程访问本地网心云容器魔方界面…

MySQL 窗口函数温故知新

本文用于复习数据库窗口函数,希望能够温故知新,也希望读到这篇文章的有所收获。 本文以:MySQL为例 参考文档: https://www.begtut.com/mysql/mysql-window-functions.html 使用的样例数据:https://www.begtut.com/m…

对象池模式-Object Pool Pattern

原文地址:https://jaune162.blog/design-pattern/object-pool-pattern/ 原文中可下载高清SVG矢量类图 引言 对象池模式(Object Pool Pattern)是一种创建一组可重用对象的设计模式。它通过维护一个预分配的对象集合,避免了频繁地创建和销毁对象所带来的性能开销。在需要使用…

力扣_字符串11—实现前缀树(字典树、Trie树)

题目 方法 对于每一个节点&#xff0c;初始化一个长度为26的数组&#xff0c;用来存储对应字母子节点的地址对于每一个节点&#xff0c;初始化一个 b o o l bool bool 变量用来表示是否为叶子节点 代码 class Trie { private:vector<Trie*> children vector<Trie…

ESP8266智能家居(1)——开发环境的搭建

1.前期介绍 本次打算使用esp8266的开发板——NodeMCU&#xff0c;进行物联网相关项目的学习。开发环境使用Arduino软件。 NodeMCU实物图为&#xff1a; 开发环境截图为&#xff1a; 2.软件下载 我使用的arduino版本为1.8.5&#xff0c;其安装包如下&#xff1a; 【免费】ar…

学习总结22

解题思路 简单模拟。 代码 #include <bits/stdc.h> using namespace std; long long g[2000000]; long long n; int main() {long long x,y,z,sum0,k0;scanf("%lld",&n);for(x1;x<n;x)scanf("%lld",&g[x]);for(x1;x<n;x){scanf(&qu…

GEE必须会教程—时间都去哪了(Date参数类型)

时间和空间是世界存在的两种基本属性&#xff0c;大部分的数据都有特有的通道存储时间信息&#xff0c;用户需要通过获取数据存储的信息&#xff0c;来判断数据的可用性&#xff0c;以及数据在时间上发生的变化。在遥感上&#xff0c;空间数据集合中&#xff0c;时间信息显得更…

django配置视图并与模版进行数据交互

目录 安装django 创建一个django项目 项目结构 创建视图层views.py 写入视图函数 创建对应视图的路由 创建模版层 配置项目中的模版路径 创建模版html文件 启动项目 浏览器访问结果 安装django pip install django 创建一个django项目 这里最好用命令行完成&#xf…

SQL注入之DNSLog外带注入

一、认识&#xff1a; 什么是dnslog呢&#xff1f; DNS就是域名解析服务&#xff0c;把一个域名转换成对应的IP地址&#xff0c;转换完成之后&#xff0c;DNS服务器就会有一个日志记录本次转换的时间、域名、域名对应的ip、请求方的一些信息&#xff0c;这个日志就叫DNSLog。…

汉诺塔问题—java详解(附源码)

来源及应用 相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上&#xff0c;有三根杆(编号A、B、C)&#xff0c;在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标&#xff1a;把A杆上的金盘全部移到C杆上&#xff0c;并仍…

【Nacos】构建云原生应用的动态服务发现、配置管理和服务管理平台【企业级生产环境集群搭建应用】

基础描述 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和…

猫头虎分享已解决Bug || Spring Error: Request method ‘POST‘ not supported

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

海思3559 yolov5 wk模型部署笔记

文章目录 安装3559工具链编译opencv编译项目总结 安装3559工具链 将3559工具链copy到虚拟机上&#xff0c;并解压得到安装包 解压&#xff1a; tar -zxvf aarch64-himix100-linux.tgz解压后会得到安装包文件夹&#xff1a; 安装工具链&#xff1a; sudo ./aarch64-himix100…

Unity2023.1.19没有PBR Graph?

Unity2023.1.19没有PBR Graph? 关于Unity2023.1.19没有PBR graph的说法,我没看见管方给出的答案,百度则提到了Unity2020版之后Shader Graph的“全新更新”,之前也没太注意版本的区别,以后项目尽量都留心一下。 之前文章说过,孪生智慧项目推荐使用URP渲染管线,以上的截…

Stable Diffusion 绘画入门教程(webui)-ControlNet(线稿约束)

上篇文章介绍了openpose&#xff0c;本篇文章介绍下线稿约束&#xff0c;关于线稿约束有好几个处理器都属于此类型&#xff0c;但是有一些区别。 包含&#xff1a; 1、Canny(硬边缘&#xff09;&#xff1a;识别线条比较多比较细&#xff0c;一般用于更大程度得还原照片 2、ML…

Spring Security 认证授权安全框架

Spring Security概述 1.什么是Spring Security? Spring Security是一个Java框架&#xff0c;用于保护应用程序的安全性。它提供了一套全面的安全解决方案&#xff0c;包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念&#xff0c;可以轻松地集成到任…