拆分组件

现在数据、逻辑、界面全挤在 App.jsx 里:功能越多文件越长,改一处都要小心翼翼。React 的解决思路是组件化——把页面拆成一个个"只管一件事"的小组件,再用 props 把数据从父组件传下去。本章为博客首页做一次组件拆分。

为什么要拆分

  • 复用:文章卡片在首页、搜索页都要用,抽出来写一次即可。
  • 可读:每个文件只负责一小块,看文件名就知道它渲染什么。
  • 易维护:想改卡片样式只动一个文件,不影响页面其它部分。

组件本质是函数

函数组件是一个接收 props、返回 JSX 的函数。props 是父组件通过标签属性传进来的数据对象,通常直接解构使用:

// src/components/ArticleCard.jsx
export default function ArticleCard({ post }) { // 解构 props,取出 post
  return (
    <article className="card">
      <h2>{post.title}</h2>
      <p>{post.summary}</p>
      <span>作者:{post.author}</span>
    </article>
  );
}

父组件这样传值:<ArticleCard post={posts[0]} />,子组件收到的 props 就是 { post: posts[0] }。

拆分列表组件

循环渲染的"骨架"也值得独立。ArticleList 只关心"给一批文章,铺成列表",内部再逐条引用 ArticleCard:

// src/components/ArticleList.jsx
import ArticleCard from "./ArticleCard";

export default function ArticleList({ posts }) {
  if (posts.length === 0) return <p>暂无文章</p>;
  return (
    <div>
      {posts.map((post) => (
        <ArticleCard key={post.id} post={post} />
      ))}
    </div>
  );
}

App.jsx 里就只剩组合一行:<ArticleList posts={posts} />,页面结构一目了然。

子组件如何通知父组件

props 是单向的:数据只能父传子,子组件不能修改 props。当子组件需要"操作数据"时,父组件把回调函数也作为 props 传下去,由子组件在合适时机调用:

// App.jsx
function deletePost(id) {
  setPosts(posts.filter((p) => p.id !== id));
}
<ArticleList posts={posts} onDelete={deletePost} />

// ArticleCard.jsx 里
<button onClick={() => onDelete(post.id)}>删除</button>

数据始终留在父组件,子组件只负责"上报发生了什么",这就是单向数据流。

小结

拆分组件 = 按职责把 JSX 抽成小组件 + 用 props 传递数据与回调。单向数据流让每个组件的数据来源都清晰可查。页面再复杂,也只是这样一层层组合出来的。

笔记加载中…