返回
React仿知乎移动端想法页:小白React入门必修课!
前端
2024-01-30 11:33:24
React作为前端使用频率最高的三大框架之一,其组件化开发思想备受推崇。对于学习过React的前端小伙伴来说,“React中一切都是组件”这句话可谓耳熟能详。
在本文中,我们将通过一个实战项目——React仿知乎移动端想法页,来详细介绍React组件化开发的应用。通过这个项目,你将学习到如何将复杂组件拆分为更小的可重用组件,以及如何管理组件之间的通信和状态。
前言
在这个React实战项目中,我们将构建一个仿知乎移动端想法页。在这个页面上,用户可以查看想法列表,并可以对想法进行点赞、评论和分享。
这个项目将涉及到以下知识点:
- React组件化开发
- React状态管理
- React事件处理
- React路由
- React动画
项目结构
项目结构如下:
├── App.js
├── components
│ ├── Idea.js
│ ├── IdeaList.js
│ ├── Header.js
│ ├── Footer.js
│ └── NotFound.js
├── index.js
├── package.json
└── README.md
App.js
:应用程序的主组件,负责管理路由和页面布局。components
:组件文件夹,存放所有组件。Idea.js
:想法组件,负责显示单个想法。IdeaList.js
:想法列表组件,负责显示所有想法。Header.js
:页头组件,负责显示页面标题和导航栏。Footer.js
:页脚组件,负责显示页脚信息。NotFound.js
:404页面组件,负责显示页面未找到信息。index.js
:应用程序的入口文件,负责加载应用程序。package.json
:应用程序的包配置文件。README.md
:应用程序的README文件。
构建过程
1. 安装依赖
首先,我们需要安装项目所需的依赖。
npm install
2. 创建组件
接下来,我们需要创建组件。
mkdir components
cd components
touch Idea.js IdeaList.js Header.js Footer.js NotFound.js
3. 编写组件
然后,我们需要编写组件。
// Idea.js
import React from 'react';
const Idea = (props) => {
const { idea } = props;
return (
<div className="idea">
<div className="idea-title">{idea.title}</div>
<div className="idea-content">{idea.content}</div>
<div className="idea-actions">
<button onClick={() => props.onUpvote(idea)}>👍</button>
<button onClick={() => props.onDownvote(idea)}>👎</button>
<button onClick={() => props.onComment(idea)}>💬</button>
<button onClick={() => props.onShare(idea)}>🚀</button>
</div>
</div>
);
};
export default Idea;
// IdeaList.js
import React, { useState } from 'react';
import Idea from './Idea';
const IdeaList = (props) => {
const { ideas } = props;
const [sortField, setSortField] = useState('created_at');
const sortedIdeas = ideas.sort((a, b) => {
if (a[sortField] < b[sortField]) {
return -1;
} else if (a[sortField] > b[sortField]) {
return 1;
} else {
return 0;
}
});
return (
<div className="idea-list">
<div className="idea-list-header">
<div className="idea-list-sort">
<button onClick={() => setSortField('created_at')}>按时间排序</button>
<button onClick={() => setSortField('upvotes')}>按赞数排序</button>
<button onClick={() => setSortField('comments')}>按评论数排序</button>
</div>
</div>
<div className="idea-list-body">
{sortedIdeas.map((idea) => (
<Idea
key={idea.id}
idea={idea}
onUpvote={() => props.onUpvote(idea)}
onDownvote={() => props.onDownvote(idea)}
onComment={() => props.onComment(idea)}
onShare={() => props.onShare(idea)}
/>
))}
</div>
</div>
);
};
export default IdeaList;
// Header.js
import React from 'react';
const Header = () => {
return (
<div className="header">
<div className="header-title">知乎</div>
<div className="header-nav">
<a href="#">首页</a>
<a href="#">想法</a>
<a href="#">问题</a>
<a href="#">专栏</a>
<a href="#">更多</a>
</div>
</div>
);
};
export default Header;
// Footer.js
import React from 'react';
const Footer = () => {
return (
<div className="footer">
<div className="footer-copyright">Copyright © 2023 知乎</div>
</div>
);
};
export default Footer;
// NotFound.js
import React from 'react';
const NotFound = () => {
return (
<div className="not-found">
<h1>404</h1>
<h2>页面未找到</h2>
</div>
);
};
export default NotFound;
4. 编写应用程序
接下来,我们需要编写应用程序。
// App.js
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import IdeaList from './components/IdeaList';
import Header from './components/Header';
import Footer from './components/Footer';
import NotFound from './components/NotFound';
const App = () => {
const [ideas, setIdeas] = useState([
{
id: 1,
title: 'React Hooks',
content: 'React Hooks are a new feature in React that allow you to use state and other React features without writing a class.',
upvotes: 10,
comments: 5,
shares: 2
},
{
id: 2,
title: 'Functional Components',
content: 'Functional components are a new type of component in React that are defined as arrow functions.',
upvotes: 8,
comments: 3,
shares: 1
},
{
id: 3,
title: 'Context API',
content: 'The Context API is a way to share data between components without passing props down through the component tree.',
upvotes: 6,
comments: 2,
shares: 0
}
]);
const onUpvote = (idea) => {
const updatedIdeas = ideas.map((i) => {
if (i.id === idea.id) {
return {
...i,
upvotes: i.upvotes + 1
};
} else {
return i;
}
});
setIdeas(updatedIdeas);
};
const onDownvote = (idea) => {
const updatedIdeas = ideas.map((i) => {
if (i.id === idea.id) {
return {
...i,
upvotes: i.upvotes - 1
};
} else {
return i;
}
});
setIdeas(updatedIdeas);
};
const onComment = (idea) => {
console.log(`Comment on idea ${idea.id}`);
};
const onShare = (idea) => {
console.log(`Share idea ${idea.id}`);
};
return (
<Router>
<div className="app">
<Header />
<div className="app-body">
<Routes>
<Route path="/" element={<IdeaList ideas={ideas} onUpvote={onUpvote}