【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"}};
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值