Skip to content

Commit bd75c01

Browse files
committedDec 23, 2023
✨ Implement day-02
1 parent 2fab96a commit bd75c01

28 files changed

+20967
-0
lines changed
 

‎day-02/react-basic-pro/.gitignore

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*

‎day-02/react-basic-pro/README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Getting Started with Create React App
2+
3+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4+
5+
## Available Scripts
6+
7+
In the project directory, you can run:
8+
9+
### `npm start`
10+
11+
Runs the app in the development mode.\
12+
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13+
14+
The page will reload when you make changes.\
15+
You may also see any lint errors in the console.
16+
17+
### `npm test`
18+
19+
Launches the test runner in the interactive watch mode.\
20+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21+
22+
### `npm run build`
23+
24+
Builds the app for production to the `build` folder.\
25+
It correctly bundles React in production mode and optimizes the build for the best performance.
26+
27+
The build is minified and the filenames include the hashes.\
28+
Your app is ready to be deployed!
29+
30+
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31+
32+
### `npm run eject`
33+
34+
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
35+
36+
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37+
38+
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39+
40+
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41+
42+
## Learn More
43+
44+
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45+
46+
To learn React, check out the [React documentation](https://reactjs.org/).
47+
48+
### Code Splitting
49+
50+
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51+
52+
### Analyzing the Bundle Size
53+
54+
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55+
56+
### Making a Progressive Web App
57+
58+
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59+
60+
### Advanced Configuration
61+
62+
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63+
64+
### Deployment
65+
66+
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67+
68+
### `npm run build` fails to minify
69+
70+
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

‎day-02/react-basic-pro/db.json

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"list": [
3+
{
4+
"rpid": 3,
5+
"user": {
6+
"uid": "13258165",
7+
"avatar": "http://toutiao.itheima.net/resources/images/98.jpg",
8+
"uname": "周杰伦"
9+
},
10+
"content": "哎哟,不错哦",
11+
"ctime": "10-18 08: 15",
12+
"like": 126
13+
},
14+
{
15+
"rpid": 2,
16+
"user": {
17+
"uid": "36080105",
18+
"avatar": "http://toutiao.itheima.net/resources/images/98.jpg",
19+
"uname": "许嵩"
20+
},
21+
"content": "我寻你千百度 日出到迟暮",
22+
"ctime": "11-13 11: 29",
23+
"like": 88
24+
},
25+
{
26+
"rpid": 1,
27+
"user": {
28+
"uid": "30009257",
29+
"avatar": "http://toutiao.itheima.net/resources/images/98.jpg",
30+
"uname": "黑马前端"
31+
},
32+
"content": "学前端就来黑马",
33+
"ctime": "10-19 09: 00",
34+
"like": 66
35+
}
36+
]
37+
}

‎day-02/react-basic-pro/package.json

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "react-basic-pro",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@testing-library/jest-dom": "^5.17.0",
7+
"@testing-library/react": "^13.4.0",
8+
"@testing-library/user-event": "^13.5.0",
9+
"axios": "^1.6.2",
10+
"classnames": "^2.3.2",
11+
"dayjs": "^1.11.10",
12+
"lodash": "^4.17.21",
13+
"react": "^18.2.0",
14+
"react-dom": "^18.2.0",
15+
"react-scripts": "5.0.1",
16+
"sass": "^1.69.5",
17+
"uuid": "^9.0.1",
18+
"web-vitals": "^2.1.4"
19+
},
20+
"scripts": {
21+
"start": "react-scripts start",
22+
"build": "react-scripts build",
23+
"test": "react-scripts test",
24+
"eject": "react-scripts eject",
25+
"server": "json-server --watch db.json --port 3001"
26+
},
27+
"eslintConfig": {
28+
"extends": [
29+
"react-app",
30+
"react-app/jest"
31+
]
32+
},
33+
"browserslist": {
34+
"production": [
35+
">0.2%",
36+
"not dead",
37+
"not op_mini all"
38+
],
39+
"development": [
40+
"last 1 chrome version",
41+
"last 1 firefox version",
42+
"last 1 safari version"
43+
]
44+
},
45+
"devDependencies": {
46+
"json-server": "^0.17.4"
47+
}
48+
}
3.78 KB
Binary file not shown.
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Web site created using create-react-app"
11+
/>
12+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13+
<!--
14+
manifest.json provides metadata used when your web app is installed on a
15+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16+
-->
17+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18+
<!--
19+
Notice the use of %PUBLIC_URL% in the tags above.
20+
It will be replaced with the URL of the `public` folder during the build.
21+
Only files inside the `public` folder can be referenced from the HTML.
22+
23+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24+
work correctly both with client-side routing and a non-root public URL.
25+
Learn how to configure a non-root public URL by running `npm run build`.
26+
-->
27+
<title>React App</title>
28+
</head>
29+
<body>
30+
<noscript>You need to enable JavaScript to run this app.</noscript>
31+
<div id="root"></div>
32+
<!--
33+
This HTML file is a template.
34+
If you open it directly in the browser, you will see an empty page.
35+
36+
You can add webfonts, meta tags, or analytics to this file.
37+
The build step will place the bundled scripts into the <body> tag.
38+
39+
To begin the development, run `npm start` or `yarn start`.
40+
To create a production bundle, use `npm run build` or `yarn build`.
41+
-->
42+
</body>
43+
</html>
5.22 KB
Loading
9.44 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
},
10+
{
11+
"src": "logo192.png",
12+
"type": "image/png",
13+
"sizes": "192x192"
14+
},
15+
{
16+
"src": "logo512.png",
17+
"type": "image/png",
18+
"sizes": "512x512"
19+
}
20+
],
21+
"start_url": ".",
22+
"display": "standalone",
23+
"theme_color": "#000000",
24+
"background_color": "#ffffff"
25+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://www.robotstxt.org/robotstxt.html
2+
User-agent: *
3+
Disallow:

‎day-02/react-basic-pro/src/App.js

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import './App.scss';
2+
import avatar from './images/bozai.png'
3+
import {useEffect, useRef, useState} from 'react'
4+
import _ from 'lodash'
5+
import classNames from 'classnames'
6+
import {v4 as uuidV4} from 'uuid'
7+
import dayjs from 'dayjs'
8+
import axios from "axios"
9+
10+
// 评论列表数据
11+
const list = [
12+
{
13+
"rpid": 3,
14+
"user": {
15+
"uid": "13258165",
16+
"avatar": "http://toutiao.itheima.net/resources/images/98.jpg",
17+
"uname": "周杰伦"
18+
},
19+
"content": "哎哟,不错哦",
20+
"ctime": "10-18 08: 15",
21+
"like": 126
22+
},
23+
{
24+
"rpid": 2,
25+
"user": {
26+
"uid": "36080105",
27+
"avatar": "http://toutiao.itheima.net/resources/images/98.jpg",
28+
"uname": "许嵩"
29+
},
30+
"content": "我寻你千百度 日出到迟暮",
31+
"ctime": "11-13 11: 29",
32+
"like": 88
33+
},
34+
{
35+
"rpid": 1,
36+
"user": {
37+
"uid": "30009257",
38+
"avatar": avatar,
39+
"uname": "黑马前端"
40+
},
41+
"content": "学前端就来黑马",
42+
"ctime": "10-19 09: 00",
43+
"like": 66
44+
}
45+
]
46+
47+
// 当前登录用户信息
48+
const user = {
49+
uid: '30009257',
50+
avatar,
51+
uname: 'bo'
52+
}
53+
54+
// 导航 Tab 数组
55+
const tabs = [
56+
{type: 'hot', text: '最热'},
57+
{type: 'time', text: '最新'}
58+
]
59+
60+
// 自定义 hook 封装数据请求
61+
function useGetList() {
62+
// 获取接口数据
63+
const [commentList, setCommentList] = useState([])
64+
useEffect(() => {
65+
async function getList() {
66+
const res = await axios.get('http://localhost:3001/list')
67+
setCommentList(res.data)
68+
}
69+
70+
getList()
71+
}, [])
72+
73+
return {
74+
commentList,
75+
setCommentList
76+
}
77+
}
78+
79+
// 封装评论 Item 组件
80+
function Item({item, onDel}) {
81+
return (
82+
<div className="reply-item">
83+
{/* 头像 */}
84+
<div className="root-reply-avatar">
85+
<div className="bili-avatar">
86+
<img
87+
className="bili-avatar-img"
88+
alt=""
89+
src={item.user.avatar}
90+
/>
91+
</div>
92+
</div>
93+
94+
<div className="content-wrap">
95+
{/* 用户名 */}
96+
<div className="user-info">
97+
<div className="user-name">{item.user.uname}</div>
98+
</div>
99+
{/* 评论内容 */}
100+
<div className="root-reply">
101+
<span className="reply-content">{item.content}</span>
102+
<div className="reply-info">
103+
{/* 评论时间 */}
104+
<span className="reply-time">{item.ctime}</span>
105+
{/* 评论数量 */}
106+
<span className="reply-time">点赞数:{item.like}</span>
107+
{/* 条件:user.id === item.user.id */}
108+
{user.uid === item.user.uid &&
109+
<span className='delete-btn' onClick={() => onDel(item.rpid)}>
110+
删除
111+
</span>}
112+
</div>
113+
</div>
114+
</div>
115+
</div>
116+
)
117+
}
118+
119+
function App() {
120+
// 渲染评论列表
121+
// 1. 使用 useState 维护 list
122+
// const [commentList, setCommentList] = useState(_.orderBy(list, 'like', 'desc'))
123+
124+
const {commentList, setCommentList} = useGetList()
125+
126+
// 删除功能
127+
const handleDel = (id) => {
128+
// 对 commentList 做过滤处理
129+
setCommentList(commentList.filter(item => item.rpid !== id))
130+
}
131+
132+
// tab 切换功能
133+
// 1. 点击谁就把谁的 type 记录下来
134+
// 2. 通过记录的 type 和每一项遍历时的 type 做匹配,控制激活类名的显示
135+
const [type, setType] = useState('hot')
136+
const handleTabChange = (type) => {
137+
setType(type)
138+
// 基于列表的排序
139+
if (type === 'hot') {
140+
// 根据点赞数排序
141+
setCommentList(_.orderBy(commentList, 'like', 'desc'))
142+
} else {
143+
// 根据创建时间排序
144+
setCommentList(_.orderBy(commentList, 'ctime', 'desc'))
145+
}
146+
}
147+
148+
// 发表评论
149+
const [content, setContent] = useState('')
150+
const inputRef = useRef(null);
151+
const handlePublish = () => {
152+
setCommentList([
153+
...commentList,
154+
{
155+
"rpid": uuidV4(),
156+
"user": user,
157+
"content": content,
158+
"ctime": dayjs().format('MM-DD HH:mm'),
159+
"like": 66
160+
}
161+
])
162+
// 1. 清空输入框内容
163+
setContent('')
164+
// 2. 重新聚焦
165+
inputRef.current.focus()
166+
}
167+
168+
return (
169+
<div className="app">
170+
{/* 导航 Tab */}
171+
<div className="reply-navigation">
172+
<ul className="nav-bar">
173+
<li className="nav-title">
174+
<span className="nav-title-text">评论</span>
175+
{/* 评论数量 */}
176+
<span className="total-reply">{10}</span>
177+
</li>
178+
<li className="nav-sort">
179+
{/* 高亮类名: active */}
180+
{tabs.map(item => (
181+
<span
182+
key={item.type}
183+
className={classNames('nav-item', {active: type === item.type})}
184+
onClick={() => handleTabChange(item.type)}
185+
>
186+
{item.text}
187+
</span>
188+
))}
189+
</li>
190+
</ul>
191+
</div>
192+
193+
<div className="reply-wrap">
194+
{/* 发表评论 */}
195+
<div className="box-normal">
196+
{/* 当前用户头像 */}
197+
<div className="reply-box-avatar">
198+
<div className="bili-avatar">
199+
<img className="bili-avatar-img" src={avatar} alt="用户头像" />
200+
</div>
201+
</div>
202+
<div className="reply-box-wrap">
203+
{/* 评论框 */}
204+
<textarea
205+
className="reply-box-textarea"
206+
placeholder="发一条友善的评论"
207+
value={content}
208+
ref={inputRef}
209+
onChange={(e) => setContent(e.target.value)}
210+
/>
211+
{/* 发布按钮 */}
212+
<div className="reply-box-send">
213+
<div className="send-text" onClick={handlePublish}>发布</div>
214+
</div>
215+
</div>
216+
</div>
217+
{/* 评论列表 */}
218+
<div className="reply-list">
219+
{/* 评论项 */}
220+
{commentList.map(item => (
221+
<Item key={item.rpid} item={item} onDel={handleDel} />
222+
))}
223+
224+
</div>
225+
</div>
226+
</div>
227+
)
228+
}
229+
230+
export default App

‎day-02/react-basic-pro/src/App.scss

+282
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
.app {
2+
width: 80%;
3+
margin: 50px auto;
4+
}
5+
6+
.reply-navigation {
7+
margin-bottom: 22px;
8+
9+
.nav-bar {
10+
display: flex;
11+
align-items: center;
12+
margin: 0;
13+
padding: 0;
14+
list-style: none;
15+
16+
.nav-title {
17+
display: flex;
18+
align-items: center;
19+
width: 114px;
20+
font-size: 20px;
21+
22+
.nav-title-text {
23+
color: #18191c;
24+
font-weight: 500;
25+
}
26+
.total-reply {
27+
margin: 0 36px 0 6px;
28+
color: #9499a0;
29+
font-weight: normal;
30+
font-size: 13px;
31+
}
32+
}
33+
34+
.nav-sort {
35+
display: flex;
36+
align-items: center;
37+
color: #9499a0;
38+
font-size: 13px;
39+
40+
.nav-item {
41+
cursor: pointer;
42+
43+
&:hover {
44+
color: #00aeec;
45+
}
46+
47+
&:last-child::after {
48+
display: none;
49+
}
50+
&::after {
51+
content: ' ';
52+
display: inline-block;
53+
height: 10px;
54+
width: 1px;
55+
margin: -1px 12px;
56+
background-color: #9499a0;
57+
}
58+
}
59+
60+
.nav-item.active {
61+
color: #18191c;
62+
}
63+
}
64+
}
65+
}
66+
67+
.reply-wrap {
68+
position: relative;
69+
}
70+
.box-normal {
71+
display: flex;
72+
transition: 0.2s;
73+
74+
.reply-box-avatar {
75+
display: flex;
76+
align-items: center;
77+
justify-content: center;
78+
width: 80px;
79+
height: 50px;
80+
}
81+
82+
.reply-box-wrap {
83+
display: flex;
84+
position: relative;
85+
flex: 1;
86+
87+
.reply-box-textarea {
88+
width: 100%;
89+
height: 50px;
90+
padding: 5px 10px;
91+
box-sizing: border-box;
92+
color: #181931;
93+
font-family: inherit;
94+
line-height: 38px;
95+
background-color: #f1f2f3;
96+
border: 1px solid #f1f2f3;
97+
border-radius: 6px;
98+
outline: none;
99+
resize: none;
100+
transition: 0.2s;
101+
102+
&::placeholder {
103+
color: #9499a0;
104+
font-size: 12px;
105+
}
106+
&:focus {
107+
height: 60px;
108+
background-color: #fff;
109+
border-color: #c9ccd0;
110+
}
111+
}
112+
}
113+
114+
.reply-box-send {
115+
position: relative;
116+
display: flex;
117+
flex-basis: 86px;
118+
align-items: center;
119+
justify-content: center;
120+
margin-left: 10px;
121+
border-radius: 4px;
122+
cursor: pointer;
123+
transition: 0.2s;
124+
125+
& .send-text {
126+
position: absolute;
127+
z-index: 1;
128+
color: #fff;
129+
font-size: 16px;
130+
}
131+
&::after {
132+
position: absolute;
133+
width: 100%;
134+
height: 100%;
135+
background-color: #00aeec;
136+
border-radius: 4px;
137+
opacity: 0.5;
138+
content: '';
139+
}
140+
&:hover::after {
141+
opacity: 1;
142+
}
143+
}
144+
}
145+
.bili-avatar {
146+
position: relative;
147+
display: block;
148+
width: 48px;
149+
height: 48px;
150+
margin: 0;
151+
padding: 0;
152+
border-radius: 50%;
153+
}
154+
.bili-avatar-img {
155+
position: absolute;
156+
top: 50%;
157+
left: 50%;
158+
display: block;
159+
width: 48px;
160+
height: 48px;
161+
object-fit: cover;
162+
border: none;
163+
border-radius: 50%;
164+
image-rendering: -webkit-optimize-contrast;
165+
transform: translate(-50%, -50%);
166+
}
167+
168+
// 评论列表
169+
.reply-list {
170+
margin-top: 14px;
171+
}
172+
.reply-item {
173+
padding: 22px 0 0 80px;
174+
.root-reply-avatar {
175+
position: absolute;
176+
left: 0;
177+
display: flex;
178+
justify-content: center;
179+
width: 80px;
180+
cursor: pointer;
181+
}
182+
183+
.content-wrap {
184+
position: relative;
185+
flex: 1;
186+
187+
&::after {
188+
content: ' ';
189+
display: block;
190+
height: 1px;
191+
width: 100%;
192+
margin-top: 14px;
193+
background-color: #e3e5e7;
194+
}
195+
196+
.user-info {
197+
display: flex;
198+
align-items: center;
199+
margin-bottom: 4px;
200+
201+
.user-name {
202+
height: 30px;
203+
margin-right: 5px;
204+
color: #61666d;
205+
font-size: 13px;
206+
line-height: 30px;
207+
cursor: pointer;
208+
}
209+
}
210+
211+
.root-reply {
212+
position: relative;
213+
padding: 2px 0;
214+
color: #181931;
215+
font-size: 15px;
216+
line-height: 24px;
217+
.reply-info {
218+
position: relative;
219+
display: flex;
220+
align-items: center;
221+
margin-top: 2px;
222+
color: #9499a0;
223+
font-size: 13px;
224+
225+
.reply-time {
226+
width: 86px;
227+
margin-right: 20px;
228+
}
229+
.reply-like {
230+
display: flex;
231+
align-items: center;
232+
margin-right: 19px;
233+
234+
.like-icon {
235+
width: 14px;
236+
height: 14px;
237+
margin-right: 5px;
238+
color: #9499a0;
239+
background-position: -153px -25px;
240+
&:hover {
241+
background-position: -218px -25px;
242+
}
243+
}
244+
.like-icon.liked {
245+
background-position: -154px -89px;
246+
}
247+
}
248+
.reply-dislike {
249+
display: flex;
250+
align-items: center;
251+
margin-right: 19px;
252+
.dislike-icon {
253+
width: 16px;
254+
height: 16px;
255+
background-position: -153px -153px;
256+
&:hover {
257+
background-position: -217px -153px;
258+
}
259+
}
260+
.dislike-icon.disliked {
261+
background-position: -154px -217px;
262+
}
263+
}
264+
.delete-btn {
265+
cursor: pointer;
266+
&:hover {
267+
color: #00aeec;
268+
}
269+
}
270+
}
271+
}
272+
}
273+
}
274+
275+
.reply-none {
276+
height: 64px;
277+
margin-bottom: 80px;
278+
color: #99a2aa;
279+
font-size: 13px;
280+
line-height: 64px;
281+
text-align: center;
282+
}
320 KB
Loading

‎day-02/react-basic-pro/src/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom/client';
3+
import App from './App';
4+
5+
const root = ReactDOM.createRoot(document.getElementById('root'));
6+
root.render(
7+
<App/>
8+
)

‎day-02/react-basic-pro/yarn.lock

+9,996
Large diffs are not rendered by default.

‎day-02/react-basic/.gitignore

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*

‎day-02/react-basic/README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Getting Started with Create React App
2+
3+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4+
5+
## Available Scripts
6+
7+
In the project directory, you can run:
8+
9+
### `npm start`
10+
11+
Runs the app in the development mode.\
12+
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13+
14+
The page will reload when you make changes.\
15+
You may also see any lint errors in the console.
16+
17+
### `npm test`
18+
19+
Launches the test runner in the interactive watch mode.\
20+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21+
22+
### `npm run build`
23+
24+
Builds the app for production to the `build` folder.\
25+
It correctly bundles React in production mode and optimizes the build for the best performance.
26+
27+
The build is minified and the filenames include the hashes.\
28+
Your app is ready to be deployed!
29+
30+
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31+
32+
### `npm run eject`
33+
34+
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
35+
36+
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37+
38+
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39+
40+
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41+
42+
## Learn More
43+
44+
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45+
46+
To learn React, check out the [React documentation](https://reactjs.org/).
47+
48+
### Code Splitting
49+
50+
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51+
52+
### Analyzing the Bundle Size
53+
54+
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55+
56+
### Making a Progressive Web App
57+
58+
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59+
60+
### Advanced Configuration
61+
62+
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63+
64+
### Deployment
65+
66+
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67+
68+
### `npm run build` fails to minify
69+
70+
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

‎day-02/react-basic/package.json

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "react-basic",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@testing-library/jest-dom": "^5.17.0",
7+
"@testing-library/react": "^13.4.0",
8+
"@testing-library/user-event": "^13.5.0",
9+
"react": "^18.2.0",
10+
"react-dom": "^18.2.0",
11+
"react-scripts": "5.0.1",
12+
"web-vitals": "^2.1.4"
13+
},
14+
"scripts": {
15+
"start": "react-scripts start",
16+
"build": "react-scripts build",
17+
"test": "react-scripts test",
18+
"eject": "react-scripts eject"
19+
},
20+
"eslintConfig": {
21+
"extends": [
22+
"react-app",
23+
"react-app/jest"
24+
]
25+
},
26+
"browserslist": {
27+
"production": [
28+
">0.2%",
29+
"not dead",
30+
"not op_mini all"
31+
],
32+
"development": [
33+
"last 1 chrome version",
34+
"last 1 firefox version",
35+
"last 1 safari version"
36+
]
37+
}
38+
}

‎day-02/react-basic/public/favicon.ico

3.78 KB
Binary file not shown.

‎day-02/react-basic/public/index.html

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Web site created using create-react-app"
11+
/>
12+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13+
<!--
14+
manifest.json provides metadata used when your web app is installed on a
15+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16+
-->
17+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18+
<!--
19+
Notice the use of %PUBLIC_URL% in the tags above.
20+
It will be replaced with the URL of the `public` folder during the build.
21+
Only files inside the `public` folder can be referenced from the HTML.
22+
23+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24+
work correctly both with client-side routing and a non-root public URL.
25+
Learn how to configure a non-root public URL by running `npm run build`.
26+
-->
27+
<title>React App</title>
28+
</head>
29+
<body>
30+
<noscript>You need to enable JavaScript to run this app.</noscript>
31+
<div id="root"></div>
32+
<!--
33+
This HTML file is a template.
34+
If you open it directly in the browser, you will see an empty page.
35+
36+
You can add webfonts, meta tags, or analytics to this file.
37+
The build step will place the bundled scripts into the <body> tag.
38+
39+
To begin the development, run `npm start` or `yarn start`.
40+
To create a production bundle, use `npm run build` or `yarn build`.
41+
-->
42+
</body>
43+
</html>

‎day-02/react-basic/public/logo192.png

5.22 KB
Loading

‎day-02/react-basic/public/logo512.png

9.44 KB
Loading
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
},
10+
{
11+
"src": "logo192.png",
12+
"type": "image/png",
13+
"sizes": "192x192"
14+
},
15+
{
16+
"src": "logo512.png",
17+
"type": "image/png",
18+
"sizes": "512x512"
19+
}
20+
],
21+
"start_url": ".",
22+
"display": "standalone",
23+
"theme_color": "#000000",
24+
"background_color": "#ffffff"
25+
}

‎day-02/react-basic/public/robots.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://www.robotstxt.org/robotstxt.html
2+
User-agent: *
3+
Disallow:

‎day-02/react-basic/src/App.js

+271
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
import './index.css'
2+
3+
import {createContext, useContext, useEffect, useRef, useState} from 'react'
4+
5+
6+
function Son(props) {
7+
// props 是一个对象。包含了父组件传过来的所有数据
8+
console.log(props)
9+
10+
// 子组件只能读取 props,不能修改
11+
// props.name = 'rose'
12+
13+
// 特殊的 prop:children
14+
15+
return <div>this is son. {props.name}. jsx: {props.child}. children: {props.children}</div>
16+
}
17+
18+
function Son2({onGetSonMsg}) {
19+
const sonMsg = 'this is son2 msg'
20+
return (
21+
<div>
22+
this is Son2
23+
<button onClick={() => onGetSonMsg(sonMsg)}>sendMsg</button>
24+
</div>
25+
)
26+
}
27+
28+
// 1. 子传父 A -> App
29+
// 2. 父传子 App -> B
30+
31+
function A({onGetAName}) {
32+
const name = 'this is A name'
33+
return (
34+
<div>
35+
this is A component,
36+
<button onClick={() => onGetAName(name)}>send</button>
37+
</div>
38+
)
39+
}
40+
41+
function B({name}) {
42+
return (
43+
<div>
44+
this is B component,
45+
{name}
46+
</div>
47+
)
48+
}
49+
50+
// 使用 context 跨层传递数据
51+
// App -> A -> B
52+
// 1. 使用 createContext 创建 context 对象
53+
const MsgContext = createContext()
54+
55+
// 2. 在顶层组件通过 Provider 组件提供数据
56+
57+
// 3. 在底层组件通过 userContext 钩子函数使用数据
58+
59+
function A2() {
60+
return (
61+
<div>
62+
this is A2 component
63+
<B2 />
64+
</div>
65+
)
66+
}
67+
68+
function B2() {
69+
const msg = useContext(MsgContext)
70+
return (
71+
<div>
72+
this is B2 component, {msg}
73+
</div>
74+
)
75+
}
76+
77+
// useEffect 基础使用
78+
const URL = 'https://geek.itheima.net/v1_0/channels'
79+
80+
function Son3() {
81+
// 1. 渲染时开启一个定时器
82+
useEffect(() => {
83+
const timer = setInterval(() => {
84+
console.log('定时器执行中')
85+
}, 1000)
86+
87+
return () => {
88+
clearInterval(timer)
89+
}
90+
}, [])
91+
return <div>this is son3</div>
92+
}
93+
94+
// 自定义 hook
95+
// 思路:
96+
// 1. 声明以 use 打头的函数
97+
// 2. 在函数体内封装可复用的逻辑
98+
// 3. 把组件中用到的状态或者回调 return 出去
99+
// 4. 在组件中执行自定义 hook,获取 return 的状态和回调进行使用
100+
function useToggle() {
101+
// 可复用的逻辑代码
102+
const [value, setValue] = useState(true)
103+
const toggle = () => setValue(!value)
104+
105+
// 哪些状态和回调函数需要在其他组件中使用就 return
106+
return {
107+
value,
108+
toggle
109+
}
110+
}
111+
112+
// ReactHooks 使用规则
113+
// 1. 只能在组件中或其他自定义 hook 函数中使用
114+
// const[show, setShow] = useState(true) // 错误:组件外使用
115+
// 2. 只能在组件的顶层调用,不能嵌套在 if, for 或其他函数中
116+
117+
function App() {
118+
// if (Math.random() > 0.5) {
119+
// const [show, setShow] = useState(true) // 错误:if 中使用
120+
// }
121+
122+
const [inputValue, setInputValue] = useState('')
123+
124+
// 获取 DOM
125+
// 1. 使用 useRef 创建一个 ref 对象
126+
const inputRef = useRef(null);
127+
// 2. DOM 可用时, ref.current 获取 DOM
128+
// 渲染完毕后 DOM 生成后才可用
129+
const showDom = () => {
130+
console.dir(inputRef.current)
131+
}
132+
133+
const name = 'this is app name'
134+
135+
// 子传父
136+
const [msg, setMsg] = useState('')
137+
const getMsg = (msg) => {
138+
console.log(msg)
139+
setMsg(msg)
140+
}
141+
142+
const [aName, setAName] = useState('')
143+
const getAName = (name) => {
144+
console.log(name)
145+
setAName(name)
146+
}
147+
148+
const msg2 = 'this is app msg2'
149+
150+
// useEffect 基础使用
151+
// 创建一个状态
152+
const [list, setList] = useState([])
153+
useEffect(() => {
154+
// 获取频道列表
155+
async function getList() {
156+
const res = await fetch(URL)
157+
const jsonRes = await res.json()
158+
console.log(jsonRes)
159+
setList(jsonRes.data.channels)
160+
}
161+
162+
getList()
163+
}, [])
164+
165+
// 1. 没有依赖项,执行时机:初始 + 组件更新
166+
const [count, setCount] = useState(0)
167+
// useEffect(() => {
168+
// console.log('副作用函数执行了')
169+
// })
170+
171+
// 2. 传入空数组依赖,执行时机:初始
172+
// useEffect(() => {
173+
// console.log('副作用函数执行了')
174+
// }, [])
175+
176+
// 3. 传入特定依赖项,执行时机:初始 + 依赖项变化
177+
useEffect(() => {
178+
console.log('副作用函数执行了')
179+
}, [count])
180+
181+
// 通过条件渲染模拟组件卸载
182+
const [show, setShow] = useState(true)
183+
184+
// 封装自定义 hook
185+
// 存在问题:bool 切换逻辑和当前组件耦合在一起,不能复用
186+
// const [value, setValue] = useState(true)
187+
// const toggle = () => setValue(!value)
188+
// 解决思路:自定义篇 hook
189+
const {value, toggle} = useToggle()
190+
191+
return (
192+
<div className="App">
193+
{/*表单受控绑定*/}
194+
<div>
195+
<input
196+
value={inputValue}
197+
onChange={(e) => setInputValue(e.target.value)} />
198+
</div>
199+
200+
{/*获取 DOM*/}
201+
<div>
202+
<input type="text" ref={inputRef} />
203+
<button onClick={showDom}>获取 DOM</button>
204+
</div>
205+
206+
{/*组件通信*/}
207+
{/*父传子*/}
208+
<div>
209+
<Son
210+
name={name}
211+
age={18}
212+
isTrue={false}
213+
list={['vue', 'react']}
214+
obj={{name: 'jack'}}
215+
cb={() => console.log(123)}
216+
child={<span>this is span</span>}
217+
/>
218+
<Son><span>props.children</span></Son>
219+
</div>
220+
221+
{/*子传父*/}
222+
<div>
223+
this is app, msg: {msg}
224+
<Son2 onGetSonMsg={getMsg} />
225+
</div>
226+
227+
{/*状态提升实现兄弟组件的通信*/}
228+
<div>
229+
this is App
230+
<A onGetAName={getAName} />
231+
<B name={aName} />
232+
</div>
233+
234+
{/*使用 context 跨层传递数据*/}
235+
<div>
236+
< MsgContext.Provider value={msg2}>
237+
this is App
238+
<A2 />
239+
</MsgContext.Provider>
240+
</div>
241+
242+
{/*useEffect 基础使用*/}
243+
<div>
244+
<br />
245+
this is App
246+
<ul>
247+
{list.map(item => <li key={item.id}>{item.name}</li>)}
248+
</ul>
249+
</div>
250+
251+
{/*useEffect 不同依赖项说明*/}
252+
<div>
253+
this is App <button onClick={() => setCount(count + 1)}>+{count}</button>
254+
</div>
255+
256+
{/*useEffect 清除副作用*/}
257+
<div>
258+
{show && <Son3 />}
259+
<button onClick={() => setShow(false)}>卸载 son3 组件</button>
260+
</div>
261+
262+
{/*封装自定义hook*/}
263+
<div>
264+
{value && <div>封装自定义 hook</div>}
265+
<button onClick={toggle}>toggle</button>
266+
</div>
267+
</div>
268+
)
269+
}
270+
271+
export default App

‎day-02/react-basic/src/index.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.foo {
2+
color: blue;
3+
}

‎day-02/react-basic/src/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// 项目入口
2+
3+
// 导入核心包
4+
import React from 'react';
5+
import ReactDOM from 'react-dom/client';
6+
7+
// 导入根组件
8+
import App from './App';
9+
10+
// 把 App 根组件渲染到 id 为 root 的 dom 节点上
11+
const root = ReactDOM.createRoot(document.getElementById('root'));
12+
root.render(<App/>)

‎day-02/react-basic/yarn.lock

+9,714
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.