项目源代码(for FREE)
真的是非常优质的React前端项目!
john-smilga/react-projects (github.com)
本文介绍了其中的第2、24个项目
再给大家推荐一个国外大神搭建的学习网站,也非常棒!
React Tutorial: Learn React JS - Free 11-Hour Course (scrimba.com)
第一个项目
初步框架
html&css
<html>
<head>
<link rel="stylesheet" href="index.css">
<!-- React依赖-->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- React依赖-->
</head>
<body>
<div id="root"></div> <!-- 注意这里的id-->
<script src="index.js" type="text/babel"></script>
</body>
</html>
<!-- css-->
html, body {
margin: 0;
padding: 0;
}
js
function Maincontent(){ {/* function名称第一个字母必须大写 */}
return (
<h3>🐏's missing 🐇!</h3>
)
}
ReactDOM.render(
<div> {/* 只能有一个div在外面 */}
<h1>Haha</h1>
<ul><li>Thing 1 咬🐏</li><li>Thing 2 啃🐏</li></ul>
<Maincontent /> {/* 类似一个有返回值的函数 */}
</div>, {/* 这里要有, 否则报错*/}
document.getElementById("root")
)
结果
进阶写法
import React from "react"
import ReactDOM from "react-dom"
function Header() { {/* function名称第一个字母必须大写 */}
return (
<header>
<nav>
<img src="./react-logo.png" width="40px" />
</nav>
</header>
)
}
function Footer() { {/* function名称第一个字母必须大写 */}
return (
<footer>
<small>© 2021 Ziroll development. All rights reserved.</small>
</footer>
)
}
function MainContent() { {/* function名称第一个字母必须大写 */}
return (
<div>
<h1>Reasons I'm excited to learn React</h1>
<ol>
<li>It's a popular library, so I'll be
able to fit in with the cool kids!</li>
<li>I'm more likely to get a job as a developer
if I know React</li>
</ol>
</div>
)
}
function Page() {
return (
<div>
<Header />
<MainContent />
<Footer />
</div>
)
}
ReactDOM.render(<Page />, document.getElementById("root"))
加入样式
css
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-logo {
width: 60px;
}
.nav-items {
list-style: none;
display: flex;
}
.nav-items > li {
padding: 30px;
}
js
import React from "react";
import ReactDOM from "react-dom";
import './index.css';
function Header() {
return (
<header>
<nav className="nav">
<img src={require("./react-logo.jpg")} className="nav-logo" />
{/* 借助require函数显示图片 */}
<ul className="nav-items">
<li>Pricing</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
)
}
function Page() {
return (
<div>
<Header /> {/* Page主体可以继续添加想要的部分 */}
</div>
)
}
ReactDOM.render(<Page />, document.getElementById("root"))
第二个项目
将各部分拆开,整个项目更加成熟
index.js(大框架)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
<React.StrictMode> 为严格模式, App即相当于函数体
App.js(将各部分功能继续细分)
import React, { useState } from 'react'
import data from './data'
import List from './List'
function App() {
const [people, setPeople] = useState(data)
return (
<main>
<section className='container'>
<h3>{people.length} birthdays today</h3>
<List people={people} />
<button onClick={() => setPeople([])}>clear all</button>
</section>
</main>
)
}
export default App
List.js&data.js(用数据写入变量)
import React from 'react';
const List = ({ people }) => {
return (
<>
{people.map((person) => {
const { id, name, age, image } = person;
return (
<article key={id} className='person'>
<img src={image} alt={name} />
<div>
<h4>{name}</h4>
<p>{age} years</p>
</div>
</article>
);
})}
</>
);
};
export default List;
export default [
{
id: 1,
name: 'Bertie Yates',
age: 29,
image:
'https://res.cloudinary.com/diqqf3eq2/image/upload/v1595959131/person-2_ipcjws.jpg',
},
{
id: 2,
name: 'Hester Hogan',
age: 32,
image:
'https://res.cloudinary.com/diqqf3eq2/image/upload/v1595959131/person-3_rxtqvi.jpg',
},
{
id: 3,
name: 'Larry Little',
age: 36,
image:
'https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883423/person-4_t9nxjt.jpg',
},
{
id: 4,
name: 'Sean Walsh',
age: 34,
image:
'https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883417/person-3_ipa0mj.jpg',
},
{
id: 5,
name: 'Lola Gardner',
age: 29,
image:
'https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883334/person-1_rfzshl.jpg',
},
];
效果
更大的项目
效果
布局拆分
路由设置(APP.js)
import Sidebar from "./components/sidebar/Sidebar";
import Topbar from "./components/topbar/Topbar";
import "./App.css";
import Home from "./pages/home/Home";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import UserList from "./pages/userList/UserList";
import User from "./pages/user/User";
import NewUser from "./pages/newUser/NewUser";
import ProductList from "./pages/productList/ProductList";
import Product from "./pages/product/Product";
import NewProduct from "./pages/newProduct/NewProduct";
// 引入各个函数和依赖
function App() {
return (
<Router>
<Topbar />
<div className="container">
<Sidebar />
{/* 固定的2个部分 */}
<Switch>
<Route exact path="/">
{/* 开始路由设置 */}
<Home />
</Route>
<Route path="/users">
<UserList />
</Route>
<Route path="/user/:userId">
<User />
</Route>
<Route path="/newUser">
<NewUser />
</Route>
<Route path="/products">
<ProductList />
</Route>
<Route path="/product/:productId">
<Product />
</Route>
<Route path="/newproduct">
<NewProduct />
</Route>
</Switch>
</div>
</Router>
// 仅返回一个Router标签
);
}
export default App;
具体函数功能
简单jsx
export default function Sidebar() {
// 无参数函数
return (
<div className="sidebar">
<div className="sidebarWrapper">
<div className="sidebarMenu">
<h3 className="sidebarTitle">仪表盘</h3>
<ul className="sidebarList">
<Link to="/" className="link">
<li className="sidebarListItem active">
<LineStyle className="sidebarIcon" />
主页
</li>
</Link>
<li className="sidebarListItem">
<Timeline className="sidebarIcon" />
分析
</li>
<li className="sidebarListItem">
<TrendingUp className="sidebarIcon" />
销售
</li>
</ul>
</div>
</div>
</div>
);
}
含参函数
import "./chart.css";
import {
LineChart,
Line,
XAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
export default function Chart({ title, data, dataKey, grid }) {
// 传入参数
// React专用的画图方式,借助第三方包依赖
return (
<div className="chart">
<h3 className="chartTitle">{title}</h3>
<ResponsiveContainer width="100%" aspect={4 / 1}>
<LineChart data={data}>
<XAxis dataKey="name" stroke="#5550bd" />
<Line type="monotone" dataKey={dataKey} stroke="#5550bd" />
<Tooltip />
{grid && <CartesianGrid stroke="#e0dfdf" strokeDasharray="5 5" />}
</LineChart>
</ResponsiveContainer>
</div>
);
}
界面
Home主界面
import Chart from "../../components/chart/Chart";
import FeaturedInfo from "../../components/featuredInfo/FeaturedInfo";
import "./home.css";
import { userData } from "../../dummyData";
// 提前写好的数据集
import WidgetSm from "../../components/widgetSm/WidgetSm";
import WidgetLg from "../../components/widgetLg/WidgetLg";
export default function Home() {
// 组合调用各个部分的函数功能,形成界面
return (
<div className="home">
<FeaturedInfo />
<Chart data={userData} title="用户量统计" grid dataKey="Active User"/>
<div className="homeWidgets">
<WidgetSm/>
<WidgetLg/>
</div>
</div>
);
}
项目部署
前期工作
首先可以用服务器新建立一个React项目,步骤如下
npm create-react-app 项目名称
cd 项目名称
npm run build
npm start
下面如果报错,该怎么修理怎么修理。例如:
nodejs版本问题,建议14版本(11版本过低无法运行)
端口3000或其他没有开放,用如下命令开放端口(没有直接npm install xxxxx -g
)
sudo ufw allow <端口号> 例如3000
之后还要去阿里云的控制台 ,把端口再手动开放一下。
PM2部署(nohup一直失败)
首先安装pm2
npm install xxxxx -g
下面移动到标准的react项目目录下,执行如下命令:
pm2 start --name agv npm -- start
pm2 list
pm2 delete 项目名字
agv
这是启动进程的名字,原博客和效果图如下链接所示
pm2 启动React项目 - 李悠然 - 博客园 (cnblogs.com)
我的成功截图如下:
访问链接:React Admin App
另外的,有时候项目渲染的时间较长,如果看到title有变化,那就可以提前庆祝了