2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点

news2024/11/13 23:32:06

    今天带来的是来自尚硅谷禹神2024年8月最新的TS课程的学习笔记,不得不说禹神讲的是真的超级棒!
在这里插入图片描述

文章目录

  • TS入门
    • JS中的困扰
    • 静态类型检查
    • 编译TS
      • 命令行编译
      • 自动化编译
  • 类型检查
    • 变量和函数类型检查
    • 字面量类型检查
  • 类型推断
  • 类型声明
    • 声明对象类型
    • 声明函数类型
    • 声明数组类型
  • 类型总览
    • Object类型
    • 六种新类型
      • any
      • unknown
      • never
      • void
        • 特殊情况(?_?)
      • tuple
      • enum
        • 数字枚举
        • 字符串枚举
        • 常量枚举
    • 自定义类型
      • type
      • interface接口
        • 接口继承
        • 接口自动合并
        • 接口总结
      • type与接口区别
  • 面向对象
    • 继承
    • 属性修饰符
      • 属性的简写
    • 抽象类
      • 接口与抽象类的区别
    • 类的最佳实践
  • 泛型
    • 泛型接口
    • 泛型类
    • 类型声明文件
    • props

TS入门

JS中的困扰

  1. 不清不楚的数据类型
  2. 逻辑上的漏洞
  3. 访问不存在的属性
  4. 低级的拼写错误

静态类型检查

在代码运行前进行检查,发现代码的错误或不合理之处,减小运行时异常的出现的几率,此种检查叫做 静态类型检查。TypeScript和核心就是 静态类型检查,简而言之就是把运行时的错误前置

编译TS

浏览器不能直接运行TypeScript代码,需要编译为JavaScript再交由浏览器解析器执行。

命令行编译

要把 .ts文件编译为 .js文件,需要配置TS的编译环境,步骤如下:

  1. 创建一个ts文件,作为实验对象。

  2. 全局安装TS

    npm i typescript -g
    
  3. 使用 tsc命令编译 .ts文件

    tsc ts文件名
    

自动化编译

  1. 创建TS编译控制文件

    tsc --init
    
  2. 监视目录中的 .ts文件变化

    tsc --watch
    
    1. 工程中会生成一个 tsconfig.json配置文件,其中包含着很多编译时的配置。

    2. 观察发现,默认编译的 JS版本是ES7,我们可以手动吊证其版本。

      "target":"ES_"
      
  3. (小优化)当编译出错的时候不生成 .js文件

    tsc --noEmitOnError --watch
    

    备注:当然也可以通过修改 tsconfig.json中的 noEmitOnError配置

类型检查

变量和函数类型检查

语法:

限制变量类型:
let 变量名: 数据类型

限制函数参数:
function count(x:数据类型,y:数据类型){
	//方法体
}

限制函数返回值类型:
function count(x:数据类型,y:数据类型):数据类型{
	//方法体
}

注意⚠️:数据类型写 小写

字面量类型检查

如果将 :数据类型里面的数据类型改成自己自定义的字符串,那么就会变成一个定值,以后都只能用这一个值。

例如:

let a: '你好'	//a的值只能为字符串“你好”
a = "欢迎"	//报错❌

类型推断

TS会根据我们的代码,进行类型推导,例如下面代码中的变量d,只能存储数字:

let d = -99	//TS会推断出变量d的类型是数字
d = false	//报错❌

但要注意,类型推断不是万能的,面对复杂类型时推断容易出问题,所以尽量还是明确的编写类型声明!

类型声明

声明对象类型

实际开发随时,限制一般对象,通常使用以下👇形式:

//限制person对象必须有那么属性:age为可选属性
let person1:{name:string; age?:number}
//赋值
person1 = {name:'李四',age:18}

索引签名:允许定义可以具有 任意数量的属性,这些属性的 类型是可变的,常用于:描述类型不确定的属性(具有动态属性的对象)。

语法:[索引签名:数据类型]:数据类型

例子:

let person:{
	name:string
	age?:number
	[key:string]:any
}
//赋值
person={
	name:'张三',
	age:18,
	gender:'男'
}

声明函数类型

语法:let 函数名:(key1:数据类型,key2:数据类型) => 数据类型

例子:

//声明规范
let count:(a:number,b:number)=>number
//声明函数
count = function(x,y){
	return x+y
}

注意⚠️:

  • TS中的 =>在函数类型声明的时候表示的是函数类型,描述其参数类型和返回类型。
  • JS中的 =>是一种定义函数的语法,是具体的函数实现
  • 函数类型声明还可以使用:接口、自定义类型等方式。

声明数组类型

语法:

  • 普通形式:let 数组名:数据类型[]
  • 泛型形式:let 数组名:Array<数据类型>

例子:

let arr1:string[]
let arr2:Array<string>
  
arr1 = ['a','b','c']
arr2 = ['a','b']

类型总览

JS中的数据类型

  1. String
  2. Number
  3. Boolean
  4. Null
  5. Underfined
  6. bigint
  7. symbol
  8. object(Object包含 ArrayFunctionDateError等…)

TS中的数据类型

  1. JS的所有类型
  2. 六个新类型:
    1. any
    2. unknown
    3. never
    4. void
    5. tuple
    6. enum
  3. 自定义类型:
    1. type
    2. interface

Object类型

关于 objectObject实际开发中用的相对较少,因为范围太大了。

object(小写)的含义是:所有 非原始类型,可存储:对象、函数、数组等,由于限制的废物比较宽泛,在实际开发中使用的相对比较少。

object能存储非原始类型

image-20240917131221439

image-20240917131311202

Object(大写)的含义是:能存储的类型是可以调用到object方法的类型。

简单记忆:除了 undefinednull的任何值。

image-20240917131637374

大小写的区别:

image-20240918091705062

image-20240918091804373


.lenght实现原理:

image-20240918091816008

六种新类型

any

any的含义就是:任意类型,一旦将变量类型限制为 any,那就意味着放弃了对该变量的类型检查。

//【显示any】明确的表示a的类型是any
let a: any
//以下对a的复制,均无报错警告
a = 100
a = '你好'
a = false

//【隐式any】没有明确的表示b的类型是any,但是TS会自动推断出来是any类型
let a
//以下对b的复制,均无报错警告
b = 100
b = '你好'
b = false

注意点:any类型的变量,可以赋值给任意类型的变量

let c :any
c = 9
let x:string
x=c	//不会报错

unknown

unknown的含义是:未知类型。

  1. unknown可以理解为一个安全的 any类型,适用于:不确定数据的具体类型

    //设置a的类型为unknown
    let a: unknown
    //以下对a的赋值均为正常
    a = 100
    a = false 
    a = '你好'
    
    • 注意⚠️:unknown类型的变量,不可以赋值给任意类型的变量

      //设置x的数据类型为srting
      let x: string
      x = a //会出现警告,不能将类型”unknown“分配至类型”string“
      
  2. unknown会强制开发者在使用之前进行 类型检查,从而提供更强的类型安全性。

    1. 断言:

      x = a as string
      另一种写法:
      x = <string>a
      
  3. 读取 any类型数据的任何属性都不会报错,但是 unknown都会报错

    let str1:string
    str1 = 'hello'
    str1.toUpperCase()	//无警告
    
    let str2:any
    str1 = 'hello'
    str1.toUpperCase()	//无警告
    
    let str3:unknown
    str1 = 'hello'
    str1.toUpperCase()	//报错❌
    // 解决办法:使用断言强制指定str3的类型为string
    (str3 as string).toUpperCase()
    

never

never的含义就是:任何值都不是

  1. 几乎不用 never去直接限制变量,因为没有意义。

    let a: never
    //以下对a的所有赋值都报错❌
    a = 1
    a = true
    a = underfined
    a = null
    
  2. never一般是TS主动推断出来的

    let a: string
    a = 'hello'
    if(typenof a === 'string'){
    	console.log(a.toUpperCase())
    } else {
    	console.log(a)
    	//TS会会推断a是never,因为没有never,因为没有任何一个值符合此处的逻辑
    }
    
  3. never也可用于限制函数的返回值

    //function throwReeoe(str: string):never{
    	throw new Error('程序出错!'+ str)
    }
    

void

void通常用于函数返回值声明。

含义:函数不返回任何值,调用者也不依赖其返回值进行任何操作。

function a(msg:string):void{
	console.log(msg)
}
a('你好')

注意:编码者没有编写 return去指定函数的返回值,所以a函数是没有显式返回值的,但会有一个隐式返回值,就是 undefined

即:虽然函数返回类型为 void,但也是可以接受 undefined,简单记:undefinedvoid可以接受的一种“空”

以下三种都是符合规范的:

image-20240917130132588

理解 voidundefined

  • void是一个广泛的概念,用来表达“空",而 undefined则是一种”空“的具体实现之一。
  • 因此可以说 undefinedvoid能接受的“空”状态的一种具体形式。

总结:若函数返回值类型为 void那么:

  1. 从语法上讲:函数是可以返回 undefined的,至于显示返回,还是隐式返回,这都无所谓~
  2. 从语义上讲:函数调用着不应该关心函数返回的值,也不依赖返回值进行任何操作!即使反悔了 undefined值。
特殊情况(?_?)

在函数定义时,限制函数返回值为void,那么函数的返回值就必须是空。

正常情况:

image-20240917224132010

使用类型声明限制函数返回值为 void的时候在,TS并不会严格要求函数返回为

特殊情况:

image-20240917224628064

为什么会这样呢?

是为了确保如下代码成立,我们知道 Array·prototype.push的返回一个数字,而 Array·prototype.forEach方法期望其回调的返回类型是 void

image-20240917224751052

tuple

元组(tuple)是一种特殊的数据类型,可以存储固定数量的元素,并且每个元素的类型是已知的,并且而已不同。

元组用于精确的描述一组值的类型,?表示可选元素。...数据类型[]表示任意多个元素。

例子:

image-20240917165943246

enum

枚举(enum)可以定义一组命名常量,它能增强代码的可读性,让代码更好的维护。

内容引入:

如下代码的功能是:根据调用walk时传入的不同参数,执行不同的逻辑,存在的问题是调用walk时传参时没有任何提示,编码者很容易写错字符串内容;并且用于判断逻辑的up、down、left、right是连续且相关的一组值,那此时就特别适合使用枚举举(enum)。

image-20240917170310911

数字枚举

数字枚举一种最常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点。

语法:enum 枚举名称{属性...}

字符串枚举

枚举成员的值是字符串。

image-20240917171449493

常量枚举

常量枚举是一种特殊枚举类型,它使用 const关键字定一车,在编译的时候会被内联,避免生成额外的代码。

何为编译时的内联?

所谓“内联”其实就是TS在编译的时候,会将枚举成员应用替换成他们的实际值,而不是生成额外的枚举对象。这可以减少生成的JS代码量,并提高运行的性能。

例子:

使用普通枚举:

image-20240917222447829

使用常量枚举:image-20240917222357927

自定义类型

type

语法:type 新的类型名字 = 数字类型

联合类型:是一种高级类型,它表示一个值可以是几种不同类型之一。

联合声明:
type Status = number | string

字面量写法:
type Gender = '男'|'女'

交叉类型:允许将多个类型合并为一个类型。合并后的类型将拥有所有被合并类型的成员。交叉类型通常用于对象类型。

image-20240917223742375

代码模版:

//编写接口
export interface 接口名{
	属性名:属性值,...
}
//一个自定义类型
	export type 自定义类型名称 = 数据类型<接口名>
  
//导入
	import { type 自定义类型名称 } from '@/路径'
  
//使用
  let 对象名:自定义类型名称 = {属性名:属性值,...}

interface接口

interface是一种定义结构的方式,主要作用是为:类、对象、、函数等规定一种契约这样可以确保代码的一致性和类型安全,但要注意interface只能定义格式,不能包含任何实现。

接口定义类的结构:

  1. 编写接口

    interface 类名{
    	属性名:数据类型,...
    	方法(参数:数据类型):void
    }
    
  2. 实现接口

    class 类名 implement接口名{
    	constructor(
    		定义属性:数据类型,...
    	){}
    	方法名(参数:数据类型):void{
    	//方法体
    	}
    }
    

接口定义函数结构:

  1. 编写接口

    interface 接口名{
    	(属性名:数据类型,...):数据类型;
    }
    
  2. 使用接口

    let 函数名:接口名 = (参数1,参数2...) => { return //函数体}
    

接口定义函数:

  1. 编写接口

    interface 接口名{
    	属性值:数据类型...
    	方法:(参数:数据类型) => void
    }
    
  2. 使用接口

    let 对象名:接口名 ={
    	属性名:属性值...,
    	方法(参数){	//方法体 }
    }
    
接口继承

interface继承另一个interface,从而实现代码的复用。

例子:

image-20240918000156655

接口自动合并

image-20240918000406405

接口总结

总结:何时使用接口?

  1. 定义对象的格式:描述数据模型、API响应格式、配置对象…等等,是开发中用的最多的场景。

  2. 类的契约:规定一个类需要实现哪些属性和方法。

  3. 自动合并:一般用于扩展第三方库的类型,这种特性在大型项目中可能会用到。

  4. 导出接口

    export interface 接口名{
    	属性名:属性值,...
    }
    
  5. 导入接口

    import { type 接口名 } from '@/路径'
    

type与接口区别

相同点:接口和 type都可以用来定义对象结构,两者在许多场景可以互换。

不同点:

  1. 接口:更专注定于对象的结构,支持 继承合并
    image-20240918105031989
  2. type:可以定义 类型别名联合类型交叉类型,但不支持继承和自动合并。

面向对象

image-20240917231151132

继承

image-20240917231216331

属性修饰符

修饰符含义具体规则
public公开的可以被:类内部、子类、类外部访问。
protected受保护的可以被:类内部、子类访问。
private私有的可以被:类内部访问。
readonly只读属性属性无法修改。

类的位置分析:

image-20240917231602124

属性的简写

image-20240917231740045

image-20240917231713926

抽象类

概述:抽象类是一种 无法被实例化的类,专门用来定义类的 结果和行为,类中可以写 抽象方法,也可以写 具体实现。抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现其中的抽象方法。

简写:抽象类 不能实例化,其意义是可以被继承,抽象类可以有普通方法,也可以有抽象方法。

例子:

image-20240917233357873

测试代码:

image-20240917233437953

接口与抽象类的区别

相同点:都用于定义一个 类的格式

不同点

  1. 接口:只能描述 结构,不能有任何 实现代码,一个类可以实现多个接口。
  2. 抽象类,既可以包含 抽象方法,也可以包含 具体方法,一个类只能继承一个抽象类。

类的最佳实践

何时使用 抽象类

  1. 定义 通用接口:为一组相关的类定义通用的行为(方法或属性)的时候。
  2. 提供 基础实现:在抽象类中提供某些方法或为其提供实现,这样派生类就可以继承这些实现。
  3. 确保 关键实现:强制派生类实现一些关键行为。
  4. 共享代码和逻辑:当多个类需要共享部分代码的时候,抽象类可以避免代码重复。

泛型

泛型允许我们在定义函数、类或接口时,使用类型参数来表示 未指定的类型,这些参数在具体使用时,才被指定具体的类型,泛型能 让同一段代码适用于多种类型,同时仍然保持类型的安全性。

语法::数据类型<接口名>

例子:

image-20240918110129571

泛型接口

例子:

image-20240918110307702

泛型类

例子:

image-20240918113703696

类型声明文件

类型声明文件是TS中的一种特殊文件,通常以 .d.ts作为扩展名。

它主要作用是 为现有的JS代码提供类型信息,使得TS能够在使用这些JS库或模块的时候进行 类型检查和提示

语法:declare

例子:

demo.js文件

image-20240918114116343

demo.d.ts文件

image-20240918114123149

index.ts

image-20240918114357102

props

image-20240918092431234

// 定义一个接口,限制每个Person对象的格式
export interface PersonInter {
id:string,
name:string,
 age:number
}

// 定义一个自定义类型Persons
export type Persons = Array<PersonInter>

App.vue中代码:

<template>
	<Person :list="persons"/>
</template>

<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import {reactive} from 'vue'
 import {type Persons} from './types'

 let persons = reactive<Persons>([
  {id:'e98219e12',name:'张三',age:18},
   {id:'e98219e13',name:'李四',age:19},
    {id:'e98219e14',name:'王五',age:20}
  ])
</script>

Person.vue中代码:

<template>
<div class="person">
<ul>
  <li v-for="item in list" :key="item.id">
     {{item.name}}--{{item.age}}
   </li>
 </ul>
</div>
</template>

<script lang="ts" setup name="Person">
import {defineProps} from 'vue'
import {type PersonInter} from '@/types'

// 第一种写法:仅接收
// const props = defineProps(['list'])

// 第二种写法:接收+限制类型
// defineProps<{list:Persons}>()

// 第三种写法:接收+限制类型+指定默认值+限制必要性
let props = withDefaults(defineProps<{list?:Persons}>(),{
  list:()=>[{id:'asdasg01',name:'小猪佩奇',age:18}]
})
console.log(props)
</script>

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

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

相关文章

深度学习02-pytorch-08-自动微分模块

​​​​​​​ 其实自动微分模块&#xff0c;就是求相当于机器学习中的线性回归损失函数的导数。就是求梯度。 反向传播的目的&#xff1a; 更新参数&#xff0c; 所以会使用到自动微分模块。 神经网络传输的数据都是 float32 类型。 案例1: 代码功能概述&#xff1a; 该…

【Python篇】深入机器学习核心:XGBoost 从入门到实战

文章目录 XGBoost 完整学习指南&#xff1a;从零开始掌握梯度提升1. 前言2. 什么是XGBoost&#xff1f;2.1 梯度提升简介 3. 安装 XGBoost4. 数据准备4.1 加载数据4.2 数据集划分 5. XGBoost 基础操作5.1 转换为 DMatrix 格式5.2 设置参数5.3 模型训练5.4 预测 6. 模型评估7. 超…

重生之我们在ES顶端相遇第14 章 - ES 节点类型

文章目录 前言Coordinating nodeMaster-eligible nodeData nodeCoordinating only nodeRemote-eligible nodeMachine learning node 前言 通过前面的学习&#xff0c;我们已经初步的掌握了 ES 的大部分用法。 后面的篇章会介绍 ES 集群相关的内容。 本文着重介绍 ES 节点类型&…

华为HarmonyOS地图服务 3 - 如何开启和展示“我的位置”?

一. 场景介绍 本章节将向您介绍如何开启和展示“我的位置”功能&#xff0c;“我的位置”指的是进入地图后点击“我的位置”显示当前位置点的功能。效果如下&#xff1a; 二. 接口说明 “我的位置”功能主要由MapComponentController的方法实现&#xff0c;更多接口及使用方法…

软考高级:逻辑地址和物理地址转换 AI解读

一、题目 设某进程的段表如下所示&#xff0c;逻辑地址&#xff08; &#xff09;可以转换为对应的物理地址。 A. &#xff08;0&#xff0c;1597&#xff09;、&#xff08;1&#xff0c;30&#xff09;和&#xff08;3&#xff0c;1390&#xff09; B. &#xff08;0&…

Vue3 中组件传递 + css 变量的组合

文章目录 需求效果如下图所示代码逻辑代码参考 需求 开发一个箭头组件&#xff0c;根据父组件传递的 props 来修改 css 的颜色 效果如下图所示 代码逻辑 代码 父组件&#xff1a; <Arrow color"red" />子组件&#xff1a; <template><div class&…

3DMAX乐高积木插件LegoBlocks使用方法

3DMAX乐高积木插件LegoBlocks&#xff0c;用户可以通过控件调整和自定义每个乐高积木的外观和大小。 【适用版本】 3dMax2009或更高版本&#xff08;不仅限于此范围&#xff09; 【安装方法】 3DMAX乐高积木插件无需安装&#xff0c;使用时直接拖动插件脚本文件到3dMax视口中…

TS 运行环境

1、TS Playground&#xff08;在线&#xff09; TS Playground 是一个在线 TypeScript 编辑器&#xff0c;它允许你编写、共享和学习 TypeScript 代码。 2、Stackblitz&#xff08;在线&#xff09; StackBlitz 是面向web开发人员的基于浏览器的协作IDE。StackBlitz消除了耗时…

握手传输 状态机序列检测(记忆科技笔试题)_2024年9月2日

发送模块循环发送0-7&#xff0c;在每个数据传输完成后&#xff0c;间隔5个clk&#xff0c;发送下一个 插入寄存器打拍处理&#xff0c;可以在不同的时钟周期内对信号进行同步&#xff0c;从而减少亚稳态的风险。 记忆科技笔试题&#xff1a;检测出11011在下一个时钟周期输出…

Python | 读取.dat 文件

写在前面 使用matlab可以输出为 .dat 或者 .mat 形式的文件&#xff0c;之前介绍过读取 .mat 后缀文件&#xff0c;今天正好把 .dat 的读取也记录一下。 读取方法 这里可以使用pandas库将其作为一个dataframe的形式读取进python&#xff0c;数据内容格式如下&#xff0c;根据…

VulnHub-Narak靶机笔记

Narak靶机笔记 概述 Narak是一台Vulnhub的靶机&#xff0c;其中有简单的tftp和webdav的利用&#xff0c;以及motd文件的一些知识 靶机地址&#xff1a; https://pan.baidu.com/s/1PbPrGJQHxsvGYrAN1k1New?pwda7kv 提取码: a7kv 当然你也可以去Vulnhub官网下载 一、nmap扫…

zabbix7.0容器化部署测试--(1)准备容器镜像

本文为zabbix7.0容器化部署测试系统文档之一&#xff0c;准备容器镜像。拟测试数据库后台为PostgreSQL16并启用timescaledb插件。 一、准备数据库容器镜像 因为不确定zabbix7.0对数据库timescaledb插件的版本要求&#xff0c;准备了现个镜像版本 1、准备timescaledb-2.14.2插…

linux 基础(一)mkdir、ls、vi、ifconfig

1、linux简介 linux是一个操作系统&#xff08;os: operating system&#xff09; 中国有没有自己的操作系统&#xff08;华为鸿蒙HarmonyOS&#xff0c;阿里龙蜥(Anolis) OS 8、百度DuerOS都有&#xff09; 计算机组的组成&#xff1a;硬件软件 硬件&#xff1a;运算器&am…

【速成Redis】03 Redis 五大高级数据结构介绍及其常用命令 | 消息队列、地理空间、HyperLogLog、BitMap、BitField

前言&#xff1a; 上篇博客我们讲到redis五大基本数据类型&#xff08;也是就下图的第一列&#xff09;。 【速成Redis】02 Redis 五大基本数据类型常用命令-CSDN博客文章浏览阅读1k次&#xff0c;点赞24次&#xff0c;收藏10次。该篇适用于速成redis。本篇我们将讲解&#…

MySQL | 知识 | NULL值是怎么存储的

NULL值有哪些语法影响 我们使用mysql时&#xff0c;使用 xx !aa 这种条件为什么无法筛选出值为NULL的字段呢。 是的&#xff0c;MySQL 中null 值确实无法通过这种条件筛选出来&#xff0c;因为 null 值的定义就跟普通值不一样。 拿官网的例子来说&#xff1a; mysql> INSE…

在Java中基于GeoTools的Shapefile读取乱码的问题解决办法

目录 前言 1、Shapefile属性字段编码的情况&#xff1a; 一、Shp文件常见的字符集编码 1、System编码 2、ISO-8859-1编码 3、UTF-8编码 二、GeoTools解析实战 1、未进行字符处理 2、乱码问题的解决 3、转码支持 4、属性字段编码结果 三、总结 前言 文件编码&#x…

RabbitMQ:交换机详解(Fanout交换机、Direct交换机、Topic交换机)

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

【笔记】第二节 轧制、热处理和焊接工艺

2.2 钢轨的轧制工艺 坯料进厂按标准验收, 然后装加热炉加热, 加热好的钢坯经高压水除鳞后进行轧制。轧出的钢轨经锯切、打印到中央冷床冷却, 然后装缓冷坑进行缓冷。缓冷后的钢轨进行矫直、轨端加工和端头淬火。钢轨入库前逐根进行探伤和外观检查。 钢轨的轧制 #mermaid-svg-…

【Delphi】使用 TPrototypeBindSource 和 LiveBindings 设计器示例

本教程展示了如何使用 LiveBindings Designer 和 TPrototypeBindSource 可视化地创建控件之间的 LiveBindings&#xff0c;以便快速开发只需很少或无需源代码的应用程序。 注意&#xff1a; TPrototypeBindSource 可用于为项目中的 LiveBindings 生成样本数据。在应用程序原型化…

公私域互通下的新商机探索:链动2+1模式、AI智能名片与S2B2C商城小程序的融合应用

摘要&#xff1a;在数字化时代&#xff0c;公私域流量的有效融合已成为企业获取持续增长动力的关键。本文旨在探讨如何通过链动21模式、AI智能名片以及S2B2C商城小程序源码的综合运用&#xff0c;实现公私域流量的高效互通&#xff0c;进而为门店创造巨大商机。通过分析这些工具…