React组件化开发
React组件思想 – 分而治之
根据组件定义方式
函数组件:functional Component
- 没有生命周期 也会被更新并挂载,但是没有生命周期函数
- 没有this对象
- 没有内部状态
类: Class Component
- 组件名称大写字符开头(不管类还是函数组件)
- jsx中标签要小写
- 因为标签大写会被当成组件
- 类组件需要继承自 React.Component
- 类组件必须实现render函数
Render函数的返回值
当render被调用 ,他会检查 this.props和this.state的变化,并返回一下类型之一:
- React元素
- 通常由JSX创建
- 数组或者fragments:使render方法可以返回多个元素
- Portals
- 可以渲染子节点到不同的DOM子树中
- 字符串 数值类型
- 布尔类型或者null :什么都不渲染
根据组件内部是否有状态需要维护
- 无状态组件
- 有状态组件
根据组件的职责
- 展示型组件
- 容器型组件
生命周期
-从销毁到创建的过程
生命周期 – 分为很多阶段
- 装载阶段(Mount)
- 更新过程(Updating)
- 卸载过程(Unmounting)
生命周期函数
-React通过生命周期函数告诉我们当前处于什么阶段
生命周期解析
Constructor
- 如果不初始化state 或不进行方法绑定,则不需要为React组件实现构造函数
- Constructor通常只做两件事情
- 通过给this.state赋值对象来初始化内部的state
- 为事件绑定实例(this).
componentDidMount
- componentDidMount()会在组件挂载后(插入DOM树中)立即调用
- componentDidMount中通常进行的操作:
- 依赖DOM操作可以在这里进行
- 在这里发送网络请就是最好的地方
- 可以在此处添加一些订阅(会在componentWillUnmount取消订阅)
componentDidUpdate(prevProps,prevState,snapshot)
- 会在更新后会被立即调用,首次渲染不会执行此方法。
- 当组件更新后,可以在此处对 DOM 进行操作;
- 如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求;(例如,当 props 未发生变化时,则不会执行网络请求)。
componentWillUnmount
- componentWillUnmount() 会在组件卸载及销毁之前直接调用。
- 在此方法中执行必要的清理操作
不常用生命周期函数
- getDerivedStateFromProps:
- state 的值在任何时候都依赖于 props时使用;该方法返回一个对象来更新state;
- getSnapshotBeforeUpdate:
- 在React更新DOM之前回调的一个函数,可以获取DOM更新前的一些信息(比如说滚动位置);
- shouldComponentUpdate(SCU):
- 决定render渲染
组件数据传递
组件的嵌套
组件之间通信
父组件传递给子组件 - 函数|类组件
类组件
1 | import React, { Component } from 'react' |
源码中:
1 | /** |
就是将父组件中的数据放在了props super(props), super(props)相当于将Component中this 改变为子类中的this Component中保存传入props 所以保存了props
继承的本质:
1 | var Person = /*#__PURE__*/function () { |
函数组件
1 | import React, { Component } from 'react' |
属性验证
- prop-types
子组件传递父组件
某些情况,我们也需要子组件向父组件传递消息:
- 在vue中是通过自定义事件来完成的;
- 在React中同样是通过props传递消息,只是让父组件给子组件传递一个回调函数,在子组件中调用这个函数即可;
1 | import React, { Component } from 'react' |
React 实现插槽 (slot)
源码中的createElement
React.createElement的函数调用 config中存放的属性 然后对config进行了遍历 然后放到了props里面 props.children = childArray,由于源码中的这步操作 所以props中的children 里面存放的是标签中的内容
1 | export function createElement(type, config, children) { |
实现插槽两种方案:
1.0
//App.js <NavBar> <span>1</span> <strong>1</strong> <span>1</span> </NavBar> //NavBar.js <div className="nav-bar nav-item"> <div className="nav-left"> {this.props.children[0]} </div> <div className="nav-center"> {this.props.children[1]} </div> <div className="nav-right"> {this.props.children[2]} </div> </div> <!--hexoPostRenderEscape:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 2.0</span><br><span class="line"></span><br><span class="line">* ```js</span><br><span class="line"> //App.js</span><br><span class="line"> </span><br><span class="line"> <NavBar2 leftSlot={<span>1</span>}</span><br><span class="line"> centerSlot={<strong>1</strong>}</span><br><span class="line"> rightSlot = { <span>3</span>}</span><br><span class="line"> /></span><br><span class="line"> </span><br><span class="line"> //NavBar2.0.js</span><br><span class="line"> <div className="nav-bar nav-item"></span><br><span class="line"> <div className="nav-left"></span><br><span class="line"> {leftSlot}</span><br><span class="line"> </div></span><br><span class="line"> <div className="nav-center"></span><br><span class="line"> {centerSlot}</span><br><span class="line"> </div></span><br><span class="line"> <div className="nav-right"></span><br><span class="line"> {rightSlot}</span><br><span class="line"> </div></span><br><span class="line"> </div></span><br></pre></td></tr></table></figure>:hexoPostRenderEscape-->