面试中问框架,常常会问到一些原理性的东西,明明一直在用,也知道怎么用, 但面试时却答不上来,也是挺尴尬的,就干脆把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
shouldComponentUpdate
,这个方法用来判断是否须要调用 render 方法重绘 dom。
由于 dom 的描绘很是消耗性能,若是咱们能在这个方法中可以写出更优化的 dom diff 算法,能够极大的提升性能。web
1.把树形结构按照层级分解,只比较同级元素。 2.经过给列表结构的每一个单元添加的惟一 key值进行区分同层次的子节点的比较。 3.React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字) 4.合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty. 到每个事件循环结束, React 检查全部标记 dirty 的 component 从新绘制。 5.选择性渲染。开发人员能够重写 shouldComponentUpdate 提升 diff 的性能。
图片源自:react精髓之一---diff算法面试
实现原理:算法
1. 用 js对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中。 2. 当状态变动的时候,从新构造一棵新的对象树。而后对比新旧虚拟DOM树,记录两棵树差别。 3. 把 2 所记录的差别应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。 缘由:虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法减小了对真实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
state 是一种数据结构
,用于组件挂载时所需数据的默认值。state 可能会随着时间的推移而发生突变,但多数时候是做为用户事件行为的结果。
Props则是组件的配置
。props 由父组件传递给子组件,而且就子组件而言,props 是不可变的(immutable)
。
父子:父传子:props; 子传父:子调用父组件中的函数并传参;
兄弟:利用redux实现。
全部关系都通用的方法:利用PubSub.js
订阅
原理:当调用setState时,它并不会当即改变,而是会把要修改的状态放入一个任务队列,等到事件循环结束时,再合并指更新。
所以,setState有 异步,合并更新
更新两个特性。
这里应该须要了解下 Batch Update 。
使用:
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 })
参考连接: React 中 setState() 为何是异步的?、 react的setstate原理
1.保证内部的一致性
由于props是要等到父组件渲染事后才能拿到,也就是不能同步更新,state出于统一性设成异步更新。
2.性能优化
举例说你正在一个聊天窗口输入,若是来了一条新消息又要render,那就会阻塞你的当前操做,致使延迟什么的。
3.支持state在幕后渲染
异步可使state在幕后更新,而不影响你当前旧的页面的交互,提高用户体验。
详情能够点击上面的参考连接,写的很详细的。
另外:setstate在原生事件,setTimeout,setInterval,promise等异步操做
中,state会同步更新
。
优点:
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能够与已知的库或框架很好地配合。
讲一些项目中用到的小的点:
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
有些是我的意见,仅供参考。
相同点:
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,固然这也不是绝对。
用户页面行为触发一个Action
,而后,Store
自动调用 Reducer
,而且传入两个参数:当前 State 和收到的 Action。Reducer 会返回新的 State 。每当state更新以后,view
会根据state触发从新渲染。
Redux做为一个通用模块,主要仍是用来处理应用中state的变动,经过react-redux作链接,能够在React+Redux的项目中将二者结合的更好。
react-redux是一个轻量级的封装库,它主要经过两个核心方法实现:
Provider:从最外部封装了整个应用,并向connect模块传递store。 Connect: 一、包装原组件,将state和action经过props的方式传入到原组件内部。 二、监听store tree变化,使其包装的原组件能够响应state变化
理解:中间件就是要对redux的store.dispatch方法作一些改造,以实现其余的功能。
我用过redux-thunk
,就拿它举例。
背景:Redux 的基本作法,是用户发出 Action,Reducer 函数马上算出新的 State,View 从新渲染,但这是作同步。 而若是有异步请求时,那就不能知道何时获取的数据有存进store里面,所以此时须要在请求成功时返回一个标识或状态,并在此时再触发action给reducer传值。 所以,为了解决异步的问题,就引入了中间件的概念。
做用: redux-thunk 帮助你统一了异步和同步 action 的调用方式,把异步过程放在 action 级别解决,对 component 调用没有影响。
引入使用可参照: 理解redux和redux的中间件redux-thunk的认识
原文连接: 异步方案选型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) 异步操做的流程是能够控制的,能够随时取消相应的异步操做。
缺点:学习成本高。
原文连接不记得了(囧...)
相同点:
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
原理:实现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不太稳定,在升级版本的时候须要进行代码变更。
我只挑了一部分。
原文连接: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是一个预编译模块方案,它会分析你的项目结构将其打包成适合浏览器加载的模块。
打包原理:把全部依赖打包成一个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高阶组件
定义: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'
高阶组件部分还有待补充。