🟡React基础

本文最后更新于:2022年9月6日 晚上

项目初始化

使用vite快速生成React18项目

1
2
3
pnpm create vite

> react

快速开始

src目录新建main.jsx作为入口

src/main.jsx

1
2
3
4
5
6
7
import { createRoot } from "react-dom/client";

// 创建根元素
const root = createRoot(document.getElementById("root"));

// 在根元素渲染
root.render(<h1>🎉Hello React</h1>);

组件

src新建components文件夹存放组件

components文件夹新建Hello文件夹封装<h1>🎉Hello React</h1>

src/components/Hello/index.jsx

1
2
3
4
5
function Hello () {
return (<h1>🎉Hello React</h1>)
}

export { Hello }

src/main.jsx

1
2
3
4
5
6
7
8
9
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Hello } from './components/Hello'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Hello />
</StrictMode>
)

JSX

src/components/JSX.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function JSX () {
const Article = {
title: '## JSX',
content: 'JSX是一个JavaScript XML扩展'
}

const nowTime = () => new Date().toLocaleString()

return (
<div>
<h2>{Article.title}</h2>
<p>{Article.content}</p>
<time>{nowTime()}</time>
</div>
)
}

export { JSX }

src/main.jsx

1
2
3
4
5
6
7
8
9
/* 省略部分模块导入 */
import { JSX } from './components/JSX'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Hello />
<JSX />
</StrictMode>
)

CSS样式

className

可使用className(即HTML标签的class)属性为组件添加CSS样式

src/components/CssClass/index.css

1
2
3
4
5
6
7
8
9
10
11
12
.content {
color: #4ebe54;
font-weight: 600;
}

.content>.red {
color: #ff6262;
}

.content>.blue {
color: #125dff;
}

src/components/CssClass/index.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import './index.css'

function CssClass() {
const color = 'blue'

return (
<div>
<h2>## ClassName</h2>
<p className="content">
<span className="red">红色</span>
<span className={color}>蓝色</span>
<span>绿色</span>
</p>
</div>
)
}

export { CssClass }

src/main.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Hello } from './components/Hello'
import { CssClass } from './components/CssClass'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Hello />
<!-- 演示CSS作用域 -->
<p className="content">外部content样式</p>
<CssClass />
</StrictMode>
)

可以看到组件的CSS会作用到全局,若class名称相同就会很麻烦

style内联

使用内联的CSS可避免样式的污染

src/components/CssStyle/index.jsx

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
function CssStyle () {
const color = 'blue'

const styles = {
content: {
color: '#4ebe54',
fontWeight: '600',
},
red: {
color: '#ff6262',
},
blue: {
color: '#125dff',
},
}

return (
<div>
<h2>## CSS Style</h2>
<p style={styles.content}>
<span style={styles.red}>红色</span>
<span style={styles[color]}>蓝色</span>
<span>绿色</span>
</p>
</div>
)
}

export { CssStyle }

React官方不推荐使用内联样式,并且写内联CSS可能没有语法提示,效率较低

CSS modules

使用打包工具为CSS自动配置一个哈希值来模拟一个私有CSS

使用vite可方便的配置CSS modules

vite.config.js

1
2
3
4
5
6
7
8
9
// ...

export default defineConfig({
// ...
css: {
modules: true,
}
})

src/components/CssModules/index.module.css

1
2
3
4
5
6
7
8
9
10
11
12
.content {
color: #4ebe54;
font-weight: 600;
}

.content>.red {
color: #ff6262;
}

.content>.blue {
color: #125dff;
}

src/components/CssModuls/index.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import styles from './index.module.css'

function CssModule() {
console.log(styles)
const color = 'blue'

return (
<div>
<h2>## CSS Modules</h2>
<p className={styles.content}>
<span className={styles.red}>红色</span>
<span className={styles[color]}>蓝色</span>
<span>绿色</span>
</p>
</div>
)
}

export { CssModule }

组件传参

函数组件可接收一个对象(Object),其含有传递给组件的参数

src/components/Props/index.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Props(props) {
return (
<div>
<h2>## Props</h2>
<p>
{props.name} is
<time> {props.age} </time>
year old.
</p>
</div>
);
}

export { Props };

src/main.jsx

1
2
3
4
5
6
7
8
9
/* 省略部分模块导入 */
import { Props } from './components/Props'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Hello />
<Props name="Jonathan" age="20" />
</StrictMode>
)

State

Reactstate类似vue中的reactive

若要实现一个计数器组件,使用下面的写法时,count值在按钮点击时会改变,但DOM实例并没有更新.

若我们在触发count值改变后手动render组件则可以改变DOM实例.

src/components/State/index.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Counter() {
let count = 1;

const setCounte = () => {
count++;
console.log(count);
};

return (
<div>
<h2>## State</h2>
<p>{count}</p>
<button onClick={setCounte}>+</button>
</div>
);
}

export { Counter };

state就是用于在值变化后自动render的,计数器组件可改写为如下形式,

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
import { useState } from 'react'

function Counter() {
const [count, setCount] = useState(1);
/**
* useState()返回一个长度为2的数组
* 第一个值为useState的传入值
* 第二个值为一个方法用于改变传入值(通常把该方法以set为前缀命名)
*/

/**
* ❌
*/
// const setCounte = () => {
// setCount(count + 1);
// };

/**
* ✔️回调方式确保state不会使用旧值(异步)
*/
const setCounte = () => {
setCount((preCount) => {
preCount + 1
})
}

return (
<div>
<h2>## State</h2>
<p>{count}</p>
<button onClick={setCounte}>+</button>
</div>
);
}

export { Counter };
  • setState()为异步执行
  • setState()diff算法优化,当值不同时才会重新刷新
  • 推荐使用回调函数方式设置state

获取原生DOM元素

可以直接使用document的原生方法获取DOM但效率不高.

useRef()函数可返回一个

1
2
3
4
5
6
7
8
9
import { useRef } from 'react'

function GetDom() {
const domH2 = useRef()

return (
<h2 ref={ domH2 }>Ref</h1>
)
}

🟡React基础
https://qingshaner.com/React基础/
作者
清山
发布于
2022年1月24日
许可协议