概念
# 概念
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
挂载和卸载
当组件第一次加载到 DOM 中的时候,这在 React 中被称为挂载。
同样,每当组件生成的这个 DOM 被移除的时候,这在 React 中被称为卸载。
组件各自隔离
function App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); } // 每个 Clock 组件都建立了自己的定时器并且独立更新。
1
2
3
4
5
6
7
8
9
10数据传递
有两种方法
props
和state
props
用于传递不可变数据state
可以根据与用户交互来改变写法
函数组件统一使用形参props接受数据
点击查看
function HelloMessage(props) { return <h1>Hello {props.name}!</h1>; } const element = <HelloMessage name="Runoob"/>; ReactDOM.render( element, document.getElementById('example') );
1
2
3
4
5
6
7
8
9
10可以设置默认属性
defaultProps
点击查看
class HelloMessage extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } HelloMessage.defaultProps = { name: 'Runoob' }; const element = <HelloMessage/>; ReactDOM.render( element, document.getElementById('example') );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18在父组件中使用
state
,子组件中接受props
点击查看
class WebSite extends React.Component { constructor() { super(); this.state = { name: "菜鸟教程", site: "https://www.runoob.com" } } render() { return ( <div> <Name name={this.state.name} /> <Link site={this.state.site} /> </div> ); } } class Name extends React.Component { render() { return ( <h1>{this.props.name}</h1> ); } } class Link extends React.Component { render() { return ( <a href={this.props.site}> {this.props.site} </a> ); } } ReactDOM.render( <WebSite />, document.getElementById('example') );
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
React事件处理
驼峰写法
点击查看
最容易写错的就是
onClick
<button onClick={activateLasers}> 激活按钮 </button>
1
2
3阻止默认行为:
e.preventDefault();
如果要用ES6类来写的话需要注意
在构造函数中,使用
this.state
创建必要的变量环境在构造函数中,使用
this.handleClick = this.handleClick.bind(this)
修改指针因为
<button onClick={this.handleClick}>
触发时,this指向button对象,而非定义的ES6环境,如果没有这句,this的值是undefined。替代
bind
的做法属性初始化器来正确的绑定回调函数:
class LoggingButton extends React.Component { // 这个语法确保了 `this` 绑定在 handleClick 中 // 这里只是一个测试 handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14传递回调函数
render() { // 这个语法确保了 `this` 绑定在 handleClick 中 return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> );
1
2
3
4
5
6
7使用这个语法有个问题就是每次 LoggingButton 渲染的时候都会创建一个不同的回调函数。在大多数情况下,这没有问题。然而如果这个回调函数作为一个属性值传入低阶组件,这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中绑定或使用属性初始化器语法来避免这类性能问题。
向事件中传参
// 替换bind方法2: 使用回调函数 <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> // bind方法 <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
1
2
3
4
条件渲染
React 中的条件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素
if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />;
1
2
3
4使用元素进行驱动,核心使用
this.setState
... handleLoginClick() { this.setState({isLoggedIn: true}); } handleLogoutClick() { this.setState({isLoggedIn: false}); } render() { const isLoggedIn = this.state.isLoggedIn; let button = null; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19技巧:使用
&&
关键代码:
<h1>Hello!</h1> {unreadMessages.length > 0 && <h2> 您有 {unreadMessages.length} 条未读信息。 </h2> } // 在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。 // 因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
1
2
3
4
5
6
7
8
9技巧:三元表达式
condition ? true : false。
快速创建列表
map 方法,前提必须要给一个key
const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> );
1
2
3
4
5
6
7
8key最好使用数据的id,在数据没有id时,使用序列号索引
const todoItems = todos.map((todo, index) => // 只有在没有确定的 id 时使用 <li key={index}> {todo.text} </li> );
1
2
3
4
5
6key的位置,应该在同级的
<li>
或者同级的<ListItem>
React API
setState:
setState(object nextState[, function callback])
- 不能在组件内部通过this.state修改状态,因为该状态会在调用setState()后被替换。
- setState()并不会立即改变this.state,而是创建一个即将处理的state
- setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染。
- setState()总是会触发一次组件重绘,除非在
shouldComponentUpdate()
中实现了一些条件渲染逻辑。
replaceState:
replaceState(object nextState[, function callback])
- callback,可选参数,回调函数。该函数会在replaceState设置成功,且组件重新渲染后调用
setProps
- props相当于组件的数据流,它总是会从父组件向下传递至所有的子组件中。
- 向组件传递数据
- 通知
React.render()
重新渲染 - 更新组件的方式:1.
React.render()
2.setProps
replaceProps
- replaceProps()方法与setProps类似,但它会删除原有 props。
isMounted
- 用于判断组件是否已挂载到DOM中。可以使用该方法保证了**setState()和forceUpdate()**在异步场景下的调用不会出错
React 组件生命周期
- Mounting:修改DOM/ Unmounting:已移出真实 DOM
- Updating:重新渲染
- 具体的方法
- DOM相关
- componentWillMount
- componentDidMount
- componentWillUnmount
- 数据相关
- componentWillReceiveProps
- shouldComponentUpdate
- DOM相关
React AJAX
componentDidMount 方法中的 Ajax 来获取
R