React新起点(一)

1. 简介

React是一个JavaScript库,用于构建交互式网站,并且能够快捷创建SPA(Single Page App)

2. 起步

使用命令创建项目

1
npx create-react-app little-blog

在项目目录中找到package.json文件,使用其中的start脚本进行预览

在终端中输入npm run start之执行该脚本

node_moudles/目录下的内容通常是项目所需的依赖,如果clone的项目中没有,可以通过运行npm install,使系统根据项目当中的package.json文件下载

3. React 组件

1
2
3
4
5
6
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

目前在index.js当中只有App这个组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}

对应于App组件的代码便是这个App(),其返回的类似于HTML的结构被称为jsx,最终通过babel将jsx编写的内容转换为对应的HTML

jsx与HTML最大的区别在于添加class到元素的方式,在jsx当中,使用className属性,因为class被JavaScript使用了,在jsx被转换为HTML时,className属性会被转为class

image-20230604153452459

另外,由于当前使用的是18的版本,不需要在js文件顶部导入react,如果低于17版本可能需要显式import

image-20230604153638848 image-20230604153742013

接下来,清理掉<div>里面的内容,自己进行内容的编写

1
2
3
4
5
6
7
function App() {
return (
<div className="App">
{/* 添加内容 */}
</div>
);
}
1
2
3
4
5
6
7
8
9
function App() {
return (
<div className="App">
<div className='content'>
<h1>新起点</h1>
</div>
</div>
);
}
image-20230604154523196

添加一个标题,然后保存修改,进行页面的本地预览

4. 动态值

使用{}在jsx的模板中可以输出js定义的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function App() {

const title = 'Welcome to My New Blog!'; // 定义
const likes = 100;

return (
<div className="App">
<div className='content'>
<h1>{ title }</h1> // 对应js的常量
<p>点赞:{likes}</p>
</div>
</div>
);
}

js定义的各种类型在输出时react都会转换为string,布尔和对象除外

image-20230604161148796

使用{}在标签的属性中也可以使用动态值,以便于逻辑的需要进行动态的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function App() {

const title = 'Welcome to My New Blog!';
const likes = 100;
const link = "https://wwww.baidu.com"

return (
<div className="App">
<div className='content'>
<h1>{ title }</h1>
<p>点赞:{ likes }</p>
<a href={ link }>百度</a>
</div>
</div>
);
}
image-20230604161441209 image-20230604161521049

5. 多个组件组合

app.js默认情况下在组件树的最顶端,作为根组件

image-20230604165000605

创建另一个组件Navbar,新建一个Navbar.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const Navbar = () => {
return (
<nav className="navbar">
<h1>Little Blog</h1>
<div className="links">
<a href="/">Home</a>
|
<a href="/new">New</a>
</div>
</nav>
);
}

export default Navbar;

编写完成后,将组件引入到App.js,嵌入到原本的jsx模板当中

1
import Navbar from './Navbar';    // 在顶部引入组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function App() {

const title = 'Welcome to My New Blog!';
const likes = 100;
const link = "https://wwww.baidu.com"

return (
<div className="App">
<Navbar />
<div className='content'>
<h1>{ title }</h1>
<p>点赞:{ likes }</p>
<a href={ link }>百度</a>
</div>
</div>
);
}

使用<Navbar />使用组件

image-20230604170305857 image-20230604170352720

接下来,把原来<App />当中的内容再抽出来,用<Home />替换,再创建一个Home.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Home = () => {

const title = 'Welcome to My New Blog!';
const likes = 100;
const link = "https://wwww.baidu.com"

return (
<div className="home">
<h1>{title}</h1>
<p>点赞:{likes}</p>
<a href={link}>百度</a>
</div>
);
}

export default Home;
1
import Home from './Home';
1
2
3
4
5
6
7
8
9
10
11
function App() {

return (
<div className="App">
<Navbar />
<div className='content'>
<Home />
</div>
</div>
);
}

按照同样的步骤将<Home />加入,替换原来<div>当中的内容,使用<div>将页面划分一个个组件

image-20230604171937781

6. 增加样式

image-20230623230319187

App.js本身引入一个CSS样式文件,并且这份应用于根组件的样式文件会作用于所有组件,因为React会把所有的样式加入到网页文件的<head>当中

image-20230623230644354 image-20230623230843075

浏览器显示的<head>当中的样式与App.css当中的样式正好对应

我们需要为组件设置各自的样式,因此先将App.css文件删除,使用index.css加入一些基础的样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@import url(//fonts.googleapis.com/css?family=Quicksand:400,700);

* {
margin: 0;
font-family: "Quicksand";
color: #333;
}

.navbar {
padding: 20px;
display: flex;
align-items: center;
max-width: 600px;
margin: 0 auto;
border-bottom: #f2f2f2;
}

.navbar h1 {
color: #7d7dd9;
}

.navbar .links {
margin-left: auto;
}

.navbar a {
margin-left: 16px;
text-decoration: none;
padding: 6px;
}

.navbar a:hover {
color: #7d7dd9;
}

.content {
max-width: 600px;
margin: 40px auto;
padding: 20px;
}
image-20230624112831140

如果想要使用内联样式表,可以添加在组件中添加{}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Navbar = () => {
return (
<nav className="navbar">
<h1>Little Blog</h1>
<div className="links">
<a href="/">Home</a>
|
<a href="/new"
style={{
color: '#ff0000',
fontFamily: "monospace"
}}>New</a>
</div>
</nav>
);
}

内联样式表使用的是style属性,通过{}在后面加入JSX语法中的值,而里面另一层{}代表这个样式内容是一个JS对象,因为CSS样式本身是键值对的形式,属性的名称便是key,而属性的值就是对应的value

image-20230624114008979

7. 添加点击事件

先在页面上添加一个按钮,使用<button>

image-20230624135302214

接下来定义一个事件

1
2
3
const handleClick = () => {
console.log("执行点击");
}

将事件绑定到按钮上

1
<button onClick={handleClick}>点一下,玩一年</button>

image-20230624141852308

执行点击会进行事件的调用

如果需要传值,我们可以将函数名更换为箭头函数

1
<button onClick={() => handleClick()}>点一下,玩一年</button>

事件对象会自动作为函数的第一个参数

1
<button onClick={(e) => handleClick(e)}>点一下,玩一年</button>
1
2
3
const handleClick = (e) => {
console.log("执行点击", e);
}

添加一个参数e,用于接收事件参数,并将其打印到控制台当中

image-20230624155607671

image-20230624155631186

如果不使用箭头函数,也可以直接使用函数获取,并且直接通过事件对象去访问其内部的属性

8. 使用状态(useState hook)

直接使用语句进行变量的修改并不会使页面重新渲染,如果需要动态进行修改,并且触发重新渲染,需要用到useState

useState从react库中引入

1
import { useState } from "react";

首先,需要对需要进行更新的变量进行初始化

1
const [name, setName] = useState('Hugo');

这里的第一个参数name是变量名,初始值是"Hugo",用于更新它的值的setter是setName

1
2
3
const handleClick = (e) => {
setName('Michael'); // 更新值
}
image-20230624164103394

image-20230624164210031

image-20230624164229220

通过点击事件调用setName更新值,同时触发页面进行重新渲染,最终,在页面展示的就是内容发生了更改