当前位置: 首页 > news >正文

TypeScript JSX

介绍

在线的免费的代码转换器工具:可以把HTML 代码移植到 JSX 语法。还支持很多其他的转换。

JSX 是 ECMAScript 的一种类似 XML 的语法扩展,没有任何定义的语义。它不打算由引擎或浏览器实现。它并不是将 JSX 纳入 ECMAScript 规范本身的提议。它旨在供各种预处理器(转译器)使用这些标记转换为标准 ECMAScript。

JSX 是一种在 JavaScript 中编写类似 XML 结构来描述用户界面的语法。

TypeScript支持内嵌,类型检查以及将JSX直接编译为JavaScript。

基本用法

想要使用JSX必须做两件事:

  1. 给文件一个.tsx扩展名:
    • 向开发工具和编译器表明该文件中可能包含 JSX 语法。
  2. 启用jsx选项
    • 启用 jsx 选项通常是在 tsconfig.json 文件中进行配置。

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-classtitle 的值 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 元素)的检查主要包括以下几个方面:

  1. TypeScript 会检查使用的固有元素名称是否正确。
    • 必须使用正确的 HTML 元素名称,如 <div><p><span> 等。使用错误或不存在的元素名称会导致编译错误。
// 以下使用是合法的
<input type="text" placeholder="Enter text" />// 以下使用会引发错误
<myInvalidElement />  // 不存在这样的固有元素
  1. 对于固有元素的属性,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 方法。

MyComponentMyFactoryFunction 是有效的,因为它们创建的对象都有 render 方法,符合 JSX.ElementClass 的要求。

NotAValidComponentNotAValidFactoryFunction 是无效的,因为它们创建的对象没有 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 属性,类型为布尔值。

固有元素的属性类型检查

  1. 确定属性类型的方式:
  • 对于基于值的元素(如类组件或无状态函数组件),属性类型的确定稍微复杂一些。它取决于先前确定的在元素实例类型上的某个属性的类型,而具体使用哪个属性来确定类型取决于 JSX.ElementAttributesProperty 的定义。
  • 如果未指定 JSX.ElementAttributesProperty,在 TypeScript 2.8 及以后版本中,将使用类元素构造函数或无状态函数组件调用的第一个参数的类型。
declare namespace JSX {interface ElementAttributesProperty {props; // 指定用来使用的属性名}
}class MyComponent {props: {foo?: string;};
}// `MyComponent`的元素属性类型为`{foo?: string}`
<MyComponent foo="bar" />;
  1. 支持可选属性和必须属性:
    元素属性类型可以定义可选属性和必须属性。
    示例:
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 属性,类型为数字。

额外属性和泛型类型

  1. JSX.IntrinsicAttributes 接口:
    • JSX.IntrinsicAttributes 接口可以用来指定额外的属性,这些属性通常不会被组件的 propsarguments 使用。例如在 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 中明确声明。

  1. 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 可以用来描述可能传递给组件的通用属性,这些属性不是由组件明确定义的属性,而是类似 styleclassNamekey 等在 JSX 中经常使用的属性。

示例:

interface MyComponentProps {customProp: string;
}function MyComponent({customProp
}: MyComponentProps & JSX.IntrinsicAttributes) {return (<div className={/*...*/} style={/*...*/}>{customProp}</div>);
}

在示例中,MyComponent 组件除了接收自定义的 customProp 属性外,还可以接收 JSX.IntrinsicAttributes 中定义的那些通用属性,如 classNamestyle
如果不使用 JSX.IntrinsicAttributes,当尝试在使用 MyComponent 时传递 classNamestyle 等属性时,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

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

java里的序列化反序列化、HttpMessageConverter、Jackson、消息转化器、对象转化器...都是啥?

前段时间在学习SSM框架&#xff08;spring boot、spring MVC、mybatis&#xff09;后端项目的时候&#xff0c;发现他们的项目里&#xff1a;响应类Result类要实现Serializable接口、转化响应给前端的时间数据的格式要用到什么“消息转换器”MappingJackson2HttpMwssageConvert…...

GNU/Linux - memtool使用

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

Qt5.12.8源码交叉编译带openssl版本

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

串行并行数据转换

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

推荐一个优秀的 .NET MAUI 组件库

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

用Manim创建条形图【BarChart】

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

iMES工厂管家:强大的工厂管理系统

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

iOS ------ 事件响应链

响应者链 响应者链是由一系列链接在一起的响应者&#xff08;UIResponser之类&#xff1a;UIApplication&#xff0c;UIViewController&#xff0c;UIView&#xff09;注组成的。一般情况下&#xff0c;一条响应链开始于第一响应者&#xff0c;结束于application对象。如果一个…...

Go 语言 switch 语句的特点

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

【递归】什么是递归-C语言为例

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

vue针对低版本浏览器不兼容es6特性解决方案,

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

嵌入式内存管理高频面试题及参考答案(4万字长文)

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

TinyWebserver的复现与改进(2):项目的整体框架

上文我们成功运行了代码&#xff0c;本文我们将对项目的整体流程作一下讲解 如果你之前没做过相关的内容&#xff0c;对服务器的⾼并发模型也⼀⽆所知&#xff0c;不建议继续做下去&#xff0c;需要的前置知识有&#xff1a; Linux的基本命令&#xff08;⭐&#xff09;多进程…...

R 语言学习教程,从入门到精通,R 字符串(10)

1、R 字符串 R 语言字符串可以使用一对单引号 ’ ’ 或一对双引号 " " 来表示。 单引号字符串中可以包含双引号。 单引号字符串中不可以包含单引号。 双引号字符串中可以包含单引号。 双引号字符串中不可以包含双引号。 以下示例演示来字符串的使用&#xff1a; a …...

QT 简易音乐播放器

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

代码随想录八股训练营day32

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

11.面试题——消息队列RabbitMQ

1.RabbitMQ是什么&#xff1f;特点是什么&#xff1f; RabbitMQ是一种开源的消息队列中间件&#xff0c;用于在应用程序之间进行可靠的消息传递。它实现了AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;协议&#xff0c;提供了强大的消息处理能力。RabbitMQ的…...

MySQL运维-日志

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

synchronized重量级锁的实现原理是怎样的

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

探索 GLTF 的世界:3D 内容的未来

在 3D 内容创作领域&#xff0c;GLTF 正在掀起波澜&#xff0c;成为跨不同平台提供丰富互动体验的未来标准。GL 传输格式 &#xff08;GLTF&#xff09; 由 Khronos Group 开发&#xff0c;是一种用于在工具和服务之间传输 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欺骗篇

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

Linux 系统框架分析(一)

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

Leetcode 剑指 Offer II 090.打家劫舍 II

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

上海冷链配送新篇章 华鼎冷链科技以卓越服务餐饮品牌

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

学习鸿蒙-应用市场申请签名

1.需要的文件概念 .cer / .p7b / .p12 / .csr HarmonyOS应用/服务通过数字证书&#xff08;.cer文件&#xff09;和Profile文件&#xff08;.p7b文件&#xff09;来保证应用/服务的完整性。在申请数字证书和Profile文件前&#xff0c;首先需要通过DevEco Studio来生成密钥&am…...

LayUi插件

文档&#xff1a;日期和时间组件文档 - Layui layDate安装 npm install layui-laydate...

使用tailwindcss轻松实现移动端rem适配

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

2021-11-08 51单片机2位秒表启动清零

缘由c51单片机&#xff0c;程序&#xff0c;仿真图&#xff0c;求帮助-编程语言-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_…...