当前位置: 首页 > news >正文

华为HarmonyOS NEXT 原生应用开发:鸿蒙中组件的组件状态管理、组件通信 组件状态管理小案例(好友录)!

文章目录

  • 组件状态管理
      • 一、@State装饰器
          • 1. @State装饰器的特点
          • 2. @State装饰器的使用
      • 二、@Prop装饰器(父子单向通信)
          • 1. @Prop装饰器的特点
          • 2. @Prop装饰器的使用示例
      • 三、@Link装饰器(父子双向通信)
          • 1. @Link装饰器的特点
          • 3. @Link使用示例
      • 四、@Provide/@Consume装饰器(祖孙后代双向通信)
          • 1. 特点
          • 2. 使用条件
      • 五、@Observed装饰器和@ObjectLink装饰器
          • 1. 特点:
          • 2. 使用说明
          • 代码示例:
      • 六、拓展装饰器
      • 组件状态管理案例练习 - 好友录

组件状态管理

一、@State装饰器

1. @State装饰器的特点

● @State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、@ObjectLink装饰变量之间建立双向数据同步。
● @State装饰的变量生命周期与其所属自定义组件的生命周期相同

2. @State装饰器的使用
  • 简单示例:

以下示例为@State装饰的简单类型,count被@State装饰成为状态变量,count的改变引起Button组件的刷新:
● 当状态变量count改变时,查询到只有Button组件关联了它;
● 执行Button组件的更新方法,实现按需刷新。

@Entry
@Component
struct MyComponent {@State count: number = 0;build() {Button(`click times: ${this.count}`).onClick(() => {this.count += 1;})}
}
  • 该装饰器修饰的变量将别 UI 框架监视。
  • 需要注意,该变量访问权只在该组件中,且必须初始化。

二、@Prop装饰器(父子单向通信)

1. @Prop装饰器的特点

● 传递的是数据的深拷贝,每次都会拷贝数据源然后流转到子组件, 并且支持嵌套传递。
在父子组件中,使用该装饰器实现单向数据流。
● 父组件:数据源修改数据,@Prop修饰的变量都会进行覆盖变化。
● 子组件:对@Prop修饰的变量进行数据修改,并不会影响到父组件(数据源)。

在这里插入图片描述

2. @Prop装饰器的使用示例
  • 父组件发生变化,数据流向子组件,实现单向同步,而子组件修改数据,不影响父组件数据源。子组件你数据使劲修改,父组件最终修改数据,都会同步到子组件!

在这里插入图片描述

@Entry
@Component
struct CStatusPage {@State age: number = 0build() {Column({ space: 20 }) {Column({ space: 20 }) {Text("父组件: " + this.age).fontSize(20)// 给子组件传参ChildComponent({age: this.age})}.width("50%").height(200).justifyContent(FlexAlign.Center).padding(20).backgroundColor(Color.Pink)Row({space: 100 }) {Button("父组件 + 1").onClick(() => {this.age++})}.width("100%").justifyContent(FlexAlign.Center)}.height('100%').width('100%').justifyContent(FlexAlign.Center)}
}@Component
struct ChildComponent {// 接收父组件参数@Prop age: number = 0build() {Column() {Row() {Text("子组件:" + this.age).fontSize(18)}.width("80%").height(100).backgroundColor(Color.Green)Button("子组件 + 1").onClick(() => {this.age++})}}
}

三、@Link装饰器(父子双向通信)

1. @Link装饰器的特点

双向数据流:@Link装饰的变量与其父组件中的数据源共享相同的值。
● 浅拷贝,直接将引用地址进行共享,同样支持嵌套。

  • 限制条件
    ● @Link装饰器不能在@Entry装饰的组件中使用。
    ● 禁止子组件在本地初始化数据(父类数据直接流到子类,允许访问和修改,若是赋值就没有意义)。
    ● 私有,只能在所属组件内访问。
3. @Link使用示例

和上方 @Prop 大差不差,@Link 是双向数据流,父组件可以修改子,子也可以修改父组件。

@Entry
@Component
struct CStatusPage {@State age: number = 0build() {Column({ space: 20 }) {Column({ space: 20 }) {Text("父组件: " + this.age).fontSize(20)// 给子组件传参ChildComponent({age: this.age})}.width("50%").height(200).justifyContent(FlexAlign.Center).padding(20).backgroundColor(Color.Pink)Row({space: 100 }) {Button("父组件 + 1").onClick(() => {this.age++})}.width("100%").justifyContent(FlexAlign.Center)}.height('100%').width('100%').justifyContent(FlexAlign.Center)}
}@Component
struct ChildComponent {// 接收父组件参数 (需要注意不能有初始值,因为和父组件共享一份,有初始值就没有意义了)@Link age: numberbuild() {Column() {Row() {Text("子组件:" + this.age).fontSize(18)}.width("80%").height(100).backgroundColor(Color.Green)Button("子组件 + 1").onClick(() => {this.age++})}}
}

四、@Provide/@Consume装饰器(祖孙后代双向通信)

1. 特点

双向数据流、UI框架可以跨多层检测。
使用场景: 一般在一个组件中嵌套两层一及以上的组件使用,否则直接用@Link就可以解决一层父子通信的问题。

@Provide:@Provide装饰的状态变量自动对其所有后代组件可用.

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

2. 使用条件

使用说明:熟

  1. @Consume修饰的状态变量不能主动初始化,只能接受祖先Provide的初始化
  2. @Provide修饰的状态变量必须初始化,可以用于初始化子组件,但不能被父组件初始化。
  3. 两个组件之间状态变量名和类型需要保持一致。
  4. 组件内变量名同名了(当然,进行取别名 @Consume(“别名”)),子组件直接使用别名即可! @Provide(“别名”),子组件同样直接使用别名。
    需要注意:随着新版本的更新优化,组组件有别名的子组件就用别名,有的子组件用了父组件原名的就用其原名,不相互影响。
  • 祖先组件代码
import { SonComponents } from '../components/SonComponents'
@Entry
@Component
struct Index {@State message: string = 'component1';@Provide user: string = 'admin'build() {Column({ space: 50}) {Text(this.message).fontSize(50)Row() {SonComponents()}}.height('100%').width('100%')}
}
  • 第一层组件代码
import { Sun } from '../components/Sun'
@Component
export struct SonComponents {build() {Column() {Text('SonComponents2').fontSize(40)Sun()}.width('100%').height('100%')}
}
  • 第三层组件代码
@Component
export struct Sun {@Consume user: stringbuild() {Column() {Text(this.user).fontSize(40)}.width('100%').height('100%')}
}

在这里插入图片描述

五、@Observed装饰器和@ObjectLink装饰器

1. 特点:

在这里插入图片描述

2. 使用说明

● @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
● @ObjectLink中的属性可以被修改,但是不能直接覆盖自身

代码示例:
// 允许@ObjectLink装饰的数据属性赋值
this.objLink.a= ...
// 不允许@ObjectLink装饰的数据自身赋值
this.objLink= ...
class ClassA {public c: number;constructor(c: number) {this.c = c;}
}@Observed
class ClassB {public a: ClassA;public b: number;constructor(a: ClassA, b: number) {this.a = a;this.b = b;}
}
  • ClassB被@Observed装饰,其成员变量的赋值的变化是可以被观察到的,但对于ClassA,没有被@Observed装饰,其属性的修改不能被观察到。
@ObjectLink b: ClassB// 赋值变化可以被观察到
this.b.a = new ClassA(5)
this.b.b = 5// ClassA类没有被@Observed装饰,嵌套在ClassB类中其属性的变化观察不到
this.b.a.c = 5

六、拓展装饰器

@Require修饰符
● 主要用于数据参数校验,添加该修饰符后,必须传递参数,故此也可以不给初始值。
@Track修饰符 (主要用于做新能优化的)

在这里插入图片描述

组件状态管理案例练习 - 好友录

  • 可以跟着源码写一遍熟悉一下,主要练习组件通信。

在这里插入图片描述

  • 数据模型文件源码
let nextId = 1// 随机姓名数组
const NameArr: string[] = ["子涵", "天宇", "雨欣", "晨曦", "思琪", "佳怡", "子轩", "浩然", "梦洁","文博", "子涵", "明轩", "诗涵", "子轩", "明轩", "子涵", "天宇", "雨欣","晨曦", "思琪", "佳怡", "子轩", "浩然", "梦洁", "文博", "诗涵", "子轩","明轩", "子涵", "天宇", "雨欣", "晨曦", "思琪", "佳怡", "子轩", "浩然","梦洁", "文博", "诗涵", "子轩", "明轩", "子涵", "天宇", "雨欣", "晨曦","思琪", "佳怡", "子轩", "浩然", "梦洁", "文博", "诗涵", "子轩", "明轩","子涵", "天宇", "雨欣", "晨曦", "思琪", "佳怡", "子轩", "浩然", "梦洁","文博", "诗涵", "子轩", "明轩", "子涵", "天宇", "雨欣", "晨曦", "思琪","佳怡", "子轩", "浩然", "梦洁", "文博", "诗涵", "子轩", "明轩", "小欣","梦洁", "文博", "诗涵", "子轩", "明轩", "子涵", "天宇", "雨欣", "晨曦","思琪", "佳怡", "子轩", "浩然", "梦洁", "文博", "诗涵", "子轩", "明轩","欣姚"
]
// 随机生成的 手机号码@Observed
export class Person {id: numbername: stringphone: stringisStar: boolean = falseconstructor(name: string, phone: string) {this.id = nextId++this.name = namethis.phone = phone}
}export function getPhonePerson (): Person {let personArr = new Person(randomNameHandle(), randomPhoneNumberHandle())return personArr
}// 随机生成姓名
export function randomNameHandle(): string {let name: string = ""let randomNameNumber: number = Math.floor(Math.random() * 100 )name = NameArr[randomNameNumber]return name
}// 生成随机的手机号
export function randomPhoneNumberHandle(): string {// 生成 11 位随机数字let phoneNumber = '';for (let i = 0; i < 11; i++) {phoneNumber += Math.floor(Math.random() * 10).toString();}return phoneNumber;
}
  • index文件源码
import { Person, getPhonePerson } from "./model/DataModel"
import { promptAction } from '@kit.ArkUI'@Entry
@Component
struct Index {// 当前的id值@State PhonePerson: Person[] = [getPhonePerson(), getPhonePerson(), getPhonePerson()]// id容器,我需要得到子组件给我的当前id值@State currentContactID: number = -1// false 选择, true 取消@State titleTextBoolean: boolean = false@State deleteArrList: number[] = []build () {Column() {// 标题Row({ space: 10 }) {Text('联系人').fontSize(24).fontWeight(FontWeight.Bold)Blank()Button(this.titleTextBoolean ? "取消" : "选择").fontColor(Color.White).fontSize(14).backgroundColor(this.titleTextBoolean ? Color.Red : "#007dfe").onClick(() => {this.titleTextBoolean = ! this.titleTextBooleanthis.deleteArrList = []})Button(" + ").fontColor(Color.White).fontSize(14).onClick(() => {// 新增联系人(往数组追加对象)this.PhonePerson.push(getPhonePerson())})}.width('100%')// 主体列表List({ space: 10 }) {ForEach(this.PhonePerson, (item: Person, index: number) => {ListItem() {// 联系人项目ContactPersonComponent({// 将当前对象传递下去item: item,currentContactID: this.currentContactID,titleTextBoolean: this.titleTextBoolean,deleteArrList: this.deleteArrList})}})}.margin({ top: 10 }).layoutWeight(1)// 底部按钮if (this.titleTextBoolean) {Button(this.deleteArrList.length === 0 ? "取消" :  "删除").fontColor(Color.White).backgroundColor(this.deleteArrList.length === 0 ? Color.Gray : Color.Red).onClick(() => {if (this.deleteArrList.length === 0) {promptAction.showToast({message: "操作取消!",textColor: "#FFCCAA"})this.titleTextBoolean = false} else {for(let item = 0; item < this.PhonePerson.length; item++) {for(let i = 0; i < this.deleteArrList.length; i++) {if (this.PhonePerson[item].id === this.deleteArrList[i]) {this.PhonePerson.splice(item, 1)}}}// 复原操作this.titleTextBoolean = false// 每次删除完成后,重置数组this.deleteArrList = []promptAction.showToast({message: "删除成功!",textColor: "#8ADAB2"})}})}}.width('100%').height('100%').padding(15).backgroundColor("#ffd6d4d4")}
}@Component
struct ContactPersonComponent {@ObjectLink item: Person@State showFlag: boolean = false@Link @Watch("onClickContactChange") currentContactID: number@Prop titleTextBoolean: boolean@Link deleteArrList: number[]onClickContactChange() {// 只要id发生变化,则将id 不等于当前的联系人详细信息项关闭if(this.currentContactID != this.item.id) {this.showFlag = false}}build() {Column({ space: 15 }) {Row({ space: 10 }) {if (this.titleTextBoolean) {Toggle({ type: ToggleType.Checkbox})  // {type: 按钮类型, isOn: 按钮是否选中状态}.selectedColor("#FFB0B0") // Toggle按钮组件 选中时候的颜色.onChange((value: boolean) => {// value值为true和false,二者之间随时切换!如果用户点击就为true,在次点击就为falseif (value) {this.deleteArrList.push(this.item.id)} else {// 获取该元素在deleteArrList的位置,以便后续删除操作let index: number = this.deleteArrList.indexOf(this.item.id)this.deleteArrList.splice(index,  1)}})}Image($r("app.media.startIcon")).width(35).height(35)Text(this.item.name)Blank()Image(this.item.isStar ? $r("app.media.select_collection") : $r("app.media.collection")).width(24).onClick(() => {this.item.isStar = ! this.item.isStar// 弹框提示if (this.item.isStar) {promptAction.showToast({message: `收藏成功!`,alignment: Alignment.Bottom,offset: { dx: 0, dy: -200},textColor: "#9ADE7B"})} else {promptAction.showToast({message: `取消收藏!`,alignment: Alignment.Bottom,offset: { dx: 0, dy: -200},textColor: Color.Red})}})}.width('100%').height(60)if (this.showFlag) {Divider().strokeWidth(2).color(Color.Black)Row({ space: 20 }) {Text("手机号码:")Text(this.item.phone)}.width('100%').justifyContent(FlexAlign.Start).padding(15)}}.backgroundColor(Color.White).padding({ top: 5, bottom: 5, left: 10, right: 10 }).borderRadius(15).onClick(() => {this.showFlag = ! this.showFlagthis.currentContactID = this.item.id  // 将当前点击的联系人 id 给父组件})}
}

相关文章:

华为HarmonyOS NEXT 原生应用开发:鸿蒙中组件的组件状态管理、组件通信 组件状态管理小案例(好友录)!

文章目录 组件状态管理一、State装饰器1. State装饰器的特点2. State装饰器的使用 二、Prop装饰器&#xff08;父子单向通信&#xff09;1. Prop装饰器的特点2. Prop装饰器的使用示例 三、Link装饰器&#xff08;父子双向通信&#xff09;1. Link装饰器的特点3. Link使用示例 四…...

node.js 环境配置

node_global下创建node_modules 系统变量 新建NODE_Path -> node_modules的路径 用户变量 编辑Path 编辑…\npm为 node_modules的路径 系统变量 Path 新建 %NODE_PATH% CMD测试 npm install express -g 报错 npm error code ETIMEDOUT源的连接超时&#xff0c;没用了要换源 …...

高并发数据采集场景下Nginx代理Netty服务的优化配置

高并发数据采集场景下&#xff0c;要优化Nginx反向代理来支持多个Netty数采服务并保证稳定的性能&#xff0c;可以从以下几个方面对Nginx进行优化配置。 直连模式&#xff08;直接通过 Nginx 处理与后端 Netty 服务的连接&#xff0c;而不作为反向代理&#xff09;&#xff0c;…...

【C++算法】40.模拟_N 字形变换

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a; 题目链接&#xff1a; 6. N 字形变换 题目描述&#xff1a; 解法 解法一&#xff1a;模拟 a,b,c,d,e,f,g...... n4 弄个矩阵放进去&#xff0c;最后从左往右读取。 解法二&#xff1a;模拟优化-…...

【云计算】虚拟化技术

目录 1. 虚拟化技术在云计算中的那些地方发挥了关键作用&#xff1f; 2. 比较VMare&#xff0c;Xen等虚拟化产品的关键技术&#xff0c;以及对云计算技术提供的支持&#xff1f; 3. 服务器虚拟化&#xff0c;存储虚拟化和网络虚拟化都有哪些实现方式&#xff1f; 4. 讨论桌面…...

手机租赁系统开发指南一站式服务流程解析

内容概要 手机租赁系统的开发是一个复杂但有趣的过程&#xff0c;像搭建乐高一样&#xff0c;只要找到合适的模块&#xff0c;就能打造出一个宾至如归的租赁平台。在这部分&#xff0c;我们将对开发流程的整体结构进行简要概述&#xff0c;并指出每个环节的重要性。 首先&…...

【机器学习】—时序数据分析:机器学习与深度学习在预测、金融、气象等领域的应用

云边有个稻草人-CSDN博客 目录 引言 1. 时序数据分析基础 1.1 时序数据的特点 1.2 时序数据分析的常见方法 2. 深度学习与时序数据分析 2.1 深度学习在时序数据分析中的应用 2.1.1 LSTM&#xff08;长短期记忆网络&#xff09; 2.2 深度学习在金融市场预测中的应用 2…...

OBS + SRS:打造专业级直播环境的入门指南

OBS SRS&#xff1a;打造专业级直播环境的入门指南 1. OBS简介2. OBS核心功能详解2.1 场景&#xff08;Scenes&#xff09;管理2.2 源&#xff08;Sources&#xff09;控制2.3 混音器功能2.4 滤镜与特效2.5 直播控制面板 3. OBS推流到SRS服务器配置指南3.1 环境准备3.2 OBS推流…...

收银系统源码-会员管理

会员制早已成为门店经营首选的营销工具&#xff0c;尤其是针对连锁多门店会员管理尤为重要。 必然要求门店的收银系统需要支持会员管理&#xff0c;能提供多种会员权益&#xff1b; 1.会员类型 收银系统支持常规会员、plus付费会员、可绑定实体卡&#xff1b; plus会员&…...

MongoDB深化与微软的合作,新增人工智能和数据分析集成和微软 Azure Arc支持

日前&#xff0c;在微软Ignite技术大会上&#xff0c;MongoDB公司宣布面向MongoDB与微软共同客户推出三项新功能&#xff0c;双方协作更进一步。首先&#xff0c;需要构建由检索增强生成 (RAG) 技术驱动的应用程序的客户&#xff0c;现在可以选择MongoDB Atlas作为微软Azure AI…...

对流层路径延迟对SAR方位压缩的影响(CSDN_20240301)

目录 仿真参数 方位向脉冲压缩与高阶多普勒参数的关系 仿真结果 2m分辨率 1m分辨率 0.5m分辨率 0.3m分辨率 0.2m分辨率 0.1m分辨率 0.05m分辨率 小结 对流层路径延迟对方位脉冲压缩的影响 仿真参数 地球参数 赤道半径&#xff08;m&#xff09; 6378140 极半径&a…...

RK3588 Linux实例应用(2)——SDK与编译

SDK包编译与使用 一、安装SDK包1.1 安装软件依赖1.2 Git 配置1.3 安装 SDK1.4 安装第三方开源库 二、编译SDK包 一、安装SDK包 安装的步骤和原子哥一样的&#xff0c;我讲一下注意的细节。 看正点原子路径为&#xff1a;开发板光盘A盘→10、用户手册→02、开发文档→02【正点原…...

深入探究 Scikit-learn 机器学习库

一、数据处理与准备 &#xff08;一&#xff09;数据加载 内置数据集&#xff1a;Sklearn 自带一些经典数据集&#xff0c;如鸢尾花数据集&#xff08;load_iris&#xff09;、波士顿房价数据集&#xff08;load_boston&#xff09;等。这些数据集方便初学者快速上手实践&…...

PAT甲级-1114 Family Property

题目 题目大意 共有n个户主&#xff0c;每个户主的房产按照“ 户主id 父亲id 母亲id 孩子个数 孩子的id 房产数 房产面积 ”的格式给出。如果父亲或母亲不存在&#xff0c;值为-1。每个户主及其父亲母亲孩子可以构成一个家庭&#xff0c;不同户主如果有相同的家人&#xff0c;…...

5.2 JavaScript 案例 - 轮播图

JavaScript - 轮播图 文章目录 JavaScript - 轮播图基础模版一、刷新页面随机轮播图案例二、轮播图 定时器版三、轮播图完整版 基础模版 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"…...

使用IP自签名SSL证书

最近需要创建WebSocket服务器并使用SSL证书&#xff0c;由于是内网测试&#xff0c;所以需要使用指定IP的自签SSL证书。 其实笔者前面博文 使用nexus3作为Docker镜像仓库 解决nexus3登录x509: certificate has expired or is not yet valid 中有创建过相应的证书&#xff0c;这…...

数据库中的运算符

1.算术运算符 算术运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达式&#xff0c;对数值或表达式进行加&#xff08;&#xff09;、减&#xff08;-&#xff09;、乘&#xff08;*&#xff09;、除&#xff08;/&#xff09;和取模&#xff08;%&…...

定制erp真的很贵吗?

定制ERP真的很贵吗&#xff1f;这个问题&#xff0c;相信很多企业在考虑是否实施ERP系统时&#xff0c;都会纠结。特别是对于一些中小型企业&#xff0c;预算有限&#xff0c;心里总会有个疑问&#xff1a;花大价钱定制一个系统&#xff0c;真的值得吗&#xff1f;其实&#xf…...

Java Integer的数值比较

文章目录 环境问题答案说明解决办法其它总结 环境 Windows 11 专业版Java 21 问题 下面这段代码的运行结果是什么&#xff1f; Integer i1 0;int i2 0;for (int n 0; n < 200; n) {if (i1 ! i2) {System.out.println("i1 " i1 ", i2 " i2);b…...

QGroundControl之5-AppSettings.cc

介绍 应用程序设置 Application Settings &#xff0c;这里看下语言选择功能&#xff0c;它是怎么和json文件关联起来的&#xff0c;刚刚看的时候&#xff0c;很是奇怪这么多的json文件作用。 1.AppSettings.cc 文件怎么和App.SettingsGroup.json关联 在AppSettings.cc文件没…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...