Web前端浅谈ArkTS组件开发

本文由JS老狗原创。
有幸参与本厂APP的鸿蒙化改造,学习了ArkTS以及IDE的相关知识,并有机会在ISSUE上与鸿蒙各路大佬交流,获益颇丰。

本篇文章将从一个Web前端的视角出发,浅谈ArkTS组件开发的基础问题,比如属性传递、插槽、条件渲染等。

创建项目

这个过程简单过一下,不赘述。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

组件与页面

创建好项目后,我们会自动跳到初始首页,代码如下:

@Entry
@Component
struct Index {@State message: string = 'Hello World';build() {RelativeContainer() {Text(this.message).id('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }})}.height('100%').width('100%')}
}

首先注意页面Index是按struct定义。我们在这里不深入讨论struct的含义,照猫画虎即可。主要看前面的装饰器。

  • @Entry 表示该页面为一个独立的Page,可通过router进行跳转。
  • @Component 对该对象封装之后,即可进行页面渲染,并构建数据->视图的更新,可以看成是一个mvvm结构的模版,类似对React.Component的集成,或者是vuedefineComponent的语法糖。
  • build 渲染,可以对标React组件中的render(),或者vue中的setup()。当使用@Component装饰器之后,必须显式声明该方法,否则会有系统报错。

另外需要注意的是,在build()中仅可以使用声明式的写法,也就是只能使用表达式。可以看成是jsx的一个变体:

// 请感受下面组件函数中 return 之后能写什么
export default () => {return (<h1>Hello World</h1>)
}
@Component
export default struct SomeComponent {build() {// console.log(123) // 这是不行的Text('Hello World')}
}

如果有条件可以打开IDE实际操作体会一下。

独立组件

上面组件的示例代码中,我们并没有使用@Entry装饰器。是的这就足够了,上面的代码就是一个完整组件的声明。

我们把组件单拎出来:
在这里插入图片描述

在这里插入图片描述

@Component
export struct CustomButton {build() {Button('My Button')}
}

刚才的首页做一下改造,使用前端惯用的flex布局:

import { CustomButton } from './CustomButton'@Entry
@Component
struct Index {@State message: string = 'Hello World';build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).id('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold)CustomButton()}.height('100%').width('100%')}
}

在这里插入图片描述
最基本的组件定义和使用,就是如此了。

样式簇

web前端不同,ArkTS没有css,但ArkTS通过链式写法,实现了常用的css样式定义。只要有css方案,基本都可以通过链式写法,把想要的样式出来。
在这里插入图片描述

这样散养的样式并不常用,Web前端会用class来声明样式集。类似的功能,可以通过@Extend@Styles两个装饰器实现。

Style装饰器

import { CustomButton } from './CustomButton'@Entry
@Component
struct Index {@State message: string = 'Hello World';// 声明Style簇@StylesHelloWorldStyle() {.backgroundColor(Color.Yellow).border({ width: { bottom: 5 }, color: '#ccc' }).margin({ bottom: 10 })}build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).id('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold).HelloWorldStyle()  // 注意这里调用样式簇CustomButton()}.height('100%').width('100%')}
}

在这里插入图片描述

@Styles装饰器也可以单独修饰function函数:

@Styles
function HelloWorldStyle2() {.backgroundColor(Color.Yellow).border({ width: { bottom: 5 }, color: '#000' }).margin({ bottom: 10 })
}@Entry
@Component
struct Index {//...
}

使用@Styles装饰器可以定义一些布局类的基础样式,比如背景,内外边距等等;如果定义在组件内部,有助于提升组件内聚;定义在外部,可以构建基础样式库。

而像fontSizefontColor之类的仅在部分组件上具备的属性定义,在@Styles中无法使用。所以这里就需要用到@Extends装饰器。

Extend装饰器

import { CustomButton } from './CustomButton'@Extend(Text)
function TextStyle() {.fontSize(50).fontWeight(FontWeight.Bold).id('HelloWorld')
}@Entry
@Component
struct Index {@State message: string = 'Hello World';@StylesHelloWorldStyle() {.backgroundColor(Color.Yellow).border({ width: { bottom: 5 }, color: '#ccc' }).margin({ bottom: 10 })}build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).TextStyle().HelloWorldStyle()CustomButton()}.height('100%').width('100%')}
}

此外@Extend还可以带参数:

@Extend(Text)
function TextStyle(fontSize: number = 50, fontColor: ResourceStr | Color = '#f00') {.fontSize(fontSize).fontColor(fontColor).fontWeight(FontWeight.Bold).id('HelloWorld')
}

然后直接调用

Text(this.message).TextStyle(36, '#06c').HelloWorldStyle()

我们就得到了:

在这里插入图片描述

@Extend装饰器不能装饰struct组件内部成员函数,这是与@Styles装饰器的一处不同。

事件回调

各种事件也都可以出来:

import { promptAction } from '@kit.ArkUI'@Component
export struct CustomButton {build() {Column() {Button('My Button').onClick(() => {promptAction.showToast({message: '你点我!'})})}}
}

请注意这里使用了promptAction组件来实现toast效果:

在这里插入图片描述

事件回调的参数

对Web开发者来说,首先要注意的是:没有事件传递————没有冒泡捕获过程,不需要处理子节点事件冒泡到父节点的问题。

此外点击事件的回调参数提供了比较全面的详细信息UI信息,对实现一些弹框之类的UI展示比较有帮助。

在这里插入图片描述

比如event.target.area可以获取触发组件本身的布局信息:

在这里插入图片描述

自定义事件

我们改一下上面的组件代码,在组件中声明一个成员函数onClickMyButton,作为Button点击的回调:

@Component
export struct CustomButton {onClickMyButton?: () => voidbuild() {Column() {Button('My Button').onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})}}
}

然后改一下Index页面代码,定义onClickMyButton回调:

build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {// ...CustomButton({onClickMyButton: () => {promptAction.showToast({message: '你又点我!'})}})}.height('100%').width('100%')
}

在这里插入图片描述

属性与状态

mv(x)架构下,数据模型(model)一般分为属性状态两种概念,且都应当驱动视图(view)更新。

  • 属性(property),指外部(父级)传入值,自身只可读不可更改;如需要修改,则要通过回调通知父组件。
  • 状态(state),私有值,用于内部逻辑计算;一般来讲,状态的数据结构复杂度,与组件复杂度正相关。

ArkTS中,组件(struct)成员有诸多修饰符可选。基于个人的开发经验和习惯,我推荐使用单向数据流方式,模型层面仅使用@Prop@State来实现组件间交互。下面简单讲一下使用:

@State状态装饰器

在之前的代码中,可以看到一个用@State声明的状态值message

@State装饰的成员,可以对标reactuseState成员,或者vue组件中data()的某一个key

@Prop属性装饰器

@State装饰的成员,可以对标reactuseState成员,或者vue组件中data()的某一个key

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'build() {Column() {Button(this.text)  // 使用该属性.onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})}}
}

在父级调用

CustomButton({text: '我的按钮'
})

在这里插入图片描述

状态和属性的更改

再完善一下组件:

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'@Prop count: number = 0build() {Column() {// 这里展示计数Button(`${this.text}(${this.count})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})}}
}

这里声明了两个属性textcount,以及一个自定义事件onClickMyButton

父级声明一个状态clickCount,绑定子组件的count属性,并在子组件的自定义事件中,增加clickCount的值。预期页面的计数随clickCount变化,按钮组件的计数随属性count变化,两者应当同步。

@Entry
@Component
struct Index {@State message: string = 'Hello World';@State clickCount: number = 0@StylesHelloWorldStyle() {.backgroundColor(Color.Yellow).border({ width: { bottom: 5 }, color: '#ccc' }).margin({ bottom: 10 })}@BuilderSubTitle() {// 这里展示计数Text(`The message is "${this.message}", count=${this.clickCount}`).margin({ bottom: 10 }).fontSize(12).fontColor('#999')}build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).TextStyle(36, '#06c').HelloWorldStyle2()this.SubTitle()ItalicText('ItalicText')CustomButton({text: '点击次数',count: this.clickCount,onClickMyButton: () => {this.clickCount += 1}})}.height('100%').width('100%')}
}

实际效果:

在这里插入图片描述

符合预期。

属性监听

使用@Watch装饰器,可以监听@Prop装饰对象的变化,并能指定监听方法:

@Prop @Watch('onChange') count: number = 0private onChange(propName: string) {console.log('>>>>>>', propName)
}

@Watch装饰器调用onChange时,会把发生变化的属性名作为参数传递给onChange;也就是说,我们可以只定义一个监听方法,通过入参propName来区分如何操作。

@Prop @Watch('onChange') count: number = 0
@Prop @Watch('onChange') stock: number = 0private onChange(propName: string) {if(propName === 'count') {//...} else if(propName === 'stock') {//...}
}

我们下面用@Watch监听属性count,实现属性更改驱动组件内部状态变化。首先改造组件:

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'@Prop @Watch('onChange') count: number = 0// 内部状态@State private double: number = 0private onChange() {this.double = this.count * 2}build() {Column() {Button(`${this.text}(${this.count} x 2 = ${this.double})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})}}
}

在这里插入图片描述

效果可以对标react中的useEffect,或者vue中的observer或者watch

这里有一个隐含的问题:当@Prop被第一次赋值的时候,不会触发@Watch监听器。比如我们把页面状态clickCount初始化为3,这时候尬住了:

在这里插入图片描述

在web的解决方案中,这种问题自然是绑定组件生命周期。同样,ArtTS也是如此:

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'@Prop @Watch('onChange') count: number = 0@State private double: number = 0private onChange() {this.double = this.count * 2}build() {Column() {Button(`${this.text}(${this.count} x 2 = ${this.double})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})}// 这里绑定生命周期.onAttach(() => {this.onChange()})}
}

本文为了简便,直接在onAttach中使用监听函数初始化。具体情况请自行斟酌。

在这里插入图片描述

条件渲染

用过react的人都知道三目表达式的痛:

// 以下伪代码 未验证
export default MyPage = (props: { hasLogin: boolean; userInfo: TUserInfo }) => {const { hasLogin, userInfo } = propsreturn <div className='my-wrapper'>{hasLogin ? <UserInfo info={userInfo} /> : <Login />}</div>
}

前面提过,由于return后面词法限制,只能使用纯表达式写法。或者,把return包裹到if..else中,总归不是那么优雅。

ArkTS则直接支持在build()中使用if...else分支写法:

build() {Column() {Button(`${this.text}(${this.count} x 2 = ${this.double})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})if(this.count % 2 === 0) {Text('双数').fontColor(Color.Red).margin({ top: 10 })} else {Text('单数').fontColor(Color.Blue).margin({ top: 10 })}}.onAttach(() => {this.onChange()})
}

在这里插入图片描述

函数式组件

这里的函数式的命名,是纯字面的,并不是reactFunctional Component的意思。

这类组件由@Builder装饰器声明,对象可以是一个单独的function,抑或是struct组件中的一个方法。

需要特别注意的是,这里的function是指通过function声明的函数,不包括**箭头函数(Arrow Function) **。

import { CustomButton } from './CustomButton'@Extend(Text)
function TextStyle(fontSize: number = 50, fontColor: ResourceStr | Color = '#f00') {.fontSize(fontSize).fontColor(fontColor).fontWeight(FontWeight.Bold).id('HelloWorld')
}@Builder
function ItalicText(content: string) {Text(content).fontSize(14).fontStyle(FontStyle.Italic).margin({ bottom: 10 })
}@Entry
@Component
struct Index {@State message: string = 'Hello World';@StylesHelloWorldStyle() {.backgroundColor(Color.Yellow).border({ width: { bottom: 5 }, color: '#ccc' }).margin({ bottom: 10 })}@BuilderSubTitle() {Text(`The message is "${this.message}"`).margin({ bottom: 10 }).fontSize(12).fontColor('#999')}build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).TextStyle(36, '#06c').HelloWorldStyle()this.SubTitle()ItalicText('ItalicText')CustomButton()}.height('100%').width('100%')}
}

上面的代码中,声明了一个外部组件ItalicText,一个内部组件this.SubTitle,可以在build()中直接使用。

在这里插入图片描述

由于@Builder的装饰对象是一个function函数,所以这个组件可以带参数动态渲染。

实现插槽

ArkTS中提供了@BuilderParam装饰器,可以让@Builder以参数的形式向其他组件传递。这为实现插槽提供了条件。

我们首先在组件中声明一个@BuilderParam,然后植入到组件的build()中。改造组件代码:

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'@Prop @Watch('onChange') count: number = 0@State private double: number = 0// 插槽@BuilderParam slot: () => voidprivate onChange() {this.double = this.count * 2}build() {Column() {Button(`${this.text}(${this.count} x 2 = ${this.double})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})if(this.count % 2 === 0) {Text('双数').fontColor(Color.Red).margin({ top: 10 })} else {Text('单数').fontColor(Color.Blue).margin({ top: 10 })}// 植入插槽,位置自定if(typeof this.slot === 'function') {this.slot()}}.onAttach(() => {this.onChange()})}
}

页面代码更改:

build() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(this.message).TextStyle(36, '#06c').HelloWorldStyle2()this.SubTitle()ItalicText('ItalicText')CustomButton({text: '点击次数',count: this.clickCount,onClickMyButton: () => {this.clickCount += 1},// 定义插槽slot: () => {this.SubTitle()}})}.height('100%').width('100%')
}

在这里插入图片描述

这种单一插槽的情况,可以有更优雅的写法:

在这里插入图片描述

请注意:单一插槽,也就是说组件中仅包含一个@BuilderParam成员,且与成员命名无关。

如果有多个@BuilderParam成员,下面那种嵌套写法会在编译期报错:

[Compile Result]  In the trailing lambda case, 'CustomButton' must have one and only one property decorated with @BuilderParam, and its @BuilderParam expects no parameter.

这错误提示给出两点要求:

  • 仅有一个@BuilderParam装饰成员
  • 该成员函数不能有参数

看一个多插槽的例子,继续优化组件:

@Component
export struct CustomButton {onClickMyButton?: () => void@Prop text: string = 'My Button'@Prop @Watch('onChange') count: number = 0@State private double: number = 0@BuilderParam slot: () => void@BuilderParam slot2: () => voidprivate onChange() {this.double = this.count * 2}build() {Column() {Button(`${this.text}(${this.count} x 2 = ${this.double})`).onClick(() => {if(typeof this.onClickMyButton === 'function') {this.onClickMyButton()}})if(typeof this.slot === 'function') {this.slot()}if(this.count % 2 === 0) {Text('双数').fontColor(Color.Red).margin({ top: 10 })} else {Text('单数').fontColor(Color.Blue).margin({ top: 10 })}if(typeof this.slot2 === 'function') {this.slot2()}}.onAttach(() => {this.onChange()})}
}

在这里插入图片描述

请注意:在向@BuilderParam插槽传入@Builder的时候,一定包一层箭头函数,否则会引起this指向问题。

写在最后

从个人感受来讲,如果一个开发者对TS有充分的使用经验,进入ArkTS之后,只要对ArkTS的方言、开发模式和基础库做简单了解,基本就能上手开发了,总体门槛不高。

最后吐几个槽点:

  • 语法方面:虽然叫ts,但ts的类型推断几乎没有;没有type类型声明;不能一次性声明嵌套的复杂类型;没有any/unkown类型,Object有点类似unknown,仅此而已;不支持解构取值。
  • 文档系统不完善,使用不方便,检索困难。
  • 开发工具在模拟器或者真机下没有热更,每次更改都要重新编译,效率不高。

不过,上面的槽点只是有点烦,习惯就好。

关于 OpenTiny

在这里插入图片描述

OpenTiny 是一套企业级 Web 前端开发解决方案,提供跨端、跨框架、跨版本的 TinyVue 组件库,包含基于 Angular+TypeScript 的 TinyNG 组件库,拥有灵活扩展的低代码引擎 TinyEngine,具备主题配置系统TinyTheme / 中后台模板 TinyPro/ TinyCLI 命令行等丰富的效率提升工具,可帮助开发者高效开发 Web 应用。

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~
OpenTiny 官网:https://opentiny.design/
OpenTiny 代码仓库:https://github.com/opentiny/
TinyVue 源码:https://github.com/opentiny/tiny-vue
TinyEngine 源码: https://github.com/opentiny/tiny-engine
欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI~ 如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~

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

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

相关文章

hamcrest 断言框架使用示例和优势分析

引言 在软件测试领域&#xff0c;断言是验证代码行为是否符合预期的关键环节。Hamcrest 断言框架&#xff0c;以其独特的匹配器&#xff08;Matcher&#xff09;概念和清晰的失败信息&#xff0c;赢得了广泛的赞誉。尽管 Python 标准库中没有内置的 Hamcrest 库&#xff0c;但…

【Linux】-----工具篇(编译器gcc/g++,调试器gdb)

目录 一、gcc/g 简单认识 程序的翻译过程认识gcc 预处理(宏替换) 编译 汇编 链接 宏观认识 如何理解&#xff08;核心&#xff09; 什么是链接&#xff1f; 链接的分类 二、gdb 基本的认识 基本操作及指令 安装gdb 启动gdb ​编辑 显示源代码(list) 运行程序…

SQL labs-SQL注入(三,sqlmap使用)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; 盲注简述&#xff1a;是在没有回显得情况下采用的注入方式&#xff0c;分为布尔盲注和时间盲注。 布尔盲注&#xff1a;布尔仅有两种形式&#xff0c;ture&#…

学习笔记:MySQL数据库操作3

1. 创建数据库和表 创建数据库 mydb11_stu 并使用该数据库。创建 student 表&#xff0c;包含字段&#xff1a;学号&#xff08;主键&#xff0c;唯一&#xff09;&#xff0c;姓名&#xff0c;性别&#xff0c;出生年份&#xff0c;系别&#xff0c;地址。创建 score 表&…

C#、Net6、WebApi报表方案

目录 1 Pdf表单方案 1.1出现如下错误提示: 1.2 字体路径使用 2 Docx报表模板方案 2.1 pdf方案缺陷 2.2 解决方案 3 Spire.Doc报表方案 3.1 Docx方案缺陷 3.2 解决方案 4 插入复选框 5 WebApi文件流下载接口 6 软件获取方式 1 Pdf表单方案 使用【Adobe Acrobat P…

python—pandas基础(2)

文章目录 列操作修改变量列筛选变量列使用.loc[]&#xff08;基于标签)使用.iloc[]&#xff08;基于整数位置&#xff09;使用.filter()方法 删除变量列添加变量列 变量类型的转换Pandas 支持的数据类型在不同数据类型间转换 建立索引新建数据框时建立索引读入数据时建立索引指…

Vue---vue3+vite项目内使用devtools,快速开发!

背景 我们在前期开发时&#xff0c;一般使用chrome或者edge浏览器&#xff0c;会使用vue-devtools或react-devtools&#xff08;此插件个人未使用&#xff0c;可百度下是否可内嵌入项目&#xff01;&#xff09;来审查vue项目&#xff1b;这个需要安转浏览器插件才可支持&…

使用PyTorch导出JIT模型:C++ API与libtorch实战

PyTorch导出JIT模型并用C API libtorch调用 本文将介绍如何将一个 PyTorch 模型导出为 JIT 模型并用 PyTorch 的 CAPI libtorch运行这个模型。 Step1&#xff1a;导出模型 首先我们进行第一步&#xff0c;用 Python API 来导出模型&#xff0c;由于本文的重点是在后面的部署…

【odoo17】后端py方法触发右上角提示组件

概要 在前面文章中&#xff0c;有介绍过前端触发的通知服务。 【odoo】右上角的提示&#xff08;通知服务&#xff09; 此文章则介绍后端触发方法。 内容 直接上代码&#xff1a;但是前提一定是按钮触发&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; def bu…

【css】实现扫光特效

对于要重点突出的元素&#xff0c;我们经常可以看到它上面打了一个从左到右的斜向扫光&#xff0c;显得元素亮闪闪的&#xff01;类似于下图的亮光动效 关键步骤 伪元素设置position :absolute【也可以不用伪元素&#xff0c;直接创建一个absolute元素盖在上面】设置渐变line…

Mike21粒子追踪模型particle tracking如何展示粒子轨迹

前言&#xff1a; 随着模型的推广&#xff0c;模型的很多模块也问的多了起来&#xff0c;PT粒子追踪模块最近群友也在问&#xff0c;结果算了出来&#xff0c;却实现不了展示运动轨迹。今天就写段简单的PT后处理的方法吧。 注意&#xff1a;MIKE21输出模块中不但输出了关于水…

Axure怎么样?全面功能评测与用户体验分析!

软件 Axure 曾经成为产品经理必备的原型设计工具&#xff0c;被认为是专门为产品经理设计的工具。但事实上&#xff0c;软件 Axure 的使用场景并不局限于产品经理构建产品原型。UI/UX 设计师还可以使用 Axure 软件构件应用程序 APP 原型&#xff0c;网站设计师也可以使用 Axure…

如何系统的学习C++和自动驾驶算法

给大家分享一下我的学习C和自动驾驶算法视频&#xff0c;收藏订阅都很高。打开下面的链接&#xff0c;就可以看到所有的合集了&#xff0c;订阅一下&#xff0c;下次就能找到了。 【C面试100问】第七十四问&#xff1a;STL中既然有了vector为什么还需要array STL中既然有了vec…

QSqlQuery增删改查

本文记录使用QSqlQuery实现增删改查的过程。 目录 1. 构建表格数据 声明变量 表格、数据模型、选择模型三板斧设置 列表执行查询 列表的水平表头设置 2. 新增一行 构建一个空行 通过dialog返回的修改行数据&#xff0c;update更新 3. 更新一行 获取到需要更新的行 通…

Spring Bean - xml 配置文件创建对象

类型&#xff1a; 1、值类型 2、null &#xff08;标签&#xff09; 3、特殊符号 &#xff08;< -> < &#xff09; 4、CDATA <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/bea…

信息安全技术解析

在信息爆炸的今天&#xff0c;信息技术安全已成为社会发展的重要基石。随着网络攻击的日益复杂和隐蔽&#xff0c;保障数据安全、提升防御能力成为信息技术安全领域的核心任务。本文将从加密解密技术、安全行为分析技术和网络安全态势感知技术三个方面进行深入探讨&#xff0c;…

WPF启动失败报System.Windows.Automation.Peers.AutomationPeer.Initialize()错误解决

问题描述 win10系统上WPF程序启动后就崩溃&#xff0c;通过查看崩溃日志如下&#xff1a; 应用程序: xxx.exe Framework 版本: v4.0.30319 说明: 由于未经处理的异常&#xff0c;进程终止。 异常信息: System.TypeLoadException 在 System.Windows.Automation.Peers.Automatio…

leetcode-105. 从前序与中序遍历序列构造二叉树

题目描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,nu…

重塑生态体系 深挖应用场景 萤石诠释AI时代智慧生活新图景

7月24日&#xff0c;“智动新生&#xff0c;尽在掌控”2024萤石夏季新品发布会在杭州举办。来自全国各地的萤石合作伙伴、行业从业者及相关媒体&#xff0c;共聚杭州&#xff0c;共同见证拥抱AI的萤石&#xff0c;将如何全新升级&#xff0c;AI加持下的智慧生活又有何不同。 发…

【WinDbg读取蓝屏的dmp日志】iaStorAC.sys 蓝屏解决

读取蓝屏日志&#xff1a; Window偶尔一次蓝屏不用管。 经常蓝屏重置或重装系统。 想要知道为什么蓝屏&#xff0c;通过WinDbg查看蓝屏日志。 蓝屏日志查找和配置 1&#xff0c;蓝屏那一刻拍照蓝屏的界面&#xff0c;即可知道基本的蓝屏信息。 2&#xff0c;蓝屏日志的配置…