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 关键字的锁机制的一部分,用于在高竞争情况下确保线程的同步。重量级锁主要通过操作系统的线程同步机制实现,通常涉及阻塞线程、上下文切换等开销较大的操作。以下是重量级锁…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
