React学习笔记

本文主要为react的学习笔记,基于react文档

React学习笔记

JSX简介

基本用法:使用{},在大括号中放入任何有效的JavaScript表达式。

1
2
const name = 'a';
const element = <h1>Hello {name}</h1>;

或者诸如2+2user.firstNameformatName(user)等表达方法。

JSX本身也是表达式,转为普通的JS函数调用,取值后得到JS对象。可以在iffor中使用JSX,当参数传入,以及返回JSX。

1
2
3
4
5
6
function getGreeting(user){
if(user){
return <h1>Hello,{formatName(user)}</h1>;
}
return <h1>Hello Stranger</h1>;
}

和html类似,可以使用属性或者在属性值用大括号插入js表达式(注意,不要引号,引号和大括号只有一个)。

1
const elem = <img src={user.avatarUrl}></img>

JSX可以防范XSS注入,会进行转义,所以不用担心。

1
2
const title = response.potentiallyMaliciousInput;
const elem = <h1>{title}</h1>;

在使用中,Babel会将JSX转译为React.createElement()函数调用,转化为基本的React元素。

元素渲染

元素是构成React应用的最小砖块,描述了屏幕上看到的内容。开销不大。

将React元素渲染倒根DOM节点,只需要一起传入ReactDOM.render()中:

1
2
const elem = <h1>hello world</h1>;
ReactDOM.render(element,document.getElementById('root'));

React元素为不可变对象,更新UI的唯一的方式是创建全新的元素,并且传入ReactDOM.render()

1
2
3
4
5
6
7
8
9
10
function tick(){
const elem = (
<div>
<h1>hello world</h1>
<h2>It is {new Date().toLocaleTimeString()}</h2>
</div>
);
ReactDom.render(elem,document.getElemById('root'));
}
setInterval(tick, 1000);

但在实践中,只调用以此ReactDOM.render(),注意这点。

ReactDOM会将元素以及子元素与之前的状态进行比较,只进行最小的更新。

组件与Props

可以用JS函数或者ES6的类来定义组件,接收props(属性),返回React元素。如下两种方法是等效的:

1
2
3
4
5
6
7
8
9
function Welcome(props){
return <h1>hello {props.name}</h1>;
}

class Welcome extends React.Compoent {
render(){
return <h1>hello {this.props.name}</h1>;
}
}

在使用中,组件可以是react元素:

1
const elem = <Welcome name='2'/>

当React元素为用户子当以自建时候,JSX所接收的属性以及子组件会转化为单个对象props传递给组件。

组件名字必须大写字母开头,小写字母被认为是原生DOM标签。

props是只读的,这意味着不改变入参,有着纯函数性质。

State与生命周期

state与props类似,但state是私有的,并且完全受控于当前组件。

class组件应当始终使用props参数调用父类的构造函数。在构造函数中,state被赋初值。,使用setState进行更改。

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
class Clock extends React.Component{
//构造函数 初始化
constructor(props){
super(props);
this.state = {
date: new Date(),
};
}

//更新函数
tick(){
this.setState({date: new Date()});
}

//生命周期方法,在渲染到DOM中后运行
componentDidMount(){
this.timerID = setInterval(
()=>this.tick(),1000
);
}

//清除计时器
componentWillUnmount(){
clearInterval(this.timerID);
}

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

function App() {
return (
<div>
<Clock/>
<Clock/>
<Clock/>
</div>
);
}

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

<Clock/>被传给ReactDOM后,会调用构造函数,初始化state,之后调用render方法,渲染输出,然后调用ComponentDidMount()方法向浏览器请求设置计时器,每秒调用tick()方法,tick()使用setState()更新,React便会更新DOM。组件被移除后,调用componentWillUnmount()方法卸除计时器。

不要直接修改state,这样不会重新渲染组件。只能在构造函数赋值。

state和props可能异步更新,可以用在setState()中传函数解决,如下所示:

1
2
3
4
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));

state的更新可能被合并。

state可以作为props向下传递。

事件处理

事件采用小驼峰方法命名,使用JSX的时候传入函数。必须显式采用preventDefault来阻止默认行为。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}

return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}

e是一个合成事件。

在初始化时候应当绑定this,作为js特性,避免锅。

条件渲染

使用if-else或逻辑运算符来控制渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}

return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}

如果不想渲染,可以直接返回null。

1
2
3
4
function WarningBanner(props) {
if (!props.warn) {
return null;
}

注意,生命周期方法还是会调用。

列表和key

使用map()方法将数组映射成<li></li>,记得在映射的时候指定key值,用于辨析元素是否改变,添加,删除。

1
2
3
4
5
6
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);

key应当独一无二,用于标识。不建议用索引来当key值,但这是默认做法。

key在兄弟结点中必须唯一,但全局不一定唯一。

表单

可以用onChange传入函数来控制组件维护的state

Author

王钦砚

Posted on

2021-01-24

Licensed under

CC BY-NC-SA 4.0

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×