【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(下)

news2024/12/26 20:56:26

系列文章目录

【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(上)
【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(下)


文章目录

  • 系列文章目录
  • 前言
  • 一、装饰器语法
    • 6.@Builder
      • 语法:
        • (1)在组件内创建(按值传递):
        • (2)在组件外创建(按值传递)
        • (3)对象字面量入参形式(引用传递)
      • 示例1:
      • 示例2:
      • 示例3:
    • 7.@BuilderParam
      • 语法:
      • 示例1:
      • 示例2:
    • 8.@Styles
      • 语法:
      • 示例1:
      • 示例2:
    • 9.@Extend
      • 语法:
      • 示例:
    • 10.@LocalStorageProp和@LocalStorageLink
      • 语法:
      • 示例
    • 11.@StorageProp和@StorageLink
      • 语法:
      • 示例:
  • 二、 总结


前言

HarmonyOS NEXT(鸿蒙应用)开发快速入门教程ArkTS语法之装饰器篇(下),基于HarmonyOS NEXT Beta1版本(api 12)讲解。


一、装饰器语法

6.@Builder

自定义组件除了通过@Component申明方式构建,也可以通过函数方式构建。@Builder就是用来装饰函数定义一个轻量级组件(UI元素),因此@Builder装饰器也简称为自定义构建函数,返回一个组件或UI元素。类似vue的render函数,通过函数形式来构建UI元素。

语法:

(1)在组件内创建(按值传递):
@Component
struct Demo {
   @Builder 函数名(参数1:类型,参数2:类型,.....) {
    }
 }

调用:

this.函数名(参数1:类型,参数2:类型,.....)
(2)在组件外创建(按值传递)
@Builder function 函数名(参数1:类型,参数2:类型,.....) {
}

@Component
struct Demo {
 }

调用:

函数名(参数1:类型,参数2:类型,.....)
(3)对象字面量入参形式(引用传递)
class ClassName{
   a:xxxx
   b:xxxx
   c:xxxx
}

@Component
struct Demo {
   @Builder 函数名($$:ClassName) {
    }
 }
 

调用

函数名({
  a:value,
  b:value2,
  c:value3,
  ......
  .......
})

说明:
1、在组件内创建称为私有自定义构建函数,只有当前组件能使用,在组件外创建称为全局自定义构建函数,所有组件都能使用。
2、入参有2种写法,一种像上面示例传递多个形参方式,称为按值传递,另一种把多个参数写成对象字面量形式(只有一个入参)传入,这种叫按引用传递。按值传递只会在首次渲染时候有效,后续修改入参值将无法响应UI变化,而引用传递修改对象字面量属性值会响应UI变化,所以推荐入参全部写成对象字面量形式。

示例1:

按引用传递

class BuilderParams {
  image: Resource | string = ''
  label: string = ''
}

@Entry
@Component
struct Parent {
  @State image: Resource = $r('app.media.home')//图标
  @State label: string = '首页'; //标签

  //自定义构建函数
  @Builder
  childBuilder(params: BuilderParams) {
    Column({ space: 6 }) {
      Image(params.image).width(100)
      Text(params.label).fontSize(16)
    }
  }

  build() {
    Column({ space: 30 }) {
      this.childBuilder({ image: this.image, label: this.label })
      Button('改变图标和标签').onClick(() => {
        this.image = $r('app.media.mine')
        this.label = '我的'
      })
    }.width('100%')
  }
}

运行效果:

请添加图片描述

示例2:

示例1也可以改成 如下直接访问外部状态变量,效果一样

@Entry
@Component
struct Parent {
  @State image: Resource = $r('app.media.home')//图标
  @State label: string = '首页'; //标签

  //自定义构建函数
  @Builder
  childBuilder() {
    Column({ space: 6 }) {
      Image(this.image).width(100)
      Text(this.label).fontSize(16)
    }
  }

  build() {
    Column({ space: 30 }) {
      this.childBuilder()
      Button('改变图标和标签').onClick(() => {
        this.image = $r('app.media.mine')
        this.label = '我的'
      })
    }.width('100%')
  }
}

示例3:

示例1也可以改成全局构建自定义函数,效果一样

class BuilderParams {
  image: Resource | string = ''
  label: string = ''
}

//全局自定义构建函数
@Builder
function childBuilder(params: BuilderParams) {
  Column({ space: 6 }) {
    Image(params.image).width(100)
    Text(params.label).fontSize(16)
  }
}

@Entry
@Component
struct Parent {
  @State image: Resource = $r('app.media.home')//图标
  @State label: string = '首页'; //标签


  build() {
    Column({ space: 30 }) {
      childBuilder({ image: this.image, label: this.label })
      Button('改变图标和标签').onClick(() => {
        this.image = $r('app.media.mine')
        this.label = '我的'
      })
    }.width('100%')
  }
}

@Builder和@Component都可以自定义组件,我们要怎么选择呢?

@Builder主要封装轻量级UI元素,组件参数传递只靠入参或者直接访问外部状态变量,无生命周期函数、无法使用其他装饰器功能,有开发的局限性,而@Component适用于构建复杂逻辑的组件,有自己的生命周期可以使用各种类型装饰器,可实现更复杂的场景。

实际开发根据自己的需求场景去选择,如果2种方式都满足,选择@Builder方式性能会更好。

7.@BuilderParam

@BuilderParam相当于vue的插槽作用(slot),先在子组件调用@BuilderParam修饰的函数占位,具体渲染内容从父组件传入,通过上面介绍我们知道@Builder是用来自定义一个组件,父组件通过@Builder生成的组件当参数传入子组件,子组件拿到@Builder组件在占位地方填充渲染。所以可以简单理解和记忆@BuilderParam是子组件的入参(函数类型),入参类型是@Builder函数。

语法:

子组件:

 @Builder A() {};
 @BuilderParam B:类型=this.A
 build(){
    ...
    ...
    //插槽占位
    this.B()
 }

ps:@BuilderParam装饰的函数初始值必须设置且只能是@Builder装饰的函数

父组件:

//自定义插槽内容
@Builder C(){
}
build(){
    ...
    ...
   child({B:this.C})
 }

如果只有一个插槽,父组件可以省略自定义构建函数,直接在子组件内嵌套写布局,此方式叫尾随闭包初始化组件,相当于vue中的默认插槽场景

父组件

build(){
    ...
    ...
   child(){
    //自定义插槽内容
     ......
     ......
    }
 }

示例1:

只有一个@BuilderParam



@Entry
@Component
struct Parent {

  @Builder customBuild(){
    //插槽内容
    Button('插槽按钮')
  }

  build() {
    Column({ space: 30 }) {
      Child({customBuilderParam:this.customBuild})
    }.width('100%')
  }
}

@Component
struct  Child{
  @Builder customBuilder() {};
  @BuilderParam customBuilderParam:()=>void=this.customBuilder
  build() {
    Column(){
        Text('child组件')
         //插槽占位
        this.customBuilderParam()
    }
  }
}

示例2:

只有一个@BuilderParam可以写成尾随闭包方式:



@Entry
@Component
struct Parent {


  build() {
    Column({ space: 30 }) {
      Child(){
        //插槽内容
        Button('插槽按钮')
      }
    }.width('100%')
  }
}

@Component
struct  Child{
  @Builder customBuilder() {};
  @BuilderParam customBuilderParam:()=>void=this.customBuilder
  build() {
    Column(){
        Text('child组件')
         //插槽占位
        this.customBuilderParam()
    }
  }
}

运行效果:
在这里插入图片描述

8.@Styles

@Styles用于装饰函数,函数内封装公共通用属性或通用事件,提供给需要的组件复用。类似scss里面的@mixin的作用

语法:

和@Builder类似@Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字

(1)全局:

@Styles function functionName() { ... }

调用:

组件(){

}.functionName()

(2)组件内:

// 在组件内
@Component
struct Demo{
  @Styles functionName() {
    .height(100)
  }
}

调用:

组件(){

}.functionName()

使用限制规则:
1、@Styles仅支持通用属性和通用事件
2、@Styles修饰的方法不支持入参
3、只能在当前文件内使用,不支持export导出给其他文件使用
4、组件内的@Styles优先级高于全局@Style

示例1:

全局定义

//全局公共样式
@Styles
function globalStyle() {
  .width('100%')
  .height(100)
  .padding(10)
  .backgroundColor(Color.Green)
  .border({ width: 1, color: Color.Black, style: BorderStyle.Solid })
  .borderRadius(10)
}


@Entry
@Component
struct Parent {
  build() {
    Column({ space: 30 }) {
      Text('text1').fontColor(Color.White).globalStyle()
      Text('text2').fontColor(Color.White).globalStyle()
      Text('text3').fontColor(Color.White).globalStyle()
    }.width('100%')
    .padding(20)
  }
}


运行效果:
在这里插入图片描述

示例2:

组件内定义

@Entry
@Component
struct Demo {
  @State bgColor: ResourceColor = Color.Yellow //背景色
  @State iHeight: number = 100 //高度

  //组件内样式
  @Styles
  globalStyle() {
    .width('100%')
    .height(this.iHeight)
    .border({ width: 1, color: Color.Black, style: BorderStyle.Solid })
    .backgroundColor(this.bgColor)
    .borderRadius(10)
    .onClick(() => {
      //高度+10
      this.iHeight += 10
    })
  }

  //按钮样式
  @Styles
  custButtonStyle(){
    .width(200)
    .height(80)
    .onClick(() => {
      //切换背景色
      this.bgColor = this.bgColor === Color.Pink ? Color.Yellow : Color.Pink
    })
  }

  build() {
    Column({ space: 30 }) {
      Column() {
        Text('点击高度+10')
      }
      .justifyContent(FlexAlign.Center)
      .globalStyle()

      Button('改变颜色').custButtonStyle()
    }.width('100%')
    .padding(20)
  }
}


运行效果:

请添加图片描述

从上述示例看,尽管@Styles装饰的函数不能写入参数,但是我们可以把@Style定义在组件内,并通过this去访问组件内的状态变量,达到动态传参的效果。

9.@Extend

@Extend跟@Styles功能类似,都是用来抽离组件属性和事件,@Extend针对的是某个具体系统组件单独设置,单独使用,而@Styles所有组件通用。

语法:

@Extend(系统组件名) function functionName(入参可选) { ... }

使用规则:
1、和@Styles不同,@Extend仅支持在全局定义,不支持在组件内部定义。
2、和@Styles不同,@Extend支持封装指定组件的私有属性、私有事件和自身定义的全局方法。
3、和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。
4、只支持扩展原生组件,不支持自定义组件

示例:

/**
 * 自定义按钮样式
 * @param height:按钮高
 * @param width :按钮宽
 * @param backgourndColor :按钮背景色
 * @param type //按钮样式
 */
@Extend(Button)
function customButton(height: number, width: number, backgourndColor: ResourceColor, type: ButtonType) {
  .height(height)
  .width(width)
  .type(type)
  .backgroundColor(backgourndColor)
  .fontColor(Color.White)
  .fontSize(14)
}

@Entry
@Component
struct Demo {
  build() {
    Column({ space: 30 }) {
      Button('提交').customButton(50, 300, Color.Blue, ButtonType.Capsule)
      Button('删除').customButton(60, 60, Color.Red, ButtonType.Circle)
    }.width('100%')
    .padding(20)
  }
}


运行效果:

在这里插入图片描述


从以下开始的装饰器都是跟数据本地存储相关

10.@LocalStorageProp和@LocalStorageLink

@LocalStorageProp和@LocalStorageLink是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。

简单说每个注册的路由页面(@Entry装饰的组件)单独享有和管理一个LocalStorage实例,包括该页面引入的子孙组件共用同一个LocalStorage来存取数据。每个页面单独使用互不影响,默认不能相互访问,不能覆盖存储,关闭页面LocalStorage实例被系统回收数据被清除,类似web sessionStorage。

@LocalStorageProp(key)是和LocalStorage实例中key对应的属性建立单向数据同步。LocalStorage实例中key数据改变,@LocalStorageProp(key)装饰的变量也将跟着改变并能响应UI变化。
@LocalStorageLink(key)是和LocalStorage实例中key对应的属性建立双向数据同步,两者区别跟@Prop和@Link一样,一个数据单向流动一个双向绑定,其他作用一致。

语法:

创建LocalStorage实例:

let storage: LocalStorage = new LocalStorage();
storage.setOrCreate(key,value)//创建属性
storage.setOrCreate(key2,value2)//创建属性
storage.setOrCreate(key3,value3)//创建属性
...
...
@Entry(storage)//页面绑定LocalStorage
@Component
struct Parent {

}

组件调用:

@Entry(storage)
@Component
struct Parent {
    @LocalStorageProp(key) 变量:类型=默认值 
    @LocalStorageLink(key) 变量:类型=默认值 
}

修改值:
分两种方式,如果是@LocalStorageLink(key)双向绑定只要修改@LocalStorageLink绑定变量即可。另一种通过调用LocalStorage实例的方法修改

storage.set(key,value)

也可以通过storage获取值:

storage.get(key)

判断key是否存在

storage.has(key)

删除LocalStorage中所有的属性

storage.clear()

更多的api可以查看LocalStorage9+文档

示例


//城市地区对象
class AddressProp{
  city:string
  area:string

  constructor(city:string,area:string) {
    this.city=city
    this.area=area
  }
}

let storage: LocalStorage = new LocalStorage();
storage.setOrCreate('name','李磊')
storage.setOrCreate('age',0)
storage.setOrCreate('address',new AddressProp('厦门市','思明区'))


@Entry(storage)
@Component
struct Parent {
   @LocalStorageProp('name') name:string='' //姓名
   @LocalStorageLink('age') age:number=0 //年龄
   @LocalStorageLink('address') address:AddressProp=new AddressProp('','') //地址

  build() {
    Column({ space: 20 }) {
      Text(`姓名:${this.name}`)
      Text(`年龄:${this.age}`)
      //子组件
      Child()
      Button('修改姓名').onClick(()=>{
         storage.set('name','小明')
      })
      Button('修改年龄').onClick(()=>{
        this.age=20
      })
      Button('修改城市').onClick(()=>{
         this.address.city='福州市'
      })
      Button('修改地区').onClick(()=>{
        this.address.area='鼓楼区'
      })
      Button('修改城市+地区').onClick(()=>{
        storage.set('address',new AddressProp('泉州市','丰泽区'))
      })
    }.padding(20).alignItems(HorizontalAlign.Start)
  }
}

//子组件
@Component
struct Child {
  @LocalStorageLink('address') address:AddressProp=new AddressProp('','')
  build() {
    Column({space:20}){
      Text(`地址:${this.address.city}${this.address.area}`)
    }

  }
}


运行效果:
请添加图片描述

11.@StorageProp和@StorageLink

@StorageProp和@StorageLink是应用全局的UI状态存储,与之对应的是全局静态类AppStorage。和进程绑定,同一进程下的所有页面共用,生命周期和LocalStorage类似,当关闭应用将被回收,如果想要数据持久化本地保存需要结合PersistentStorage使用。

语法:

@Entry
@Component
struct Parent {
    @StorageLink(key) 变量:类型=默认值 
    @StorageProp(key) 变量:类型=默认值 
}

无需创建实例,直接使用

AppStorage和LocalStorage实例内置方法一样

AppStorage.setOrCreate(key,value) //创建属性
AppStorage.set(key,value) //设置值
AppStorage.get(key) //获取值
AppStorage.has(key)//判断是否存在属性
AppStorage.clear()//清除所有属性

示例:

Index.ets (第一个页面)

import { router } from '@kit.ArkUI'

//商品对象类型
export class GoodsProp{
  name:string
  price:number
  image:Resource|string

  constructor(name:string,price:number,image:Resource|string) {
    this.name=name
    this.price=price
    this.image=image
  }
}
//创建属性并设置初始值
AppStorage.setOrCreate('category','水果')
AppStorage.setOrCreate('place','海南')
AppStorage.setOrCreate('goods',new GoodsProp('榴莲',200,'https://img0.baidu.com/it/u=211945568,1824960805&fm=253&fmt=auto&app=120&f=JPEG?w=399&h=399'))


@Entry
@Component
struct Demo {
  @StorageProp('category') category:string=''
  @StorageLink('place') place:string=''
  @StorageLink('goods') goods:GoodsProp=new GoodsProp('',0,'')
  build() {
    Column({ space: 20 }) {
      Text(`类别:${this.category}`)
      Text(`产地:${this.place}`)
      Text(`名称:${this.goods.name}`)
      Text(`价格:¥${this.goods.price}`)
      Image(this.goods.image).width(100)
      Button('修改商品信息').onClick(()=>{
        //修改商品信息
        AppStorage.set('category','饮料')
        this.place='福建'
        this.goods=new GoodsProp('雪津啤酒',10,'https://img1.baidu.com/it/u=3892212987,1352825001&fm=253&fmt=auto&app=138&f=JPEG?w=283&h=800')

      })
      Button('跳转下一页').onClick(()=>{
        router.pushUrl({url:'pages/Second'})
      })

    }.padding(20).alignItems(HorizontalAlign.Start)
  }
}

Second.ets(第二个页面)

import {GoodsProp} from './Index'
import { router } from '@kit.ArkUI'

@Entry
@Component
struct  Second{
  @StorageLink('category') category:string=''
  @StorageProp('place') place:string=''
  @StorageProp('goods') goods:GoodsProp=new GoodsProp('',0,'')
  build() {
    Column({ space: 20 }) {
      Text(`类别:${this.category}`)
      Text(`产地:${this.place}`)
      Text(`名称:${this.goods.name}`)
      Text(`价格:¥${this.goods.price}`)
      Image(this.goods.image).width(100)
      Button('修改商品信息').onClick(()=>{
        //修改商品信息
        this.category="食物"
        AppStorage.set('place','北京')
        AppStorage.set('goods',new GoodsProp('北京烤鸭',50,'https://img2.baidu.com/it/u=543904622,2448295859&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667'))


      })
      Button('返回上一页').onClick(()=>{
        router.back()
      })

    }.padding(20).alignItems(HorizontalAlign.Start)
  }
}

运行效果:

请添加图片描述

想要持久化数据只需页面开头用PersistentStorage.persistProp(key,value)初始化属性即可

例如上个例子改为:
Index.ets:

import { router } from '@kit.ArkUI'



//商品对象类型
export class GoodsProp{
  name:string
  price:number
  image:Resource|string

  constructor(name:string,price:number,image:Resource|string) {
    this.name=name
    this.price=price
    this.image=image
  }
}

PersistentStorage.persistProp('category','水果')
PersistentStorage.persistProp('place','海南')
PersistentStorage.persistProp('goods',new GoodsProp('榴莲',200,'https://img0.baidu.com/it/u=211945568,1824960805&fm=253&fmt=auto&app=120&f=JPEG?w=399&h=399'))


@Entry
@Component
struct Demo {
  @StorageProp('category') category:string=''
  @StorageLink('place') place:string=''
  @StorageLink('goods') goods:GoodsProp=new GoodsProp('',0,'')
  build() {
    Column({ space: 20 }) {
      Text(`类别:${this.category}`)
      Text(`产地:${this.place}`)
      Text(`名称:${this.goods.name}`)
      Text(`价格:¥${this.goods.price}`)
      Image(this.goods.image).width(100)
      Button('修改商品信息').onClick(()=>{
        //修改商品信息
        AppStorage.set('category','饮料')
        this.place='福建'
        this.goods=new GoodsProp('雪津啤酒',10,'https://img1.baidu.com/it/u=3892212987,1352825001&fm=253&fmt=auto&app=138&f=JPEG?w=283&h=800')

      })
      Button('跳转下一页').onClick(()=>{
        router.pushUrl({url:'pages/Second'})
      })

    }.padding(20).alignItems(HorizontalAlign.Start)
  }
}




二、 总结

至此11个常用的装饰器已经讲完了,完全掌握你将能从容应对大部分的需求场景开发。v2版本官方也在加速推进开发中,我们完全能期待下一个版本正式发布,因为v2版本又会新增多个实用装饰器,改进v1版本不足将带来更加便捷的开发方式。例如有类似vue中的compute计算属性装饰器、类似@click装饰事件的装饰器,以及对对象深度监听支持等。

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

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

相关文章

室内北斗定位系统常用的几种定位方式

随着科技的不断进步,室内定位技术日益成熟,为人们的日常生活和工作带来了极大的便利。特别是在室内环境中,北斗卫星定位系统通过一系列创新技术,实现了高精度、高可靠的定位服务。接下来就由深圳沧穹科技给大家具体介绍室内北斗定…

OpenCL 学习(2)---- OpenCL Platform 和 Device

目录 OpenCL PlatformOpenCL Device参考代码 OpenCL Platform opencl 支持的 Platform 可以使用 clGetPlatformIDs 函数查询,函数原型如下: clGetPlatformIDs(cl_uint /* num_entries */,cl_platform_id * /* platforms */,cl_uint * …

解锁亚马逊测评自养号防关联新技术

解锁亚马逊测评自养号防关联的新技术主要包括以下几个方面,这些技术旨在提高测评过程的安全性,降低账号被关联的风险: 1. 独立纯净IP技术 独立纯净IP:采用独立、纯净且未受污染的国外IP地址,确保这些IP未被标记或列入…

CSS clip-path 属性的使用

今天记录一个css属性clip-path,首先介绍下这个属性。 clip-path 是CSS中的一个神奇属性,它能够让你像魔术师一样,对网页元素施展“裁剪魔法”——只展示元素的一部分,隐藏其余部分。想象一下,不用依赖图片编辑软件&am…

JavaWeb--纯小白笔记04:Tomcat整合IDEA

IDEA整合Tomcat 1.点击Idea的导航栏里的Run,选择Edit Configurations 2.点击左上角的"",向下翻找到Tomcat Server 选择里面的Local 3.创建一个web工程,点击IDEA的File-->new-->project 然后选择Java Enterprise,…

【网络安全】网络基础第一阶段——第一节:网络协议基础---- OSI与TCP/IP协议

从今天起,我们正式进入第二部分——网络基础。继续学习网络基础、网络协议等相关内容🌟🌟🌟 目录 一、OSI模型 1.1 分层思想 1.2 OSI参考模型 1.3 数据封装与解封装 1.3.1 数据的封装过程 1.3.2 数据的解封装过程 二、TCP/…

实现信创Linux桌面录制成MP4(源码,银河麒麟、统信UOS)

信创国产化已是大势所趋,在国产操作系统上的应用开发的需求越来越多,比如,有客户需要在银河麒麟和统信UOS上实现录制桌面生成一个mp4文件。那么这个要如何实现了? 一. 技术方案 要完成这些功能,具体来说,…

初写MySQL四张表:(4/4)

进度条很喜人,你是否已经修炼到这一步了呢? 初写MySQL四张表:(1/4)-CSDN博客 初写MySQL四张表:(2/4)_数据库表样例-CSDN博客 初写MySQL四张表:(3/4)-CSDN博客 若现在你已经有了前面的基础,那就正式开始吧。 四张表: 这次在实现…

JavaScript 基础 - 第20天_Node.js入门

文章目录 Day01_Node.js入门提前安装软件目录学习目标01.什么是 Node.js目标讲解小结 02.fs模块-读写文件目标讲解小结 03.path模块-路径处理目标讲解小结 04.案例-压缩前端html目标讲解小结 05.案例-压缩前端JS目标讲解小结 06.认识URL中的端口号目标讲解小结 07.http模块-创建…

花生壳、神卓互联等主流内网穿透技术分享

目录 贝锐花生壳 PHTunnel技术 神卓互联WanGooe Tunnel 技术 贝锐花生壳 PHTunnel技术 贝锐花生壳内网穿透服务商,(使用技术:底层采用自研 PHTunnel技术)除了具备无需公网IP,无需搭建专线、3步创建映射等优势,还拥有可靠、稳定的…

JAVA开源项目 图书馆管理系统 计算机毕业设计

本文项目编号 T 044 ,文末自助获取源码 \color{red}{T044,文末自助获取源码} T044,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

Go 语言框架接入阿里云的报警通知与日志实时追踪与监控

在现代应用开发中,实时监控和报警是确保系统稳定性和高可用性的重要组成部分。 本文将介绍如何使用 Go 语言框架接入阿里云的报警通知与日志追踪。 ## 1. 环境准备 ### 1.1 安装 Go 确保你的开发环境中已经安装了 Go 语言。可以从 [Go 官网](https://golang.org/d…

使用 Docker 部署 RStudio 的终极教程

一.介绍 在现代数据科学和统计分析领域,RStudio 是一个广受欢迎的集成开发环境(IDE),为用户提供了强大的工具来编写、调试和可视化 R 代码。然而,传统的 RStudio 安装可能面临环境配置复杂、版本兼容性等问题。Docker…

SpringCloud Alibaba之Seata处理分布式事务

(学习笔记,必用必考) 问题:Transactional 的9种失效场景? 1、介绍 1.1、简介 官网地址:Apache Seata 源码地址:Releases apache/incubator-seata GitHub Seata是一款开源的分布式事务解决…

Redis面试真题总结(四)

文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ AOF 持久化? AOF(Append Only File&#x…

基于机器学习的区域能源生产与消费的分析与预测系统实现,前端layui,后端flask,可视化echarts

1 绪论 1.1选题的意义 基于机器学习的区域能源生产与消费的分析与预测研究具有重要意义。随着能源需求不断增长和资源供给压力加大,能源生产与消费的合理规划和管理成为当务之急。通过机器学习技术,可以对大规模的能源数据进行深入挖掘和分析&#xff…

Qt-QTextEdit的输入类控件(30)

目录 描述 相关属性 相关信号 使用 文本内容改变时触发 选中内容时发生改变 光标位置发生改变时触发 可复制,可撤销,可恢复发生改变时触发 undo撤销 redo恢复 copy复制 描述 这是一个多行输入框 有两个很像的,需要注意一下&…

【软件工程】实体联系图

一、数据模型 二、实体联系图(E-R图) 例题 选择题

CSS-Grid布局详解

前言 Grid 栅格布局 是 CSS 语言中非常强大的种布局,它提供了丰富的工具属性,可以轻松实现复杂且灵活的布局设计,因此想要完美使用CSS Grid 也有一定的难度和复杂性,我自己也是花了不少时间才真正掌握它的使用,在这篇…

【软件造价咨询】工程活动工作量分布占比的统计分析

在软件项目管理中,准确估算工程活动的工作量是确保项目按时、按预算完成的关键。工程活动工作量分布基准数据明细提供了一种量化工作量的方法,可以帮助团队成员更好地预测和把控不同工程活动所需的工作量。本文将探讨工程活动工作量分布基准数据明细的意…