React专题:react,redux以及react-redux常见一些面试题

面试中问框架,常常会问到一些原理性的东西,明明一直在用,也知道怎么用,
但面试时却答不上来,也是挺尴尬的,就干脆把react相关的问题查了下资料,再按本身的理解整理了下这些答案。

react生命周期有哪些

组件载入阶段:
componentWillMount:组件即将被装载、渲染到页面上,只调用1次
componentDidMount:组件真正在被装载以后,这里能够拿到真实DOM执行操做,只调用1次css

运行中状态:
componentWillReceiveProps(nextProps):组件将要接收到新属性的时候调用,在这时setState不会触发额外的render,由于此时已经有一次来自父组件引起的render了。html

shouldComponentUpdate:组件接受到新属性或者新状态的时候(返回 false,接收数据后不更新,阻止 render ,后面的函数不会继续执行)
componentWillUpdate:组件即将更新不能修改属性和状态
componentDidUpdate:组件已经更新vue

销毁阶段:
componentWillUnmount:组件即将销毁,这时候能够销毁绑定的事件监听或者定时器什么的。react

有些好像把render也算进生命周期了:
render:组件在这里生成虚拟的 DOM 节点webpack

react在哪一个生命周期作优化

shouldComponentUpdate,这个方法用来判断是否须要调用 render 方法重绘 dom。
由于 dom 的描绘很是消耗性能,若是咱们能在这个方法中可以写出更优化的 dom diff 算法,能够极大的提升性能。web

react的diff算法是怎么完成的

1.把树形结构按照层级分解,只比较同级元素。
2.经过给列表结构的每一个单元添加的惟一 key值进行区分同层次的子节点的比较。
3.React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
4.合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.
    到每个事件循环结束, React 检查全部标记 dirty 的 component 从新绘制。
5.选择性渲染。开发人员能够重写 shouldComponentUpdate 提升 diff 的性能。

clipboard.png
图片源自:react精髓之一---diff算法面试

react虚拟DOM实现原理,以及为何虚拟 dom 会提升性能

实现原理:算法

1. 用 js对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中。
2. 当状态变动的时候,从新构造一棵新的对象树。而后对比新旧虚拟DOM树,记录两棵树差别。
3. 把 2 所记录的差别应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

缘由:虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法减小了对真实DOM的操做次数,从而提升性能。

react怎么从虚拟dom中拿出真实dom

Refs 是 React 提供给咱们的安全访问 DOM 元素或者某个组件实例的句柄。
咱们能够为元素添加 ref 属性而后在回调函数中接受该元素在 DOM 树中的句柄,该值会做为回调函数的第一个参数返回。或者ref能够传字符串。vuex

例如:<input ref=((input)=>{return this.name=input}) />, this.name.value取值
或者 <input ref="name" />,this.refs.name取值json

React中的props和state的用法

state 是一种数据结构,用于组件挂载时所需数据的默认值。state 可能会随着时间的推移而发生突变,但多数时候是做为用户事件行为的结果。
Props则是组件的配置。props 由父组件传递给子组件,而且就子组件而言,props 是不可变的(immutable)

react组件之间如何通讯

父子:父传子:props; 子传父:子调用父组件中的函数并传参;
兄弟:利用redux实现。
全部关系都通用的方法:利用PubSub.js订阅

react的setState的原理及用法

原理:当调用setState时,它并不会当即改变,而是会把要修改的状态放入一个任务队列,等到事件循环结束时,再合并指更新。
所以,setState有 异步,合并更新更新两个特性。

这里应该须要了解下 Batch Update

clipboard.png

使用:
1.最多见的用法就是传入一个对象。

this.setState({
        isLoading:false
    })

2.还能够接收一个函数

this.setState((prevState,props)=>{
        // 要作的事件
        return {isLoading:false};
    })

3.由于setState是异步的,因此它还能够接收第二个参数,一个回调函数

this.setState({count:2},()=>{
        isLoading:this.state.count===2 ? true : false
    })

setState为何是异步的

参考连接: React 中 setState() 为何是异步的?react的setstate原理

1.保证内部的一致性

由于props是要等到父组件渲染事后才能拿到,也就是不能同步更新,state出于统一性设成异步更新。

2.性能优化

举例说你正在一个聊天窗口输入,若是来了一条新消息又要render,那就会阻塞你的当前操做,致使延迟什么的。

3.支持state在幕后渲染

异步可使state在幕后更新,而不影响你当前旧的页面的交互,提高用户体验。

详情能够点击上面的参考连接,写的很详细的。

另外:setstate在原生事件,setTimeout,setInterval,promise等异步操做中,state会同步更新

react的优点以及特色

优点:

1. 实现对虚拟DOM的操做,使得它速度快,提升了Web性能。
2. 组件化,模块化。react里每个模块都是一个组件,组件化开发,可维护性高。
3. 单向数据流,比较有序,有便于管理,它随着React视图库的开发而被Facebook概念化。
4. 跨浏览器兼容:虚拟DOM帮助咱们解决了跨浏览器问题,它为咱们提供了标准化的API,甚至在IE8中都是没问题的。

不足:

1. react中只是MVC模式的View部分,要依赖引入不少其余模块开发。、
2. 当父组件进行从新渲染操做时,即便子组件的props或state没有作出任何改变,也会一样进行从新渲染。

特色: 

1. 声明式设计:React采用声明范式,能够轻松描述应用。
2. 高效:React经过对DOM的模拟,最大限度地减小与DOM的交互。
3. 灵活:React能够与已知的库或框架很好地配合。

React如何性能优化

讲一些项目中用到的小的点:

1. 充分利用shouldComponentUpdate函数,不过这须要你的组件尽可能最小化,若是当前组件数据过于复杂,实际上是很难优化的。
2. 给你的DOM遍历上加上惟一的key,注意尽可能不要用index,由于若是你新DOM中删了某一个节点,它会从新排列index,
那跟原来同层级一比就都会彻底不同,而从新渲染了,因此最好使用id值什么的做key值。

3. 能用const声明的就用const。
4. DOM里少用箭头函数,固然其实要传参时也仍是得用。再者,函数bind尽可能写在constructor,避免每次render从新bind。
5. 减小对真实DOM的操做。
6. 若是是用webpack搭建环境的话,当一个包过大加载过慢时,可分打成多个包来优化。
react-perf性能查看工具,可自行了解下: react-perf

react与vue的对比

有些是我的意见,仅供参考。

相同点:

1. 都用虚拟DOM实现快速渲染
2. 我以为父子,兄弟通讯这些都挺像的,也都有本身的状态管理器:react=>redux, vue=>vuex
3. 都是轻量级框架
4. 如今vue也在渐渐吸取react中的一些语法,好比JSX语法,类式声明写法等

不一样点:

1. React属于单向数据流——MVC模式,vue则属于双向——MVVM模式。
2. react兼容性比vue好,vue不兼容IE8.
3. react采用JSX语法,vue采用的则是html模板语法。
4. vue的css能够有组件的私有做用域,react则没有。
5. react比vue好的另外一点是,它是团队维护,而vue属于我的,通常来讲,大型项目更倾向于react,小型则用vue,固然这也不是绝对。

Redux的实现流程

用户页面行为触发一个Action,而后,Store 自动调用 Reducer,而且传入两个参数:当前 State 和收到的 Action。Reducer 会返回新的 State 。每当state更新以后,view会根据state触发从新渲染。

react-redux的实现原理

Redux做为一个通用模块,主要仍是用来处理应用中state的变动,经过react-redux作链接,能够在React+Redux的项目中将二者结合的更好。
react-redux是一个轻量级的封装库,它主要经过两个核心方法实现:

Provider:从最外部封装了整个应用,并向connect模块传递store。
Connect: 
    一、包装原组件,将state和action经过props的方式传入到原组件内部。
    二、监听store tree变化,使其包装的原组件能够响应state变化

redux中间件的理解,以及用过哪些中间件

理解:中间件就是要对redux的store.dispatch方法作一些改造,以实现其余的功能。

我用过redux-thunk,就拿它举例。

背景:Redux 的基本作法,是用户发出 Action,Reducer 函数马上算出新的 State,View 从新渲染,但这是作同步。

而若是有异步请求时,那就不能知道何时获取的数据有存进store里面,所以此时须要在请求成功时返回一个标识或状态,并在此时再触发action给reducer传值。
所以,为了解决异步的问题,就引入了中间件的概念。

做用: redux-thunk 帮助你统一了异步和同步 action 的调用方式,把异步过程放在 action 级别解决,对 component 调用没有影响。

引入使用可参照: 理解redux和redux的中间件redux-thunk的认识

redux-thunk VS redux-saga对比 异步处理方案中间件

原文连接: 异步方案选型redux-saga 和 redux-thunk

redux-thunk
缺点:

(1).一个异步请求的action代码过于复杂,且异步操做太分散,相对比saga只要调用一个call方法就显得简单多了。
(2).action形式不统一,若是不同的异步操做,就要写多个了。

优势:学习成本低

redux-saga:
优势:

(1)集中处理了全部的异步操做,异步接口部分一目了然(有提供本身的方法)
(2)action是普通对象,这跟redux同步的action如出一辙({type:XXX})
(3)经过Effect,方便异步接口的测试
(4)经过worker和watcher能够实现非阻塞异步调用,而且同时能够实现非阻塞调用下的事件监听
(5) 异步操做的流程是能够控制的,能够随时取消相应的异步操做。

缺点:学习成本高。

比较redux和vuex的区别

原文连接不记得了(囧...)
相同点:

1.数据驱动视图,提供响应式的视图组件
2.都有virtual DOM, 组件化开发,经过props参数进行父子组件数据的传递,都实现webComponents规范
3.都支持服务端渲染  
4.都有native解决方案,reactnative(facebook团队) vs weex(阿里团队)

不一样点:

1.vuex是一个针对VUE优化的状态管理系统,而redux仅是一个常规的状态管理系统(Redux)与React框架的结合版本。
2.开发模式:React自己,是严格的view层,MVC模式;Vue则是MVVM模式的一种方式实现
3.数据绑定:Vue借鉴了angular,采起双向数据绑定的方式;React,则采起单向数据流的方式
4.数据更新:Vue采起依赖追踪,默认是优化状态:按需更新;
    React在则有两种选择:
    1)手动添加shouldComponentUpdate,来避免冗余的vdom,re-render的状况
    2)Components 尽量都用 pureRenderMixin,而后采用 redux 结构 + Immutable.js
5.社区:react相比来说仍是要大于vue,毕竟背后支撑团队不一样。
    facebook vs 我的!固然目前vue的增加速度是高于react的增速,不知道将来的发展趋势是如何。

总之:期待构建一个大型应用程序——选择React,期待应用尽量的小和快——选择Vue

react-router的实现原理

原理:实现URL与UI界面的同步。其中在react-router中,URL对应Location对象,
而UI是由react components来决定的,这样就转变成location与components之间的同步问题。

优势:

1.风格: 与React融为一体,专为react量身打造,编码风格与react保持一致,例如路由的配置能够经过component来实现
2.简单: 不须要手工维护路由state,使代码变得简单
3.强大: 强大的路由管理机制,体如今以下方面
4.路由配置: 能够经过组件、配置对象来进行路由的配置
5.路由切换: 能够经过<Link> Redirect进行路由的切换
6.路由加载: 能够同步记载,也能够异步加载,这样就能够实现按需加载
7.使用方式: 不只能够在浏览器端的使用,并且能够在服务器端的使用

缺点:API不太稳定,在升级版本的时候须要进行代码变更。

react router3到4有什么改变

我只挑了一部分。
原文连接:https://blog.csdn.net/qq_3548...

1. V4再也不使用V3里的{props.children}(表明全部路由-我的理解),而V4丢给 DOM 的是咱们的应用程序自己.
2. V4还同时支持同时渲染多个路由,1和2均可参照下面代码,当访问 /user 时,两个组件都会被渲染。(V3可实现但过程复杂)
<div className="primary-layout">
    <header>
      Our React Router 4 App
      <Route path="/user" component={UsersMenu} />
    </header>
    <main>
      <Route path="/" exact component={HomePage} />
      <Route path="/user" component={UsersPage} />
    </main>
  </div>;
3.获取路由的路径匹配,可使用props.match.path获取,match上还有match.params,match.url等属性。
注:url是浏览器的url的一部分,path是给router写的路径
4.多了一个限制未登陆的用户访问某些路由功能,能够在应用程序顶端中设置一个主入口,区别登陆和未登陆UI展现界面。

对webpack的理解:

参考连接: webpack配置整理

概念: webpack是一个预编译模块方案,它会分析你的项目结构将其打包成适合浏览器加载的模块。
打包原理:把全部依赖打包成一个bundle.js文件,经过代码分割成单元片断并按需加载。
核心思想:

1.一切皆模块,一个js,或者一个css文件也都当作一个模块,
2.按需加载,传统的模块打包工具(module bundlers)最终将全部的模块编译生成一个庞大的bundle.js文件。
    可是在真实的app里边,“bundle.js”文件可能有10M到15M之大可能会致使应用一直处于加载中状态。
    所以Webpack使用许多特性来分割代码而后生成多个“bundle”文件,并且异步加载部分代码以实现按需加载。

基础配置项:

1. entry:{} 入口,支持多入口
2. output 出口
3. resolve 处理依赖模块路径的解析
4. module 处理多种文件格式的loader
5. plugins 除了文件格式转化由loader来处理,其余大多数由plugin来处理
6. devServer 配置 webpack-dev-server
7. 搭配package.json配置环境变量,以及脚本配置。
"scripts": {
    "build": "webpack --mode production",
    "start": "webpack-dev-server --mode development"
}

"scripts": {
    "build_": "NODE_ENV=production webpack",
    "start_": "NODE_ENV=development webpack-dev-server"
}

react高阶组件

参考资料: 浅谈React高阶组件
通俗理解 React 高阶函数
深刻浅出React高阶组件
定义:js里的高阶函数的定义是接收一个函数做为参数,并返回一个函数。redux的connect就是一个高阶函数。
那react高阶组件就是指接收一个react组件做为入参,并返回一个新react组件的组件。

好处:它不用关心组件从哪来,也就是不用本身去引入不少个组件了。
一个简单的高阶组件:(写法不是惟一)

export default function withHeader(WrappedComponent){
        return class HOC extends component{
            return (
                <div className="wrap">
                    <div>这是一段普通的文字</div>
                    <WrappedComponent {...this.props} />
                </div>
            )
        }
    }

直接引入:import withHeader from 'withHeader'

高阶组件部分还有待补充。

相关文章
相关标签/搜索