React与Vue的区别

(1) 监听数据变化的实现原理不同
(2) 数据流的不同
(3) HoC 和 mixins
(4) 组件通信的区别
(5) 模板渲染方式的不同
(6) Vuex 和 Redux 的区别

redux中间件

中间件提供第三方插件的模式,自定义拦截action->reducer的过程,变为action->middlewares->reducer,这种机制可以让我们改变数据流,实现如异步action,action过滤,日志输出,异常报告等功能。
redux-logger 提供日志输出
redux-thunk 异步处理
redux-promise 异步操作

React组件划分业务组件、技术组件

根据组件的职责将组件分为UI组件和容器组件,UI组件负责Ui的呈现,容器组件负责管理数据和逻辑。两者通过react-Redux提供connect方法联系起来。

react生命周期函数

  • 初始化渲染阶段(组件进入dom的阶):
  1. getDefaultProps:获取实例的默认属性
  2. getInitialState:获取每个实例的初始化状态
  3. componentWillMount:组件即将被装载、渲染到页面上
  4. render:组件在这里生成虚拟的 DOM 节点
  5. componentDidMount:组件真正在被装载之后
  • 更新阶段(一旦组件被添加到dom上,它只有在props和state发生变化时更新和重新渲染):
  1. componentWillReceiveProps:组件将要接收到属性的时候调用
  2. shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
  3. componentWillUpdate:组件即将更新不能修改属性和状态
  4. render:组件重新描绘
  5. componentDidUpdate:组件已经更新
  • 销毁阶段(组件被销毁和删除):
  1. componentWillUnmount:组件即将销毁
  2. V17.0之后的版本删除的钩子函数
    a. componentWillMount
    b. componentWillReceiveProps
    c. componentWillUpdate
    在 v16.3以上版本新增的钩子函数
  3. getDerivedStateFromProps
  4. getSnapshotBeforeUpdate

    React性能优化是哪个周期函数

    shouldComponentUpdate()这个方法判断是否需要调用rander方法重新描绘dom,因为dom的描绘消耗性能。如果我们在shouldComponentUpdate方法写出dom diff算法,能极大优化性能。

    diff算法

    1、把树形结构按照层级分解,只比较同级元素
    2、把列表结构的每个单元添加唯一的key属性,方便比较。
    3、React只会匹配相同class的component(class 是组件的名字)合并操作,调用component的setState方法的时候,React会将其标为dirty,到每一个事件循环结束,React检查所有标记dirty的component重新绘制。
    5、选择性子树渲染,开发人员可以重写shouldComponentUpdate提高diff性能。
    react面试题 - 图1

    React性能法案

    1、重写shouldComponentUpdate来代替没必要的渲染
    2、使用production版本的react
    3、使用key来帮助React识别列表中所有子组件的最小变化

    Redux遵循的三个原则?

  5. 单一事实来源:整个应用的状态存储在单个store中的对象/状态树里。单一状态树可以更容易的跟随时间的变化,并调试和检查应用程序。

  6. 状态是只读的:改变状态的唯一方法是触发一个动作。
  7. 使用纯函数更改:纯函数:返回值取决于参数值的参数。

    redux

    redux是一个应用数据流框架,主要是解决组件间状态共享问题。
    核心方法:action(用来描述发生了什么事情的对象)、store(整个程序的状态/对象保存在Store中)、reducer(一个确定状态将如何变化的地方)、view(只展示store提供的数据)
    工作流程:
    a view调用store的dispath接收action传入store
    b Store自动调用Reducer,传入两个参数,当前的state和收到的Action,Reducer会返回新的state。
    c State一旦有变化,Store就会调用监听函数,来更新View。
    因此一次用户交互流程结束,由此看出,在整个流程中数据是单向流动的。
    3b82bf93d6d03888884c98811f7ff0a.jpg

    Redux是如何工作的?

  • Provider:Provider的作用是从最外部封装了整个应用,并向connect模块传递store。
  • connect:负责连接React和Redux
    • 获取state:connect通过context获取Provider的store,通过store.getState获取整个store tree上的所有state
    • 包装原组件:将state和action通过props的方式传入到原组件内部wrapWithConnect返回一个ReactComponent对象Connect,Connect重新render外部传入的原组件wrapWithConnect,并把connect的mapStateToProps和mapDispatchToProps的组件上原有的props合并后,通过属性的方式传给wrapWithConnect。
    • 监听store tree变化:connect缓存了store tree中的state的状态,通过当前的state状态和变化前state状态比较,确定是否通过this.setState方法触发Connect和子组件重新渲染。

      redux-saga和redux-thunk的区别

      redux-saga可以解决thunk 的两个问题:
      1.action的形式不统一
      2.就是异步操作太为分散,分散在了各个action中 不易维护
      3.saga将异步操作放到统一的一个文件中处理

      redux-sage的优缺点

      优点:
      (1)集中处理了所有的异步操作,异步接口部分一目了然
      (2)action是普通对象,这跟redux同步的action一模一样
      (3)通过Effect,方便异步接口的测试
      (4)通过worker 和watcher可以实现非阻塞异步调用,并且同时可以实
      现非阻塞调用下的事件监听
      (5) 异步操作的流程是可以控制的,可以随时取消相应的异步操作。
      缺点:太复杂,学习成本较高

      redux-saga的effect方法

      put:对应的是middleware中的dispatch方法,可以发送一个动作
      call: 表示异步调用,其中call表示的是阻塞调用,
      fork:表示异步调用,表示的是非阻塞调用。
      take:监听action,返回监听到的action对象
      delay:延时
      takeEvery:予以相当于 on ,允许并发action
      all:创建effect的描述信息,用来命令中间件,并行多个effect,并等待他们全部完成

      flux思想

      Flux思想最大特点:数据单向流动
      1、用户访问View
      2、View发出用户的Action
      3、Dispatcher收到Action,要求Store进行更新
      3、Store进行更新后,发出一个change事件
      5、View收到change事件后,更新页面

      React解决了什么问题?

      1、组件复用问题
      2、性能问题
      3、兼容性问题

      React优势?

      1、react速度快:引用了虚拟Dom的概念,安插在JavaScript逻辑和实际 Dom之间,性能好
      2、跨浏览器兼容性:虚拟dom帮助开发者解决了浏览器兼容性的问题,且提供统一的API
      3、组件化,模块化,可维护性提高
      4、单向数据流。。。。

      类组件与函数式组件之间有何不同?

      1、类组件不仅允许使用额外的功能,包括生命周期钩子和自身状态,也能直接使组件访问store并维持状态
      2、函数式组件当组件接收props,并将组建自身渲染到页面时,该组件就是一个‘无状态组件’,没有生命周期和this,不执行与UI无关的逻辑处理。

      组件的state与props之间有何不同?

      state是一个数据结构,用于组件挂载时所需数据的默认值,state会随着时间的推移发生突变,大部分作为用户事件行为的结果。
      props由父组件传递给子组件,对于子组件来说,props是不可变的。组件不能改变自身的props,但是可以将子组件的props放在一起统一管理。props可以传递数据、回调函数。

      React在何处发起Ajax请求?

      componentDidMount。

      React中ref作用?

      可以用于获取Dom节点或者React组件的引用,将组件渲染配置函数返回。
      适用情况:
  1. 处理焦点、文本选择、媒体控制
  2. 触发强制动画
  3. 继承第三方dom库
  4. 如果可以通过申明实现,尽量避免使用refs

    展示组件与容器组件的不同

    展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,只关心UI状态。
    容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。

    React 高阶组件、Render props 和 hooks有什么区别?

    React 高阶组件:接收一个组件作为参数,返回一个组件的函数

    1. function withSubscription(WrapperdComponent, selectData) {
    2. return class extend React.Component {
    3. consturctor(props) {
    4. super(props)
    5. this.state = {
    6. data: selectData(DataSource, props)
    7. }
    8. }
    9. render() {
    10. return <WrapperdComponent data={this.state.data} {...this.props} />
    11. }
    12. }
    13. }
  • 优点:
    • 逻辑复用
    • 不影响被包裹的组件的内部逻辑
  • 缺点
    • 高阶组件传递给被包裹组件的props如果重名的话,会发生覆盖

      Render props:告知组件需要渲染什么内容的函数

      ```javascript Class DataProvider extends React.Components { state = { name: “Alice” }
      render() { return (
      1. <div>
      2. <p>共享数据组件自己内部的 render</p>
      3. { this.props.render(this.state) }
      4. <div/>
      ) } }

(

共享的 render {data.name}</>) } />

  1. - 优点
  2. - 数据共享
  3. - 逻辑复用
  4. - 缺点
  5. - 生命周期、statethis等复杂度
  6. - 不能在 return 之外访问数据
  7. <a name="NdzGS"></a>
  8. ## **Hooks:**通过自定义 hook,可以很轻松的实现逻辑复用。
  9. ```javascript
  10. function useSubscription() {
  11. const data = DataSource.getComments()
  12. return [data]
  13. }
  14. function CommentList(props) {
  15. const {data} = props
  16. const [subData] = useSubscription()
  17. return (
  18. <div>
  19. this is data: {data},
  20. this is subData: {subData}
  21. <div/>
  22. )
  23. }
  • 使用直观
  • 不存在 hoc 的重名问题
  • 不存在 render props 的嵌套问题
  • 能在 return 之外访问数据

    何为高阶组件(HOC)?

    高阶组件是一个组件为参数并返回一个新组件的函数,HOC共享React组件之间的行为,如果发现在不同的地方写了大量代码做一件事,可以将代码重构为可重用的HOC。常见的如React的connect函数。

    构造函数调用super(props)的目的?

    super调用前,子类不能使用this。在es2015,子类必须在constructor调用super。将props传递给super使子类能够在构造函数中使用this.props。

    setState是异步还是同步?

  • setState的异步不是说内部由异步代码实现,其本身执行的过程与代码都是同步的。

  • 因为合成事件和钩子函数的调用顺序是在update之前,导致合成事件和钩子函数没法立马拿到更新后的值,形成所谓的“异步”。但是第二个参数,回调函数可以拿到更新的结果
  • setState的批量更新优化也是建立在”异步“(合成事件、钩子函数)之上,在”异步“中如果对同一个值进行多次setState,setState的批量更新策略会对其覆盖,取最后一次的执行。如果同时setState多个不同的值,更新时会对其进行合并更新。 ```javascript import $axios from ‘utils/request’; import React from “react”; class Demo extends React.Component { constructor() { super(); this.state = {
    1. count: 0,
    }; this.add = this.add.bind(this); }

componentDidMount() { this.getList(); }

async getList() { let res = await $axios.get(“/house/list”); this.setState({ list: res.result }); // 在非事件函数中却是同步的 console.log(this.state.list); }

// 事件函数中, 是异步的 add() { this.setState({ count: this.state.count + 1, }); console.log(this.state.count); // 0

  1. // 若想获取更新好的count,setState添加回调函数
  2. this.setState({
  3. count: this.state.count + 1},
  4. ()=> {
  5. console.log(this.state.count);
  6. }
  7. );

}

render() { return (

{this.state.count}
); } }

export default Demo;

  1. - **React事件函数使用**,this.xxx=this.xxx.bind(this),React"知道”什么时候退出该事件,什么时候批量更新,表现为**异步行为**
  2. - 例如ajax、addEventListener绑定,函数脱离react控制,react不知道什么时候批量更新,表现为同步
  3. - (对于合成事件和钩子函数是“异步”的,在原生事件和setTimeOut都是同步的。)
  4. <a name="A8gJn"></a>
  5. # setState之后发生了那些事情?
  6. 1、代码调用了setState函数之后,React会将传入的参数对象与组件当前的状态合并,触发协调器。<br />2、协调器以相对高效的方式根据新的状态构建React元素树,并着手重新渲染整个UI界面<br />3、React得到元素树后,自动计算新的树与老树的节点的差异,根据差异对界面进行最小化重渲染<br />4、在Diff算法中,React相对精确的知道位置发生改变以及应该如何改变,按需更新,而不是重新更新。
  7. <a name="Ty6CI"></a>
  8. # setState之后干了什么
  9. <a name="VvE77"></a>
  10. # setState与replaceState区别?
  11. - setState只是修改部分状态,相当于Object.assign,只是覆盖,不改变原来的状态。
  12. - replaceState是完全替换原来的状态,相当于赋值,新的state会替换另一个对象,如果新的state的属性减少,那么state会没有这个属性。
  13. <a name="cHMps"></a>
  14. # 传递给setState的参数是一个callback而不是一个对象
  15. 因为this.props和this.state可能是异步的,不能依赖它们的值去计算下一个state。
  16. <a name="DN9f5"></a>
  17. # React中key的作用
  18. 1. key是React追踪列表的元素被修改,被添加或者被移除的辅助标志
  19. 2. key具有唯一性,可以避免不必要的元素重复渲染
  20. <a name="w78Iq"></a>
  21. # 什么是虚拟Dom,工作原理?
  22. 虚拟Dom是一个轻量级的JavaScript对象。它是一个节点数,将元素、它们的属性和内容作为对象及其属性。React渲染函数会创建一个节点树,然后它响应数据模型变化更新这颗节点树,节点树的变化是用户或系统的变化产生的。
  23. <a name="ab7uz"></a>
  24. # 为什么虚拟 dom 会提高性能?
  25. 1. 虚拟dom相当于在js和真实dom中间加了个缓存,利用dom diff算法避免没有必要的dom操作,从而提高性能
  26. 2. 用JavaScript对象结构表示Dom树的结构,然后用这个树构建成一个真正的Dom树,插入到文档中
  27. 3. 当状态变更时,重新构造一颗新的对象树,新的树与旧的树对比,记录差异
  28. 4. 将3记录的差异应用到1所构建的真正dom树,视图更新
  29. 5. 无需手动操作Dom:虚拟Dom的diff和patch都是在一次更新中自动进行的,我们无需手动操作Dom,提高开发效率。
  30. 6. 跨平台性
  31. <a name="JjfPV"></a>
  32. # 真实DOM与虚拟Do区别?
  33. ![8523ece929f3cddb17c7d899651c197.jpg](https://cdn.nlark.com/yuque/0/2022/jpeg/25963140/1665544039177-da89ac5d-e498-45cc-969d-0045c96b3465.jpeg#clientId=u4feba380-c5e1-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=drop&height=441&id=u5dd48f72&margin=%5Bobject%20Object%5D&name=8523ece929f3cddb17c7d899651c197.jpg&originHeight=1041&originWidth=1028&originalType=binary&ratio=1&rotation=0&showTitle=false&size=203541&status=error&style=none&taskId=u93b8bb06-6287-4f44-ad21-65c9b0c8c00&title=&width=435)
  34. <a name="kjd0q"></a>
  35. # 何为受控组件?
  36. 在 React 中,包含表单元素的组件将会在 state 中追踪输入的值,并且每次通过 onChange 等事件会更新 state,重新渲染组件。一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为"受控元素"。例如直接使用ref获得表单的值,叫做’非受控组件‘。
  37. <a name="sJkeb"></a>
  38. # 区分有状态和无状态组件?
  39. ![e5d6533537c1aa65c8ce8c720a033e3.jpg](https://cdn.nlark.com/yuque/0/2022/jpeg/25963140/1666668646527-b76f76c6-796e-4d8f-ad9f-66ca0d5c4b21.jpeg#clientId=u4dd3b4ac-27d5-4&crop=0.0349&crop=0.3963&crop=0.9692&crop=0.8178&errorMessage=unknown%20error&from=drop&height=1293&id=u84580e52&margin=%5Bobject%20Object%5D&name=e5d6533537c1aa65c8ce8c720a033e3.jpg&originHeight=2400&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=590035&status=error&style=none&taskId=u5d9e9400-e8af-48da-9867-241b4c0117f&title=&width=582)
  40. <a name="zvIrz"></a>
  41. # 何为高阶组件(HOC)?
  42. 高阶组件是一个组件为参数并返回一个新的组件的函数。HOC可以允许重用代码、逻辑和引导抽象。例如Redux中的connect函数。HOC最好的方式是共享组件之间的状态。
  43. <a name="PjmpS"></a>
  44. # 为什么建议传递给setState的参数是一个callback,而不是一个对象
  45. 因为this.props和this.state的更新可能是异步的,不能依赖他们的值去计算下一个state
  46. ```tsx
  47. import { PureComponent } from "react"
  48. import "./App.css"
  49. class App extends PureComponent {
  50. constructor(props) {
  51. super(props)
  52. this.state = {
  53. count: 0
  54. }
  55. }
  56. changeCount() {
  57. this.setState({ count: this.state.count + 1 })
  58. this.setState({ count: this.state.count + 1 })
  59. this.setState({ count: this.state.count + 1 })
  60. console.log(this.state.count)
  61. }
  62. render() {
  63. return (
  64. <div className="App">
  65. {this.state.count}
  66. <button onClick={() => this.changeCount()}>+</button>
  67. </div>
  68. )
  69. }
  70. }
  71. export default App

image.png

  1. import { PureComponent } from "react"
  2. import "./App.css"
  3. class App extends PureComponent {
  4. constructor(props) {
  5. super(props)
  6. this.state = {
  7. count: 0
  8. }
  9. }
  10. changeCount() {
  11. // 传回调函数就能得到预期的结果
  12. this.setState(state => {
  13. return { count: state.count + 1 }
  14. })
  15. this.setState(state => {
  16. return { count: state.count + 1 }
  17. })
  18. this.setState(state => {
  19. return { count: state.count + 1 }
  20. })
  21. console.log(this.state.count)
  22. }
  23. render() {
  24. return (
  25. <div className="App">
  26. {this.state.count}
  27. <button onClick={() => this.changeCount()}>+</button>
  28. </div>
  29. )
  30. }
  31. }
  32. export default App

image.png

除了在构造函数中绑定 this,还有其它方式吗

  1. //此时this指向定义的组件
  2. // 方式1
  3. <button onClick={() => { this.changeCount(); }} > + </button>
  4. // 方式2
  5. <button onClick={this.changeCount.bind(this)} > + </button>

在构造函数中调用super(props)的目的?

1、没有super()调用之前,子类不能使用this。(在es6中,子类必须在constructor调用super())
2、传递props,便于子类能在constructor访问this.props

React三种构建组件的方式

React.createClass()、class组件、函数式组件

react新特性

context

可以跨组件传参,既从根节点可以直接传参到叶子节点

  1. // 1.创建
  2. const ThemeContext = React.createContext('light');
  3. // 2.传参
  4. <ThemeContext.Provider value="dark">
  5. 组件名
  6. </ThemeContext.Provider>
  7. //3.接收参数
  8. function MyButton(props){
  9. return <ThemeContext.Consumer>{
  10. theme=><button className={theme}>按钮</button>
  11. }
  12. </ThemeContext.Consumer>
  13. }

hooks
  1. useState 可以在函数式组件中使用state ,并且可以调用函数更改state的值
  2. useEffect useEffect它与 React 类中的 componentDidMount,componentDidUpdate,和componentWillUnmount 有相同的功能,但是统一为单个 API
  3. memo 是在 函数式组件中,如果有组件不需要更新时,调用memo,相当于 类组件中的 shouldComponentUpdate
  4. lazy\Suspense\错误边界(Error boundaries)
  5. useReduce等

    react项目优化

    1、使用Fragment或者空节点
    2、类组件使用shouldComponentUpdate,减少不必要的渲染
    3、多使用函数式组件,减少使用类组件
    4、函数式组件使用memo避免重复渲染
    5、使用React.lazy()和Suspense进行懒加载
    6、异常捕获边界(Error Boundaries)捕获发生异常的react组件,将异常组件和正常的组件分隔开,提供用户体验
    7、骨架评,用于页面初始化加载,避免出现白屏的现象
    8、长列表优化
    虚拟化长列表:只加载可视范围内的数据
    9、根据性能优化工具修改代码
    10、使用chrome的Performance工具
    11、React Devtools的Profiler工具分析:通过React.Profiler组件包裹需要分析渲染时间的组件(不适合生产环境)。
    12、SEO优化:预渲染
    13、图片懒加载
    14、使用react-lazyload插件:当组件未出现在屏幕内时,不去挂载该组件,而是使用 placeholder 去渲染,让滚动使内容出现后,组件会被挂载。
    15、for循环中的key优化
    16、在使用了定时器的页面,页面离开时,停止未完成的渲染
    1. componentWillUnmount = () => {
    2. //停止定时器
    3. clearInterval(this.inter);
    4. //如果页面跳转时,setState还没有执行完,就停止它,return
    5. this.setState = (state,callback)=>{
    6. return;
    7. };
    8. }

    react路由传参

    1.params(动态路由传参)
    1. <Route path='/path/:name' component={Path}/>
    2. <link to="/path/2">xxx</Link>
    3. this.props.history.push({pathname:"/path/" + name});
    4. 读取参数用:this.props.match.params.name
    优势 : 刷新地址栏,参数依然存在
    缺点:只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。
    2.query
    1. <Route path='/query' component={Query}/>
    2. <Link to={{ path : ' /query' , query : { name : 'sunny' }}}>
    3. this.props.history.push({pathname:"/query",query: { name : 'sunny' }});
    4. 读取参数用: this.props.location.query.name
    优势:传参优雅,传递参数可传对象;
    缺点:参数在地址栏不显示,刷新地址栏,参数丢失
    3.state
    1. <Route path='/sort ' component={Sort}/>
    2. <Link to={{ path : ' /sort ' , state : { name : 'sunny' }}}>
    3. this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }});
    4. 读取参数用: this.props.location.state.name
    同query差不多,只是属性不一样,而且state传的参数是加密的, 刷新页面参数不丢失
    4.search
    1. <Route path='/web/departManange ' component={DepartManange}/>
    2. <link to="web/departManange?tenantId=12121212">xxx</Link>
    3. this.props.history.push({pathname:"/web/departManange?tenantId" + row.tenantId});
    4. 读取参数用: this.props.location.search
    优缺点同params

createElement和cloneElement的区别?

createElement函数是JSX编译之后创建的React元素。
React.createElement(type,[props],[…children]) 第一个参数是标签名(div、span)或组件,第二个参数是传入的属性,第三个参数是组件的子组件。
cloneElement函数复制某个元素并传入props,传入的参数是react元素,而不是标签或者组件,新添加的属性会并入原有的属性,传入到返回的新元素中,子元素则替代。
React.cloneElement(element,[props],[…children])

什么时候使用class Component,什么时候使用Function?

当组件具有state和生命周期时,使用类组件,否则使用函数式组件。

在react中,Element与Component有什么区别?

  • React Element 是描述屏幕上所见内容的数据结构,是对Ui的对象表述。典型的React Element是利用JSX构建的生命是代码片转换为createElement的调用组合。
  • React Component是一个函数或者一个类,可以接收参数输入,并返回某个React Element。

    什么是JSX?

    JSX 是Javascript Xml的简写,是React使用的一种文件,类似HTML的模板语法。

    1. render(){
    2. return (
    3. <div>
    4. <h1>hello</h1>
    5. </div>
    6. )
    7. }

    React的render()目的

    每一个React组件都必须有一个render().它渲染多个html元素,必须将html元素放入到一个封闭的标记内,例如

    等。它返回一个react元素,是原生Dom组件的表示。且是一个纯函数。

    如何理解“react中,一切都是组件”这句话

    组件是构成React应用UI的构建块。这些组件根据UI分成小的独立的可复用的部分。每一个组件都独立存在且不影响其他的组件。

    与es5相比,React的Es6语法的不同?(了解)

  • require与import ```typescript //es5 const React =require(‘react’)

//es6 import React from ‘react’

  1. - exportexports
  2. ```typescript
  3. //es5
  4. module.exports=Components
  5. //es6
  6. export default Components
  • component与function

    1. //es5
    2. var MyComponents=React.createClass({
    3. render(){
    4. return <h3>haha</h3>
    5. }
    6. })
    7. //es6
    8. class MyComponents extends React.Components{
    9. render(){
    10. return <h3>haha</h3>
    11. }
    12. }
  • props ```typescript //es5 var MyComponents=React.createClass({ propTypes:{name:React.PropTypes.string} render(){ return

    {this.props.name}

    } })

//es6 class MyComponents extends React.Components{ render(){ return

{this.props.name}

} } MyComponents.propTypes={ name:PropTypes.string }

  1. - state
  2. ```typescript
  3. //es5
  4. var MyComponents=React.createClass({
  5. getInitialState:{name:'haha'},
  6. render(){
  7. return <h3>{this.state.name}</h3>
  8. }
  9. })
  10. //es6
  11. class MyComponents extends React.Components{
  12. constructor(){
  13. super()
  14. this.state={name:'haha'}
  15. }
  16. render(){
  17. return <h3>{this.state.name}</h3>
  18. }
  19. }

为什么浏览器无法读取jsx?

浏览器只能处理Javascript对象,而不能读取Javascript对象中的jsx。为了让浏览器读取Jsx对象,需要使用Babel这样的jsx转换器,将jsx转成JavaScript让浏览器读取。

React的合成事件是什么?

合成事件是围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同的浏览器的行为合并为一个API。这么做为了确保事件在不同浏览器显示一致的属性。

为什么需要React的路由?

React用来定义多个路由,当用户定义特定的Url时,如果url和Router定义的的任何的路由的路径匹配,用户将重定向到该特定的路由。所以需要在应用中添加一个Router库,允许创建多个路由,每个路由都会给我们提供一个独特的视图。

React通讯方式

父组件向子组件通讯:props
子组件向父组件通讯:props+回调函数
兄弟组件通讯:找到共同的父节点,结合父节点,转发通讯
跨层级通讯:Context provider和consumer
发布订阅模式:发布者发布事件,订阅者监听事件并做出反应,引入event模块
全局状态管理工具:借助redux和Mobx。

mixin、hoc、Render props、react-hooks优劣如何?

Mixin的缺陷:

  • 组件与Mixin存在隐性依赖,导致依赖关系不透明,维护成本和理解成本高。
  • 多个Mixin之间可能冲突(定义的state的字段相同)

HOC:

  • HOC通过外层组件通过props影响内层组件的状态,而不是直接改变State,降低了耦合性
  • HOC存在天然的层级结构(组件书结构),降低复杂度

HOC缺陷:

  • HOC无法从外部访问子组件的state,所以无法通过shouldComponentUpdat过滤不必要的更新-后续可以通过React.PureComponent解决这个问题
  • Ref传递问题:Ref被隔断,-后续React.forwardRef解决问题
  • HOC可能出现包裹多层组件的情况,增加复杂度
  • 不可见性原有外层再包装一个组件,不清楚外层的包装
  • 命名冲突:高阶足见多次嵌套,没有使用命名空间容易导致冲突,覆盖老属性

Render props 解决HOC缺陷

  • 嵌套过深
  • 使用繁琐:HOC可以借助装饰器语法

React Hooks

  • 简洁:解决HOC和Render的嵌套问题
  • 解耦:将UI与状态分开
  • 函数友好:函数式组件:解决this指向问题,生命周期等。
  • 组合:hooks可以用另外的hooks形成新的hooks,变化万千。

缺陷:
破坏了PureComponent浅比较的性能优化效果(为了去最新的props和state,每次render都要重新创建事件处理函数。==可以使用React.memo,使用useMome,useCallback

如何理解Fiber?

React Fiber可以理解为:React内部实现的一套状态更新机制,支持任务不同优先级,可
中断与恢复,再恢复后可以服用之前的中间状态。

  1. 作为架构,之前的React15的Reconciler采用递归的方式执行,数据保存在递归调用栈中(stack Reconciler)。React16的Reconciler基于Fiber节点实现,被称为Fiber Reconciler。
  2. 作为静态的数据结构来说,每一个Fiber节点对应一个React element,保存该组件的类型(函数组件/类组件/原生组件…)对应的Dom节点等信息
  3. 作为动态的工作单元来说,每一个Fiber节点保存是本次更新该组件改变的状态,要执行的工作(需要被删除/被插入页面中/被更新…)
  4. https://www.yuque.com/jianlegelaji/sobbrd/uyuwis