0%

react学习笔记

React:一个javascript库,DOM的一个抽象层
JSX:React的语法糖
react bootstrap:react版的bootstrap
formik:Form辅助库,Helper
redux:组件间状态变化时的处理中心
route:处理路由

初步了解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
https://zh-hans.reactjs.org/docs/create-a-new-react-app.html#create-react-app

npx create-react-app learn_react_bootstrap
cd learn_react_bootstrap
npm start

入门文档:https://zh-hans.reactjs.org/docs/hello-world.html

https://zh-hans.reactjs.org/tutorial/tutorial.html

react bootstrap库:
https://react-bootstrap.github.io/getting-started/introduction/
npm install react-bootstrap bootstrap


formik:https://formik.org/docs/tutorial

redux:https://www.reduxjs.cn/introduction/getting-started

react-router:https://reactrouter.com/web/guides/quick-start

React中一些基础概念

元素渲染

React库会维护一个JS的虚拟DOM对象,并由React DOM模块负责让网页的DOM和虚拟DOM保持一致。
使用ReactDOM.render()方法可以将元素渲染到DOM树。

例子:

1
2
3
4
5
6
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';

const element = <h1>Hello</h1>;
ReactDOM.render(element, document.getElementById('root'));

组件

把代码封装为方法,可在多处复用,可传参。
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';

class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

class User extends React.Component {
render() {
return <Welcome name="Zjs" />
}
}

ReactDOM.render(<User />, document.getElementById('root'));

动态更新组件内的参数值

组件生命周期有三种状态,1. mounting(安装) 2.updating(更新) 3. unmounting (卸载)
每种状态分别有类似构造和析构的函数,will和did,进入状态前调用will,进入状态后调用did。

默认的组件就是render之后就完事了,想要动态更新就不行,如果想要动态更新(比如ajax)就要借助 this.state,组件内使用this.state的值,而this.state的值变化后,组件所使用的this.state值也会变,DOM就会重新渲染变化的值。

例子:

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
41
42
43
44
45
46
47
48
49
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Container, Row, Col } from 'react-bootstrap';

class TimeExample extends React.Component {

// 组件构造函数,组件创建时被调用
constructor(props) {
super(props); // 继承父类this对象,因为要使用this.state
this.state = {
date: new Date()
};
console.log('init TimeExample');
}

// 组件挂载之后调用
componentDidMount() {
// setInterval 函数的作用是周期性调用一个函数,相当于一个定时器
// 将定时器的ID保存在this的变量中

// 可以理解为这里执行一个ajax,将返回值更新到this.state内,那么组件就可以从this.state内读取动态更新的值并更新DOM
this.LoopID = setInterval(
() => {
this.setState({
date: new Date()
});
console.log(this.state);
},
1000
);
}

// 组件被卸载的时候调用,比如被close,被remove
componentWillUnmount() {
// 清除定时器
clearInterval(this.LoopID);
}

render() {
return (
<div>
<h2>Now: {this.state.date.toLocaleTimeString()}</h2>
</div>
);
}
}

ReactDOM.render(<TimeExample />, document.getElementById('root'));

事件

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Modal, closeButton, Col } from 'react-bootstrap';

class ClickExample extends React.Component {

// 构造方法,在state存储值
constructor(props) {
super(props);
this.state = {
modal_show: false
}
}

// 点击后改变state内的值,联动改变DOM
clickMe() {
this.setState({
modal_show: true
})
// alert();
}

// 隐藏
handleClose() {
this.setState({
modal_show: false
})
}

// 使用react bootstrap的Button、Modal
render() {
return (
<>
<Button variant="success" onClick={() => this.clickMe()}>绑定事件</Button>
<Modal show={this.state.modal_show}
onHide={() => {
this.handleClose();
}}
>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>react bootstrap modal</Modal.Body>
<Modal.Footer>
<Button
variant="secondary"
onClick={() => {
this.handleClose();
}}
>
Close
</Button>
</Modal.Footer>
</Modal>
</ >
)
}
}

ReactDOM.render(<ClickExample />, document.getElementById('root'));

if判断

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Modal, closeButton, Col } from 'react-bootstrap';

class ClickExample extends React.Component {

// 构造方法,在state存储值
constructor(props) {
super(props);
this.state = {
login_status: false // true-已登录 false-未登录
}
}

login() {
this.setState({
login_status: true
})
}

logout() {
this.setState({
login_status: false
})
}

render() {
const login_status = this.state.login_status;
// let buttons;
// if (login_status) {
// buttons = <Button variant="success" onClick={() => {
// this.logout();
// }}>退出登录</Button>
// } else {
// buttons = <Button variant="success" onClick={() => {
// this.login();
// }}>登录</Button>
// }
return (
<>
{this.state.login_status
?
<Button variant="success" onClick={() => {
this.logout();
}}>退出登录</Button>
:
<Button variant="success" onClick={() => {
this.login();
}}>登录</Button>
}
</ >
)
}
}

ReactDOM.render(<ClickExample />, document.getElementById('root'));

数据渲染

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Table } from 'react-bootstrap';

import './index.css';
/*
.table {
width: 50%;
margin: 0 auto;
margin-top: 5%;
}
*/

class Menu extends React.Component {

constructor(props) {
super(props);
this.state = {
data: []
};
}

componentDidMount() {
// ajax init data
this.setState({
data: [
{
'id': 1,
'firstname': 'jun',
'lastname': 'zhang',
},
{
'id': 5,
'firstname': 'jun2',
'lastname': 'zhang2',
},
{
'id': 3,
'firstname': 'jun3',
'lastname': 'zhang3',
},
]
});
}

render() {
const listItems = this.state.data.map((data) =>
<tr>
<td>{data.id}</td>
<td>{data.firstname}</td>
<td>{data.lastname}</td>
<td>{data.firstname}.{data.lastname}</td>
</tr>
);
return (
<>
<Table striped bordered hover className="table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</Table>
</ >
)
}
}

ReactDOM.render(<Menu />, document.getElementById('root'));

表单处理

使用formik这个form处理库
npm install formik
https://formik.org/docs/tutorial#installation

使用yup做字段规则 校验
npm install yup
https://github.com/jquense/yup

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { InputGroup, Col, Button, Form } from 'react-bootstrap';
import './index.css';
import { Formik } from "formik";
import * as yup from "yup";

const schema = yup.object().shape({
username: yup.string().required('请填写用户名'),
terms: yup.bool().required().oneOf([true], '请先阅读并同意协议'),
});

function FormExample() {

function submitForm(values) {
console.log('ajax 提交数据');
console.log(values);
}

return (
<Formik
validationSchema={schema}
onSubmit={(values) => { submitForm(values) }}
initialValues={{
username: '',
terms: false,
}}
>
{({
handleSubmit,
handleChange,
handleBlur,
values,
touched,
isValid,
errors,
}) => (
<Form noValidate onSubmit={handleSubmit}>
<Form.Row>
<Form.Group as={Col} md="6" controlId="validationFormik03">
<Form.Label>用户名</Form.Label>
<Form.Control
type="text"
placeholder="username"
name="username"
value={values.username}
onChange={handleChange}
isInvalid={!!errors.username}
/>
<Form.Control.Feedback type="invalid">
{errors.username}
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
<Form.Group>
<Form.Check
required
name="terms"
label="我已认真阅读并同意协议"
onChange={handleChange}
isInvalid={!!errors.terms}
feedback={errors.terms}
id="validationFormik0"
/>
</Form.Group>
<Button type="submit">提交</Button>
</Form>
)}
</Formik>
);
}

ReactDOM.render(<FormExample />, document.getElementById('root'));

组件间共享父类的 state

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
41
42
43
44
45
46
47
48
49
50
51
52
53
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { InputGroup, Col, Button, Form } from 'react-bootstrap';
import './index.css';

class CheckRate extends React.Component {
render() {
return (
<>
{this.props.number > 6.5 ?
<span>汇率高</span>
:
<span>汇率低</span>}
</>
);
};

}

class Rate extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
input_rate: ''
};
}

handleChange(e) {
this.setState({
input_rate: e.target.value
});
}

render() {
const input_rate = this.state.input_rate;

return (
<>
<h2>汇率检测器,输入一个浮点值以检测汇率高低.</h2>
<span>输入汇率:</span>
<input
value={input_rate}
onChange={this.handleChange} />
<CheckRate
number={input_rate} />
</>
);
}
}

ReactDOM.render(<Rate />, document.getElementById('root'));

ajax

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
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';

class Rate extends React.Component {

// 组件挂载后
componentDidMount() {
fetch("http://api.apishop.net/common/hearthStone/queryCardListByKeyword")
.then(res => res.json())
.then(
(result) => {
console.log(result);
},
(error) => {
console.log("error");
console.log(error);
}
)
}

render() {
return (
<>
</>
);
}
}

ReactDOM.render(<Rate />, document.getElementById('root'));

redux

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
41
42
43
44
45
npm install redux


import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';

// 计数器
function counter(state = 0, action) {
switch (action.type) {
case 'ADD':
return state + 1;
break;

case 'DEL':
return state - 1;
break;
default:
return state;
break;
}
}

// 创建一个状态对象
let store = createStore(counter);

// 注册监听器,在状态改变时做对应处理
store.subscribe(
() => {
console.log(store.getState())
}
);

// 更新state
store.dispatch({
type: 'ADD'
});

store.dispatch({
type: 'ADD'
});

store.dispatch({
type: 'DEL'
});

https://tech.meituan.com/2017/07/14/redux-design-code.html

route

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
npm install react-router-dom


import React from 'react';
import reactDom from 'react-dom';
import {
BrowserRouter as Router,
Switch,
Route,
Link,
BrowserRouter
} from "react-router-dom";

function Home() {
return (
<h2>首页</h2>
);
}

function About() {
return (
<h2>关于我们</h2>
);
}

function Links() {
return (
<h2>友情链接</h2>
);
}

export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/links">Links</Link>
</li>
</ul>
</nav>

<Switch>
<Router exact path="/">
<Home />
</Router>
<Router path="/about">
<About />
</Router>
<Router path="/links">
<Links />
</Router>
</Switch>
</div>
</Router>
);
}

reactDom.render(<App />, document.getElementById('root'));

欢迎关注我的其它发布渠道