React JSX语法介绍(JS XML)(一种JS语法扩展,允许在JS代码中编写类似HTML的标记语言)Babel编译

在线调试网站:https://zh-hans.react.dev/learn

文章目录

  • JSX:现代前端开发的声明式语法
    • 概述
    • JSX的本质与工作原理
      • 什么是JSX
      • JSX转换流程
    • JSX语法特性
      • 表达式嵌入(JSX允许在大括号内嵌入任何有效的JavaScript表达式)
      • 属性传递(JSX中的属性传递遵循特定的规则)
      • 条件渲染(JSX支持多种条件渲染模式)
      • 列表渲染(使用map方法渲染数组数据)
    • JSX与传统HTML的区别
      • 属性命名差异
      • 事件处理差异
    • JSX的优势
      • 声明式编程
      • 组件化开发
    • JSX编译过程
      • Babel转换示例
      • 编译配置
    • 最佳实践
      • 组件结构规范
      • 性能优化技巧
    • 常见问题与解决方案
      • Key属性的重要性
      • 事件处理中的this绑定
    • 总结

JSX:现代前端开发的声明式语法

概述

JSX(JavaScript XML)是Facebook开发的一种JavaScript语法扩展,它允许在JavaScript代码中编写类似HTML的标记语言。作为React生态系统的核心组成部分,JSX为开发者提供了一种更直观、更声明式的方式来描述用户界面。

JSX的本质与工作原理

什么是JSX

JSX本质上是一种语法糖,它将类HTML的语法转换为JavaScript函数调用。当编写JSX代码时,实际上是在创建React元素的描述,这些描述最终会被转换为虚拟DOM。

// JSX语法(我们写React时需要编写的代码,这种代码浏览器无法识别,需要通过Babel编译)
const element = <h1 className="greeting">Hello, World!</h1>;// 转换后的JavaScript(经过Babel编译)
const element = React.createElement('h1',                    // 元素类型{ className: 'greeting' }, // 属性对象'Hello, World!'          // 子元素内容
);

JSX转换流程

JSX源代码<人写>
Babel编译器
React.createElement调用
虚拟DOM对象
React渲染引擎
真实DOM

JSX语法特性

表达式嵌入(JSX允许在大括号内嵌入任何有效的JavaScript表达式)

// 变量嵌入
const name = "React开发者";
const greeting = <h1>欢迎, {name}!</h1>;// 函数调用
function formatName(user) {return user.firstName + ' ' + user.lastName; // 拼接用户姓名
}const user = {firstName: '张',  // 用户姓lastName: '三'    // 用户名
};const element = (<h1>Hello, {formatName(user)}!  {/* 调用函数并显示结果 */}</h1>
);// 主应用组件
export default function MyApp() {return (<div><h1>欢迎来到我的应用</h1>{/* 使用 element 变量 */}{element}</div>);
}

在这里插入图片描述

属性传递(JSX中的属性传递遵循特定的规则)

参考文章:React JSX属性传递规则(事件处理函数名必须用驼峰式;内联样式必须是JavaScript对象,键名用驼峰命名;className、htmlFor;自定义属性要以data-开头、动态属性绑定)

// 字符串属性
const element1 = <div className="container">内容</div>;// 表达式属性
const isActive = true;                    // 定义状态变量
const className = isActive ? 'active' : 'inactive'; // 根据状态确定样式类名const element2 = (<button className={className}                 // 动态classNameonClick={() => console.log('点击')}   // 事件处理函数disabled={!isActive}                  // 动态禁用状态>按钮文字</button>
);// 主应用组件
export default function MyApp() {return (<div><h1>欢迎来到我的应用</h1>{/* 使用 element1 变量 */}{element1}{/* 使用 element2 变量 */}{element2}</div>);
}

在这里插入图片描述

条件渲染(JSX支持多种条件渲染模式)

// 用户问候组件
function UserGreeting({ isLoggedIn, user, logout }) {// 使用三元运算符进行条件渲染return (<div>{isLoggedIn ? (                     // 如果已登录<h1>欢迎回来, {user.name}!</h1>   // 显示欢迎信息) : (                              // 如果未登录<h1>请先登录</h1>                // 显示登录提示)}{/* 使用逻辑AND运算符 */}{isLoggedIn && (                   // 只有登录时才显示<button onClick={logout}>退出</button>)}</div>);
}// 主应用组件
export default function MyApp() {const isActive = true;                 // 登录状态const user = { name: "用户" };         // 用户信息const logout = () => console.log("退出登录"); // 退出登录函数return (<div>{/* 使用 UserGreeting 组件 */}<UserGreeting isLoggedIn={isActive}            // 传递登录状态user={user}                      // 传递用户信息logout={logout}                  // 传递退出函数/></div>);
}

在这里插入图片描述

列表渲染(使用map方法渲染数组数据)

import React from 'react';// TodoList 组件
function TodoList({ todos, toggleTodo }) {return (<ul>{todos.map((todo) => (            // 遍历待办事项数组<li key={todo.id}                 // 为每个元素提供唯一keyclassName={todo.completed ? 'completed' : ''} // 根据完成状态设置样式><span>{todo.text}</span>      {/* 显示任务内容 */}<button onClick={() => toggleTodo(todo.id)} // 切换完成状态的处理函数>{todo.completed ? '撤销' : '完成'} {/* 根据状态显示按钮文字 */}</button></li>))}</ul>);
}// 主应用组件
export default function MyApp() {// 使用 useState 管理待办事项状态const [todos, setTodos] = React.useState([{ id: 1, text: '学习 React', completed: false },{ id: 2, text: '写代码练习', completed: true },{ id: 3, text: '阅读文档', completed: false }]);// 处理待办项状态切换const toggleTodo = (id) => {setTodos(todos.map(todo =>todo.id === id ? { ...todo, completed: !todo.completed } : todo));};return (<div><h2>待办事项</h2>{/* 使用 TodoList 组件并传递必要 props */}<TodoList todos={todos}         // 传递待办事项数组toggleTodo={toggleTodo} // 传递状态切换函数/></div>);
}

在这里插入图片描述

JSX与传统HTML的区别

属性命名差异

HTML属性JSX属性说明
classclassName避免与JavaScript关键字冲突
forhtmlFor避免与for循环关键字冲突
tabindextabIndex采用驼峰命名法

事件处理差异

// HTML方式
// <button onclick="handleClick()">点击</button>// JSX方式
function MyComponent() {const handleClick = () => {           // 定义事件处理函数console.log('按钮被点击了');        // 输出点击日志};return (<button onClick={handleClick}>      {/* 使用驼峰命名的事件属性 */}点击</button>);
}

JSX的优势

声明式编程

JSX采用声明式编程范式,开发者只需要描述界面应该是什么样子,而不需要关心如何操作DOM:

// 声明式:描述最终状态
function Counter() {const [count, setCount] = useState(0); // 状态管理Hookreturn (<div><p>当前计数: {count}</p>           {/* 显示当前计数值 */}<button onClick={() => setCount(count + 1)} // 点击时增加计数>增加</button></div>);
}

组件化开发

JSX天然支持组件化开发模式:

// 可复用的按钮组件
function Button({ children, variant = 'primary', onClick }) {// 根据variant构建样式类名// `btn` 是基础样式类名(定义按钮基本样式)// `btn-${variant}` 是动态样式类名(根据传入的variant参数变化)// 比如当 variant="primary" 时,最终类名是 "btn btn-primary"const className = `btn btn-${variant}`;  return (<button className={className}              // 应用样式类onClick={onClick}                  // 绑定点击事件>{children}                         {/* 渲染子元素 */}</button>);
}// 使用组件
function App() {return (<div>{/* 主要按钮示例 */}<Button variant="primary" onClick={() => alert('主要按钮')}>主要按钮                         {/* 作为children传递 */}</Button>{/* 次要按钮示例 */}<Button variant="secondary" onClick={() => alert('次要按钮')}>次要按钮</Button></div>);
}

JSX编译过程

Babel转换示例

// 原始JSX代码
const element = (<div className="container"><h1>标题</h1><p>段落内容</p></div>
);// Babel编译后的代码
const element = React.createElement("div",                                // 元素类型{ className: "container" },          // 属性对象React.createElement("h1", null, "标题"), // 第一个子元素React.createElement("p", null, "段落内容") // 第二个子元素
);

编译配置

现代构建工具中的JSX配置:

// Babel配置 (.babelrc)
{"presets": ["@babel/preset-react"               // React预设,包含JSX转换],"plugins": ["@babel/plugin-transform-react-jsx" // JSX转换插件]
}

最佳实践

组件结构规范

// 推荐的组件结构
function UserCard({ user, onEdit, onDelete }) {// 1. 状态和副作用Hookconst [isEditing, setIsEditing] = useState(false);// 2. 事件处理函数const handleEditClick = () => {       // 编辑按钮点击处理setIsEditing(true);                 // 进入编辑模式onEdit(user.id);                    // 调用父组件传入的编辑回调};const handleDeleteClick = () => {     // 删除按钮点击处理if (window.confirm('确定要删除吗?')) { // 确认删除操作onDelete(user.id);                // 调用删除回调}};// 3. 渲染逻辑return (<div className="user-card"><img src={user.avatar} alt={user.name} /> {/* 用户头像 */}<h3>{user.name}</h3>              {/* 用户姓名 */}<p>{user.email}</p>               {/* 用户邮箱 */}<div className="actions"><button onClick={handleEditClick}>编辑</button><button onClick={handleDeleteClick}>删除</button></div></div>);
}

性能优化技巧

// 使用React.memo进行组件优化
const MemoizedUserCard = React.memo(UserCard, (prevProps, nextProps) => {// 自定义比较函数,只有user对象变化时才重新渲染return prevProps.user.id === nextProps.user.id &&prevProps.user.name === nextProps.user.name;
});// 使用useCallback优化事件处理函数
function UserList({ users, onUserUpdate }) {const handleUserEdit = useCallback((userId) => {// 编辑逻辑,使用useCallback避免子组件不必要的重渲染onUserUpdate(userId);}, [onUserUpdate]);                   // 依赖数组return (<div>{users.map(user => (<MemoizedUserCard key={user.id}                 // 稳定的key值user={user}onEdit={handleUserEdit}       // 优化后的回调函数/>))}</div>);
}

常见问题与解决方案

Key属性的重要性

// 错误示例:缺少key或使用不稳定的key
function BadList({ items }) {return (<ul>{items.map((item, index) => (<li key={index}>              {/* 使用index作为key是不推荐的 */}{item.name}</li>))}</ul>);
}// 正确示例:使用稳定唯一的key
function GoodList({ items }) {return (<ul>{items.map((item) => (<li key={item.id}>            {/* 使用唯一ID作为key */}{item.name}</li>))}</ul>);
}

事件处理中的this绑定

// 类组件中的事件绑定
class MyComponent extends React.Component {constructor(props) {super(props);this.state = { count: 0 };// 方法1:在构造函数中绑定this.handleClick = this.handleClick.bind(this);}// 方法2:使用箭头函数handleClick = () => {this.setState({ count: this.state.count + 1 });};render() {return (<button onClick={this.handleClick}>  {/* 正确绑定的事件处理器 */}计数: {this.state.count}</button>);}
}

总结

JSX作为React生态系统的核心语法扩展,通过其声明式的特性和强大的表达能力,大大简化了前端开发的复杂度。它不仅提供了直观的组件编写方式,还通过编译时优化确保了运行时的高效性能。

理解JSX的工作原理和最佳实践,对于掌握现代React开发至关重要。随着前端生态的不断发展,JSX的应用场景也在不断扩展,从传统的Web应用到React Native移动开发,JSX都展现出了其强大的适应性和实用性。

通过合理运用JSX的各种特性,开发者能够构建出更加优雅、可维护的用户界面,这正是JSX在现代前端开发中不可替代的价值所在。

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

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

相关文章

Unity UI系统中RectTransform详解

一、基础代码示例 public GameObject node; var rect node.GetComponent<RectTransform>();Debug.Log($"anchoredPosition----{rect.anchoredPosition}"); Debug.Log($"offsetMin.x--{rect.offsetMin}"); Debug.Log($"offsetMax.x--{rect.of…

【数据库】并发控制

并发控制 在数据库系统&#xff0c;经常需要多个用户同时使用。同一时间并发的事务可达数百个&#xff0c;这就是并发引入的必要性。 常见的并发系统有三种&#xff1a; 串行事务执行&#xff08;X&#xff09;&#xff0c;每个时刻只有一个事务运行&#xff0c;不能充分利用…

我们来学mysql -- “数据备份还原”sh脚本

数据备份&还原 说明执行db_backup_cover.sh脚本 说明 环境准备&#xff1a;来源数据库(服务器A)&#xff1b;目标数据库(服务器B)dbInfo.sh脚本记录基本信息 来源库、目标库的ip、port及执行路径 # MySQL 客户端和 mysqldump 的路径 MYSQL_CLIENT"/work/oracle/mysql…

【NLP 78、手搓Transformer模型结构】

你以为走不出的淤泥&#xff0c;也迟早会云淡风轻 —— 25.5.31 引言 ——《Attention is all you need》 《Attention is all you need》这篇论文可以说是自然语言处理领域的一座里程碑&#xff0c;它提出的 Transformer 结构带来了一场技术革命。 研究背景与目标 在 Transfo…

深入理解CSS常规流布局

引言 在网页设计中&#xff0c;理解元素如何排列和相互作用至关重要。CSS提供了三种主要的布局方式&#xff1a;常规流、浮动和定位。本文将重点探讨最基础也是最常用的常规流布局&#xff08;Normal Flow&#xff09;&#xff0c;帮助开发者掌握页面布局的核心机制。 什么是…

树结构详细介绍(javascript版)

树结构的基本概念 树是一种非线性数据结构&#xff0c;由节点和连接节点的边组成。与线性数据结构&#xff08;如数组、链表&#xff09;不同&#xff0c;树具有层次结构&#xff0c;非常适合表示有层次关系的数据。 树的基本术语 节点 (Node)&#xff1a; 树中的基本单元&a…

element-plus bug整理

1.el-table嵌入el-image标签预览时&#xff0c;显示错乱 解决&#xff1a;添加preview-teleported属性 <el-table-column label"等级图标" align"center" prop"icon" min-width"80"><template #default"scope"&g…

RabbitMQ和MQTT区别与应用

RabbitMQ与MQTT深度解析&#xff1a;协议、代理、差异与应用场景 I. 引言 消息队列与物联网通信的重要性 在现代分布式系统和物联网&#xff08;IoT&#xff09;生态中&#xff0c;高效、可靠的通信机制是构建稳健、可扩展应用的核心。消息队列&#xff08;Message Queues&am…

零基础远程连接课题组Linux服务器,安装anaconda,配置python环境(换源),在服务器上运行python代码【3/3 适合小白,步骤详细!!!】

远程连接服务器 请查阅之前的博客——零基础远程连接课题组Linux服务器&#xff0c;安装anaconda&#xff0c;配置python环境&#xff08;换源&#xff09;&#xff0c;在服务器上运行python代码【1/3 适合小白&#xff0c;步骤详细&#xff01;&#xff01;&#xff01;】&am…

Redis最佳实践——安全与稳定性保障之访问控制详解

Redis 在电商应用的安全与稳定性保障之访问控制全面详解 一、安全访问控制体系架构 1. 多层级防护体系 #mermaid-svg-jpkDj2nKxCq9AXIW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jpkDj2nKxCq9AXIW .error-ico…

vue2源码解析——响应式原理

文章目录 引言数据劫持收集依赖数组处理渲染watchervue3中的响应式 引言 vue的设计思想是数据双向绑定、数据与UI自动同步&#xff0c;即数据驱动视图。 为什么会这样呢&#xff1f;这就不得不提vue的响应式原理了&#xff0c;在使用vue的过程中&#xff0c;我被vue的响应式设…

gcc相关内容

gcc 介绍&#xff1a;linux就是由gcc编译出来的&#xff0c;而且好像之前Linux只支持gcc编译。gcc全称为gnu compiler collection&#xff0c;它是gnu项目的一个组成部分。gnu致力于创建一个完全自由的操作系统&#xff0c;我感觉意思就是完全开源的操作系统。gnu有很多组件和…

android 图片背景毛玻璃效果实现

图片背景毛玻璃效果实现 1 依赖 // Glide implementation("com.github.bumptech.glide:glide:4.16.0") kapt("com.github.bumptech.glide:compiler:4.16.0") implementation("jp.wasabeef:glide-transformations:4.3.0") 2 布局<com.googl…

【Java开发日记】你会不会5种牛犇的yml文件读取方式?

前言 除了烂大街的Value和ConfigurationProperties外&#xff0c;还能够通过哪些方式&#xff0c;来读取yml配置文件的内容&#xff1f; 1、Environment 在Spring中有一个类Environment&#xff0c;它可以被认为是当前应用程序正在运行的环境&#xff0c;它继承了PropertyReso…

Spring Boot事务失效场景及解决方案

事务失效场景1&#xff1a;方法非public修饰 原因 Spring事务基于动态代理&#xff08;AOP&#xff09;实现&#xff0c;非public方法无法被代理拦截&#xff0c;导致事务失效。 代码示例 Service public class OrderService {Transactionalprivate void createOrder() { //…

电子电路:怎么理解时钟脉冲上升沿这句话?

时钟脉冲是数字电路中用于同步各组件操作的周期性信号&#xff0c;通常表现为高低电平交替的方波。理解其关键点如下&#xff1a; 时钟脉冲的本质&#xff1a; 由晶振等元件生成&#xff0c;呈现0/1&#xff08;低/高电平&#xff09;的规律振荡每个周期包含上升沿→高电平→下…

docker部署redis mysql nacos seata rabbitmq minio onlyoffice nginx实战

docker部署redis mysql nacos seata rabbitmq minio onlyoffice nginx实战 一、环境介绍 操作系统&#xff1a;ubuntu22.04 软件环境&#xff1a;docker、docker-compose 二、docker安装 版本规定到26.1.3版本过低会引起莫名其妙的问题。打开终端。更新软件包列表&#x…

全面解析:npm 命令、package.json 结构与 Vite 详解

全面解析&#xff1a;npm 命令、package.json 结构与 Vite 详解 一、npm run dev 和 npm run build 命令解析 1. npm run dev 作用&#xff1a;启动开发服务器&#xff0c;用于本地开发原理&#xff1a; 启动 Vite 开发服务器提供实时热更新&#xff08;HMR&#xff09;功能…

【Oracle】TCL语言

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. TCL概述1.1 什么是TCL&#xff1f;1.2 TCL的核心功能 2. 事务基础概念2.1 事务的ACID特性2.2 事务的生命周期 3. COMMIT语句详解3.1 COMMIT基础语法3.2 自动提交与手动提交3.3 提交性能优化 4. ROLLBACK语句…

OpenCV CUDA模块直方图计算------用于在 GPU 上执行对比度受限的自适应直方图均衡类cv::cuda::CLAHE

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::CLAHE 是 OpenCV 的 CUDA 模块中提供的一个类&#xff0c;用于在 GPU 上执行对比度受限的自适应直方图均衡&#xff08;Contrast Limi…