UI=render(data)
一: prop 和 state 的对比
总结 prop 和 state 的区别:
prop 用于定义外部接口, state 用于记录内部状态
prop 的赋值在外部世界使用组件时, state 的赋值在组件内部
组件不应该改变 prop 的值, state 存在的目的就是让组件来改变的.
this.setState() 函数所做的事情, 首先是改变 this.state 的值, 然后驱动组件更新过程.
二: 组件的生命周期
生命周期经历如下三个过程:
装载过程 Mount: 组件第一次在 DOM 树中渲染的过程. componentWillMount componentDidMount
更新过程 Update: 当组件被重新渲染的过程 componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,componentDidupdate
卸载过程 Unmount: 组件从 DOM 中删除的过程 componentWillUnmount
装载过程
1,constructor
构造函数: 有状态的组件才需要定义, 目的是:
初始化 state
绑定成员函数的 this 环境
2,render
render 函数不做实际的渲染动作, 只是然后一个 JSX 的描述结构, 最终由 React 来操作渲染. render 函数是一个纯函数.
更新过程
1,componentWillReceiveProps(nextProps)
只要父组件的 render 函数被调用, 在 render 函数里面被渲染的子组件就会经历更新过程, 不管父组件传给子组件的 props 有没有改变, 都会触发 componentWillReceiveProps 函数.
通过 this.setState 方法触发的更新过程不会调用这个函数.
2,shouldComponentUpdate(nextProps,nextState)
render 函数返回结果将用于构造 DOM 对象, 而 shouldComponentUpdate 函数返回一个布尔值, 告诉 React 库这个组件在这次更新过程中是否要继续.
通过 this.setstate 函数引发更新过程, 并不是立刻更新组件的 state 值, 在执行到函数 shouldComponentUpdate 的时候, this.state 依然是 this.setState 函数执行之前的值.
三: 组件向外传递数据
父到子组件: prop
子到父组件: 将函数像其他对象一样作为 prop 的值从父组件传递给子组件, 又可以被子组件作为函数调用.
四: Redux
React 组件中 state 和 prop 的局限: state 没有全局状态, prop 一层一层的传递.
Redux 的基本原则:
唯一数据源
保持只读状态
数据改变只能通过纯函数完成
1, 唯一数据源
唯一数据源指的是应用的状态数据应该只存储在唯一的一个 store 上
2, 保持状态只读
不能直接修改状态, 要修改 store 的状态, 必须要通过派发一个 action 对象完成. 驱动用户界面渲染, 就要改变应用的状态, 但是改变状态的方法不是去修改状态上值, 而是创建一个新的状态对象返回给 Redux, 由 Redux 完成新的状态的组装.
3, 数据改变只能通过纯函数完成
reducer(state,action),redux 的 reducer 只负责计算状态, 不负责存储状态.
Redux 中的每个 action 构造函数都返回一个 action 对象, action 构造函数只负责创建对象, 要派发 action 就需要调用 store.dispatch 函数.
五: 容器组件和傻瓜组件
在 Redux 框架下, 一个 React 组件基本就是完成以下两个功能:
外层 (容器组件): 和 Redux Store 打交道, 读取 Store 的状态, 用于初始化组件的状态, 同时还要监听 Store 的状态改变; 当 Store 状态发生变化时, 需要更新组件状态, 从而驱动组件重新渲染; 当需要更新 Store 状态时, 就要派发 action 对象.
内层 (展示组件): 根据当前 props 和 state, 渲染出用户界面.
1, 组件 Context
所谓 Context, 就是'上下文环境', 让一个树状组件上所有组件都能访问一个共同的对象. Provider 只是把渲染工作完全交给子组件, 它扮演的只是提供 Context.
2,React-Redux
改进 React 的两个方法:
把一个组件拆分为容器组件和傻瓜组件, 使用 connect 连接.
使用 React 的 Context 来提供一个所有组件都可以直接访问的 Context, 使用 Provider 实现.
mapStateToProps 函数: 把 Store 上的状态转化为内层傻瓜组件的 props
mapDispatchToProps 函数: 把内层傻瓜组件中的用户动作转化为派送给 Store 的动作
六: Redux 中间件
Redux 的单向数据流是同步操作, 驱动 Redux 流程的是 action 对象, 每一个 action 对象被派发到 Store 上之后, 同步的被分配给所有的 reducer 函数, 每个 reducer 都是纯函数, 纯函数不产生任何副作用, 自然是完成数据操作之后立刻同步返回, reducer 返回的结果又被同步的拿去更新 Store 上的状态数据, 更新状态数据的操作会立刻被同步给监听 Store 状态改变的函数, 从而引发作为视图的 React 组件更新过程.
在 Redux 的单向数据流中, 在 action 对象被 reducer 函数处理之前, 是插入异步功能的时机. 在 Redux 架构下, 一个 action 对象在通过 store.dispatch 派发, 在调用 reducer 函数之前, 会先经过一个中间件的环节, 这就是产生异步操作的机会.
使用名为 middlewares 的数组来存储所有的中间件, 如果需要导入中间件放在 middlewares 数组中就可以.
异步 action 对象
如果没有 redux-thunk 中间件的存在, 这样一个函数类型的 action 对象就被派发出来会一路发送到各个 reducer 函数, 有了 redux-thunk 中间件之后, 这些 action 对象没有机会触及到 reducer 函数, 在中间件一层被 redux-thunk 截获.
redux-thunk 的工作就是检查 action 对象是不是函数, 如果不是函数就放行, 完成普通 action 对象的生命周期, 而如果发现 action 对象就是函数, 那就执行函数, 并把 Store 的 dispatch 函数和 getState 函数作为参数传递到函数中去, 处理过程到此为止, 不会让这个异步 action 对象继续往前派发到 reducer 函数.
异步 action 最终还是要产生同步 action 派发才能对 Redux 系统产生影响; 访问服务器的异步 action, 无论成败, 都要通过派发 action 对象改变 Redux Store 上的状态完结.
action 对象被派发时, 会让 React 组件进入各自不同的三种状态:
异步操作正在进行中
异步操作已经成功完成
异步操作已经失败
来源: https://juejin.im/post/5b1a77ff6fb9a01e5a3a5008