React中的JSX和React elements的概念

本文深入探讨了JSX语法在React中的应用,解释了JSX如何转换为React元素对象,以及这些元素如何被渲染成DOM节点的过程。通过具体示例,展示了JSX与React.createElement方法之间的等价性。

Introducing JSX

  • JSX语法实际上是在创建对象,产生的对象称为React elements;

  • 对这些React elements进行渲染,构建出DOM

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
// => 等于如下写法:
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

// => 创建出的对象(React elements)如下形式:
// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

更多讨论:issue

<think>好的,用户现在的问题是关于在React中如何扩展JSX.IntrinsicElements来包括hospitalInfo属性。用户之前已经询问过类似的问题,并且之前的回答中提到了三种方法,其中第一种是扩展全局JSX类型声明。用户现在特别关注如何在React中通过声明合并或自定义类型来实现这一点,同时参考了站内引用中的信息。 首先,我需要回顾之前的回答,确保现在的解决方案与之前一致,同时结合用户提供的引用内容。根据引用[1],用户知道React中组件的命名规则:小写字母开头的元素是内置HTML组件,大写字母开头的是自定义组件。但用户可能在这里遇到了问题,因为他们可能尝试使用小写组件名,比如<hospitalInfo>,而根据React的规则,这会被识别为HTML元素,但实际是自定义组件,所以需要正确扩展类型声明。 用户现在明确想用声明合并或自定义类型来扩展JSX.IntrinsicElements。根据TypeScript的文档,声明合并允许扩展已有的接口。在React中,JSX.IntrinsicElements接口包含了所有内置的HTML元素类型。用户需要添加一个自定义的元素类型,比如hospitalInfo,并定义其属性。 我需要检查之前的回答中的方法1是否正确,并可能需要进一步详细说明。例如,在之前的回答中提到在全局声明文件中扩展JSX.IntrinsicElements,但用户现在需要更具体的指导,特别是在React中的实现。 另外,用户提供的引用[2]提到在Vue3中的解决方法,但用户现在的问题是React,所以需要排除Vue相关的配置,专注于ReactTypeScript的结合。 可能的步骤包括: 1. 创建或编辑全局类型声明文件(如react-app-env.d.ts或global.d.ts)。 2. 使用declare global来扩展JSX.IntrinsicElements接口。 3. 定义hospitalInfo组件所需的属性。 4. 确保组件在React中以正确的方式使用,可能需要注意组件名称的大小写问题,因为React区分大小写,大写开头的组件名会被识别为自定义组件,而小写会被视为HTML元素。但用户可能想保持小写,所以需要特别处理,或者建议用户遵循React的命名规范,使用大写开头的组件名。 但根据用户的问题,他们可能希望继续使用小写的组件名,如<hospitalInfo>,因此需要在类型声明中明确添加该元素到JSX.IntrinsicElements,即使这在React中并不常见,因为通常推荐大写组件名。不过用户可能有特殊需求,比如与某些库或遗留代码的兼容。 需要解释声明合并的过程,并给出具体的代码示例。同时,需要提醒用户,如果使用小写组件名,可能需要配置Babel或TypeScript编译器,确保正确转换。但可能用户已经处理了这部分,只是类型声明的问题。 此外,需要确保用户在组件实现中正确导出组件,并在使用的时候正确导入,否则即使类型声明正确,运行时仍可能出错。 最后,验证步骤也很重要,比如检查类型提示是否出现,编译是否通过,以及运行时是否正常工作。</think>### 解决方案:在React中扩展JSX.IntrinsicElements的正确方法 #### 核心原理 React通过组件名称大小写区分内置HTML元素自定义组件[^1]。若需要为**小写组件名**(如$<hospitalInfo/>$)添加类型支持,必须通过**声明合并**扩展$JSX.IntrinsicElements$接口,定义该元素允许的属性类型。 --- ### 分步实现 #### 1. 创建全局类型声明文件 在项目根目录或`src/types`目录下创建声明文件(如`react-app-env.d.ts`): ```typescript // react-app-env.d.ts declare namespace JSX { interface IntrinsicElements { // 定义小写组件名对应的属性 hospitalinfo: { // 必填/选填属性 hospitalName: string; address?: string; // HTML通用属性(如className) className?: string; }; } } ``` *命名规范:组件名在声明中必须使用全小写(hospitalinfo)匹配JSX中的实际标签名* #### 2. 实现React组件 创建对应的React组件文件`HospitalInfo.tsx`: ```tsx // 组件名称必须首字母大写(React规范) export const HospitalInfo = ({ hospitalName, address, className }: { hospitalName: string; address?: string; className?: string; }) => { return ( <div className={className}> <h3>{hospitalName}</h3> {address && <p>{address}</p>} </div> ); }; ``` #### 3. 全局注册组件(可选) 若需直接使用$<hospitalinfo/>$标签而非导入组件,需全局注册: ```tsx // global-components.tsx import { HospitalInfo } from './HospitalInfo'; declare global { namespace JSX { interface IntrinsicElements { hospitalinfo: React.DetailedHTMLProps< React.HTMLAttributes<HTMLElement> & { hospitalName: string; address?: string; }, HTMLElement >; } } } // 将组件挂载到全局对象(根据实际框架调整) if (typeof window !== 'undefined') { (window as any).HospitalInfo = HospitalInfo; } ``` #### 4. 使用组件 ```tsx // 方式1:通过全局注册直接使用 <hospitalinfo hospitalName="上海瑞金医院" address="瑞金二路197号" /> // 方式2:常规导入使用(推荐) import { HospitalInfo } from './HospitalInfo'; <HospitalInfo hospitalName="上海瑞金医院" /> ``` --- ### 关键验证点 1. **类型提示检查**:在TSX文件中输入$<hospitalinfo$应触发自动补全提示`hospitalName``address`属性 2. **编译检测**:运行`tsc --noEmit`应无类型错误 3. **DOM渲染验证**:检查浏览器Elements面板确认组件渲染结果包含指定属性 --- ### 注意事项 1. **命名冲突**:避免使用与HTML5规范冲突的标签名(如`<header>`已存在) 2. **属性继承**:通过`React.HTMLAttributes`可继承标准HTML属性: ```typescript interface IntrinsicElements { hospitalinfo: React.HTMLAttributes<HTMLElement> & { customProp: string; }; } ``` 3. **框架差异**:此方法仅适用于React+TypeScript项目,Vue/Angular需不同配置[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值