鸿蒙Harmony应用开发—ArkTS-@Provide装饰器和@Consume装饰器:与后代组件双向同步

@Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。

其中@Provide装饰的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先组件提供的变量。

说明:

从API version 9开始,这两个装饰器支持在ArkTS卡片中使用。

概述

@Provide/@Consume装饰的状态变量有以下特性:

  • @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。

  • 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。

  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。

// 通过相同的变量名绑定
@Provide a: number = 0;
@Consume a: number;// 通过相同的变量别名绑定
@Provide('a') b: number = 0;
@Consume('a') c: number;

@Provide和@Consume通过相同的变量名或者相同的变量别名绑定时,@Provide装饰的变量和@Consume装饰的变量是一对多的关系。不允许在同一个自定义组件内,包括其子组件中声明多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或别名需要唯一且确定,如果声明多个同名或者同别名的@Provide装饰的变量,会发生运行时报错。

装饰器说明

@State的规则同样适用于@Provide,差异为@Provide还作为多层后代的同步源。

@Provide变量装饰器说明
装饰器参数别名:常量字符串,可选。
如果指定了别名,则通过别名来绑定变量;如果未指定别名,则通过变量名绑定变量。
同步类型双向同步。
从@Provide变量到所有@Consume变量以及相反的方向的数据同步。双向同步的操作与@State和@Link的组合相同。
允许装饰的变量类型Object、class、string、number、boolean、enum类型,以及这些类型的数组。
支持Date类型。
API11及以上支持Map、Set类型。
支持类型的场景请参考观察变化。
API11及以上支持上述支持类型的联合类型,比如string | number, string | undefined 或者 ClassA | null,示例见@Provide_and_Consume支持联合类型实例。
注意
当使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验,比如:@Provide a : string | undefined = undefined是推荐的,不推荐@Provide a: string = undefined

支持ArkUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
不支持any。
必须指定类型。
@Provide变量的@Consume变量的类型必须相同。
被装饰变量的初始值必须指定。
支持allowOverride参数允许重写,只要声明了allowOverride,则别名和属性名都可以被Override。示例见@Provide支持allowOverride参数。
@Consume变量装饰器说明
装饰器参数别名:常量字符串,可选。
如果提供了别名,则必须有@Provide的变量和其有相同的别名才可以匹配成功;否则,则需要变量名相同才能匹配成功。
同步类型双向:从@Provide变量(具体请参见@Provide)到所有@Consume变量,以及相反的方向。双向同步操作与@State和@Link的组合相同。
允许装饰的变量类型Object、class、string、number、boolean、enum类型,以及这些类型的数组。
支持Date类型。
支持类型的场景请参考观察变化。
API11及以上支持上述支持类型的联合类型,比如string | number, string | undefined 或者 ClassA | null,示例见@Provide_and_Consume支持联合类型实例。
注意
当使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验,比如:@Consume a : string | undefined

支持ArkUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
不支持any。
必须指定类型。
@Provide变量和@Consume变量的类型必须相同。
@Consume装饰的变量,在其父组件或者祖先组件上,必须有对应的属性和别名的@Provide装饰的变量。
被装饰变量的初始值无,禁止本地初始化。

变量的传递/访问规则说明

@Provide传递/访问说明
从父组件初始化和更新可选,允许父组件中常规变量(常规变量对@Prop赋值,只是数值的初始化,常规变量的变化不会触发UI刷新,只有状态变量才能触发UI刷新)、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰的变量装饰变量初始化子组件@Provide。
用于初始化子组件允许,可用于初始化@State、@Link、@Prop、@Provide。
和父组件同步否。
和后代组件同步和@Consume双向同步。
是否支持组件外访问私有,仅可以在所属组件内访问。

图1 @Provide初始化规则图示

zh-cn_image_0000001552614217

@Consume传递/访问说明
从父组件初始化和更新禁止。通过相同的变量名和alias(别名)从@Provide初始化。
用于初始化子组件允许,可用于初始化@State、@Link、@Prop、@Provide。
和祖先组件同步和@Provide双向同步。
是否支持组件外访问私有,仅可以在所属组件内访问

图2 @Consume初始化规则图示

zh-cn_image_0000001502094666

观察变化和行为表现

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。

  • 当装饰的数据类型为class或者Object的时候,可以观察到赋值和属性赋值的变化(属性为Object.keys(observedObject)返回的所有属性)。

  • 当装饰的对象是array的时候,可以观察到数组的添加、删除、更新数组单元。

  • 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYearsetMonthsetDatesetHourssetMinutessetSecondssetMillisecondssetTimesetUTCFullYearsetUTCMonthsetUTCDatesetUTCHourssetUTCMinutessetUTCSecondssetUTCMilliseconds 更新Date的属性。

@Component
struct CompD {@Consume selectedDate: Date;build() {Column() {Button(`child increase the day by 1`).onClick(() => {this.selectedDate.setDate(this.selectedDate.getDate() + 1)})Button('child update the new date').margin(10).onClick(() => {this.selectedDate = new Date('2023-09-09')})DatePicker({start: new Date('1970-1-1'),end: new Date('2100-1-1'),selected: this.selectedDate})}}
}@Entry
@Component
struct CompA {@Provide selectedDate: Date = new Date('2021-08-08')build() {Column() {Button('parent increase the day by 1').margin(10).onClick(() => {this.selectedDate.setDate(this.selectedDate.getDate() + 1)})Button('parent update the new date').margin(10).onClick(() => {this.selectedDate = new Date('2023-07-07')})DatePicker({start: new Date('1970-1-1'),end: new Date('2100-1-1'),selected: this.selectedDate})CompD()}}
}
  • 当装饰的变量是Map时,可以观察到Map整体的赋值,同时可通过调用Map的接口setcleardelete 更新Map的值。详见装饰Map类型变量。

  • 当装饰的变量是Set时,可以观察到Set整体的赋值,同时可通过调用Set的接口addcleardelete 更新Set的值。详见装饰Set类型变量。

框架行为

  1. 初始渲染:

    1. @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
    2. 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
    3. 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存在map中查找到的@Provide变量,并把自己注册给@Provide。
  2. 当@Provide装饰的数据变化时:

    1. 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
    2. 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
  3. 当@Consume装饰的数据变化时:

    通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。

使用场景

在下面的示例是与后代组件双向同步状态@Provide和@Consume场景。当分别点击CompA和CompD组件内Button时,reviewVotes 的更改会双向同步在CompA和CompD中。

@Component
struct CompD {// @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量@Consume reviewVotes: number;build() {Column() {Text(`reviewVotes(${this.reviewVotes})`)Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)}.width('50%')}
}@Component
struct CompC {build() {Row({ space: 5 }) {CompD()CompD()}}
}@Component
struct CompB {build() {CompC()}
}@Entry
@Component
struct CompA {// @Provide装饰的变量reviewVotes由入口组件CompA提供其后代组件@Provide reviewVotes: number = 0;build() {Column() {Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)CompB()}}
}

装饰Map类型变量

说明:

从API version 11开始,@Provide,@Consume支持Map类型。

在下面的示例中,message类型为Map<number, string>,点击Button改变message的值,视图会随之刷新。

@Component
struct Child {@Consume message: Map<number, string>build() {Column() {ForEach(Array.from(this.message.entries()), (item: [number, string]) => {Text(`${item[0]}`).fontSize(30)Text(`${item[1]}`).fontSize(30)Divider()})Button('Consume init map').onClick(() => {this.message = new Map([[0, "a"], [1, "b"], [3, "c"]])})Button('Consume set new one').onClick(() => {this.message.set(4, "d")})Button('Consume clear').onClick(() => {this.message.clear()})Button('Consume replace the first item').onClick(() => {this.message.set(0, "aa")})Button('Consume delete the first item').onClick(() => {this.message.delete(0)})}}
}@Entry
@Component
struct MapSample {@Provide message: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]])build() {Row() {Column() {Button('Provide init map').onClick(() => {this.message = new Map([[0, "a"], [1, "b"], [3, "c"], [4, "d"]])})Child()}.width('100%')}.height('100%')}
}

装饰Set类型变量

说明:

从API version 11开始,@Provide,@Consume支持Set类型。

在下面的示例中,message类型为Set<number>,点击Button改变message的值,视图会随之刷新。

@Component
struct Child {@Consume message: Set<number>build() {Column() {ForEach(Array.from(this.message.entries()), (item: [number, string]) => {Text(`${item[0]}`).fontSize(30)Divider()})Button('Consume init set').onClick(() => {this.message = new Set([0, 1, 2, 3, 4])})Button('Consume set new one').onClick(() => {this.message.add(5)})Button('Consume clear').onClick(() => {this.message.clear()})Button('Consume delete the first one').onClick(() => {this.message.delete(0)})}.width('100%')}
}@Entry
@Component
struct SetSample {@Provide message: Set<number> = new Set([0, 1, 2, 3, 4])build() {Row() {Column() {Button('Provide init set').onClick(() => {this.message = new Set([0, 1, 2, 3, 4, 5])})Child()}.width('100%')}.height('100%')}
}

Provide_and_Consume支持联合类型实例

@Provide和@Consume支持联合类型和undefined和null,在下面的示例中,count类型为string | undefined,点击父组件Parent中的Button改变count的属性或者类型,Child中也会对应刷新。

@Component
struct Child {// @Consume装饰的变量通过相同的属性名绑定其祖先组件Ancestors内的@Provide装饰的变量@Consume count: string | undefined;build() {Column() {Text(`count(${this.count})`)Button(`count(${this.count}), Child`).onClick(() => this.count = 'Ancestors')}.width('50%')}
}@Component
struct Parent {build() {Row({ space: 5 }) {Child()}}
}@Entry
@Component
struct Ancestors {// @Provide装饰的联合类型count由入口组件Ancestors提供其后代组件@Provide count: string | undefined = 'Child';build() {Column() {Button(`count(${this.count}), Child`).onClick(() => this.count = undefined)Parent()}}
}

@Provide支持allowOverride参数

allowOverride:@Provide重写选项。

说明:

从API version 11开始使用。

名称类型必填说明
allowOverridestring是否允许@Provide重写。允许在同一组件树下通过allowOverride重写同名的@Provide。如果开发者未写allowOverride,定义同名的@Provide,运行时会报错。
@Component
struct MyComponent {@Provide({allowOverride : "reviewVotes"}) reviewVotes: number = 10;
}
@Component
struct GrandSon {// @Consume装饰的变量通过相同的属性名绑定其祖先内的@Provide装饰的变量@Consume("reviewVotes") reviewVotes: number;build() {Column() {Text(`reviewVotes(${this.reviewVotes})`) // Text显示10Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)}.width('50%')}
}@Component
struct Child {@Provide({ allowOverride: "reviewVotes" }) reviewVotes: number = 10;build() {Row({ space: 5 }) {GrandSon()}}
}@Component
struct Parent {@Provide({ allowOverride: "reviewVotes" }) reviewVotes: number = 20;build() {Child()}
}@Entry
@Component
struct GrandParent {@Provide("reviewVotes") reviewVotes: number = 40;build() {Column() {Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)Parent()}}
}

在上面的示例中:

  • GrandParent声明了@Provide("reviewVotes") reviewVotes: number = 40
  • Parent是GrandParent的子组件,声明@Provide为allowOverride,重写父组件GrandParent的@Provide("reviewVotes") reviewVotes: number = 40。如果不设置allowOverride,则会抛出运行时报错,提示@Provide重复定义。Child同理。
  • GrandSon在初始化@Consume的时候,@Consume装饰的变量通过相同的属性名绑定其最近的祖先的@Provide装饰的变量。
  • GrandSon查找到相同属性名的@Provide在祖先Child中,所以@Consume("reviewVotes") reviewVotes: number初始化数值为10。如果Child中没有定义与@Consume同名的@Provide,则继续向上寻找Parent中的同名@Provide值为20,以此类推。
  • 如果查找到根节点还没有找到key对应的@Provide,则会报初始化@Consume找不到@Provide的报错。

常见问题

@BuilderParam尾随闭包情况下@Provide未定义错误

在此场景下,CustomWidget执行this.builder()创建子组件CustomWidgetChild时,this指向的是HomePage。因此找不到CustomWidget的@Provide变量,所以下面示例会报找不到@Provide错误,和@BuilderParam连用的时候要谨慎this的指向。

错误示例:

class Tmp {a: string = ''
}@Entry
@Component
struct HomePage {@Builderbuilder2($$: Tmp) {Text(`${$$.a}测试`)}build() {Column() {CustomWidget() {CustomWidgetChild({ builder: this.builder2 })}}}
}@Component
struct CustomWidget {@Provide('a') a: string = 'abc';@BuilderParambuilder: () => void;build() {Column() {Button('你好').onClick((x) => {if (this.a == 'ddd') {this.a = 'abc';}else {this.a = 'ddd';}})this.builder()}}
}@Component
struct CustomWidgetChild {@Consume('a') a: string;@BuilderParambuilder: ($$: Tmp) => void;build() {Column() {this.builder({ a: this.a })}}
}

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

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

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

相关文章

YOLOv8 如何实现多主干特征融合方式 | GhostNet+ShuffleNet / SwinTransformer+ShuffleNet

文章目录 前言模块添加方法双特征提取例子`GhostNet+ShuffleNet` 双主干结构图代码`Swin+ShuffleNet` 双主干结构图代码参数量与计算量1. 什么是YOLO-Magic框架?2. 如何加入这个框架?3. 加入后如何使用框架?4. GitHub组织是什么?

LeetCode-热题100:39.组合总和

题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被…

使用 Python 读取 Word 文件

使用 Python 读取 Word 文件 0. 引言安装必要的库 1. 读取和提取 Word 文件中的文本2. 提取 Word 文件中的图片 0. 引言 要使用 Python 读取 Word 文件并识别其中的对象&#xff08;如图片&#xff09;和文本&#xff0c;你可以使用 python-docx 库来处理文本&#xff0c;和 d…

大数定律与中心极限定理

大数定律与中心极限定理 大数定律切比雪夫不等式依概率收敛切比雪夫大数定律辛钦大数定律伯努利大数定律 中心极限定理列维-林德伯格中心极限定理&#xff08;Lindeberg-Levy central limit theorem&#xff09;棣莫弗-拉普拉斯中心极限定理&#xff08;De Moivre-Laplace cent…

【运放】LM358和LM324

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

python脚本for循环

使用python脚本单个输出Hello单词。 for循环实例&#xff1a; ​ [rootkvm-72 py]# cat for02.py #for i in hello: #for i in "hello": #for i in hello: for i in """hello""":print("i ", i)​ 单个字符输出结果&…

C语言运算符优先级

C语言运算符的优先级&#xff08;从高到低&#xff09;如下所示&#xff1a; 1. ()&#xff1a;括号 2. []&#xff1a;数组索引 3. . 和 ->&#xff1a;结构体和联合体成员选择 4. 和 --&#xff1a;自增和自减 5. !&#xff1a;逻辑非 6. ~&#xff1a;位取反 7. -&…

力扣---打家劫舍---动态规划

思路 1&#xff1a; 我将res[i]定义为&#xff1a;一定要取第 i 个房子的前提下&#xff0c;能获取的最大金额。那么直接用cnt从头记录到尾&#xff0c;每个房子的res最大值即是答案。那么递推公式是什么&#xff1f;res[i]max(res[i-2],res[i-1],...,res[0])nums[i]。数组初始…

如何配置nginx反向代理服务器

配置Nginx作为反向代理服务&#xff0c;你需要编辑Nginx的配置文件&#xff08;通常是nginx.conf或在其下的某个sites-available目录下的特定域名配置文件&#xff09;&#xff0c;并在其中添加反向代理相关配置块。以下是一个基本的反向代理配置示例&#xff1a; # 假设这是位…

mysql中的数据类型大全纯干货------------时间日期类型

简介(类型预览): 在mysql8.0版本中支持的类型主要有: YEAR类型表示年 DATE类型表示年,月,日 TIME类型表示时,分,秒 DATETIME类型表示年,月,日,时,分,秒 TIMESTAMP类型通常表示带时区的年,月,日,时,分,秒 数据类型单位占用字节格式下限上限YEAR年1YYY或…

C# StableDiffusion StableDiffusionSharp 脱离python臃肿的环境

目录 说明 效果 项目 代码 下载 C# StableDiffusion StableDiffusionSharp 脱离python臃肿的环境 说明 Stable Diffusion in pure C/C github地址&#xff1a;https://github.com/leejet/stable-diffusion.cpp C# Wrapper for StableDiffusion.cpp github地址&#x…

Java的三大特性之一——继承

前言 http://t.csdnimg.cn/uibg3 在上一篇中我们已经讲解过封装&#xff0c;这里就主要讲解继承与多态 继承 1.为什么需要继承 Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是现实…

zabbix6.4监控mysql数据库

目录 一、前提二、配置mysql数据库模板三、配置监控的mysql主机 一、前提 已经搭建好zabbix-server 在需要监控的mysql服务器上安装zabbix-agent2 上述安装步骤参考我的上篇文章&#xff1a;通过docker容器安装zabbix6.4.12图文详解&#xff08;监控服务器docker容器&#xf…

RAII 与智能指针

1.什么是 RAII 1.概念 Resource Acquisition Is Initialization 资源获取即初始化。一般分为 3 步&#xff0c;当我们在main函数中声明一个局部对象的时候&#xff0c;会自动调用构造函数进行对象的初始化&#xff0c;当整个main函数执行完成后&#xff0c;自动调用析构函数来…

用Compute Shader处理图像数据后在安卓机上不能正常显示渲染纹理

1&#xff09;用Compute Shader处理图像数据后在安卓机上不能正常显示渲染纹理 2&#xff09;折叠屏适配问题 3&#xff09;Prefab对DLL中脚本的引用丢失 4&#xff09;如何优化Unity VolumeManager中的ReplaceData 这是第378篇UWA技术知识分享的推送&#xff0c;精选了UWA社区…

css的box-shadow详解

CSS的box-shadow属性用于在元素框上添加阴影效果。它可以为元素提供外阴影或内阴影&#xff0c;并且可以控制阴影的颜色、偏移距离、模糊半径以及扩展半径。 box-shadow属性的基本语法如下&#xff1a; box-shadow: h-shadow v-shadow blur spread color inset;下面是各个参数…

超快的 AI 实时语音转文字,比 OpenAI 的 Whisper 快4倍 -- 开源项目 Faster Whisper

faster-whisper 这个项目是基于 OpenAI whisper 的模型&#xff0c;在上面的一个重写。 使用的是 CTranslate2 的这样的一个库&#xff0c;CTranslate2 是用于 Transformer 模型的一个快速推理引擎。 在相同精度的情况下&#xff0c;faster-whisper 的速度比 OpenAI whisper …

web开发必备之跨域

1.什么是跨域&#xff1f; 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域 举个例子或许比较生动 当前所在页面请求的页面是否同域原因https://www.csdn.net/https://blog.csdn.net/weixin_56703682√同源&#xff08;同域名同协议同端口&#x…

【网站项目】294火车票订票系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

EI Scopus双检索| 2024年智能交通与未来出行国际会议(CSTFM 2024)

会议简介 Brief Introduction 2024年智能交通与未来出行国际会议(CSTFM 2024) 会议时间&#xff1a;2024年10月18日-20日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;CSTFM 2024-2024 International Conference on Smart Transportation and Future Mobility(CSTFM 202…