前端面试题视频解说
constructor 为什么不先渲染?
由ES6的继承规定得悉,不论子类写不写constructor,在new实例的过程都会给补上constructor。
所以:constructor钩子函数并不是不可短少的,子组件能够在一些状况略去。比方不本人的state,从props中获取的状况
react 版本差别
react16.8 hooks
React 16之后有三个生命周期被废除(但并未删除)
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
官网打算在17版本齐全删除这三个函数,只保留UNSAVE_前缀的三个函数,目标是为了向下兼容,
react 16.4 新增
getSnapshotBeforeUpdate
getDerivedStateFromProps
对于废除的生命周期函数,官网会采纳逐渐迁徙的形式来实现版本的迁徙:
16.3:为不平安的生命周期引入别名,UNSAFE_componentWillMount、UNSAFE_componentWillReceiveProps 和 UNSAFE_componentWillUpdate。(旧的生命周期名称和新的别名都能够在此版本中应用。)
将来 16.x 版本:为 componentWillMount、componentWillReceiveProps 和 componentWillUpdate 启用废除告警。(旧的生命周期名称和新的别名都将在这个版本中工作,然而旧的名称在开发模式下会产生一个正告。)
17.0:删除 componentWillMount、componentWillReceiveProps 和 componentWillUpdate。(在此版本之后,只有新的 “UNSAFE_” 生命周期名称能够应用。)。
如何在 ReactJS 的 Props上利用验证?
当应用程序在开发模式下运行时,React 将主动查看咱们在组件上设置的所有 props
,以确保它们具备正确的数据类型。对于不正确的类型,开发模式下会在控制台中生成正告音讯,而在生产模式中因为性能影响而禁用它。强制的 props
用 isRequired
定义的。
上面是一组预约义的 prop 类型:
- React.PropTypes.string
- React.PropTypes.number
- React.PropTypes.func
- React.PropTypes.node
React.PropTypes.bool
例如,咱们为用户组件定义了如下的propTypes
import PropTypes from "prop-types";class User extends React.Component { render() { return ( <> <h1>Welcome, {this.props.name}</h1> <h2>Age, {this.props.age}</h2> </> ); }}User.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number.isRequired,};
setState办法的第二个参数有什么用?应用它的目标是什么?
它是一个回调函数,当 setState办法执行完结并从新渲染该组件时调用它。在工作中,更好的形式是应用 React组件生命周期之——“存在期”的生命周期办法,而不是依赖这个回调函数。
export class App extends Component { constructor(props) { super(props); this.state = { username: "雨夜清荷", }; } render() { return <div> {this.state.username}</div>; } componentDidMount() { this.setstate( { username: "有课前端网", }, () => console.log("re-rendered success. ") ); }}
跨级组件的通信形式?
父组件向子组件的子组件通信,向更深层子组件通信:
- 应用props,利用两头组件层层传递,然而如果父组件构造较深,那么两头每一层组件都要去传递props,减少了复杂度,并且这些props并不是两头组件本人须要的。
- 应用context,context相当于一个大容器,能够把要通信的内容放在这个容器中,这样不论嵌套多深,都能够随便取用,对于逾越多层的全局数据能够应用context实现。
// context形式实现跨级组件通信 // Context 设计目标是为了共享那些对于一个组件树而言是“全局”的数据const BatteryContext = createContext();// 子组件的子组件 class GrandChild extends Component { render(){ return ( <BatteryContext.Consumer> { color => <h1 style={{"color":color}}>我是红色的:{color}</h1> } </BatteryContext.Consumer> ) }}// 子组件const Child = () =>{ return ( <GrandChild/> )}// 父组件class Parent extends Component { state = { color:"red" } render(){ const {color} = this.state return ( <BatteryContext.Provider value={color}> <Child></Child> </BatteryContext.Provider> ) }}复制代码
应用箭头函数(arrow functions)的长处是什么
- 作用域平安:在箭头函数之前,每一个新创建的函数都有定义本身的
this
值(在构造函数中是新对象;在严格模式下,函数调用中的this
是未定义的;如果函数被称为“对象办法”,则为根底对象等),但箭头函数不会,它会应用关闭执行上下文的this
值。 - 简略:箭头函数易于浏览和书写
- 清晰:当一切都是一个箭头函数,任何惯例函数都能够立刻用于定义作用域。开发者总是能够查找 next-higher 函数语句,以查看
this
的值
何为纯函数(pure function)
一个纯函数是一个不依赖于且不扭转其作用域之外的变量状态的函数,这也意味着一个纯函数对于同样的参数总是返回同样的后果。
怎么用 React.createElement 重写上面的代码
Question:
const element = ( <h1 className="greeting"> Hello, rdhub.cn! </h1>);
Answer:
const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, rdhub.cn!');
React 性能优化在哪个生命周期?它优化的原理是什么?
react的父级组件的render函数从新渲染会引起子组件的render办法的从新渲染。然而,有的时候子组件的承受父组件的数据没有变动。子组件render的执行会影响性能,这时就能够应用shouldComponentUpdate来解决这个问题。
应用办法如下:
shouldComponentUpdate(nexrProps) { if (this.props.num === nexrProps.num) { return false } return true;}复制代码
shouldComponentUpdate提供了两个参数nextProps和nextState,示意下一次props和一次state的值,当函数返回false时候,render()办法不执行,组件也就不会渲染,返回true时,组件照常重渲染。此办法就是拿以后props中值和下一次props中的值进行比照,数据相等时,返回false,反之返回true。
须要留神,在进行新旧比照的时候,是浅比照,也就是说如果比拟的数据时援用数据类型,只有数据的援用的地址没变,即便内容变了,也会被断定为true。
面对这个问题,能够应用如下办法进行解决:
(1)应用setState扭转数据之前,先采纳ES6中assgin进行拷贝,然而assgin只深拷贝的数据的第一层,所以说不是最完满的解决办法:
const o2 = Object.assign({},this.state.obj) o2.student.count = '00000'; this.setState({ obj: o2, })复制代码
(2)应用JSON.parse(JSON.stringfy())进行深拷贝,然而遇到数据为undefined和函数时就会错。
const o2 = JSON.parse(JSON.stringify(this.state.obj)) o2.student.count = '00000'; this.setState({ obj: o2, })复制代码
何为 JSX
JSX 是 JavaScript 语法的一种语法扩大,并领有 JavaScript 的全副性能。JSX 生产 React "元素",你能够将任何的 JavaScript 表达式封装在花括号里,而后将其嵌入到 JSX 中。在编译实现之后,JSX 表达式就变成了惯例的 JavaScript 对象,这意味着你能够在 if
语句和 for
循环外部应用 JSX,将它赋值给变量,承受它作为参数,并从函数中返回它。
constructor
答案是:在 constructor 函数外面,须要用到props的值的时候,就须要调用 super(props)
- class语法糖默认会帮你定义一个constructor,所以当你不须要应用constructor的时候,是能够不必本人定义的
- 当你本人定义一个constructor的时候,就肯定要写super(),否则拿不到this
- 当你在constructor外面想要应用props的值,就须要传入props这个参数给super,调用super(props),否则只须要写super()
React-Router怎么设置重定向?
应用<Redirect>
组件实现路由的重定向:
<Switch> <Redirect from='/users/:id' to='/users/profile/:id'/> <Route path='/users/profile/:id' component={Profile}/></Switch>复制代码
当申请 /users/:id
被重定向去 '/users/profile/:id'
:
- 属性
from: string
:须要匹配的将要被重定向门路。 - 属性
to: string
:重定向的 URL 字符串 - 属性
to: object
:重定向的 location 对象 - 属性
push: bool
:若为真,重定向操作将会把新地址退出到拜访历史记录外面,并且无奈回退到后面的页面。
Redux 怎么实现属性传递,介绍下原理
react-redux 数据传输∶ view-->action-->reducer-->store-->view。看下点击事件的数据是如何通过redux传到view上:
- view 上的AddClick 事件通过mapDispatchToProps 把数据传到action ---> click:()=>dispatch(ADD)
- action 的ADD 传到reducer上
- reducer传到store上 const store = createStore(reducer);
- store再通过 mapStateToProps 映射穿到view上text:State.text
代码示例∶
import React from 'react';import ReactDOM from 'react-dom';import { createStore } from 'redux';import { Provider, connect } from 'react-redux';class App extends React.Component{ render(){ let { text, click, clickR } = this.props; return( <div> <div>数据:已有人{text}</div> <div onClick={click}>加人</div> <div onClick={clickR}>减人</div> </div> ) }}const initialState = { text:5}const reducer = function(state,action){ switch(action.type){ case 'ADD': return {text:state.text+1} case 'REMOVE': return {text:state.text-1} default: return initialState; }}let ADD = { type:'ADD'}let Remove = { type:'REMOVE'}const store = createStore(reducer);let mapStateToProps = function (state){ return{ text:state.text }}let mapDispatchToProps = function(dispatch){ return{ click:()=>dispatch(ADD), clickR:()=>dispatch(Remove) }}const App1 = connect(mapStateToProps,mapDispatchToProps)(App);ReactDOM.render( <Provider store = {store}> <App1></App1> </Provider>,document.getElementById('root'))复制代码
React-Router 4的Switch有什么用?
Switch 通常被用来包裹 Route,用于渲染与门路匹配的第一个子 <Route>
或 <Redirect>
,它外面不能放其余元素。
如果不加 <Switch>
:
import { Route } from 'react-router-dom'<Route path="/" component={Home}></Route><Route path="/login" component={Login}></Route>复制代码
Route 组件的 path 属性用于匹配门路,因为须要匹配 /
到 Home
,匹配 /login
到 Login
,所以须要两个 Route,然而不能这么写。这样写的话,当 URL 的 path 为 “/login” 时,<Route path="/" />
和<Route path="/login" />
都会被匹配,因而页面会展现 Home 和 Login 两个组件。这时就须要借助 <Switch>
来做到只显示一个匹配组件:
import { Switch, Route} from 'react-router-dom'<Switch> <Route path="/" component={Home}></Route> <Route path="/login" component={Login}></Route></Switch>复制代码
此时,再拜访 “/login” 门路时,却只显示了 Home 组件。这是就用到了exact属性,它的作用就是准确匹配门路,常常与<Switch>
联结应用。只有当 URL 和该 <Route>
的 path 属性完全一致的状况下能力匹配上:
import { Switch, Route} from 'react-router-dom'<Switch> <Route exact path="/" component={Home}></Route> <Route exact path="/login" component={Login}></Route></Switch>
React中的setState批量更新的过程是什么?
调用 setState
时,组件的 state
并不会立刻扭转, setState
只是把要批改的 state
放入一个队列, React
会优化真正的执行机会,并出于性能起因,会将 React
事件处理程序中的屡次React
事件处理程序中的屡次 setState
的状态批改合并成一次状态批改。 最终更新只产生一次组件及其子组件的从新渲染,这对于大型应用程序中的性能晋升至关重要。
this.setState({ count: this.state.count + 1 ===> 入队,[count+1的工作]});this.setState({ count: this.state.count + 1 ===> 入队,[count+1的工作,count+1的工作]}); ↓ 合并 state,[count+1的工作] ↓ 执行 count+1的工作复制代码
须要留神的是,只有同步代码还在执行,“攒起来”这个动作就不会进行。(注:这里之所以屡次 +1 最终只有一次失效,是因为在同一个办法中屡次 setState 的合并动作不是单纯地将更新累加。比方这里对于雷同属性的设置,React 只会为其保留最初一次的更新)。
(在构造函数中)调用 super(props) 的目标是什么
在 super()
被调用之前,子类是不能应用 this
的,在 ES2015 中,子类必须在 constructor
中调用 super()
。传递 props
给 super()
的起因则是便于(在子类中)能在 constructor
拜访 this.props
。
何为 redux
Redux 的根本思维是整个利用的 state 放弃在一个繁多的 store 中。store 就是一个简略的 javascript 对象,而扭转利用 state 的惟一形式是在利用中触发 actions,而后为这些 actions 编写 reducers 来批改 state。整个 state 转化是在 reducers 中实现,并且不应该有任何副作用。
何为高阶组件(higher order component)
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和疏导形象。最常见的可能是 Redux 的 connect
函数。除了简略分享工具库和简略的组合,HOC最好的形式是共享 React 组件之间的行为。如果你发现你在不同的中央写了大量代码来做同一件事时,就应该思考将代码重构为可重用的 HOC。
练习
- 写一个反转其输出的 HOC
- 写一个从 API 提供数据给传入的组件的 HOC
- 写一个实现 shouldComponentUpdate 来防止 reconciliation 的 HOC
- 写一个通过
React.Children.toArray
对传入组件的子组件进行排序的 HOC