nodejs 019: React组件 JSX基础语法规则

embedded/2024/11/13 3:51:14/
  • 注:本文为JSX基础语法规则总结,除一二级标题外的大部分内容由LLM生成
  • JSX(JavaScript XML)是一种语法扩展,主要用于 React 项目。它让我们可以在 JavaScript 中直接编写类似 HTML 的代码,简化了定义 UI 组件的过程( JSX有点像JAVA的JSP)。
  • JSX 将标记和逻辑紧密结合,使代码更具可读性和可维护性。JSX 是一个由 React 引入的概念,现在在其他框架(如 Vue 3)中也得到了应用。

Ⅰ.JSX 的基本概念

  1. 类似 HTML 的语法

    const element = <h1>Hello, world!</h1>;
    
  2. 在组件中使用 JSX
    JSX 最常用于定义 React 组件的结构。React 组件是一个返回 JSX 的函数或类,可以将复杂的 UI 拆分成独立、可复用的组件。例如:

    function Welcome(props) {return <h1>Hello, {props.name}</h1>;
    }
    

JSX 的特点和优势

  • 内嵌表达式:在 JSX 中可以嵌入任何 JavaScript 表达式,只需将其包裹在 {} 中。

    const name = 'React';
    const element = <h1>Hello, {name}</h1>;
    
  • 支持条件渲染:可以使用 JavaScript 的条件运算符进行条件渲染。

    function Greeting(props) {const isLoggedIn = props.isLoggedIn;return (<div>{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}</div>);
    }
    
  • 支持循环渲染:可以通过 map 等方法来渲染列表。

    const numbers = [1, 2, 3, 4, 5];
    const listItems = numbers.map((number) =><li key={number.toString()}>{number}</li>
    );return <ul>{listItems}</ul>;
    

Ⅱ.className

  • className 是 JSX 中用于指定 HTML 元素 CSS 类的属性。在标准的 HTML 中,我们使用 class 属性来指定样式,但在 JSX 中,因为 class 是 JavaScript 的保留字,所以改成了 className

  • 在 JSX 中设置 className 非常简单,类似于 HTML 的 class,只需在元素上添加 className 属性并赋值一个字符串即可:

function MyComponent() {return <div className="my-class">Hello, World!</div>;
}
  • 动态设置 className ;

    1. 三元运算符

使用三元运算符来根据条件设置 className

function MyComponent({ isActive }) {return <div className={isActive ? "active" : "inactive"}>Hello, World!</div>;
}
    1. 模板字符串

如果需要组合多个类,可以使用模板字符串(ES6 的字符串模板语法):

function MyComponent({ isActive, isLarge }) {return <div className={`${isActive ? "active" : ""} ${isLarge ? "large" : ""}`}>Hello, World!</div>;
}
    1. 使用条件库 classnames

在大型项目中管理多个条件类时,可以使用 classnames 库。它简化了 className 的管理,让代码更加清晰易读:

npm install classnames

使用示例:

import classNames from 'classnames';function MyComponent({ isActive, isLarge }) {const classes = classNames({active: isActive,large: isLarge,'extra-class': true,});return <div className={classes}>Hello, World!</div>;
}

在上面的代码中,classnames 自动生成类名字符串。如果 isActiveisLargetrue,生成的 className 会是 active large extra-class

通过样式文件使用 className

通常,我们会在组件中用 className 连接 CSS 样式表,方法是将样式写在 CSS 文件中,然后通过 className 引用。

使用 CSS 模块

在 React 中也可以使用 CSS 模块,这样可以避免样式的全局污染。CSS 模块会自动生成独特的类名,以保证样式只在当前组件中有效。

  • 首先,创建一个 CSS 模块文件,比如 MyComponent.module.css

    /* MyComponent.module.css */
    .active {color: red;
    }.large {font-size: 2em;
    }
    
  • 在组件中导入这个 CSS 模块并应用样式:

    import styles from './MyComponent.module.css';function MyComponent({ isActive, isLarge }) {return (<div className={`${isActive ? styles.active : ""} ${isLarge ? styles.large : ""}`}>Hello, World!</div>);
    }
    

使用 className,可以轻松地将 CSS 应用到 JSX 元素中,并且能动态地控制它们。

Ⅲ.首字母大小写和自定义组件

在 React 中,组件的命名约定非常重要,尤其是当涉及到首字母大小写的使用和自定义组件的区分时。以下是相关的细节:

1. 首字母大小写的规则

React 通过组件名称的首字母大小写来区分 HTML 元素和自定义 React 组件:

  • 首字母大写:React 认为这是一个自定义组件。自定义组件通常是函数或类,并且在 JSX 中渲染时,React 会调用它返回的 JSX 结构。例如,<MyComponent /> 被认为是一个 React 组件。

    function MyComponent() {return <div>Hello from MyComponent!</div>;
    }function App() {return <MyComponent />;
    }
    
  • 首字母小写:React 会将其当作标准 HTML 元素(如 <div><span>)来渲染。如果在 JSX 中写 <mycomponent />,React 会尝试将其当作 HTML 标签而不是组件,导致渲染失败或产生警告。

2. 自定义组件的编写

在 React 中编写自定义组件时,我们通常遵循 PascalCase(即每个单词的首字母大写)命名规范,这样可以避免和 HTML 标签冲突,并符合 React 社区的常规习惯。例如:

function UserProfile() {return <div>User Profile Component</div>;
}

使用自定义组件时可以传递 props

function UserProfile({ name }) {return <div>Hello, {name}!</div>;
}function App() {return <UserProfile name="Alice" />;
}

3. 动态渲染自定义组件

有时,我们可能需要动态选择组件进行渲染。可以通过对象映射来实现动态组件的选择,例如:

function Home() {return <div>Home Component</div>;
}function About() {return <div>About Component</div>;
}const components = {home: Home,about: About,
};function App({ componentName }) {const Component = components[componentName];return Component ? <Component /> : <div>Component Not Found</div>;
}// 使用示例
<App componentName="home" />; // 渲染 Home 组件

4. 使用小写首字母的自定义标签(非 React 推荐)

尽管不推荐,但在某些情况下可能需要使用小写的自定义标签。可以通过直接创建元素来实现。React 提供了 React.createElement 函数,可以用来创建 React 元素而不依赖 JSX。例如:

function app() {return React.createElement("custom-element", { id: "myId" }, "Hello!");
}

不过,为了遵循 React 社区的最佳实践,尽量避免这种方式。

5. CSS 组件样式约定

对于自定义组件的样式,可以使用对应的 className,配合 CSS 文件或者 CSS 模块。CSS 模块可以使样式在组件间隔离,避免样式冲突。

// MyComponent.module.css
.myComponent {color: blue;
}// MyComponent.jsx
import styles from './MyComponent.module.css';function MyComponent() {return <div className={styles.myComponent}>Styled Component</div>;
}

总结

  • 自定义组件的名称应始终以大写字母开头,以便 React 能够正确识别它们。
  • 可以使用 props 为组件传递数据,保持组件的可复用性。
  • 动态选择和渲染自定义组件时,可以用对象映射来选择特定组件。
  • 使用 CSS 模块或 className 控制组件样式,保持组件之间的样式隔离。

Ⅳ.style要写成对象的形式

在 JSX 中,style 属性需要写成 JavaScript 对象的形式,而不是普通的字符串或 CSS 样式规则。每个 CSS 属性都需要用 JavaScript 对象的语法表示。

基本写法

在 React 中使用 style 属性时,应该使用 驼峰命名(camelCase),因为在 JavaScript 中 - 是无效字符。

例如,background-color 需要写成 backgroundColor

function MyComponent() {return (<div style={{ backgroundColor: 'blue', color: 'white', padding: '10px' }}>Hello, World!</div>);
}

上面的 style 属性接收一个 JavaScript 对象,其中每个 CSS 属性都以键值对的形式表示。

动态设置样式

你可以在 style 对象中动态设置样式属性,通过变量或者表达式来实现。例如,可以根据组件的状态改变样式:

function MyComponent({ isActive }) {return (<divstyle={{color: isActive ? 'green' : 'gray',fontWeight: isActive ? 'bold' : 'normal',}}>Status: {isActive ? 'Active' : 'Inactive'}</div>);
}

多个样式对象的组合

如果有多个样式对象,可以通过 JavaScript 的扩展运算符 {...}Object.assign 合并样式:

const baseStyle = {color: 'white',fontSize: '16px',
};const activeStyle = {color: 'green',fontWeight: 'bold',
};function MyComponent({ isActive }) {return (<div style={{ ...baseStyle, ...(isActive ? activeStyle : {}) }}>Hello, World!</div>);
}

示例:样式对象与内联样式

const containerStyle = {display: 'flex',justifyContent: 'center',alignItems: 'center',height: '100vh',backgroundColor: '#282c34',
};function App() {return (<div style={containerStyle}><h1 style={{ color: 'white', fontSize: '2em' }}>Welcome to My App</h1></div>);
}

在这个示例中,containerStyle 是一个样式对象,并且在 App 组件中通过 style={containerStyle} 赋给 div 标签;h1 的样式则直接写在内联 style 中。

注意事项

  • 单位:数值型的 CSS 属性(如 width, height, fontSize)通常不需要单位,会自动以像素 (px) 处理。例如:fontSize: 20 表示 20px
  • 嵌套样式:不能在 style 对象中直接嵌套选择器,如 :hover@media,这些需要通过 CSS 文件或 CSS-in-JS 解决方案(如 styled-components)来实现。

使用对象形式的 style 属性可以更灵活地实现样式的动态更新,也能充分利用 JavaScript 的表达能力。

Ⅴ.监听事件

1. 添加事件监听器

  • 在 React 中,事件监听器使用 camelCase 形式,比如 onClickonMouseEnter 等。事件处理函数通常是一个箭头函数或组件方法。

示例:一个按钮的点击事件

function App() {function handleClick() {console.log("Button clicked!");}return <button onClick={handleClick}>Click me</button>;
}
  • 注:不要写函数的执行结果

2. 事件对象

React 中的事件处理函数会接收到一个合成事件(SyntheticEvent),它是对原生事件的封装,与原生 DOM 事件 API 类似且跨浏览器兼容。

示例:使用事件对象


function App() {function handleClick(event) {console.log("Button clicked at position:", event.clientX, event.clientY);}return <button onClick={handleClick}>Click me</button>;
}

在这个示例中,event.clientXevent.clientY 是点击事件发生的鼠标位置。

3. 使用箭头函数传递参数

如果需要给事件处理函数传递参数,可以使用箭头函数。

示例:传递自定义参数

function App() {function handleClick(name) {console.log(`Hello, ${name}!`);}return <button onClick={() => handleClick("Alice")}>Greet Alice</button>;
}

这里我们用箭头函数 () => handleClick("Alice") 将参数传递给 handleClick

4. 事件的常用类型

React 支持大多数常见的 DOM 事件,包括但不限于:

  • 鼠标事件onClick, onDoubleClick, onMouseEnter, onMouseLeave, onMouseMove
  • 键盘事件onKeyDown, onKeyUp, onKeyPress
  • 表单事件onChange, onSubmit, onFocus, onBlur
  • 窗口事件onResize, onScroll
  • 剪贴板事件onCopy, onPaste
import React, { useState } from "react";
import type { MouseEvent } from "react";function MouseTracker() {const [position, setPosition] = useState({ x: 0, y: 0 });// 使用 MouseEvent 类型为事件处理函数添加类型定义function handleMouseMove(event: MouseEvent<HTMLDivElement>) {setPosition({x: event.clientX,y: event.clientY,});}return (<divonMouseMove={handleMouseMove}style={{width: "400px",height: "300px",border: "2px solid black",display: "flex",alignItems: "center",justifyContent: "center",}}><p>Mouse Position: ({position.x}, {position.y})</p></div>);
}export default MouseTracker;

5. 阻止默认行为和事件传播

可以通过 event.preventDefault()event.stopPropagation() 控制事件的行为。

示例:阻止表单提交的默认刷新行为

function App() {function handleSubmit(event) {event.preventDefault();console.log("Form submitted!");}return (<form onSubmit={handleSubmit}><button type="submit">Submit</button></form>);
}

在这个示例中,通过 event.preventDefault() 阻止了表单的默认提交行为。

6. 事件解绑

在 React 中,通常不需要手动解绑事件。React 的合成事件系统会自动管理事件的绑定和解绑,以确保性能和资源使用。

7. 使用 useEffect 监听全局事件

如果需要监听全局事件(例如 windowdocument 的事件),可以使用 useEffect 钩子在组件挂载时添加事件监听,并在卸载时移除。

import { useEffect } from 'react';function App() {useEffect(() => {function handleResize() {console.log("Window resized!");}window.addEventListener("resize", handleResize);return () => {window.removeEventListener("resize", handleResize);};}, []);return <div>Resize the window to see the effect!</div>;
}

在这里,我们使用 useEffect 监听 windowresize 事件,并在组件卸载时清理该事件监听器。

Ⅵ.{}和判断

  • {}中不能放置大段js代码,需要通过&& 和 三目运算符进行条件判断

    错误示例

    // 这会导致错误
    return (<div>{if (isLoggedIn) { <p>Welcome back!</p> }}</div>
    );
    

    正确示例

    let message;
    if (isLoggedIn) {message = <p>Welcome back!</p>;
    } else {message = <p>Please log in.</p>;
    }return <div>{message}</div>;
    
使用 && 运算符

&& 运算符通常用来在条件为 true 时渲染内容,否则什么都不显示。

const isLoggedIn = true;
return (<div>{isLoggedIn && <p>Welcome back!</p>}</div>
);

解释

  • 如果 isLoggedIntrue,则渲染 <p>Welcome back!</p>
  • 如果 isLoggedInfalse,则什么也不渲染。
使用三目运算符 ? :

三目运算符允许你根据条件返回不同的内容。

const isLoggedIn = true;
return (<div>{isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>}</div>
);

解释

  • 如果 isLoggedIntrue,则渲染 <p>Welcome back!</p>
  • 如果 isLoggedInfalse,则渲染 <p>Please log in.</p>

通过使用 &&? : 运算符,React 组件能够以简洁的方式实现条件渲染。

Ⅶ.{}和循环

在 React JSX 中,{} 用于嵌入 JavaScript 表达式,但它不能直接包含 for 循环语句,因为 for语句 而不是 表达式。因此,如果想在 React 中循环渲染多个元素,需要使用 JavaScript 的 数组方法(如 map())来实现。

使用 map() 渲染列表

const items = ["Apple", "Banana", "Cherry"];function ItemList() {return (<ul>{items.map((item, index) => (<li key={index}>{item}</li>))}</ul>);
}export default ItemList;

解释

  • 使用 items.map() 遍历 items 数组,并为每个 item 返回一个 <li> 元素。
  • key 属性用于唯一标识每个元素,帮助 React 识别列表中的元素变化,以提高渲染效率。

在组件中使用循环

如果你确实需要使用 for 循环,可以在 JSX 之外创建一个变量来存储结果,并在 JSX 中引用该变量。

const items = ["Apple", "Banana", "Cherry"];function ItemList() {const listItems = [];for (let i = 0; i < items.length; i++) {listItems.push(<li key={i}>{items[i]}</li>);}return <ul>{listItems}</ul>;
}export default ItemList;

解释

  • 先使用 for 循环将 <li> 元素推入 listItems 数组。
  • 然后在 JSX 中使用 {listItems} 渲染列表。

JSX语法注意项目:

  • 属性命名:在 JSX 中,classclassName 替代,forhtmlFor 替代,以避免与 JavaScript 保留字冲突。
// 正确的写法(React JSX)
<label htmlFor="username">Username:</label>
<input id="username" type="text" />// 错误的写法
<label for="username">Username:</label>
<input id="username" type="text" />
  • JSX 必须封闭标签:如果标签没有内容,必须使用自闭合形式 <br />,否则会报错。
  • 每个JSX片段只能有一个根节点 :
function MyComponent() {return (<><div>Element 1</div><div>Element 2</div></>);
}

http://www.ppmy.cn/embedded/136071.html

相关文章

网络协议都有哪些?

网络协议是为计算机网络中进行数据交换而建立的规则、标准或约定的集合。以下是一些常见的网络协议&#xff1a; TCP/IP协议&#xff1a;传输控制协议/因特网互联协议&#xff0c;又名网络通讯协议&#xff0c;是Internet最基本的协议、Internet国际互联网络的基础。由网络层的…

SpringBoot在城镇保障性住房管理中的应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理城镇保障性住房管理系统的相关信息成为必然…

HarmonyOS开发 - 餐饮APP中多门店多窗口打开实例补充

specified启动模式为指定实例模式&#xff0c;有一些特殊场景&#xff0c;例如多门店应用中每次打开一个门店都希望能新建一个门店实例&#xff0c;而重复打开同一个门店都是同一门店实例。 此篇为餐饮APP中多门店实例的补充内容&#xff0c;以解决同一门店多次点击重复创建新窗…

2024 Rust现代实用教程 closures闭包

文章目录 一、闭包基础概念1.如何使用闭包 二、闭包获取参数byreference与byvalue1.获取外部参数2.所有权转移move 三、闭包是怎么工作的1.闭包在底层是怎么工作的&#xff1f;2.FnOnce,FnMut,Fn特质 四、闭包类型FnOnce、FnMut和Fn做函数参数的实例参考 一、闭包基础概念 闭包…

Unity Windows 2023 Release-Notes

&#x1f308;Unity Windows 2023 Release-Notes 本文信息收集来自自动搜集工具&#x1f448; 版本更新内容2023.2.13Windows: Fixed Double backslash becoming single backslash when passing a Network path as a command line argument.(UUM-55979)2023.2.9Windows: Fixed…

斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)

斗破Qt目录&#xff1a; 斗破Qt编程入门系列之前言&#xff1a;认识Qt&#xff1a;Qt的获取与安装&#xff08;四星斗师&#xff09; 斗破QT编程入门系列之一&#xff1a;认识Qt&#xff1a;初步使用&#xff08;四星斗师&#xff09; 斗破QT编程入门系列之二&#xff1a;认识…

C++【string类,模拟实现string类】

&#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: C专栏 目录 为什么学习string类 C语言中的字符串 标准库中的string类 auto和范围for auto关键字 迭代器 范围for string类的常用接口说明和使用 1. string类对象的常见构造 2.string类对象的容量操作 3…

【无标题】西安交通大学提出少锚点的端到端车道线检测算法Polar R-CNN

Abstract 车道线检测在自动驾驶中是一个关键且充满挑战的任务&#xff0c;特别是在实际场景中&#xff0c;由于车道线可能因其他车辆而被遮挡、形状纤细且长度较长&#xff0c;检测难度增大。现有基于锚点的检测方法通常依赖于预设的锚点来提取特征&#xff0c;并随后对车道线…