https://github.com/lulujianglab/blog/issues/34

一、生命周期

1,初始化的执行顺序,初始生命周期执行过程详解

class initSate extends Component {
constructor(props, context) {
super()
this.state = {}
}
// 只调用一次,实例之间共享引用
getDefaultProps() { }
// 初始化每个实例特有的状态
getInitialState() { }
// render之前最后一次修改的机会
componentWillMount() { }
// 只能访问到this.props、this.state,只是一个顶层组件,不允许修改状态和Dom输出
render() {
return (
<div></div>
)
}
// 成功render并渲染完成真实的DOM之后触发,可以修改Dom
componentDidMount() { }
}
export default initSate
2,运行中阶段可以使用的函数,运行中的顺序
 
class runSate extends Component {
constructor(props, context) {
super()
this.state = {}
}
// 父组件修改属性触发,可以修改新属性、修改状态
componentWillReceiveProps() { }
// 用于组件优化,返回false会防止render调用
shouldComponentUpdate() { }
// 不能修改属性和状态
componentWillUpdate() { }
// 只能访问到this.props、this.state,只是一个顶层组件,不允许修改状态和Dom输出
render() {
return (
<div></div>
)
}
// 可以修改Dom
componentDidUpdate() { }
}
export default runSate
3,摧毁阶段使用的函数的
class destroySate extends Component {
constructor(props, context) {
super()
this.state = {}
}
// 在删除组件之前进行清理操作,比如计时器和事件监听器
componentWillUnmount() { }
// 只能访问到this.props、this.state,只是一个顶层组件,不允许修改状态和Dom输出
render() {
return (
<div></div>
)
}
}
export default destroySate

二、react的数据传递—单项数据流
1,父--子------父传递属性,子—this.props.num
2,子--父-------子:onChange={this.props.handleEmail}—父:handleEmail(){}
例子省略
三,react调试原理
性能存在问题:
1,父组件更新默认触发所有子组件的更新
2,列表类型组件默认更新方式复杂
解决方法:
子组件覆盖shoudComponentUpdate的方法,自行判断是否更新
给列表组件添加key属性
如图所示:
http://confluence.daojia-inc.com/pages/viewpage.action?pageId=85659735
控制台的监控性能解析
1,React.addons.start():开始
2,   React.addons.stop():结束
3,分析结果
React.addons.perf.printInclusive()
四,公共组件方法拆分----pureRenderMixin的介绍
// 主文件---混入mixin
const BannerListM = mixinHoc(BannerList)
// mixinHoc文件

export default function mixinHoc(importComponent) {

class MixinHoc extends Component {

constructor(props) {
super(props)
}

componentWillUnmount() {
const { setDialogShow } = this.props
// 重置关闭Dialog弹出框
setDialogShow(false)
}

render() {
const Component = importComponent

return Component
? <Component {...this.props} />
: null
}
}

// redux state映射处理
const mapStateToProps = (state) => {
return {}
}

// redux dispatch映射处理
const mapDispatchToProps = (dispatch, ownProps) => {
return {
setDialogShow(data) {
dispatch(setDialogShow(data))
}
}
}

return connect(mapStateToProps, mapDispatchToProps)(MixinHoc)
}
五,中间间的讲解

react 本质上是一个 JavaScript 的库,是创建UI接口的视图层框架

(图一)

如图一所示,假如蓝色组件需要和灰色组件通信,只使用 react 视图层框架,就需要调用父组件函数的形式通信,逐层往父级通信

但对于大型应用来说,这样实现基本不太可能,过多的组件会造成维护困难,那应该怎么做呢?

这个时候就应该在 react 视图层框架上配套一个数据层框架 — Redux ,结合应用

redux 要求我们把数据都放在 store 公共存储空间,当绿色组件想要去传递数据时,只需要改变 store 里边对应的数据,灰色区域会自动感知到 store 有变化,就会重新去 store 取数据,从而灰色组件就能得到新的数据

这样的操作流程对于深层次的组件是非常适用的,组件与组件之间的数据传递会变得非常简单

组件改变,修改数据,其他组件再来取值。这就是 Redux 的基础设计理念

使用 Redux-thunk 中间件进行ajax请求发送

如果我们把这种异步的请求,或者把一些非常复杂的逻辑都放在组件里进行实现时,这个组件会显得过于臃肿

所以遇到这种异步请求或者非常复杂的逻辑,最好是把它移出到其他页面进行统一的处理,

这个时候 Redux-thunk 这个中间件就显得至关重要了,它可以将这些异步请求或者是复杂的逻辑放到 action 去处理,那如何使用 Redux-thunk 这个中间件呢?

打开github,搜索 Redux-thunk ,star最多的项目,就是Redux-thunk

按照它的使用说明进行如下操作

  1. import { createStore, applyMiddleware } from 'redux'
  2. import reducer from './reducer'
  3. import thunk from 'redux-thunk'
  4.  
  5. const store = createStore(
  6. reducer,
  7. applyMiddleware(thunk) // applyMiddleware可以使用中间件模块
  8. )
  9.  
  10. export default store

需要注意的是:

  1. 中间件是通过创建 redux 的 store 时使用的,所以这个中间件是指的 redux 中间件,而不是 react 中间件

  2. 原则上 action 返回的是一个对象,但当我们使用 redux-thunk 中间件后, action 就可以返回一个函数了,继而可以在函数里边进行异步操作,也就可以把 TodoList 获取数据的请求放入这个函数中了

接着操作,在 actionCreator 中创建 action 的函数,然后数据传给 store

那问题来了,怎么传呢?本质还是调用 dipatch 方法,但是现在 actionCreactor 这个文件里并没有 store 这个数据仓库,也就没有 dispatch 这个方法,怎么办呢?

实际上,当我们创建一个内容是函数的 action 时,返回的函数就会自动接收到 store.dispatch 这个方法,所以只要在返回的函数里调用 dispatch ,然后派发 action 就好了, store 判断接收的 action 是一个对象,就会接收并发送给 reducer 进行数据更新操作

  1. export const getTodoList = () => {
  2. return (dispatch) => {
  3. axios.get('/list.json').then((res) => {
  4. const data = res.data
  5. const action = initListAction(data)
  6. dispatch(action)
  7. })
  8. }
  9. }

在 TodoList 组件中引用这个创建内容是函数的 action

  1. componentDidMount() {

const action = getTodoList ();
store.dispatch(action);
}

有的小伙伴可能会有疑问,就一个ajax请求,放在 componentDidMount 会有影响吗?

考虑到后期代码量的增加,如果把异步函数放在组件的生命周期里,这个生命周期函数会变得越来越复杂,组件就会变得越来越大

所以,还是应该把这种复杂的业务逻辑或者异步函数拆分到一个地方进行管理,现在借助 redux-thunk ,就可以放在 actionCreactor 里边集中管理,除此之外,在做自动化测试的时候,测试 actionCreactor 这个方法,也会比测组件的生命周期函数要简单的多

到底什么是 Redux 中间件

view 到 redux 的过程中会派发一个 action , action 通过 Store 的 dispatch 方法,会派发给 store , store接收到 action ,再连同之前的 state 一起传给 reducer , reducer 返回一个新的数据给 store , store 就可以去改变自己的 state ,组件接收到新的 state 就可以重新渲染页面了

redux的中间件在这个流程里边,指的是谁和谁之间呢?指的是 action 和 store 中间

action 通过 dispatch 方法被传递给 store ,那么 action 和 store 之间是不是就是 dispatch 这个方法呢?实际上,我们说的中间件就是指的 dispatch 方法的一个封装,或者是对 dispatch 方法的一个升级

最原始的 dispatch 方法,接收到对象 action 后会传递给 store ,这就是没有中间件的情况

对 dispatch 方法做了一个升级后,也就是使用中间件时,再调用 dispatch 方法,如何给 dispatch 传递的仍然是个对象, dispatch 就会把这个对象传给 store ,跟之前的方法没有任何区别;但是假如传的是个函数,就不会直接传递给 store 了,会让这个函数先执行,然后执行完之后需要调用 store ,这个函数再去调用 store

dispatch方法会根据参数的不同,执行不同的事情,如果参数是对象,就直接传给store,如果是函数,那就把函数执行结束

所以,redux的中间件原理很简单,就是对 store 的 dispatch 方法做一个升级,既可以接收对象,又可以接收函数了,那是用什么方法进行的升级的呢?就是用 redux-thunk 这个中间件进行升级的

当然,redux的中间件还有 redux-log ,原理就是在派发 action 给 store 之前先 console.log 出来;还有 redux-saga ,接下来需要讲解的

React-Redux 的使用

目前我们已经了解了 react 和 redux ,那 React-Redux 是什么呢?它是一个第三方的模块,可以在 react 中非常方便是使用 redux

重新来编写 todolist 功能,在 index 文件中引入 react-redux

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import TodoList from './TodoList'
  4. import { Provider } from 'react-redux'
  5. import store from './store'
  6.  
  7. const App = (
  8. <Provider store={store}>
  9. <TodoList />
  10. </Provider>
  11. )
  12.  
  13. ReactDOM.render(App, document.getElementById('root'))

Provider 实质是一个组件,是一个提供器,是 react-redux 的一个核心API,连接着 store , Provider 里边所有的组件,都有能力获取到 store 里边的内容

react-redux 的另一个核心方法叫做 connect ,接收三个参数,最后一个参数是连接的组件,前面两个是连接的规则

之前说 Provider 组件连接了 store , Provider 内部的组件有能力获取到 store ,是怎样获取的呢?就是通过 connect 这个方法获取到里面的数据的

意思是让 TodoList 组件和 store 进行连接,所以 connect 方法的意思是做连接,在做连接时需要有一定的方式和规则,就是用 mapStateToProps 方法来做关联,翻译为中文就是把 store 里的数据 inputValue 映射到组件 inputValue 这个位置,为组件的 props 的数据

  1. import React, { Component } from 'react'
  2. import { connect } from 'react-redux'
  3.  
  4. class TodoList extends Component {
  5. render () {
  6. return (
  7. <div>
  8. <div>
  9. <input value={this.props.inputValue} />
  10. <button>提交</button>
  11. </div>
  12. <ul>
  13. <li>Dell</li>
  14. </ul>
  15. </div>
  16. )
  17. }
  18. }
  19.  
  20. const mapStateToProps = (state) => {
  21. return {
  22. inputValue: state.inputValue,
  23.  
  24. }
  25. }
  26.  
  27. export default connect(mapStateToProps, null)(TodoList)

如果需要对 store 的数据做修改,dispatch 是指的 store.dispatch ,可以通过 mapDispatchToProps 方法把 store.dispatch 挂载到props上,为什么呢?

因为想要改变 store 里的内容,就要调用 dispatch 方法, dispatch 方法被映射到了 props 上,所以就可以通过 this.props.dispatch 方法去调用了

  1. import React, { Component } from 'react'
  2. import { connect } from 'react-redux'
  3.  
  4. class TodoList extends Component {
  5. render () {
  6. return (
  7. <div>
  8. <div>
  9. <input value={this.props.inputValue} onChange={this.props.handleInputChange} />
  10. <button>提交</button>
  11. </div>
  12. <ul>
  13. <li>Dell</li>
  14. </ul>
  15. </div>
  16. )
  17. }
  18. }
  19.  
  20. const mapStateToProps = (state) => {
  21. return {
  22. inputValue: state.inputValue
  23. }
  24. }
  25. const mapDispatchToProps = (dispatch) => {
  26. return {
  27. handleInputChange(e) {
  28. const action = {
  29. type: 'change_input_value',
  30. value: e.target.value
  31. }
  32. dispatch(action)
  33. }
  34. }
  35. }
  36.  
  37. export default connect(mapStateToProps, mapDispatchToProps)(TodoList)

现在在 input 里输入值的功能就完成了,那todolist的增加功能怎么实现呢?

(TodoList.js)

  1. <button onClick={this.props.handleClick}>提交</button>
  2.  
  3. const mapDispatchToProps = (dispatch) => {
  4. return {
  5. handleInputChange(e) {
  6. const action = {
  7. type: 'change_input_value',
  8. value: e.target.value
  9. }
  10. dispatch(action)
  11. },
  12.  
  13. handleClick() {
  14. const action = {
  15. type: 'add_todo_item'
  16. }
  17. dispatch(action)
  18. }
  19. }
  20. }

(reducer.js)

  1. export default (state = defaultState, action) => {
  2. if (action.type === 'change_input_value') {
  3. const newState = JSON.parse(JSON.stringify(state))
  4. newState.inputValue = action.value
  5. return newState
  6. }
  7. if (action.type === 'add_todo_item') {
  8. const newState = JSON.parse(JSON.stringify(state))
  9. newState.list.push(newState.inputValue)
  10. newState.inputValue = ''
  11. return newState
  12. }
  13. return state
  14. }

点击这个 button 的时候,会执行 handleClick 这个方法,这个方法会把创建出来的 action 传给 store ,再传给 reducer, reducer 接收到这个 action 之后,去处理数据,把新的数据返回出去,新的数据就包含列表项的新内容了,数据发生了改变,todolist 组件恰好又通过 connect 跟数据做了连接,所以这块是个自动的流程,数据一旦发生改变,这个组件自动就会跟的变

以前还需要 store.subscribe 做订阅,现在连订阅都可以不用了,页面自动跟随数据发生变化

这样写就实现了增加 item 的功能,

比如 item 的删除操作, action 要通过 actionCreator 来创建,同时,还需要把 action 的 type 字符串放在 actionType 里面进行管理等等

创建 TodoList 这个组件,正常来说都是 export default TodoList ,把这个组件导出出去,但是�现在 export defalut 出的东西是通过 connect 方法执行的结果,connect 方法做了一件什么事呢?

它把这些映射关系和业务逻辑集成到了 TodoList 这个 UI 组件之中,所以 connect 方法可以这样理解,TodoList 是一个 UI 组件,当你用 connect 把这个 UI 组件和一些数据和逻辑相结合时,返回的内容实际就是一个容器组件了,容器组件可以理解成数据处理包括派发这样的业务逻辑,对 UI 组件进行包装,去调用这些UI组件,数据和方法都准备好了

有的小伙伴可能在网上看到过这样的描述,react-redux 组件既有 UI 组件,又有容器组件。UI 组件就是 TodoList 这个东西,而容器组件就是 connect 方法返回的结果,或者说 connect 方法执行生成的内容

所以 export default 导出的内容就是 connect 方法执行的结果,是一个容器组件

react生命周期,中间件、性能优化、数据传递、mixin的使用的更多相关文章

  1. 【React】393 深入了解React 渲染原理及性能优化

    如今的前端,框架横行,出去面试问到框架是常有的事. 我比较常用React, 这里就写了一篇 React 基础原理的内容, 面试基本上也就问这些, 分享给大家. React 是什么 React是一个专注 ...

  2. 【React学习笔记】React生命周期梳理(16.X前后两种)

    React生命周期 「16版本以前的:」 生命周期流程图 组件从生成到被挂在到页面上的一系列过程 根据流程图打印的执行顺序图: 流程讲解: 初始化流程 start 开始创建组件 在这个周期中做的事情 ...

  3. React 生命周期

    前言 学习React,生命周期很重要,我们了解完生命周期的各个组件,对写高性能组件会有很大的帮助. Ract生命周期 React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 初始化 1.g ...

  4. React生命周期简单详细理解

    前言 学习React,生命周期很重要,我们了解完生命周期的各个组件,对写高性能组件会有很大的帮助. Ract生命周期 React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 初始化 1.g ...

  5. React生命周期执行顺序详解

    文章内容转载于https://www.cnblogs.com/faith3/p/9216165.html 一.组件生命周期的执行次数是什么样子的??? 只执行一次: constructor.compo ...

  6. vue生命周期和react生命周期对比

    一 vue的生命周期如下图所示(很清晰)初始化.编译.更新.销毁 二 vue生命周期的栗子 注意触发vue的created事件以后,this便指向vue实例,这点很重要 <!DOCTYPE ht ...

  7. 前端005/React生命周期

    ES6中React生命周期 一.React生命周期 React生命周期主要包括三个阶段:初始化阶段.运行中阶段和销毁阶段. 在React不同的生命周期里,会依次触发不同的钩子函数. 二.React的生 ...

  8. React生命周期

    在react生命周期中,分2段执行,一个挂载的生命周期,一个是组件发生了数据变动,或者事件触发而引发的更新生命周期. 注:react生命周期很重要,对于很多组件场景的应用发挥重要作用,而且不熟悉生命周 ...

  9. 22.1 、react生命周期(一)

    在每个react组件中都有以下几个生命周期方法~我们需要在不同阶段进行讨论 组件生命周期概述 1.初始化 在组件初始化阶段会执行 constructor static getDerivedStateF ...

  10. react复习总结(2)--react生命周期和组件通信

    这是react项目复习总结第二讲, 第一讲:https://www.cnblogs.com/wuhairui/p/10367620.html 首先我们来学习下react的生命周期(钩子)函数. 什么是 ...

随机推荐

  1. js重点--原型链

    通过将一个构造函数的原型对象指向父类的实例,就可以调用父类中的实例属性及父类的原型对象属性,实现继承. function animals(){ this.type = "animals&qu ...

  2. Tomcat系列(8)——Tomcat运行模式连接数和线程池

    Connector的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据:然后分配线程让Engine(也就是Servlet容器)来处理这个请求,并把产生的Reques ...

  3. 深入理解line-height与vertical-align——前端布局常用属性

    line-height.font-size.vertical-align是设置行内元素布局的关键属性.这三个属性是相互依赖的关系,改变行间距离.设置垂直对齐等都需要它们的通力合作.下面将主要介绍lin ...

  4. C语言strcpy,strncpy和strlcpy讲解

    前言 C风格的字符串处理函数有很多,如strcpy().strcat()等等. strcpy与strcat char* strcpy (char* dest, const char* src); ch ...

  5. BLSTM的训练算法、解码算法以及模型的改进

    摘要 BLSTM解码时,解码器需要等待整个音频到达后才开始解码,因为时间反方向的前向传播需要末尾的历史信息.BLSTM这一延时问题使其不适用与实时语音识别.context-sensitive-chun ...

  6. java笔试要点(java多线程)

    一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌 ...

  7. AXI4 STREAM DATA FIFO

    参考:http://www.xilinx.com/support/documentation/ip_documentation/axis_infrastructure_ip_suite/v1_1/pg ...

  8. jmeter创建时间函数

    固定格式的年月日 ${__time(yyyyMMdd,)} 20151214 //返回年月日 ${__time(HHmmss,)} 092816 //返回时分秒 ${__time(yyyyMMdd-H ...

  9. docker load 镜像时出现:open /var/lib/docker/tmp/docker-import-500852078/repositories: no such file or dir

    网上下载了一些镜像的压缩包,使用docker load的时候会出现如下错误: open /var/lib/docker/tmp/docker-import-500852078/repositories ...

  10. Java中的String、StringBuilder以及StringBuffer

    https://www.cnblogs.com/dolphin0520/p/3778589.html