写点什么

react 高频面试题自测

作者:beifeng1996
  • 2022-10-14
    浙江
  • 本文字数:4729 字

    阅读完需:约 16 分钟

createElement 和 cloneElement 有什么区别?

createElement 是 JSX 被转载得到的,在 React 中用来创建 React 元素(即虚拟 DOM)的内容。cloneElement 用于复制元素并传递新的 props。

了解 redux 吗?

  • redux 是一个应用数据流框架,主要解决了组件之间状态共享问题,原理是集中式管理,主要有三个核心方法:action store reduce

  • 工作流程 view 调用 store 的 dispatch 接受 action 传入的 store,reduce 进行 state 操作

  • view 通过 store 提供的 getState 获取最新的数据

  • redux 的优点:

  • 新增的 state 对状态的管理更加明确

  • 流程更加规范,减少手动编写代码,提高编码效率

  • redux 的缺点:

  • 当数据更新是有时候组件不需要,也要重新绘制,影响效率

哪个生命周期发送 ajax

  • componentWillMount 在新版本 react 中已经被废弃了

  • 在做 ssr 项目时候,componentWillMount 要做服务端数据的获取,不能被占用

  • 所以在 componentDidMount 中请求

什么是高阶组件(HOC)

  • 高阶组件(Higher Order Componennt)本身其实不是组件,而是一个函数,这个函数接收一个元组件作为参数,然后返回一个新的增强组件,高阶组件的出现本身也是为了逻辑复用,举个例子


function withLoginAuth(WrappedComponent) {  return class extends React.Component {
constructor(props) { super(props); this.state = { isLogin: false }; }
async componentDidMount() { const isLogin = await getLoginStatus(); this.setState({ isLogin }); }
render() { if (this.state.isLogin) { return <WrappedComponent {...this.props} />; }
return (<div>您还未登录...</div>); } }}
复制代码

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

shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在shouldComponentUpdate方法中能够写出更优化的dom diff算法,可以极大的提高性能

调和阶段 setState 内部干了什么

  • 当调用 setState 时,React 会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态

  • 这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)

  • 一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较( diff )


通过这样做, React 将会知道发生的确切变化,并且通过了解发生什么变化,只需在绝对必要的情况下进行更新即可最小化 UI 的占用空间

为什么不直接更新 state 呢 ?

如果试图直接更新 state ,则不会重新渲染组件。


// 错误This.state.message = 'Hello world';
复制代码


需要使用setState()方法来更新 state。它调度对组件state对象的更新。当state改变时,组件通过重新渲染来响应:


// 正确做法This.setState({message: ‘Hello World’});
复制代码

Redux 中间件原理

  • 指的是 action 和 store 之间,沟通的桥梁就是 dispatch,action 就是个对象。比如你用了 redux-thunk,action 也可以是个函数,怎么实现这个过程,就是通过中间件这个桥梁帮你实现的。action 到达 store 之前会走中间件,这个中间件会把函数式的 action 转化为一个对象,在传递给 store

类组件(Class component)和函数式组件(Functional component)之间有何不同

  • 类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态

  • 当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件(dumb components)或展示组件


参考:前端react面试题详细解答

同时引用这三个库 react.js、react-dom.js 和 babel.js 它们都有什么作用?

  • react:包含 react 所必须的核心代码

  • react-dom:react 渲染在不同平台所需要的核心代码

  • babel:将 jsx 转换成 React 代码的工具

React 中的高阶组件运用了什么设计模式?

使用了装饰模式,高阶组件的运用:


function withWindowWidth(BaseComponent) {  class DerivedClass extends React.Component {    state = {      windowWidth: window.innerWidth,    }    onResize = () => {      this.setState({        windowWidth: window.innerWidth,      })    }    componentDidMount() {      window.addEventListener('resize', this.onResize)    }    componentWillUnmount() {      window.removeEventListener('resize', this.onResize);    }    render() {      return <BaseComponent {...this.props} {...this.state}/>    }  }  return DerivedClass;}const MyComponent = (props) => {  return <div>Window width is: {props.windowWidth}</div>};export default withWindowWidth(MyComponent);
复制代码


装饰模式的特点是不需要改变 被装饰对象 本身,而只是在外面套一个外壳接口。JavaScript 目前已经有了原生装饰器的提案,其用法如下:


@testable   class MyTestableClass {}
复制代码

React key 是干嘛用的 为什么要加?key 主要是解决哪一类问题的

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。


在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系。


注意事项:


  • key 值一定要和具体的元素—一对应;

  • 尽量不要用数组的 index 去作为 key;

  • 不要在 render 的时候用随机数或者其他操作给元素加上不稳定的 key,这样造成的性能开销比不加 key 的情况下更糟糕。

什么是上下文 Context

Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。


  • 用法:在父组件上定义 getChildContext 方法,返回一个对象,然后它的子组件就可以通过 this.context 属性来获取


import React,{Component} from 'react';import ReactDOM from 'react-dom';import PropTypes from 'prop-types';class Header extends Component{    render() {        return (            <div>                <Title/>            </div>        )    }}class Title extends Component{    static contextTypes={        color:PropTypes.string    }    render() {        return (            <div style={{color:this.context.color}}>                Title            </div>        )    }}class Main extends Component{    render() {        return (            <div>                <Content>                </Content>            </div>        )    }}class Content extends Component{    static contextTypes={        color: PropTypes.string,        changeColor:PropTypes.func    }    render() {        return (            <div style={{color:this.context.color}}>                Content                <button onClick={()=>this.context.changeColor('green')}>绿色</button>                <button onClick={()=>this.context.changeColor('orange')}>橙色</button>            </div>        )    }}class Page extends Component{    constructor() {        super();        this.state={color:'red'};    }    static childContextTypes={        color: PropTypes.string,        changeColor:PropTypes.func    }    getChildContext() {        return {            color: this.state.color,            changeColor:(color)=>{                this.setState({color})            }        }    }    render() {        return (            <div>                <Header/>                <Main/>            </div>        )    }}ReactDOM.render(<Page/>,document.querySelector('#root'));
复制代码

简述 flux 思想

Flux 的最大特点,就是数据的"单向流动"。


  • 用户访问 View

  • View发出用户的 Action

  • Dispatcher 收到Action,要求 Store 进行相应的更新

  • Store 更新后,发出一个"change"事件

  • View 收到"change"事件后,更新页面

在 React 中页面重新加载时怎样保留数据?

这个问题就设计到了数据持久化, 主要的实现方式有以下几种:


  • Redux: 将页面的数据存储在 redux 中,在重新加载页面时,获取 Redux 中的数据;

  • data.js: 使用 webpack 构建的项目,可以建一个文件,data.js,将数据保存 data.js 中,跳转页面后获取;

  • sessionStorge: 在进入选择地址页面之前,componentWillUnMount 的时候,将数据存储到 sessionStorage 中,每次进入页面判断 sessionStorage 中有没有存储的那个值,有,则读取渲染数据;没有,则说明数据是初始化的状态。返回或进入除了选择地址以外的页面,清掉存储的 sessionStorage,保证下次进入是初始化的数据

  • history API: History API 的 pushState 函数可以给历史记录关联一个任意的可序列化 state,所以可以在路由 push 的时候将当前页面的一些信息存到 state 中,下次返回到这个页面的时候就能从 state 里面取出离开前的数据重新渲染。react-router 直接可以支持。这个方法适合一些需要临时存储的场景。

React 中 keys 的作用是什么?

KeysReact 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识


  • 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性

如何用 React 构建( build)生产模式?

通常,使用 Webpack 的 DefinePlugin 方法将 NODE ENV 设置为 production。这将剥离 propType 验证和额外的警告。除此之外,还可以减少代码,因为 React 使用 Uglify 的 dead-code 来消除开发代码和注释,这将大大减少包占用的空间。

class 类的 key 改了,会发生什么,会执行哪些周期函数?

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。


答:componentWillMount componentDidMount render

componentWillReceiveProps 调用时机

  • 已经被废弃掉

  • 当 props 改变的时候才调用,子组件第二次接收到 props 的时候

什么是高阶组件

高阶组件不是组件,是 增强函数,可以输入一个元组件,返回出一个新的增强组件


  • 属性代理 (Props Proxy) 在我看来属性代理就是提取公共的数据和方法到父组件,子组件只负责渲染数据,相当于设计模式里的模板模式,这样组件的重用性就更高了


function proxyHoc(WrappedComponent) {    return class extends React.Component {        render() {            const newProps = {                count: 1            }            return <WrappedComponent {...this.props} {...newProps} />        }    }}
复制代码


  • 反向继承


const MyContainer = (WrappedComponent)=>{    return class extends WrappedComponent {        render(){            return super.render();        }    }}
复制代码


用户头像

beifeng1996

关注

还未添加个人签名 2022-09-01 加入

还未添加个人简介

评论

发布
暂无评论
react高频面试题自测_React_beifeng1996_InfoQ写作社区