React 组件基础:JSX、Props、导入导出
搞懂 .tsx 文件是什么,JSX 语法怎么写,组件怎么传参,export default 和具名导出有什么区别。
从零搭建 Next.js 博客
- 1前端工具链入门:npm、pnpm、npx 是什么
- 2JavaScript 核心语法速览
- 3TypeScript 核心语法:给 JS 加上类型
- 4React 组件基础:JSX、Props、导入导出
- 5Next.js App Router 核心特性
React 组件基础:JSX、Props、导入导出
.tsx 是什么文件
| 后缀 | 含义 |
|---|---|
.ts |
TypeScript |
.tsx |
TypeScript + JSX(能在代码里写 HTML 标签) |
.js |
JavaScript |
.jsx |
JavaScript + JSX |
我们的页面和组件都用 .tsx,因为需要在 TypeScript 里写 HTML 结构。
JSX 是什么
JSX 是 React 发明的语法,让你在 JS/TS 里直接写 HTML:
// 这就是 JSX,看起来像 HTML,但在 .tsx 文件里
function Hello() {
return <h1>你好世界</h1>;
}
最大的特点是用 {} 插入 JS 表达式:
const name = "Mary";
const count = 3;
<h1>你好,{name}</h1> // → 你好,Mary
<p>共 {count} 篇文章</p> // → 共 3 篇文章
<p>共 {count * 2} 篇</p> // → 可以做运算
<p>{count > 0 ? "有文章" : "没有文章"}</p> // → 可以写条件
JSX 和 HTML 的区别
两者 99% 一样,只有几处不同:
// 1. class → className(class 是 JS 关键字)
<div class="box"> // ❌
<div className="box"> // ✅
// 2. 自闭合标签必须加 /
<img src="x.png"> // ❌
<img src="x.png" /> // ✅
<br> // ❌
<br /> // ✅
// 3. 注释写法不同
<!-- 注释 --> // ❌ HTML 注释在 JSX 里不能用
{/* 注释 */} // ✅
组件是什么
组件就是返回 JSX 的函数,是可以复用的 UI 片段:
// 定义一个文章卡片组件
function PostCard() {
return (
<div>
<h2>文章标题</h2>
<p>文章摘要</p>
</div>
);
}
// 使用组件,就像使用 HTML 标签
<PostCard />
规则:组件名必须大写字母开头,用来和普通 HTML 标签区分(<div> vs <PostCard />)。
Props:给组件传数据
Props 就是组件的参数,从外部传入数据:
// 定义 Props 类型
interface PostCardProps {
title: string;
date: string;
}
// 接收 Props(用对象解构直接取出字段)
function PostCard({ title, date }: PostCardProps) {
return (
<div>
<h2>{title}</h2>
<p>{date}</p>
</div>
);
}
// 使用时传入数据
<PostCard title="你好世界" date="2026-04-05" />
{ title, date } 是对象解构,等价于:
function PostCard(props: PostCardProps) {
const title = props.title;
const date = props.date;
}
组件的完整结构
// 1. 导入依赖
import Link from "next/link";
// 2. 定义 Props 类型
interface PostCardProps {
title: string;
date: string;
}
// 3. 组件函数(export default = 默认导出)
export default function PostCard({ title, date }: PostCardProps) {
// 4. 普通 JS 逻辑
const formattedDate = new Date(date).toLocaleDateString("zh-CN");
// 5. 返回 JSX
return (
<div>
<h2>{title}</h2>
<time>{formattedDate}</time>
</div>
);
}
export default vs 具名导出
// 默认导出:一个文件只能有一个
// 适合:这个文件的"主角"
export default function PostCard() {}
// 导入时名字可以随便起
import PostCard from "./PostCard";
import Card from "./PostCard"; // 也合法,是同一个东西
// 具名导出:一个文件可以有多个
// 适合:工具函数、类型定义等
export function getAllPosts() {}
export function getAllTags() {}
export interface PostMeta {}
// 导入时必须花括号,名字必须对得上
import { getAllPosts, getAllTags } from "./posts";
map 渲染列表
在 React 里,用 map 把数组渲染成 JSX 列表:
const posts = [
{ slug: "a", title: "文章一" },
{ slug: "b", title: "文章二" },
];
// 每个元素渲染一个 PostCard
// key 是必须的,帮助 React 追踪每个元素
{posts.map((post) => (
<PostCard key={post.slug} title={post.title} />
))}
Server Component vs Client Component
这是 Next.js 特有的概念:
// Server Component(默认):在服务器上运行
// 可以直接读文件、查数据库
// 不能用 useState、useEffect、事件处理
export default function PostsPage() {
const posts = getAllPosts(); // 直接读文件,完全合法
return <div>{/* ... */}</div>;
}
// Client Component:在浏览器里运行
// 文件顶部加 "use client"
"use client";
import { useState } from "react";
export default function SearchBar() {
const [query, setQuery] = useState(""); // 需要 useState
return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
}
选择原则: 默认用 Server Component,只有需要交互(点击、输入、状态)时才加 "use client"。