LAYA3.0 组件装饰器说明

news2025/1/22 16:25:29

原文

在LayaAirIDE中,如果想在IDE内展示组件脚本的属性,需要通过装饰器的规则来实现。下面分别介绍四种装饰器。

文章目录

  • 一、@regClass()
  • 二、@property()
    • 2.1 组件属性的常规使用
    • 2.2 属性访问器的装饰器使用
    • 2.3 是否序列化保存
    • 2.4 组件属性是否在IDE中显示
    • 2.5 装饰器属性标识的类型
      • 2.5.1 引擎对象类型
      • 2.5.2 自定义对象类型
      • 2.5.3 TS语言基本类型
    • 2.6 组件属性值的输入控件
    • 2.7 组件属性分类与排序
    • 2.8 装饰器属性标识参数总结
    • 2.9 装饰器属性标识特殊用法
  • 三、@runInEditor
  • 四、@classInfo()
    • 4.1 加入IDE的组件列表
    • 4.2 属性分组


一、@regClass()

开发者编写的组件脚本,需要在类定义之前使用装饰器的标识@regClass(),示例代码如下所示:

const { regClass } = Laya;

@regClass()
export class Script extends Laya.Script {
}

如下图所示,只有使用了上述的这个装饰器标识,开发者自定义的组件脚本才会被IDE识别为组件,可以被节点(实体)的属性设置面板 -> 增加组件 -> 自定义组件脚本所添加。
在这里插入图片描述
一个TS文件只能有一个类使用@regClass() 。

标记了@regClass()的类,在IDE环境内都会被编译,但最终发布时,如果这个类没有被其他类引用,也没有被添加到节点上,或者所在的预制体/场景没有发布,则这个类会被裁剪。

二、@property()

2.1 组件属性的常规使用

当开发者想将组件的属性,通过IDE暴露给外界编辑来传入数据。需要在类属性定义之前使用装饰器的标识@property(),示例代码如下所示:

const { regClass, property } = Laya;

@regClass()
export class NewScript1 extends Laya.Script {
    //装饰器属性的标准写法,适用于IDE的需要显示Tips或属性的中文别名等完整功能需求
    @property({ type: String, caption: "IDE显示用的别名", tips: "这是一个文本对象,只能输入文本哦" }) 
    public text1: string = "";

    //装饰器属性类型的简写方式,适用于只定义类型的需求
    @property(String)   
    public text2: string = "";

    constructor() {
        super();
    }
}

@property()是IDE识别组件属性并显示到IDE属性面板上的装饰器标识,类型是装饰器属性标识必须携带的参数。

如果我们不需要给属性写一个tips说明,也不需要给属性重新定义一个在IDE里显示的别名,等需求。那按上面示例的简写方式即可。

如果简写方式有语法警告,请用新版本IDE,并通过IDE的开发者 -> 更新引擎d.ts文件功能来解决,或者使用标准写法来解决。

2.2 属性访问器的装饰器使用

有的时候,开发者会通过属性访问器(getter)和属性设置器(setter)来控制属性的读写行为。

当属性访问器和属性设置器同时存在时,装饰器的属性标识@property()直接用于属性访问器之前即可,此时的组件属性与上一小节中介绍的常规使用方式一样,都是可读写的。

如果,该脚本只有属性访问器,那这个属性则是只读的,仅可以在IDE中显示,但不能编辑。

getter和setter同时存在的装饰器使用示例代码如下:

const { regClass, property } = Laya;

@regClass()
class Animal {
    private _weight: number = 0;

    @property( { type : Number } )
    get weight() : number {
        return this._weight;
    }

    set weight(value: number) {
        this._weight = value;
    }
}

2.3 是否序列化保存

通过装饰器定义为组件属性后,默认状态下,属性名与值都会被序列化保存到组件被添加的场景文件或预制体文件里。例如,scene.ls里添加完自定义组件,通过vscode打开这个scene.ls,可以找到序列化保存后的组件属性名称与值,效果如图所示。
在这里插入图片描述
序列化保存后,不仅方便在IDE中直观查看与编辑组件属性值。在运行阶段,也可以直接使用序列化存储的值,对于结构复杂的数据,直接使用序列化的值还可以节省数据结构生成带来的开销。所以,有些时候,即便是不需要在属性面板上显示与编辑,也可以通过装饰器设置为组件属性,将值序列化存储在场景或预制体文件中。

但是,也有的时候,我们的组件属性只是为了方便在IDE中理解与调整,在使用的时候,这些值其实用不到,所以,还提供了是否序列化保存的控制。当装饰器属性定义的时候,对象参数中传入serializable为false,那么该属性就不会被序列化

例如,开发者的需求是序列化保存弧度值,但弧度值在人为调整数值的时候并不直观,此时,可以在IDE里直接输入角度值但不保存,仅将转换后的弧度值存起来。示例代码如下:

const { regClass, property } = Laya;

@regClass()
export class Main extends Laya.Script {
    @property({ type: Number })
    _radian: number = 0;  //带下划线的属性,默认不会出现在IDE的属性面板上,只是用来存储输入的弧度

    @property({ type: Number, caption: "角度", serializable: false }) //这里设置serializable为false,所以degree不会被保存到场景文件中
     get degree() {
        return this._radian * (180 / Math.PI);//由于自己没有序列化保存,需要把_radian存下来的弧度反算回角度,用于IDE属性面板显示
    }
    set degree(value: number) {
        this._radian = value * (Math.PI / 180);//把输入的角度值,转成弧度给_radian存起来。
    }

    onStart() {
        console.log(this._radian); 
    }
}

2.4 组件属性是否在IDE中显示

在默认情况下,装饰器属性规则只会对非下划线的类属性标记为IDE的组件属性。

对于有下划线的属性,其实是不会被显示到IDE里,此时该组件属性的价值只剩下将值保存到场景文件中了,这一点上文有所提及,示例也有应用。

带下划线的属性如果没有序列化保存到场景文件的需求,那就不必使用装饰器了。

假如,开发者想对有下划线的属性,也要显示到IDE上,也可以做到。将修饰器属性标识的传入对象中,设置参数private为false即可。

示例代码如下:

@property({ type: "number", private: false })
_velocity: number = 0;

private参数不仅可以使得下划线属性显示,也可以通过将private设置为true,使得不带下划线的属性,不在IDE的属性面板出现。

这里,我们将前文的弧度转换示例稍作修改,代码如下:

const { regClass, property } = Laya;

@regClass()
export class Main extends Laya.Script {
    @property({ type: Number , private: true })
     radian: number = 0;  //private设置为true之后,radian不会出现在IDE的属性面板上,只是用来存储输入的弧度

    @property({ type: Number, caption: "角度", serializable: false }) //这里设置serializable为false,所以degree不会被保存到场景文件中
     get degree() {
        return this.radian * (180 / Math.PI);//由于自己没有序列化保存,需要把radian存下来的弧度反算回角度,用于IDE属性面板显示
    }
    set degree(value: number) {
        this.radian = value * (Math.PI / 180);//把输入的角度值,转成弧度给radian存起来。
    }

    onStart() {
        console.log(this.radian); 
    }
}

2.5 装饰器属性标识的类型

装饰器属性标识的类型支持引擎对象类型(例如:Laya.Vector3、Laya.Sprite3D、Laya.Camera等)、自定义的对象类型(需要标记@regClass())、以及TS语言的基本类型。

2.5.1 引擎对象类型

引擎对象类型的理解比较简单,暴露组件属性之后,直接传入对应类型的值就可以。例如Laya.Sprite3D就只能传入3D节点,试图拖入2D节点或拖入资源都是禁止的。

常用的引擎对象类型使用示例如下:


const { regClass, property } = Laya;

@regClass()
export class Main extends Laya.Script {

    @property( { type:Laya.Camera } ) //摄像机类型
    private camera: Laya.Camera;  

    @property( { type:Laya.Scene3D } ) //3D场景根节点类型
    private scene3D: Laya.Scene3D;

    @property( { type:Laya.DirectionLightCom } ) //DirectionLight组件类型
    private directionLight: Laya.DirectionLightCom;

    @property( { type:Laya.Sprite3D } ) //Sprite3D节点类型
    private cube: Laya.Sprite3D;  

    @property( { type:Laya.Prefab } ) //加载 Prefab 拿到的对象
    private prefabFromResource: Laya.Prefab;    

    @property( { type:Laya.ShurikenParticleRenderer } ) //ShurikenParticleRenderer组件类型
    private particle3D: Laya.ShurikenParticleRenderer;  

    @property( { type:Laya.Node } ) //节点类型
    private scnen2D: Laya.Node; 

    @property( { type:Laya.Box } ) //拿到 Box 组件
    private box: Laya.Box; 

    @property( { type:Laya.List } ) //拿到 List 组件
    private list: Laya.List; 

    @property( { type:Laya.Image } ) //拿到 Image 组件
    private image: Laya.Image; 

    @property( { type:Laya.Label } ) //拿到 Label 组件
    private label: Laya.Label; 

    @property( { type:Laya.Button } ) //拿到 Button 组件
    private button: Laya.Button; 

    @property( { type:Laya.Sprite } ) //拿到 Sprite 组件
    private sprite: Laya.Sprite; 

    @property( { type:Laya.Animation } ) //拿到 Animation 组件
    private anmation: Laya.Animation; 

    @property( { type:Laya.Vector3 } ) //Laya.Vector3类型
    private vector3 : Laya.Vector3;
}

如图所示,将场景中已经添加好的Image拖入到@property暴露的Image属性入口中,这样就获取到了此节点,然后可以在脚本中使用代码控制Image的属性了。
代码中使用属性参考《组件属性的代码使用》
在这里插入图片描述

2.5.2 自定义对象类型

自定义对象类型,就是设置一个自定义的引入对象。按该对象的装饰器属性标识来暴露组件属性。

例如,下面这两个TS代码:

//MyScript.ts
const { regClass, property } = Laya;

import Animal from "./Animal";

@regClass()
export class MyScript extends Laya.Script  {
    @property({ type : Animal })
    animal : Animal;
}
//Animal.ts
const { regClass, property } = Laya;

@regClass()
export default class Animal {
    @property({ type : Number })
    weight : number;
}

组件脚本MyScript中引用了Animal对象 ,并将装饰器属性标识的类型设置为Animal,尽管Animal不是继承于Laya.Script的组件脚本,但由于被组件脚本MyScript所引用并暴露给IDE,所以Animal类定义之前也需要标记@regClass(),该类下使用了@property()标识的属性,也可以出现在IDE属性面板中。

2.5.3 TS语言基本类型

最后就是常用的TS语言基本类型,不过需要注意的是,基本类型需要使用字符串的方式来描述,只有数字、字符串、布尔类型,可以用其对象类型来标记。
在这里插入图片描述
使用示例代码如下:


const { regClass, property } = Laya;

//枚举
enum TestEnum {
    A,
    B,
    C
};
//字符串形式的枚举
enum Direction {
    Up = 'UP',
    Down = 'DOWN',
    Left = 'LEFT',
    Right = 'RIGHT'
};

@regClass()
export class Script extends Laya.Script {

    @property(Number)//数字类型,等价于{ type : "number" }
    num : number;

    @property(String)//单行字符串文本类型,等价于 { type: "string"}
    str : string;

    @property(Boolean)//布尔值类型,等价于 { type: "boolean"}
    bool : boolean;

    @property("int")//整数类型,等价于 { type: Number, fractionDigits: 0 }
    int : number; 

    @property("uint") //正整数类型,等价于 { type: Number, fractionDigits: 0 , min: 0 }
    uint : number; 

    @property("text")//多行字符串文本类型,等价于 { type: String, multiline: true }
    text : string; 

    @property("any")//any类型只会被序列化,不能显示和编辑。
    a : any; 

    @property(Int8Array)//类型化数组类型,除了Int8Array,还支持Uint8Array、Int16Array、Uint16Array、Int32Array、Uint32Array、Float32Array,使用方式都类似
    i8a: Int8Array;

    @property({ type: ["number"] })//数组类型,用中括号包含数组元素类型
    arr1: number[];

    @property({ type: ["string"] })//数组类型,用中括号包含数组元素类型
    arr2: string[];

    //普通的枚举类型(可以类型简写),会显示为下拉框供用户选择
    @property(TestEnum)
    enum: TestEnum;

    //字符串形式的枚举,不能使用类型简写,如:@property(Direction)。必须下面带type参数指定的标准写法
    @property({ type: Direction })
    direc: Direction;
      //字典类型,需要用数组参数来设置类型,下面示例中的Record类型需要放到字符串内作为数组参数的第一个元素,数组参数的第二个元素是字典输入值的类型,用于决定属性面板的输入控件类型
    @property({ type: ["Record", Number] })
    dict: Record<string, number>; 

}

示例效果如图所示:
在这里插入图片描述

2.6 组件属性值的输入控件

IDE内置了number(数字输入)、string(字符串输入)、boolean(多选框)、color(颜色框+调色盘+拾色器)、vec2(XY输入组合)、vec3(XYZ输入组合)、vec4(XYZW输入组合)、asset(选择资源),这些输入控件。

通常情况下,IDE会根据组件属性类型自动选择对应的属性值输入控件。

但在某些情况下,也需要强制指定输入控件。例如,数据类型是string,但其实它表达的是颜色,用默认编辑string的控件不适合,需要在这里设置组件属性标识的参数inspector为“color”。示例代码如下:

//显示为颜色输入(如果类型是Laya.Color,则不需要这样定义,如果是字符串类型,则需要)
@property({ type: String, inspector: "color"})
color: string;

注意:按照以上方法得到的颜色,是2D组件的颜色值,例如:rgba(217, 232, 0, 1)

效果如图所示:
在这里插入图片描述

如果inspector参数为null,则不会为属性构造属性输入控件,这与hidden参数设置为true不同。hidden为true是创建但不可见,inspector为null则是完全不创建。

2.7 组件属性分类与排序

组件的属性默认会统一显示在以组件脚本名称的属性分类栏目下,效果如图所示:
在这里插入图片描述
如果开发者想对组件内的某些属性进行归类,可以通过装饰器属性标识的对象参数catalog来实现,示例代码如下:

  @property({ type : "number" })
    a : number;

    @property({ type: "string"})
    b : string;

    @property({ type: "boolean",catalog:"adv"})
    c : boolean;

    @property({ type: String, inspector: "color" ,catalog:"adv"})
    d: string;

通过上面的代码可以看出,当为多个属性(c和d)设置相同的catalog名称(“adv”),就会按catalog名称进行分类。效果如图所示:
在这里插入图片描述
如果我们想给这个分类再起个中文别名,可以通过参数catalogCaption来实现,示例代码如下(更改上述示例的d属性):

@property({ type: String, inspector: "color" ,catalog:"adv", catalogCaption:"高级组件"})
d: string;

效果如图所示
在这里插入图片描述
在面对多个组件属性分类的时候,我们还可以通过参数catalogOrder对栏目的显示顺序自定义排序。数值越小显示在前面,不提供则按属性出现的顺序。示例代码如下:

@property({ type : "number", catalog:"bb", catalogOrder:1 })
    a : number;

    @property({ type: "string"})
    b : string;

    @property({ type: "boolean", catalog:"adv"})
    c : boolean;

    @property({ type: String, inspector: "color", catalog:"adv", catalogCaption:"高级组件", catalogOrder:0})
    d: string;

效果如图所示:
在这里插入图片描述
属性分类名称catalogCaption与属性分类排序catalogOrder,在任意一个catalog相同名称的属性里配置即可,无需所有的属性都配置一次。

2.8 装饰器属性标识参数总结

上文介绍了常用装饰器属性标识的参数作用(加粗为上文出现过的),这里我们概述总结一下全部的参数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码示例如下(只列出上文没有介绍过的):

    //隐藏控制
    @property({ type: Boolean })
    a: boolean;
    @property({ type: String, hidden: "!data.a" })//将条件表达式!data.a放在了字符串中,如果a为true(在IDE中为勾选状态),则!data.a返回false,此时hidden属性表示的是显示
    hide: string = "";

    // 只读控制
    @property({ type: Boolean })
    b: boolean;
    @property({ type: String, readonly: "data.b" })//将条件表达式data.b放在了字符串中,如果b为true(在IDE中为勾选状态),则data.b就返回true,此时readonly属性表示只读
    read: string = "";

    //数据检查机制
    @property(String)
    text1: string;
    @property({ type: String, validator: "if (value == data.text1) return '不能与a值相同' " })
    text2: string = "";

    //密码输入
    @property({ type: String, password: true })
    password: string;

    //如果true或者缺省,文本输入每次输入都提交;否则只有在失焦时才提交
    @property({ type: String, submitOnTyping: false })
    submit: string;

    //输入文本的提示信息
    @property({ type: "text", prompt: "文本提示信息" })
    prompt: string;

    //显示为下拉框
    @property({ type: Number, enumSource: [{name:"Yes", value:1}, {name:"No",value:0}] })
    enumsource: number;

    //反转布尔值
    @property({ type: "boolean", reverseBool: true })
    reverseboolean : boolean;

    //允许null值
    @property({ type: String, nullable: true })
    nullable: string;

    //控制数字输入的精度和范围
    @property({ type: Number, range:[0,5], step: 0.5, fractionDigits: 3 })
    range : number;

    //显示为百分比
    @property({ type: Number, range:[0,1], percentage: true })
    percent : number;

    //固定数组长度
    @property({ type: ["number"], fixedLength: true })
    arr1: number[];

    //数组允许的操作
    @property({ type: ["number"], arrayActions: ["delete", "move"] })
    arr2: number[];

    //使数组元素编辑时限制最大值和最小值
    @property({ type: [Number], elementProps: { range: [0, 100] } })
    array1: Array<Number>;
    //如果是多维数组,则elementProps同样需要使用多层
    @property({ type: [[Number]], elementProps: { elementProps: { range: [0, 10] } } })
    array2: Array<Array<Number>>;

    //不提供透明度a值的修改
    @property({ type: Laya.Color, showAlpha: false })
    color1: Laya.Color;

    //颜色类型时,defaultColor定义一个非null时的默认值
    @property({ type: String, inspector: "color", defaultColor: "rgba(217, 232, 0, 1)" })
    color2: string;

    //显示一个checkbox决定颜色是否为null
    @property({ type: Laya.Color, colorNullable: true })
    color3: Laya.Color;

    //加载Image资源类型,设置资源路径格式
    @property({ type: String, isAsset: true, assetTypeFilter: "Image" })
    resource: string;

    //x属性出现在testposition属性之前
    @property({ type: String })
    x: string;
    //可以用position人为将testposition属性安排在x属性之前显示
    @property({ type: String, position: "before x" })
    testposition: string;

    //增加缩进,单位是层级
    @property({ type: String, addIndent:1 })
    indent1: string;
    @property({ type: String, addIndent:2 })
    indent2: string;

    //当属性改变时,调用名称为onChangeTest的函数
    @property({ type: Boolean, onChange: "onChangeTest"})
    change: boolean;
    onChangeTest() {
        console.log("onChangeTest");
    }

2.9 装饰器属性标识特殊用法

除了以上列出的基本参数属性,@property还有一些特殊的组合用法。

类型属性嵌套数组或字典
示例如下:

  @property([["string"]])
    test1: string[][] = [["a", "b", "c"], ["e", "f", "g"]];

    @property([["Record", "string"]])
    test2: Array<Record<string, string>> = [{ name: "A", value: "a" }, { name: "B", value: "b" }];

    @property({ type: ["Record", [Number]], elementProps: { elementProps: { range: [0, 10] } } })
    test3: Record<string, number[]> = { "a": [1, 2, 3], "b": [4, 5, 6] };

    @property(["Record", [Laya.Prefab]])
    test4: Record<string, Laya.Prefab[]>;

它的一个重要应用就是实现动态下拉框。前面3.2.8节介绍过有两种方式可以实现下拉框:一是设置属性类型为Enum,二是通过设置enumSource为数组。这两种方式都可以实现固定的下拉选项列表,但如果想让选项列表是动态的,可以使用以下方式:

  //这个属性提供一个get方法,返回下拉选项,这个数据一般只用于编辑器,所以设置不保存
    @property({ type: [["Record", String]], serializable: false })
    get itemsProvider(): Array<Record<string, string>> {
        return [{ name: "Item0", value: "0" }, { name: "Item1", value: "1" }];
    }
    //将enumSource设置为一个字符串,表示使用该名字的属性作为下拉数据源
    @property({ type: String, enumSource: "itemsProvider" })
    enumItems: string;

三、@runInEditor

除了在IDE属性面板上暴露组件属性,开发者还可以通过装饰器标识 @runInEditor来让组件在IDE内加载时也可以触发生命周期方法(onEnable、onStart等所有的组件脚本生命周期方法)。示例代码如下:

const { regClass, property, runInEditor } = Laya;

@regClass() @runInEditor     //重点看这里,要放到类之前,@regClass()与@runInEditor谁先谁后都可以。
export class NewScript extends Laya.Script {
    @property({ type: Laya.Sprite3D })
    sp3: Laya.Sprite3D;

    constructor() {
        super();
    }

    onEnable() {
        console.log("Game onStart", this.sp3.name);
    }
}

除非有特别的需求,我们并不建议这样做,一方面是因为静态物体更有利于IDE内进行编辑。另一方面是因为场景编辑器为了性能优化,帧率刷新要比正常运行慢很多,因此效果会与正常运行有明显差异。

四、@classInfo()

装饰器标识@classInfo()主要有两个作用:

4.1 加入IDE的组件列表

开发者的自定义组件脚本默认都位于属性设置面板的增加组件->自定义组件脚本的下面,如图所示。
在这里插入图片描述

如果我们想在这个组件列表中,将该组件加入自己定义的组件列表分类中,可以使用装饰器标识@classInfo(),示例代码如下所示:

const { regClass, property, classInfo } = Laya;

@regClass()
@classInfo( {
    menu : "MyScript",
    caption : "Main",
})
export class Main extends Laya.Script {

    onStart() {
        console.log("Game start");
    }
}

然后我们保存代码,回到IDE,会发现自定义的分类已出现在组件列表中。如图所示。
在这里插入图片描述

4.2 属性分组

假设用装饰器暴露了A、B、C、D、E,5个属性,显示效果如下:
在这里插入图片描述
当属性比较多时,可以将属性分组显示,就要用到@classInfo()了,@classInfo()可以为类型添加非数据类型的属性。例如,将BC两个属性显示在一个组里,实现方式如下:

const { regClass, property, classInfo } = Laya;

@regClass()
@classInfo({
    properties: [
        {
            name: "Group1",
            inspector: "Group",
            options: {
                members: ["b", "c"]
            },
            position: "after a"
        }
    ]
})
export class NewScript extends Laya.Script {

    @property(String)
    public a: string = "";

    @property(String)
    public b: string = "";

    @property(String)
    public c: string = "";

    @property(String)
    public d: string = "";

    @property(String)
    public e: string = "";

}

其中,members指定了属于这个分组的属性名称列表。如果属性较多,也可以用这种格式 [ “b~c” ],表示从属性b到属性c之间所有的属性。position是可选的,指示这个分组显示在哪里。显示效果如下:
在这里插入图片描述

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

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

相关文章

PostIn安装教程

PostIn是一款国产开源免费的接口管理工具&#xff0c;包含项目管理、接口调试、接口文档设计、接口数据MOCK等模块&#xff0c;支持常见的HTTP协议、websocket协议等&#xff0c;支持免登陆本地接口调试&#xff0c;同时可以对项目进行灵活的成员权限、消息通知管理等。 1、服务…

RabbitMQ--延迟队列

&#xff08;一&#xff09;延迟队列 1.概念 延迟队列是一种特殊的队列&#xff0c;消息被发送后&#xff0c;消费者并不会立刻拿到消息&#xff0c;而是等待一段时间后&#xff0c;消费者才可以从这个队列中拿到消息进行消费 2.应用场景 延迟队列的应用场景很多&#xff0c;…

后端面试题分享第一弹(状态码、进程线程、TCPUDP)

后端面试题分享第一弹 1. 如何查看状态码&#xff0c;状态码含义 在Web开发和调试过程中&#xff0c;HTTP状态码是了解请求处理情况的重要工具。 查看状态码的步骤 打开开发者工具&#xff1a; 在大多数浏览器中&#xff0c;您可以通过按下 F12 键或右键单击页面并选择“检查…

网络通信---MCU移植LWIP

使用的MCU型号为STM32F429IGT6&#xff0c;PHY为LAN7820A 目标是通过MCU的ETH给LWIP提供输入输出从而实现基本的Ping应答 OK废话不多说我们直接开始 下载源码 LWIP包源码&#xff1a;lwip源码 -在这里下载 ST官方支持的ETH包&#xff1a;ST-ETH支持包 这里下载 创建工程 …

CSS笔记基础篇02——浮动、标准流、定位、CSS精灵、字体图标

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p70https://www.bilibili.com/video/BV1kM4y127Li?vd_source…

Linux:进程(三)

1. 进程创建补充 fork之后父子两个执行流分别执行&#xff0c;fork之后谁谁先执行由调度器来决定。 一般&#xff0c;父子代码共享。当父子不再写入时&#xff0c;数据也是共享的&#xff0c;但是当有一方要写入&#xff0c;就触发写时拷贝。 fork调用失败的原因 1. 系统中有…

2025年1月21日刷题记录

1.leetcode1768题目 链接&#xff1a;1768. 交替合并字符串 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; class Solution { public:string mergeAlternately(string word1, string word2) {string word3;int a word1.size(), b word2.size();int i 0, j 0…

Mysql触发器(学习自用)

一、介绍 二、触发器语法 注意&#xff1a;拿取新的数据时用new&#xff0c;旧数据用old。

wireshark工具简介

目录 1 wireshark介绍 2 wireshark抓包流程 2.1 选择网卡 2.2 停止抓包 2.3 保存数据 3 wireshark过滤器设置 3.1 显示过滤器的设置 3.2 抓包过滤器 4 wireshark的封包列表与封包详情 4.1 封包列表 4.2 封包详情 参考文献 1 wireshark介绍 wireshark是非常流行的网络…

「2024·我的成长之路」:年终反思与展望

文章目录 1. 前言2.创作历程2.1 摆烂期2.2 转变期3. 上升期 2. 个人收获3.经验分享4. 展望未来 1. 前言 2025年1月16日&#xff0c;2024年博客之星入围公布&#xff0c;很荣幸获得了这次入围的机会。2024年对我个人是里程碑的一年&#xff0c;是意义非凡的一年&#xff0c;是充…

【RAG落地利器】向量数据库Chroma入门教程

安装部署 官方有pip安装的方式&#xff0c;为了落地使用&#xff0c;我们还是采用Docker部署的方式&#xff0c;参考链接来自官方部署: https://cookbook.chromadb.dev/running/running-chroma/#docker-compose-cloned-repo 我们在命令终端运行&#xff1a; docker run -d --…

电阻电位器可调电阻信号隔离变送器典型应用

电阻电位器可调电阻信号隔离变送器典型应用 产品描述&#xff1a; 深圳鑫永硕科技的XYS-5587系列是一进一出线性电子尺(电阻/电位计信号及位移)信号隔离变送器&#xff0c;是将输入电阻,线性电子尺,角度位移传感器信号进行采集,隔离,放大并转换成模拟量信号的小型仪表设备,并以…

[创业之路-259]:《向流程设计要效率》-1-让成功成熟业务交给流程进行复制, 把创新产品新业务新客户交给精英和牛人进行探索与创造

标题&#xff1a;成功与创新的双轨并行&#xff1a;以流程复制成熟&#xff0c;以精英驱动新知 在当今这个日新月异的商业环境中&#xff0c;企业要想持续繁荣发展&#xff0c;就必须在稳定与创新之间找到完美的平衡点。一方面&#xff0c;成熟业务的稳定运营是企业生存和发展的…

模拟飞行入坑(五) P3D 多通道视角配置 viewgroup

背景&#xff1a; P3D进行多个屏幕显示的时候&#xff0c;如果使用英伟达自带的屏幕融合成一个屏&#xff0c;或者使用P3D单独拉伸窗口&#xff0c;会使得P3D的画面被整体拉伸&#xff0c;又或者,当使用Multichannel进行多个设备联动时&#xff0c;视角同步组合需要配置&#…

Java中的错误与异常详解

Java中的错误与异常详解 Java提供了一种机制来捕获和处理程序中的异常和错误。异常和错误都继承自 Throwable 类&#xff0c;但它们有着不同的用途和处理方式。 1. Error&#xff08;错误&#xff09; Error 是程序无法处理的严重问题&#xff0c;通常由 JVM&#xff08;Java…

免费开源的三维建模软件Blender

软件介绍 Blender是一款功能强大且免费开源的三维建模、动画制作和渲染软件&#xff0c;广泛应用于影视制作、游戏开发、建筑可视化、教育及艺术创作等多个领域。 核心功能 Blender是一款全能型3D软件&#xff0c;涵盖了从建模、动画到渲染、后期合成的完整工作流程。 1、建…

ElasticSearch DSL查询之排序和分页

一、排序功能 1. 默认排序 在 Elasticsearch 中&#xff0c;默认情况下&#xff0c;查询结果是根据 相关度 评分&#xff08;score&#xff09;进行排序的。我们之前已经了解过&#xff0c;相关度评分是通过 Elasticsearch 根据查询条件与文档内容的匹配程度自动计算得出的。…

iOS 网络请求: Alamofire 结合 ObjectMapper 实现自动解析

引言 在 iOS 开发中&#xff0c;网络请求是常见且致其重要的功能之一。从获取资料到上传数据&#xff0c;出色的网络请求框架能夠大大提升开发效率。 Alamofire 是一个极具人气的 Swift 网络请求框架&#xff0c;提供了便据的 API 以完成网络请求和响应处理。它支持多种请求类…

面向对象编程——对象实例化

在python中&#xff0c;对象实例化是根据类的定义创建具体对象的过程。也就是将类当成模板&#xff0c;从而定义了对象的结构和行为&#xff0c;而实例化则是根据这个模板创建具体的对象实例。每个实例都有自己独立的状态&#xff0c;但是却共享类的结构和方法。 代码&#xff…

阿里云-银行核心系统转型之业务建模与技术建模

业务领域建模包括业务建模和技术建模&#xff0c;整体建模流程图如下&#xff1a; 业务建模包括业务流程建模和业务对象建模 业务流程建模&#xff1a;通过对业务流程现状分析&#xff0c;结合目标核心系统建设能力要求&#xff0c;参考行业建 模成果&#xff0c;形成结构化的…