著作权归该书作者所有。本读书笔记仅供个人记录学习使用,如若侵权,请通知到我,我将立即删除全部内容。
React基础
props和state
props是组件对外的接口,组件通过props接收外部传入的数据;
state是组件内部对内接口,组件内部状态的变化通过state来反应。
props是只读的,不能在组件内修改props;
state是可变的,组件的变化通过修改state来实现。
在开发React应用时,要思考哪些组件应该设计成有状态组件,哪些组件应该设计成无状态组件。应该尽可能使用无状态组件,无状态组件不用关心状态的变化,只聚焦UI展示,所以更容易复用。
通过定义少数的有状态组件管理整个应用的状态变化,并且将状态通过props传递给其余无状态组件,由无状态组件完成页面大部分UI渲染。
组件的生命周期
只有类组件才具有生命周期方法,函数组件没有生命周期方法。
- 挂载阶段:组件被创建,执行初始化,并被挂载到DOM中,完成组建的第一次渲染。
- 更新阶段:组件被挂载到DOM后,组件的props或state可以引起组件更新。
- 卸载阶段:组件从DOM中被卸载的过程
挂载阶段
- constructor:ES6构造方法,组件被创建时,首先调用此方法。该方法接收props参数,是从父组件中传入的属性对象。在这个方法中调用super(props)才能保证props被传入组件中。此方法通常用于初始化组件的state以及绑定事件。
- componentWillMount
- render:返回一个React元素而非组件的实际渲染工作,render是一个纯函数,不可在里面调用this.setState
- componentDidMount:组件被挂载到DOM后调用,通常用于向服务器请求数据。
更新阶段
- componentWillReceiveProps:在props引起组件更新过程中调用。state引起更新不会触发该方法。
- shouldComponentUpdate:决定组件是否继续执行更新过程。
- componentWillUpadte:在组件render调用前执行
- componentDidUpdate:组件更新后被调用
卸载阶段
- componentWillUnmount:组件被卸载前调用
表单
如果一个表单元素的值是由React来管理,它就是一个受控组件。非受控制组件指表单元素的状态依然由表单元素自己管理,而不是交给React组件管理,使用非受控组件使用属性ref来获取元素的值。
1 | <input type="text" ref={ (input) => this.input = input } /> |
高阶组件
HOC接收React组件作为参数,并且返回一个新的React组件。本质是一个函数,并不是组件。本质是装饰者设计模式。
使用场景
- 操作props:在被包装组件接收props前,高阶组件可以先拦截到props,对props操作后再传递给被包装组件。
- 通过ref访问组件实例
- 组件状态提升
- 用其他元素包装组件
高阶组件的实现方式:由高阶组件处理通用逻辑,然后将相关属性传递给被包装组件,这种实现方式为属性代理。还可以通过继承方式实现高阶组件:通过继承被包装组件实现逻辑的复用。继承方式实现的高阶组件常用于渲染劫持。例如当用户处于登录状态时,允许组件渲染, 否则渲染一个空组件。
注意事项
- 为了区分高阶组件,应该把被包装组件的名称也包到高阶组件的名称中,如withPersistentData
- 不要在组件的render方法中使用高阶组件,尽量不要在组件的其他生命周期方法中使用高阶组件。因为调用高阶组件每次返回一个新组件,于是每次render前一次高阶组件创建的组件都会被卸载,然后重新挂载本次创建的新组件,影响效率。
- 如果需要使用被包装组件的静态方法,需要手动复制这些静态方法,因为高阶组件返回的新组件不包含被包装组件的静态方法。
React Router
1 | npm install react-router-dom |
React Router v4 每遵循React中一切皆组件的思想,每一个Route(路由)都是一个普通的React组件
React Router 通过Router和Route两个组件完成路由功能。
一个应用只需要一个Router实例,所有的路由配置组件Route都定义为Router的子组件。
路由配置
Route是React Router中用于配置路由信息的组件,每当有一个组件需要根据URL决定是否渲染时,需要创建一个Route
- path:用来描述这个Route匹配的URL的pathname,当URL匹配一个Route时,这个Route中定义的组件将会被渲染。
match:当URL和Route匹配时,Route会创建一个match对象作为props中的一个属性传递给被渲染的组件。对象包含以下4个属性
- params:Route的path可以包含参数。例如
包含一个参数id,params从path解析到参数{id:1} - isExact:布尔值。当URL完全匹配时值为true。path=’/foo’、URL=’http://example.com/foo'完全匹配;URL='http://example.com/foo/1'部分匹配。
- path:Route的path属性。构建嵌套路由时会使用到
- url:URL的匹配部分
- params:Route的path可以包含参数。例如
Route渲染组件的方式:Route提供3个属性用来定义待渲染的组件:
- component 当URL和Route匹配时,component属性定义的组件就会被渲染:
1
<Route path='/foo' component={Foo}>
render 该方式方便为待渲染组件传递额外的属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<Route path='/foo' render={ (props) => (
<Foo {...props} data={extraProps} />
)}>
```
- children 与上述不同,children返回的组件无论路由是否匹配都会被渲染,当匹配不成功时,match属性为null
- ```js
<Router path='/foo' children={ (props) => (
<div className={props.match ? 'active' : ''}>
<Foo />
</div>
)}>
```
如果Route匹配当前URL,待渲染元素的根节点div的class将被设置为active
- Switch 和 exact。当URL和多个Route匹配时,这些Route都会执行渲染操作。如果只想当第一个匹配的Route渲染,可以把这些Route包裹到一个Switch组件中。如果想让URL和Route完全匹配时Route才渲染,可使用Route的exact属性。Switch和exact常联合使用应用于首页的导航。
```js
<Router>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/posts' component={Posts} />
<Route path='/:user' component={User} />
</Switch>
</Router>如果不使用Switch,当pathname为’posts’时,后面两个都会被匹配,但我们并不希望/:user被匹配。
如果不使用exact,’/‘,’/posts’…几乎所有URL都会被匹配到第一个Route,而又因为使用了Switch,后面的两个Route永远也不会被匹配。使用exact保证pathname只有完全匹配时,第一个Route才会被匹配。
嵌套路由:是指在Route渲染的组件内部定义新的Route
1
2
3
4
5
6
7
8
9const Posts = ( { match} ) => {
return (
<div>
{/* 这里match.url 等于 /posts */}
<Route path={`${match.url}/:id`} component={PostDetail} />
<Route exact path={match.url} component={PostList} />
</div>
)
}
链接 Link
Link是React Router提供的链接组件,一个Link组件定义了当点击该Link时,页面应该如何路由。
Link使用to属性声明要导航到的URL地址。to可以是string或object类型,当to为object类型时,可以包含pathname、search、hash、state四个属性。
1 |
|
使用history对象手动实现导航
1 | //push向浏览器历史记录新增一条 |
Redux
Redux的主要思想即描述应用的状态,如何根据action进行更新。
Redux三大原则
- 只维护一个全局状态state对象,储存在Redux的store中。
- 保持应用状态只读。不可直接修改应用状态,需要修改时必须发送action,该action描述如何修改应用状态。
- 应用状态的改变通过纯函数reducer完成。
react-redux
1 | npm install react-redux |
根据组件意图不同,可以将组件划分为两类:展示组件、容器组件。
- 展示组件–UI展示,不关心数据。
- 容器组件–逻辑处理,如发送网络请求、处理返回数据、将处理过的数据通过props传递给展示组件。
当展示组件的状态变更引起源数据变化时,展示组件通过调用容器组件提供的方法同步变化。
有/无 状态组件根据是否使用state来划分,展示组件和容器组件根据组件意图划分。
1 | connect() // 用于把React组件和Redux的store连接起来,生成一个容器组件,负责数据管理和业务逻辑 |
1 | Provider 用于容器组件获取Redux的store。该组件需要接收store属性,然后把store属性保存到context |
Plugin | README |
---|---|
Dropbox | [plugins/dropbox/README.md][PlDb] |
Github | [plugins/github/README.md][PlGh] |
Google Drive | [plugins/googledrive/README.md][PlGd] |
OneDrive | [plugins/onedrive/README.md][PlOd] |
Medium | [plugins/medium/README.md][PlMe] |
Google Analytics | [plugins/googleanalytics/README.md][PlGa] |