TypeScript JSX
介绍
在线的免费的代码转换器工具:可以把HTML 代码移植到 JSX 语法。还支持很多其他的转换。
JSX 是 ECMAScript 的一种类似 XML 的语法扩展,没有任何定义的语义。它不打算由引擎或浏览器实现。它并不是将 JSX 纳入 ECMAScript 规范本身的提议。它旨在供各种预处理器(转译器)使用这些标记转换为标准 ECMAScript。
JSX 是一种在 JavaScript 中编写类似 XML 结构来描述用户界面的语法。
TypeScript支持内嵌,类型检查以及将JSX直接编译为JavaScript。
基本用法
想要使用JSX必须做两件事:
- 给文件一个
.tsx
扩展名:- 向开发工具和编译器表明该文件中可能包含 JSX 语法。
- 启用jsx选项
- 启用 jsx 选项通常是在
tsconfig.json
文件中进行配置。
- 启用 jsx 选项通常是在
TypeScript具有三种JSX模式:
preserve
:保留 JSX 为原始的样子,不进行转换。- 保留 JSX 为原始的样子,不进行转换。
- 输出文件会带有
.jsx
扩展名。
react
:这是在使用 React 框架时常用的选项,会对 JSX 进行相应的转换。- 生成
React.createElement
,在使用前不需要再进行转换操作。 - 输出文件的扩展名为
.js
。
- 生成
react-native
:用于 React Native 开发。- 保留 JSX 为原始的样子,不进行转换。
- 输出文件的扩展名为
.js
。
模式 | 输入 | 输出 | 输出文件扩展名 |
---|---|---|---|
preserve | <div /> | <div /> | .jsx |
react | <div /> | React.createElement("div") | .jx |
react-native | <div /> | <div /> | .jx |
这些模式只在代码生成阶段起作用,类型检查并不受影响。
注意:React
标识符是写死的硬编码,所以你必须保证React(大写的R)是可用的。
以下是一个简单的 tsconfig.json
配置示例,启用了 jsx
选项为 react
:
{"compilerOptions": {"jsx": "react"}
}
在具有 .tsx
扩展名的文件中,就可以自由地使用 JSX 语法进行开发了。
JSX 中的属性设置与 HTML 类似,但需要使用驼峰命名法。比如在 HTML 中是 class
属性,在 JSX 中则是 className
。
const element = <div className="my-class">Content</div>;
可以通过使用引号""
,来将属性值指定为字符串字面量:
const element = <div className="my-class" title="This is a title">Content</div>;
className
的值 my-class
和 title
的值 This is a title
都是字符串字面量。
这种方式适用于属性值明确为固定字符串的情况。
如果属性值是动态计算的结果或者是变量,使用{}
直接将变量或表达式嵌入到 JSX 中:
const titleText = 'Dynamic Title';
const element = <div className="my-class" title={titleText}>Content</div>;
JSX 允许在模板中插入数组,数组会自动展开所有成员:
let arr = [<p>111</p>,<p>222</p>,
];
const content = (<div>{arr}</div>
);
JSX 支持条件渲染和循环渲染。
条件渲染:
const isLoggedIn = true;
const element = (<div>{isLoggedIn? <p>Welcome back!</p> : <p>Please log in.</p>}</div>
);
循环渲染:
const items = ['Apple', 'Banana', 'Orange'];
const element = (<ul>{items.map(item => <li>{item}</li>)}</ul>
);
JSX 的注释代码需要写在花括号 {}
中:
const content = ({/*注释...*/}<h1>hello world</h1>
);
as
操作符
在 TypeScript 的 JSX 中,as
操作符通常用于类型断言。
TypeScript也使用尖括号<>
来表示类型断言:
let foo = <foo>bar;
这句代码断言bar
变量是foo
类型的。
TypeScript在.tsx
文件里禁用了使用尖括号<>
的类型断言。
因为在 TypeScript 的 JSX 环境中(例如 .tsx
文件),尖括号<>
有特殊用途。
使用 as
操作符:
let foo = bar as foo;
JSX 环境中使用 as
操作符:
interface CustomButtonProps {label: string;onClick: () => void;
}
const button = (<buttonas={CustomButton}label="Click Me"onClick={() => console.log('Clicked!')}/>
);
as
操作符在.ts
和.tsx
里都可用,并且与尖括号类型断言行为是等价的。
类型检查
TypeScript 对 JSX 的类型检查涵盖了元素类型、属性类型、子元素类型以及基于值的元素类型等多个方面,通过严格的类型检查可以在开发过程中及早发现类型不匹配的问题,提高代码的质量和可维护性。
元素类型检查
元素类型检查分为固有元素、和自定义组件。
固有元素(内置的 HTML 元素)
在 TypeScript 中对 JSX 固有元素(即内置的 HTML 元素)的检查主要包括以下几个方面:
- TypeScript 会检查使用的固有元素名称是否正确。
- 必须使用正确的 HTML 元素名称,如
<div>
、<p>
、<span>
等。使用错误或不存在的元素名称会导致编译错误。
- 必须使用正确的 HTML 元素名称,如
// 以下使用是合法的
<input type="text" placeholder="Enter text" />// 以下使用会引发错误
<myInvalidElement /> // 不存在这样的固有元素
- 对于固有元素的属性,TypeScript 会根据 HTML 规范进行类型检查。
- 每个固有元素都有一组合法的属性,并且这些属性的值必须符合相应的类型。
示例:<img src="image.jpg" alt="An image" />
中,src
属性必须是一个有效的图像路径或 URL,alt
属性必须是一个字符串。
const element2 = <img src="valid-image.jpg" alt="Valid image" />; // 合法
const element4 = <img src={123} alt="Invalid" />; // 不合法, src 应该是字符串,而不是数字
自定义组件
对于自定义组件,必须确保组件已经正确定义并且在使用的作用域内可访问。TypeScript 会检查传递给自定义组件的属性是否符合组件定义的属性类型。
例如,定义一个名为 MyComponent
的自定义组件,接收一个 name
属性,类型为字符串:
interface MyComponentProps {name: string;
}function MyComponent({ name }: MyComponentProps) {return <div>Hello, {name}!</div>;
}
使用时:
// 正确的使用
const element5 = <MyComponent name="John" />;// 错误的使用,会产生编译错误
const element6 = <MyComponent name={123} />; // name 应该是字符串,而不是数字
基于值的元素类型检查
在 JSX 中,基于值的元素可能是无状态函数组件或类组件。TypeScript 会首先尝试将表达式作为无状态函数组件进行解析,如果解析成功,就完成表达式到其声明的解析操作。如果按照无状态函数组件解析失败,会继续尝试以类组件的形式进行解析。如果依旧失败,就会输出一个错误。
无状态函数组件(SFC)
组件被定义成JavaScript函数,它的第一个参数是props
对象。 TypeScript会强制它的返回值可以赋值给JSX.Element
。
function MyComponent({ name }: { name: string }) {return <div>Hello, {name}!</div>;
}
在使用时,可以直接在 JSX 表达式中通过标识符引用这个组件:
<MyComponent name="John" />
由于无状态函数组件是简单的JavaScript函数,所以可以利用函数重载:
// ClickableProps 接口定义了一个名为 children 的属性,可以是单个 JSX.Element 或者是 JSX.Element 的数组。
interface ClickableProps {children: JSX.Element[] | JSX.Element
}// HomeProps 接口继承自 ClickableProps,并添加了一个名为 home 的属性,类型为 JSX.Element。
interface HomeProps extends ClickableProps {home: JSX.Element;
}// SideProps 接口也继承自 ClickableProps,添加了一个名为 side 的属性,类型是 JSX.Element 或者 字符串。
interface SideProps extends ClickableProps {side: JSX.Element | string;
}
函数实现示例:
function MainButton(prop: HomeProps): JSX.Element;
function MainButton(prop: SideProps): JSX.Element {if ('home' in prop) {// 处理 HomeProps 类型的参数return <button>{prop.home}</button>;} else if ('side' in prop) {// 处理 SideProps 类型的参数return (<button>{typeof prop.side === 'string' ? prop.side : prop.side}</button>);}return null;
}
MainButton
函数被重载为接受两种不同类型的参数,分别是 HomeProps
类型和 SideProps
类型,并且返回值都是 JSX.Element
。
类组件
当定义类组件时,可以分别考虑元素类的类型和元素实例的类型。
元素类的类型和实例类型的概念:
- 对于 JSX 表达式
<Expr />
,元素类的类型就是Expr
的类型。如果Expr
是一个 ES6 类,那么类类型包括类的构造函数和静态部分。如果Expr
是一个工厂函数,类类型就是这个函数本身。 - 一旦确定了类类型,实例类型由类构造器或调用签名(如果存在的话)的返回值的联合构成。对于 ES6 类,实例类型是这个类的实例的类型;对于工厂函数,实例类型是这个函数的返回值类型。
示例:
class MyComponent {render() {}
}// 使用构造签名
var myComponent = new MyComponent();// 元素类的类型 => MyComponent
// 元素实例的类型 => { render: () => void }function MyFactoryFunction() {return {render: () => {}}
}// 使用调用签名
var myComponent = MyFactoryFunction();// 元素类的类型 => FactoryFunction
// 元素实例的类型 => { render: () => void }
示例中的类型分析:
- 在给出的示例中,对于
MyComponent
类:- 元素类的类型是
MyComponent
,也就是这个类本身。 - 元素实例的类型是
{ render: () => void }
,因为这个类有一个render
方法。
- 元素类的类型是
- 对于
MyFactoryFunction
:- 元素类的类型是这个工厂函数本身。
- 元素实例的类型也是
{ render: () => void }
,因为这个函数返回一个对象,该对象有一个render
方法。
元素的实例类型必须赋值给JSX.ElementClass
或抛出一个错误。
JSX.ElementClass
的作用:
- 默认情况下,
JSX.ElementClass
为{}
,这意味着在没有自定义时,JSX 元素的实例类型可以是任何对象。 - 可以通过扩展
JSX.ElementClass
来限制 JSX 的类型以符合相应的接口。 - 当定义了特定的
JSX.ElementClass
后,只有满足该接口要求的类或工厂函数创建的对象才能在 JSX 中使用。
示例:
declare namespace JSX {interface ElementClass {render: any;}
}class MyComponent {render() {}
}
function MyFactoryFunction() {return { render: () => {} }
}<MyComponent />; // 正确
<MyFactoryFunction />; // 正确class NotAValidComponent {}
function NotAValidFactoryFunction() {return {};
}<NotAValidComponent />; // 错误
<NotAValidFactoryFunction />; // 错误
在代码中通过 declare namespace JSX
并定义 interface ElementClass
为 { render: any; }
,这就要求 JSX 元素的实例必须有一个 render
方法。
MyComponent
和 MyFactoryFunction
是有效的,因为它们创建的对象都有 render
方法,符合 JSX.ElementClass
的要求。
NotAValidComponent
和 NotAValidFactoryFunction
是无效的,因为它们创建的对象没有 render
方法,不满足 JSX.ElementClass
的要求,所以在 JSX 中使用时会产生错误。
通过理解元素类的类型、实例类型以及 JSX.ElementClass
的作用,可以更好地控制和规范在 TypeScript 中使用 JSX 时的组件类型,提高代码的类型安全性和可维护性。
属性类型检查
属性类型检查的第一步是确定元素属性类型。 这在固有元素和基于值的元素之间稍有不同。
固有元素的属性类型检查
对于固有元素,其属性类型由 JSX.IntrinsicElements
接口定义。
declare namespace JSX {interface IntrinsicElements {foo: { bar?: boolean };}
}// `foo`的元素属性类型为`{bar?: boolean}`
<foo bar />;
<foo>
元素的属性类型被明确为可以有一个可选的 bar
属性,类型为布尔值。
固有元素的属性类型检查
- 确定属性类型的方式:
- 对于基于值的元素(如类组件或无状态函数组件),属性类型的确定稍微复杂一些。它取决于先前确定的在元素实例类型上的某个属性的类型,而具体使用哪个属性来确定类型取决于
JSX.ElementAttributesProperty
的定义。 - 如果未指定
JSX.ElementAttributesProperty
,在 TypeScript 2.8 及以后版本中,将使用类元素构造函数或无状态函数组件调用的第一个参数的类型。
declare namespace JSX {interface ElementAttributesProperty {props; // 指定用来使用的属性名}
}class MyComponent {props: {foo?: string;};
}// `MyComponent`的元素属性类型为`{foo?: string}`
<MyComponent foo="bar" />;
- 支持可选属性和必须属性:
元素属性类型可以定义可选属性和必须属性。
示例:
declare namespace JSX {interface IntrinsicElements {foo: { requiredProp: string; optionalProp?: number };}
}<foo requiredProp="bar" />; // 正确
<foo requiredProp="bar" optionalProp={0} />; // 正确
<foo />; // 错误, 缺少 requiredProp
<foo requiredProp={0} />; // 错误, requiredProp 应该是字符串
<foo requiredProp="bar" unknownProp />; // 错误, unknownProp 不存在
<foo requiredProp="bar" some-unknown-prop />; // 正确, `some-unknown-prop`不是个合法的标识符
在这个例子中,<foo>
元素有一个必须的 requiredProp
属性,类型为字符串,还有一个可选的 optionalProp
属性,类型为数字。
额外属性和泛型类型
JSX.IntrinsicAttributes
接口:JSX.IntrinsicAttributes
接口可以用来指定额外的属性,这些属性通常不会被组件的props
或arguments
使用。例如在 React 中,key
属性就是通过这种方式指定的。
declare namespace JSX {interface IntrinsicAttributes {// 添加 data-testid 属性作为额外属性'data-testid'?: string;}
}function MyComponent() {return <div data-testid="my-component-test-id">Hello World</div>;
}const AnotherComponent = () => {return <p data-testid="another-component-test-id">Another Component</p>;
};
在示例中,通过JSX.IntrinsicAttributes
接口定义了一个可选的data-testid
属性,这个属性可以在任何 JSX 元素上使用,而不需要在每个组件的 props
中明确声明。
JSX.IntrinsicClassAttributes<T>
泛型类型。
假设我们有一个类组件,需要支持 React 的ref
属性来获取对 DOM 元素的引用。我们可以使用JSX.IntrinsicClassAttributes<T>
泛型类型来实现。
import React, { Component } from 'react';interface MyComponentProps {title: string;
}class MyClassComponent extends Component<MyComponentProps> {render() {return <div>{this.props.title}</div>;}
}declare namespace JSX {interface IntrinsicClassAttributes<MyClassComponent> {// 允许 ref 属性ref?: React.Ref<MyClassComponent>;}
}
现在可以在使用MyClassComponent
时传递ref
属性:
const ref = React.createRef<MyClassComponent>();
<MyClassComponent title="My Title" ref={ref} />;
在这个例子中,使用JSX.IntrinsicClassAttributes<T>
泛型类型为MyClassComponent
类添加了一个可选的ref
属性,这样在使用这个类组件时就可以方便地获取对组件实例的引用。
延展操作符的使用
延展操作符可以方便地将一个对象的属性展开到 JSX 元素中。
示例:
let props = { requiredProp: 'bar' };
<foo {...props} />; // 正确let badProps = {};
<foo {...badProps} />; // 错误
JSX.IntrinsicElements
接口的作用
JSX.IntrinsicElements
接口用于定义和查找固有元素(内置 HTML 元素)的类型信息,从而进行类型检查。
JSX.IntrinsicElements
接口定义了各种固有元素及其可接受的属性和属性类型。
当在 TypeScript 中处理 JSX 时,如果没有明确指定 JSX.IntrinsicElements
接口,不对固有元素进行类型检查。这时,使用了不正确或不被支持的属性,也可能不会在编译时产生类型错误。
如果定义了 JSX.IntrinsicElements
接口,对于每个固有元素的名称及其可接受的属性,都需要在这个接口中进行查找和匹配。
例如,如果定义了如下的 JSX.IntrinsicElements
接口:
interface CustomIntrinsicElements {'button': {disabled: boolean;onClick: (event: MouseEvent) => void;};
}declare global {namespace JSX {interface IntrinsicElements extends CustomIntrinsicElements {}}
}
在上述示例中,为 button
元素自定义了其 disabled
属性必须是布尔类型,onClick
属性必须是特定类型的函数。 customStr
是自定义的属性,必须是字符串类型。
这样,当在代码中使用 <button>
元素时,如果属性的类型不符合定义,TypeScript 就会在编译时给出错误提示。
通过扩展 JSX.IntrinsicElements
,可以添加自定义的固有元素或者修改已有固有元素的默认行为:
interface CustomIntrinsicElements {// 添加自定义固有元素'myCustomElement': {customProp1: string;customProp2: number;};// 修改已有固有元素的默认行为'button': {// 在这里添加、修改或覆盖按钮元素的属性类型disabled: boolean;customButtonProp: string; };
}declare global {namespace JSX {interface IntrinsicElements extends CustomIntrinsicElements {}}
}
在组件中使用自定义或修改后的固有元素:
function MyComponent() {return (<div><myCustomElement customProp1="Value1" customProp2={123} /><button disabled={true} customButtonProp="Custom Button Prop Value" >Click Me</button></div>);
}
也可以在JSX.IntrinsicElements
上指定一个用来捕获所有字符串索引:
declare namespace JSX {interface IntrinsicElements {[elemName: string]: any;}
}
这段 TypeScript 代码通过 declare namespace JSX
声明了一个与 JSX
相关的命名空间。在这个命名空间中,定义了 IntrinsicElements
接口。
IntrinsicElements
接口中,[elemName: string]: any;
这部分表示对于任意字符串形式的元素名称(elemName
),其对应的属性类型可以是任意类型(any
)。
使用:
function MyComponent() {return <customElement someRandomProp="value" />;
}
不会导致类型错误,因为对于任何未明确定义的固有元素,其属性类型被允许为任意类型。
JSX.IntrinsicAttributes
JSX.IntrinsicAttributes
用于表示 JSX 元素的内置属性类型。
当使用 JSX 语法时,TypeScript 需要确定每个元素的属性类型。
- 对于固有元素(内置的 HTML 元素),TypeScript 内置了对这些元素常见属性的类型定义。
- 对于自定义组件,
JSX.IntrinsicAttributes
可以用来描述可能传递给组件的通用属性,这些属性不是由组件明确定义的属性,而是类似style
、className
、key
等在 JSX 中经常使用的属性。
示例:
interface MyComponentProps {customProp: string;
}function MyComponent({customProp
}: MyComponentProps & JSX.IntrinsicAttributes) {return (<div className={/*...*/} style={/*...*/}>{customProp}</div>);
}
在示例中,MyComponent
组件除了接收自定义的 customProp
属性外,还可以接收 JSX.IntrinsicAttributes
中定义的那些通用属性,如 className
和 style
。
如果不使用 JSX.IntrinsicAttributes
,当尝试在使用 MyComponent
时传递 className
或 style
等属性时,TypeScript 会报错,因为这些属性没有在 MyComponentProps
接口中定义。
JSX.IntrinsicAttributes
提供了一种方便的方式来处理在 JSX 中传递给组件的通用属性,确保类型安全。
子孙类型检查
从TypeScript 2.3开始,引入了children类型检查。
在 JSX 中,children 是元素属性类型中的一个特殊属性。当在 JSX 结构中为一个组件或元素指定子元素时,这些子元素会被插入到 children 属性中进行处理。
JSX.ElementAttributesProperty
:用于决定组件接收的属性名称。例如,可以通过自定义这个属性来指定不同的属性名来接收传入的属性值。
JSX.ElementChildrenAttribute
:用于决定 children 属性的名称。默认情况下,children 是一个特殊的属性,用于接收子元素。通过这个属性,可以自定义 children 的名称。
JSX.ElementChildrenAttribute
应该被声明在单一的属性(property)里。
declare namespace JSX {interface ElementChildrenAttribute {customChildrenName: JSX.Element[];}
}function MyComponent({ customChildrenName }: { customChildrenName: JSX.Element[] }) {return <div>{customChildrenName}</div>;
}const childElement = <p>Child Element</p>;const jsxExpression = <MyComponent customChildrenName={[childElement]} />;
在这个示例中,我们自定义了 children 的名称为 customChildrenName
,并在 MyComponent
组件中接收这个属性。在使用 MyComponent
时,我们将一个子元素通过 customChildrenName
属性传递给组件。
通过这种方式,可以更加灵活地控制组件接收子元素的方式,并且通过类型检查确保子元素的类型正确。
子元素类型检查
单个子元素
如果一个组件只接收一个子元素,可以明确指定子元素的类型。
示例:
interface SingleChildComponentProps {// child类型为 JSX.Elementchild: JSX.Element;
}
//
function SingleChildComponent({ child }: SingleChildComponentProps) {return <div>{child}</div>;
}
使用时:
const childElement = <p>Child Element</p>;// 正确的使用
const element14 = <SingleChildComponent child={childElement} />;// 错误的使用,会产生编译错误
const element15 = <SingleChildComponent child={123} />; // child 应该是 JSX.Element 类型
多个子元素
如果一个组件接收多个子元素,可以使用数组类型。
示例:
interface MultipleChildrenComponentProps {// children 类型为 JSX.Element[]children: JSX.Element[];
}function MultipleChildrenComponent({ children }: MultipleChildrenComponentProps) {return <div>{children}</div>;
}
使用时:
const childElements = [<p>Child 1</p>, <p>Child 2</p>];// 正确的使用
const element16 = <MultipleChildrenComponent children={childElements} />;// 错误的使用,会产生编译错误
const element17 = <MultipleChildrenComponent children={123} />; // children 应该是 JSX.Element 类型的数组
JSX结果类型
JSX表达式结果的类型 默认为any
。
可以通过指定JSX.Element
接口自定义JSX表达式结果的类型。
不能够从接口里检索元素,属性或JSX的子元素的类型信息。 它是一个黑盒。
相关文章:

TypeScript JSX
介绍 在线的免费的代码转换器工具:可以把HTML 代码移植到 JSX 语法。还支持很多其他的转换。 JSX 是 ECMAScript 的一种类似 XML 的语法扩展,没有任何定义的语义。它不打算由引擎或浏览器实现。它并不是将 JSX 纳入 ECMAScript 规范本身的提议。它旨在供…...

java里的序列化反序列化、HttpMessageConverter、Jackson、消息转化器、对象转化器...都是啥?
前段时间在学习SSM框架(spring boot、spring MVC、mybatis)后端项目的时候,发现他们的项目里:响应类Result类要实现Serializable接口、转化响应给前端的时间数据的格式要用到什么“消息转换器”MappingJackson2HttpMwssageConvert…...

GNU/Linux - memtool使用
在Yocto中为NXP的i.MX系列芯片构建Linux系统时,可以加入一些实用工具,比如直接操作内存的memtool。 这些工具在imx-test包中,比如imx-test_git.bb里。 比如在imx-image-core.bb中,IMAGE_INSTALL "imx-test" ࿰…...

Qt5.12.8源码交叉编译带openssl版本
一.背景 近期项目由于对接方的Qt版本是Qt5.12.8,后台服务是https的,之前用的Qt5.15.10要切换成Qt5.12.8,并且为了能支持https,必须要重新编译Qt。 二.环境 环境准备: Ubuntu版本 :18.04; openss…...

串行并行数据转换
前言 串行数据传输通常在数据传输距离较远时使用,而并行数据传输适用于短距离、高速数据交换。通过转换,可以根据实际需求选择合适的传输方式,以优化数据传输效率和速度。串行数据传输在长距离传输中可以减少信号的干扰和失真,因为…...

推荐一个优秀的 .NET MAUI 组件库
目录 前言 组件介绍 组件展示 布局 按钮 复选框 进度条 导航栏 组件地址 最后 前言 .NET MAUI 的发布,项目中可以使用这个新的跨平台 UI 框架来轻松搭建的移动和桌面应用。 为了帮助大家更快地构建美观且功能丰富的应用,本文将推荐一款优秀…...

用Manim创建条形图【BarChart】
BarChart是Manim库中用于创建条形图的函数。它允许用户通过一组值创建一个条形图,其参数可以调整条形的外观和布局。 BarChart(values, bar_namesNone, y_rangeNone, x_lengthNone, y_lengthNone, bar_colors[#003f5c, #58508d, #bc5090, #ff6361, #ffa600],bar_w…...

iMES工厂管家:强大的工厂管理系统
iMES工厂管家:强大的工厂管理系统 在现代工厂管理中,iMES工厂管家作为一款功能强大的MES系统,为用户提供了全面的管理解决方案。本文将介绍iMES工厂管家的基本信息、特点、以及如何快速部署和使用。 软件简介 iMES工厂管家是一款基于.NetCor…...

iOS ------ 事件响应链
响应者链 响应者链是由一系列链接在一起的响应者(UIResponser之类:UIApplication,UIViewController,UIView)注组成的。一般情况下,一条响应链开始于第一响应者,结束于application对象。如果一个…...

Go 语言 switch 语句的特点
在 Go 语言中,switch 语句设计得更加简洁和直观,因此不需要显式使用 break 语句来终止一个分支。这种设计决策源于 Go 语言的一些设计哲学和目标,主要包括: 自动终止: Go 语言的 switch 语句会在每个 case 执行完成后自…...

【递归】什么是递归-C语言为例
递归是指一个函数在其定义中直接或间接调用自身的编程技巧。在C语言中,递归常用于解决可以被分解为更小的子问题的问题。递归函数通常由两个主要部分组成: 基准情况:这是递归停止的条件,通常是最简单的情况。 递归情况࿱…...

vue针对低版本浏览器不兼容es6特性解决方案,
browser.min.js 解决ES6兼容IE browser.min.js,polyfill.min.js vue针对安卓低版本、ios9 不兼容 es6特性解决方案 解决IE9无法使用promise的js脚本,引入后,还需跟browser.js配合使用 Babel 默认只转换新的 JavaScript 句法,po…...

嵌入式内存管理高频面试题及参考答案(4万字长文)
目录 嵌入式系统中内存管理的重要性 嵌入式系统中的内存主要分为哪几类? 静态内存分配和动态内存分配的特点 内存对齐的概念及其作用 嵌入式系统中为什么需要关注内存碎片问题 内存分区的概念及其在嵌入式系统中的应用 内存映射文件的概念及其在嵌入式系统中的作用 虚…...

TinyWebserver的复现与改进(2):项目的整体框架
上文我们成功运行了代码,本文我们将对项目的整体流程作一下讲解 如果你之前没做过相关的内容,对服务器的⾼并发模型也⼀⽆所知,不建议继续做下去,需要的前置知识有: Linux的基本命令(⭐)多进程…...

R 语言学习教程,从入门到精通,R 字符串(10)
1、R 字符串 R 语言字符串可以使用一对单引号 ’ ’ 或一对双引号 " " 来表示。 单引号字符串中可以包含双引号。 单引号字符串中不可以包含单引号。 双引号字符串中可以包含单引号。 双引号字符串中不可以包含双引号。 以下示例演示来字符串的使用: a …...

QT 简易音乐播放器
目录 放置控件 获取mp3文件 播放音乐 准备工作 加载模块 加载头文件 new一个output对象,Mediaplayer对象 把outpout对象交给mediaplayer对象 给播放器设置音乐 播放 优化 上一曲下一曲功能 双击歌曲播放 获取音乐时长和音乐播放时间 让音乐进度条跟随音乐走 调…...

代码随想录八股训练营day32
代码随想录八股训练营day32 1、synchronized和lock的区别是什么 (1)synchronized和lock的区别是什么 synchronized和Lock都是Java中用于实现线程同步的手段,synchronized是Java的关键字,基于JVM的内置锁实现,可以用于…...

11.面试题——消息队列RabbitMQ
1.RabbitMQ是什么?特点是什么? RabbitMQ是一种开源的消息队列中间件,用于在应用程序之间进行可靠的消息传递。它实现了AMQP(Advanced Message Queuing Protocol)协议,提供了强大的消息处理能力。RabbitMQ的…...

MySQL运维-日志
错误日志 二进制日志 介绍 日志格式 日志查看 日志删除 查询日志 慢查询日志...

synchronized重量级锁的实现原理是怎样的
重量级锁(Heavyweight Locking)是 Java 中 synchronized 关键字的锁机制的一部分,用于在高竞争情况下确保线程的同步。重量级锁主要通过操作系统的线程同步机制实现,通常涉及阻塞线程、上下文切换等开销较大的操作。以下是重量级锁…...

探索 GLTF 的世界:3D 内容的未来
在 3D 内容创作领域,GLTF 正在掀起波澜,成为跨不同平台提供丰富互动体验的未来标准。GL 传输格式 (GLTF) 由 Khronos Group 开发,是一种用于在工具和服务之间传输 3D 模型和场景的开放标准。它设计紧凑、高效且易于集成…...

【深度学习】【语音】TTS, CM-TTS,TTS扩散模型,论文
CM-TTS: Enhancing Real Time Text-to-Speech Synthesis Efficiencythrough Weighted Samplers and Consistency Models CM-TTS: 提高实时文本到语音合成效率 通过加权采样器和一致性模型 Xiang Li 1, Fan Bu 1, Ambuj Mehrish 2, Yingting Li 1, Jiale Han 1, Bo Cheng 1, S…...

【网络协议】网络劫持 - ARP_DNS欺骗篇
前言 网络劫持是一种网络攻击技术,攻击者通过拦截、篡改或重定向数据流量,控制用户的网络通信路径,干扰正常的网络服务。其方式可能包括DNS劫持、ARP欺骗和HTTP劫持等。通过这些手段,攻击者可以窃取敏感信息如个人身份数据和财务信…...

Linux 系统框架分析(一)
一、linux内核结构框图 对内核结构框图有个总体的把握,有助于理解为什么驱动要这样写,为什么写的应用程序所用的C库接口能够产生这么多的事情。 框图可以看出来,linux系统,包括五个系统 一、Linux内核结构介绍 Linux 内核是操作…...

Leetcode 剑指 Offer II 090.打家劫舍 II
题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 一个专业的小偷,计划偷窃一个环形街道上沿街的房屋&a…...

上海冷链配送新篇章 华鼎冷链科技以卓越服务餐饮品牌
在快速发展的上海餐饮连锁行业中,冷链运输作为保障食品安全与品质的关键环节,正迎来前所未有的发展机遇与挑战。华鼎冷链科技作为该领域的佼佼者,正引领着上海乃至全国冷链运输行业的新风尚。 华鼎冷链科技的成功并非一蹴而就。首先ÿ…...

学习鸿蒙-应用市场申请签名
1.需要的文件概念 .cer / .p7b / .p12 / .csr HarmonyOS应用/服务通过数字证书(.cer文件)和Profile文件(.p7b文件)来保证应用/服务的完整性。在申请数字证书和Profile文件前,首先需要通过DevEco Studio来生成密钥&am…...

LayUi插件
文档:日期和时间组件文档 - Layui layDate安装 npm install layui-laydate...

使用tailwindcss轻松实现移动端rem适配
本示例节选自小卷全栈开发实战系列的《Vue3实战》。演示如何用tailwindcss所支持的rem体系轻松实现一个仿b站移动端头部导航栏rem适配。 友情声明 学习分享不易,如果小伙伴觉得有帮助,点赞支持下。满30赞,将随文附赠录屏讲解,感谢…...

2021-11-08 51单片机2位秒表启动清零
缘由c51单片机,程序,仿真图,求帮助-编程语言-CSDN问答 #include "REG52.h"sbit K1 P1^0; sbit K2 P1^1; sbit K3 P1^2; sbit K4 P1^3; sbit P1_0P2^0; sbit P1_1P2^1; sbit P1_2P2^2; sbit P1_3P2^3; sbit P1_4P2^4; sbit P1_…...