zoukankan      html  css  js  c++  java
  • 【React】相关题目总结

    1.什么是虚拟DOM?

    一种概念和模式,真实DOM的内存表示,通过ReactDOM这种库和真实DOM进行同步、调和。

    2.props和state的区别

    都是JS对象

    • props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。
    • state 的主要作用是用于组件保存、控制以及修改自己的状态,它只能在 constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state属性会导致组件的重新渲染

    3.类组件和函数组件有什么区别?

    都不能修改props;
    React是单项数据流,子组件视图根据父组件的改变而更新;

    • 类组件

    属性 props 是外界传递过来的,状态 state 是组件本身的,状态可以在组件中任意修改组件的属性和状态改变都会更新视图。
    例如:

    class Welcome extends React.Component {
      render() {
        return (
          <h1>Welcome { this.props.name }</h1>
        );
      }
    }
    ReactDOM.render(<Welcome name='react' />, document.getElementById('root'));
    
    • 函数组件
      函数组件接收一个单一的 props 对象并返回了一个React元素
    function Welcome (props) { 
    	return <h1>Welcome {props.name}</h1> 
    } 
    ReactDOM.render(<Welcome name='react' />, 
    document.getElementById('root'));
    
    • 函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。

    4.refs

    • 使用refs可以进行DOM元素或者某个组件的安全访问。
    • 给一个元素进行refs属性添加,然后接收该元素在DOM树中的句柄,这个值作为回调函数的第一个参数返回
      例如下面代码中:input包含一个refs属性,然后回调函数获取input元素的内容用this绑定到类中,供其他类函数调用
    class UnControlledForm extends Component {
      handleSubmit = () => {
        console.log("Input Value: ", this.input.value)
      }
      render () {
        return (
          <form onSubmit={this.handleSubmit}>
            <input
              type='text'
              ref={(input) => this.input = input} />
            <button type='submit'>Submit</button>
          </form>
        )
      }
    }
    

    当然函数也可以通过闭包,比如下面定义了个inputElement,来模拟this暂存ref属性的回调函数获取的值。

    function CustomForm ({handleSubmit}) {
      let inputElement
      return (
        <form onSubmit={() => handleSubmit(inputElement.value)}>
          <input
            type='text'
            ref={(input) => inputElement = input} />
          <button type='submit'>Submit</button>
        </form>
      )
    }
    
    • 创建refs,通过在构造函数内部创建this.refName = React.createRef();
     class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
      }
      render() {
        return <div ref={this.myRef} />;
      }
    }
    

    5.什么是高阶组件?

    高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。
    这是从React的组成性质派生的一种模式,我们称它们为 “纯”组件, 因为它们可以接受任何动态提供的子组件,但它们不会修改或复制其输入组件的任何行为。

    const EnhancedComponent = higherOrderComponent(WrappedComponent);
    
    • 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧
    • 高阶组件的参数为一个组件返回一个新的组件
    • 组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件

    6.constructor中super与props参数一起使用的目的是什么?

    • 在子类的构造函数constructor中,必须先调用super(props),才能在构造函数内部用this.props
    • 但是构造函数外面的this.props是都可以获取到值的
    //使用props:
    
    class MyComponent extends React.Component {
        constructor(props) {
            super(props);
            console.log(this.props);  // Prints { name: 'sudheer',age: 30 }
        }
    }
    //不使用props:
    
    class MyComponent extends React.Component {
        constructor(props) {
            super();
            console.log(this.props); // Prints undefined
            // But Props parameter is still available
            console.log(props); // Prints { name: 'sudheer',age: 30 }
        }
    
        render() {
            // No difference outside constructor
            console.log(this.props) // Prints { name: 'sudheer',age: 30 }
        }
    }
    

    7.什么是JSX

    JSX即JavaScript XML。一种在React组件内部构建标签的类XML语法。JSX为react.js开发的一套语法糖,也是react.js的使用基础。React在不使用JSX的情况下一样可以工作,然而使用JSX可以提高组件的可读性,因此推荐使用JSX。

    • 优点
    1. 允许使用熟悉的语法来定义 HTML 元素树

    2. 提供更加语义化且移动的标签;

    3. 程序结构更容易被直观化

    4. 抽象了 React Element 的创建过程;

    5. 可以随时掌控 HTML 标签以及生成这些标签的代码;

    6. 原生的 JavaScript

    8.React.createElement

    const element = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    

    等同于

    const element = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    

    9.受控组件和非受控组件

    <input>, <textarea> , 和 <select> 这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。

    • 非受react的控制的组件
    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    class Demo1 extends Component {
        render() {
            return (
                <input />
            )
        }
    }
    
    ReactDOM.render(<Demo1/>, document.getElementById('content'))
    

    在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。

    • 受控组件

    既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。

    class Demo1 extends Component {
        constructor(props) {
            super(props);
            this.state = {
                value: props.value
            }
        }
    
        handleChange(e) {
            this.setState({
                value: e.target.value
            })
        }
    
        render() {
            return (
                <input value={this.state.value} onChange={e => this.handleChange(e)}/>
            )
        }
    }
    

    10.为什么不直接更新state状态?

    我的理解是,因为之前已经初始化了组件的属性,就不能再去直接改变他了,而能够改变这个属性值的办法就是通过state事件,也就是在渲染后进行更新的时候。

    //Wrong
        This.state.message =”Hello world”;
    
    //Correct
    	This.setState({message: ‘Hello World’});
    

    11.ReactJS生命周期有哪些不同阶段?

    初始化和渲染

    在这里插入图片描述

    1. 获取props初始值

    组件类在声明时,会先调用getDefaultProps()方法来获取默认props值,这个方法会且只会在声明组件类时调用一次,这一点需要注意,它返回的默认props由所有实例共享。

    2. 获取state事件

    在组件被实例化之前,会先调用一次实例方法getInitialState()方法,用于获取这个组件的初始state

    3. 实例化之后渲染的准备工作

    componentWillMount方法会在生成虚拟DOM之前被调用,你可以在这里对组件的渲染做一些准备工作,比如计算目标容器尺寸然后修改组件自身的尺寸以适应目标容器等。

    4. render渲染

    创建一个虚拟DOM用来表示组件的结构。对于一个组件来说,render是唯一一个必须的方法。render方法需要满足这几点:
    只能通过this.props或this.state访问数据
    只能出现一个顶级组件
    可以返回null、false或任何React组件
    不能对props、state或DOM进行修改
    需要注意的是,render方法返回的是虚拟DOM

    5. 渲染完成以后对DOM的后续操作

    我们可能需要对DOM做一些操作,比如截屏、上报日志,或者初始化iScroll等第三方非React插件,可以在componentDidMount()方法中做这些事情。当然,你也可以在这个方法里通过this.getDOMNode()方法最终生成DOM节点,然后对DOM节点做爱做的事情,但需要注意做好安全措施,不要缓存已经生成的DOM节点,因为这些DOM节点随时可能被替换掉,所以应该在每次用的时候去读取

    组件被初始化完成后,它的状态会随着用户的操作、时间的推移、数据更新而产生变化,变化的过程是组件声明周期的另一部分——

    更新

    在这里插入图片描述

    1. 根据相关改变预处理数据

    当组件已经被初始化后组件调用者修改组件的属性时,组件的componentWillReceiveProps()方法会被调用,在这里,你可以对外部传入的数据进行一些预处理,比如从props中读取数据写入state

    2.判断是否必须更新,过滤无效渲染

    默认情况下,组件调用者修改组件属性时,React会遍历这个组件的所有子组件,进行“灌水”,将props从上到下一层一层传下去,并逐个执行更新操作,虽然React内部已经进行过很多的优化,这个过程是很快的,如果你追求极致性能或者你发现这个过程花费了太久时间,使用shouldComponentUpdate()——
    有时候,props发生了变化,但组件和子组件并不会因为这个props的变化而发生变化,打个比方,你有一个表单组件,你想要修改表单的name,同时你能够确信这个name不会对组件的渲染产生任何影响,那么你可以直接在这个方法里return false来终止后续行为。这样就能够避免无效的虚拟DOM对比了,对性能会有明显提升。

    如果这个时候有同学仍然饥渴难耐,那么你可以尝试 不可变数据结构(用过mongodb的同学应该懂)。

    3.更新的准备工作

    组件在更新前,React会执行componentWillUpdate()方法,这个方法类似于前面看到的componentWillMount()方法,唯一不同的地方只是这个方法在执行的时候组件是已经渲染过的。需要注意的是,不可以在这个方法中修改props或state,如果要修改,应当在componentWillReceiveProps()中修改

    4.对比虚拟DOM并替换

    然后是渲染,React会拿这次返回的虚拟DOM和缓存中的虚拟DOM进行对比,找出【最小修改点】,然后替换。

    5.更新完成后

    React会调用组件的componentDidUpdate方法,这个方法类似于前面的componentDidMount方法,你仍然可以在这里可以通过this.getDOMNode()方法取得最终的DOM节点。

    销毁

    在这里插入图片描述

    12.React context是什么?

    • 简单说就是,当你不想在组件树中通过逐层传递 props 或者 state 的方式来传递数据时,可以使用 Context 来实现 跨层级
      的组件数据传递。
    • 原来是这个样子的自上往下的数据流

    在这里插入图片描述

    • 在render的渲染时用上this.content.data可以直接跨组件数据传递

    在这里插入图片描述

    13.为什么类方法需要绑定?

    在JavaScript中, this 的值取决于当前上下文。在React类的组件方法中,开发人员通常希望引用组件的方法,因此有必要 将 这些方法 绑定 到该实例。通常,这是在构造函数中完成的,例如:

    class SubmitButton extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isFormSubmitted: false
        };
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleSubmit() {
        this.setState({
          isFormSubmitted: true
        });
      }
    
      render() {
        return (
          <button onClick={this.handleSubmit}>Submit</button>
        )
      }
    }
    

    14.React中的这三个点(…)是做什么的?

    例如,如果this.props包含a:1和b:2,则

    <Modal {...this.props} title='Modal heading' animation={false}>
    

    与以下内容相同:

    <Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>
    

    扩展符号不仅适用于该用例,而且对于创建具有现有对象的大多数(或全部)属性的新对象非常方便-在更新状态时会遇到很多问题,因为您无法修改状态值:

    this.setState(prevState => {
        return {foo: {...prevState.foo, a: "updated"}};
    });
    
  • 相关阅读:
    【Java每日一题】20161202
    【Java每日一题】20161201
    【Java每日一题】20161130
    LeetCode刷题:Reverse Words in a String(翻转字符串中的单词)
    **公司实习生笔试总结
    C++ primer学习笔记_6_函数---函数定义、参数传递
    求职面试--复习笔记3
    求职面试--复习笔记2
    一道经典面试题,atoi函数的实现
    求职面试-算法复习系列
  • 原文地址:https://www.cnblogs.com/SiriusZHT/p/14310771.html
Copyright © 2011-2022 走看看