2021前端react面试题汇总
React视频教程系列
React 实战:CNode视频教程
残缺教程目录:点击查看
React经典教程-从入门到精通
残缺教程目录:点击查看
最新最全前端毕设我的项目(小程序+VUE+Noed+React+uni app+Express+Mongodb)
残缺教程目录:点击查看
2021前端React精品教程
残缺教程目录:点击查看
1. mobox 和 redux 有什么区别?
(1)共同点
- 为了解决状态管理混乱,无奈无效同步的问题对立保护治理利用状态;
- 某一状态只有一个可信数据起源(通常命名为store,指状态容器);
- 操作更新状态形式对立,并且可控(通常以action形式提供更新状态的路径);
- 反对将store与React组件连贯,如react-redux,mobx- react;
(2)区别 Redux更多的是遵循Flux模式的一种实现,是一个 JavaScript库,它关注点次要是以下几方面∶
Action∶ 一个JavaScript对象,形容动作相干信息,次要蕴含type属性和payload属性∶
o type∶ action 类型; o payload∶ 负载数据;复制代码
- Reducer∶ 定义利用状态如何响应不同动作(action),如何更新状态;
Store∶ 治理action和reducer及其关系的对象,次要提供以下性能∶
o 保护利用状态并反对拜访状态(getState());o 反对监听action的散发,更新状态(dispatch(action)); o 反对订阅store的变更(subscribe(listener));复制代码
- 异步流∶ 因为Redux所有对store状态的变更,都应该通过action触发,异步工作(通常都是业务或获取数据工作)也不例外,而为了不将业务或数据相干的工作混入React组件中,就须要应用其余框架配合治理异步工作流程,如redux-thunk,redux-saga等;
Mobx是一个通明函数响应式编程的状态治理库,它使得状态治理简略可伸缩∶
- Action∶定义扭转状态的动作函数,包含如何变更状态;
- Store∶ 集中管理模块状态(State)和动作(action)
- Derivation(衍生)∶ 从利用状态中派生而出,且没有任何其余影响的数据
比照总结:
- redux将数据保留在繁多的store中,mobx将数据保留在扩散的多个store中
- redux应用plain object保留数据,须要手动解决变动后的操作;mobx实用observable保留数据,数据变动后主动解决响应的操作
- redux应用不可变状态,这意味着状态是只读的,不能间接去批改它,而是应该返回一个新的状态,同时应用纯函数;mobx中的状态是可变的,能够间接对其进行批改
- mobx相对来说比较简单,在其中有很多的形象,mobx更多的应用面向对象的编程思维;redux会比较复杂,因为其中的函数式编程思维把握起来不是那么容易,同时须要借助一系列的中间件来解决异步和副作用
- mobx中有更多的形象和封装,调试会比拟艰难,同时后果也难以预测;而redux提供可能进行工夫回溯的开发工具,同时其纯函数以及更少的形象,让调试变得更加的容易
2. Redux 和 Vuex 有什么区别,它们的独特思维
(1)Redux 和 Vuex区别
- Vuex改良了Redux中的Action和Reducer函数,以mutations变动函数取代Reducer,无需switch,只需在对应的mutation函数里扭转state值即可
- Vuex因为Vue主动从新渲染的个性,无需订阅从新渲染函数,只有生成新的State即可
- Vuex数据流的程序是∶View调用store.commit提交对应的申请到Store中对应的mutation函数->store扭转(vue检测到数据变动主动渲染)
艰深点了解就是,vuex 弱化 dispatch,通过commit进行 store状态的一次更变;勾销了action概念,不用传入特定的 action模式进行指定变更;弱化reducer,基于commit参数间接对数据进行转变,使得框架更加繁难;
(2)独特思维
- 单—的数据源
- 变动能够预测
实质上∶ redux与vuex都是对mvvm思维的服务,将数据从视图中抽离的一种计划。
3. Redux 中间件是怎么拿到store 和 action? 而后怎么解决?
redux中间件实质就是一个函数柯里化。redux applyMiddleware Api 源码中每个middleware 承受2个参数, Store 的getState 函数和dispatch 函数,别离取得store和action,最终返回一个函数。该函数会被传入 next 的下一个 middleware 的 dispatch 办法,并返回一个接管 action 的新函数,这个函数能够间接调用 next(action),或者在其余须要的时刻调用,甚至基本不去调用它。调用链中最初一个 middleware 会承受实在的 store的 dispatch 办法作为 next 参数,并借此完结调用链。所以,middleware 的函数签名是({ getState,dispatch })=> next => action。
4. Redux中的connect有什么作用
connect负责连贯React和Redux
(1)获取state
connect 通过 context获取 Provider 中的 store,通过 store.getState()
获取整个store tree 上所有state
(2)包装原组件
将state和action通过props的形式传入到原组件外部 wrapWithConnect 返回—个 ReactComponent 对 象 Connect,Connect 重 新 render 内部传入的原组件 WrappedComponent ,并把 connect 中传入的 mapStateToProps,mapDispatchToProps与组件上原有的 props合并后,通过属性的形式传给WrappedComponent
(3)监听store tree变动
connect缓存了store tree中state的状态,通过以后state状态 和变更前 state 状态进行比拟,从而确定是否调用 this.setState()
办法触发Connect及其子组件的从新渲染
5. React Hooks 解决了哪些问题?
React Hooks 次要解决了以下问题:
(1)在组件之间复用状态逻辑很难
React 没有提供将可复用性行为“附加”到组件的路径(例如,把组件连贯到 store)解决此类问题能够应用 render props 和 高阶组件。然而这类计划须要从新组织组件构造,这可能会很麻烦,并且会使代码难以了解。由 providers,consumers,高阶组件,render props 等其余形象层组成的组件会造成“嵌套天堂”。只管能够在 DevTools 过滤掉它们,但这阐明了一个更深层次的问题:React 须要为共享状态逻辑提供更好的原生路径。
能够应用 Hook 从组件中提取状态逻辑,使得这些逻辑能够独自测试并复用。Hook 使咱们在无需批改组件构造的状况下复用状态逻辑。 这使得在组件间或社区内共享 Hook 变得更便捷。
(2)简单组件变得难以了解
在组件中,每个生命周期经常蕴含一些不相干的逻辑。例如,组件经常在 componentDidMount 和 componentDidUpdate 中获取数据。然而,同一个 componentDidMount 中可能也蕴含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中革除。互相关联且须要对照批改的代码被进行了拆分,而齐全不相干的代码却在同一个办法中组合在一起。如此很容易产生 bug,并且导致逻辑不统一。
在少数状况下,不可能将组件拆分为更小的粒度,因为状态逻辑无处不在。这也给测试带来了肯定挑战。同时,这也是很多人将 React 与状态治理库联合应用的起因之一。然而,这往往会引入了很多抽象概念,须要你在不同的文件之间来回切换,使得复用变得更加艰难。
为了解决这个问题,Hook 将组件中互相关联的局部拆分成更小的函数(比方设置订阅或申请数据),而并非强制依照生命周期划分。你还能够应用 reducer 来治理组件的外部状态,使其更加可预测。
(3)难以了解的 class
除了代码复用和代码治理会遇到困难外,class 是学习 React 的一大屏障。咱们必须去了解 JavaScript 中 this 的工作形式,这与其余语言存在微小差别。还不能遗记绑定事件处理器。没有稳固的语法提案,这些代码十分冗余。大家能够很好地了解 props,state 和自顶向下的数据流,但对 class 却束手无策。即使在有教训的 React 开发者之间,对于函数组件与 class 组件的差别也存在一致,甚至还要辨别两种组件的应用场景。
为了解决这些问题,Hook 使你在非 class 的状况下能够应用更多的 React 个性。 从概念上讲,React 组件始终更像是函数。而 Hook 则拥抱了函数,同时也没有就义 React 的精力准则。Hook 提供了问题的解决方案,无需学习简单的函数式或响应式编程技术
6. 为什么React并不举荐优先思考应用Context?
- Context目前还处于试验阶段,可能会在前面的发行版本中有很大的变动,事实上这种状况曾经产生了,所以为了防止给今后降级带来大的影响和麻烦,不倡议在app中应用context。
- 只管不倡议在app中应用context,然而独有组件而言,因为影响范畴小于app,如果能够做到高内聚,不毁坏组件树之间的依赖关系,能够思考应用context
- 对于组件之间的数据通信或者状态治理,无效应用props或者state解决,而后再思考应用第三方的成熟库进行解决,以上的办法都不是最佳的计划的时候,在思考context。
- context的更新须要通过setState()触发,然而这并不是很牢靠的,Context反对跨组件的拜访,然而如果两头的子组件通过一些办法不影响更新,比方 shouldComponentUpdate() 返回false 那么不能保障Context的更新肯定能够应用Context的子组件,因而,Context的可靠性须要关注
7. React中什么是受控组件和非控组件?
(1)受控组件 在应用表单来收集用户输出时,例如<input><select><textearea>
等元素都要绑定一个change事件,当表单的状态发生变化,就会触发onChange事件,更新组件的state。这种组件在React中被称为受控组件,在受控组件中,组件渲染出的状态与它的value或checked属性绝对应,react通过这种形式打消了组件的部分状态,使整个状态可控。react官网举荐应用受控表单组件。
受控组件更新state的流程:
- 能够通过初始state中设置表单的默认值
- 每当表单的值发生变化时,调用onChange事件处理器
- 事件处理器通过事件对象e拿到扭转后的状态,并更新组件的state
- 一旦通过setState办法更新state,就会触发视图的从新渲染,实现表单组件的更新
受控组件缺点: 表单元素的值都是由React组件进行治理,当有多个输入框,或者多个这种组件时,如果想同时获取到全副的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种状况,呈现了非受控组件。
(2)非受控组件 如果一个表单组件没有value props(单选和复选按钮对应的是checked props)时,就能够称为非受控组件。在非受控组件中,能够应用一个ref来从DOM取得表单值。而不是为每个状态更新编写一个事件处理程序。
React官网的解释:
要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你能够应用 ref来从 DOM 节点中获取表单数据。 因为非受控组件将实在数据贮存在 DOM 节点中,所以在应用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码好看性,并且心愿疾速编写代码,应用非受控组件往往能够缩小你的代码量。否则,你应该应用受控组件。
例如,上面的代码在非受控组件中接管单个属性:
class NameForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { alert('A name was submitted: ' + this.input.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={(input) => this.input = input} /> </label> <input type="submit" value="Submit" /> </form> ); }}复制代码
总结: 页面中所有输出类的DOM如果是现用现取的称为非受控组件,而通过setState将输出的值保护到了state中,须要时再从state中取出,这里的数据就受到了state的管制,称为受控组件。
8. React中refs的作用是什么?有哪些利用场景?
Refs 提供了一种形式,用于拜访在 render 办法中创立的 React 元素或 DOM 节点。Refs 应该审慎应用,如下场景应用 Refs 比拟适宜:
- 解决焦点、文本抉择或者媒体的管制
- 触发必要的动画
- 集成第三方 DOM 库
Refs 是应用 React.createRef()
办法创立的,他通过 ref
属性附加到 React 元素上。要在整个组件中应用 Refs,须要将 ref
在构造函数中调配给其实例属性:
class MyComponent extends React.Component { constructor(props) { super(props) this.myRef = React.createRef() } render() { return <div ref={this.myRef} /> }}复制代码
因为函数组件没有实例,因而不能在函数组件上间接应用 ref
:
function MyFunctionalComponent() { return <input />;}class Parent extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { // 这将不会工作! return ( <MyFunctionalComponent ref={this.textInput} /> ); }}复制代码
但能够通过闭合的帮忙在函数组件外部进行应用 Refs:
function CustomTextInput(props) { // 这里必须申明 textInput,这样 ref 回调才能够援用它 let textInput = null; function handleClick() { textInput.focus(); } return ( <div> <input type="text" ref={(input) => { textInput = input; }} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); }复制代码
留神:
- 不应该适度的应用 Refs
ref
的返回值取决于节点的类型:
- 当
ref
属性被用于一个一般的 HTML 元素时,React.createRef()
将接管底层 DOM 元素作为他的current
属性以创立ref
。 - 当
ref
属性被用于一个自定义的类组件时,ref
对象将接管该组件已挂载的实例作为他的current
。
- 当
当在父组件中须要拜访子组件中的
ref
时可应用传递 Refs 或回调 Refs。9. React组件的构造函数有什么作用?它是必须的吗?
构造函数次要用于两个目标:
- 通过将对象调配给this.state来初始化本地状态
将事件处理程序办法绑定到实例上
所以,当在React class中须要设置state的初始值或者绑定事件时,须要加上构造函数,官网Demo:
class LikeButton extends React.Component {constructor() { super(); this.state = { liked: false }; this.handleClick = this.handleClick.bind(this);}handleClick() { this.setState({liked: !this.state.liked});}render() { const text = this.state.liked ? 'liked' : 'haven\'t liked'; return ( <div onClick={this.handleClick}> You {text} this. Click to toggle. </div> );}}ReactDOM.render(<LikeButton />,document.getElementById('example'));
构造函数用来新建父类的this对象;子类必须在constructor办法中调用super办法;否则新建实例时会报错;因为子类没有本人的this对象,而是继承父类的this对象,而后对其进行加工。如果不调用super办法;子类就得不到this对象。**留神:**- constructor () 必须配上 super(), 如果要在constructor 外部应用 this.props 就要 传入props , 否则不必- JavaScript中的 bind 每次都会返回一个新的函数, 为了性能等思考, 尽量在constructor中绑定事件### 10. React.forwardRef是什么?它有什么作用?React.forwardRef 会创立一个React组件,这个组件可能将其承受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特地有用:- 转发 refs 到 DOM 组件- 在高阶组件中转发 refs