zoukankan      html  css  js  c++  java
  • 知识点总结 REACT

    1、react中如何创建一个组件

      ES6:class 组件名 extends Component{}

      ES5:var App=React.createClass({})

    2、render函数什么时候会执行

      当this.state或者this.props发生改变的时候render函数执行

    3、react中如何对state中的数据进行修改?setState为什么是异步的

      修改数据通过this.setState(参数一,参数二)

      this.setState是一个异步函数

        参数一:需要修改的数据,对象的形式

        参数二:修改成功的回调函数,这里相当于componentDidMount,可以获取到数据更新后的DOM结构

      this.setState中的第一个参数除了可以写成一个对象以外,还可以写成一个函数,函数中第一个值为prevState,第二个值为prePprops    this.setState((prevState,prop)=>{})

      

      为什么setState是异步的:

        当批量执行state的时候可以让DOM渲染的更快,也就是说多个setState在执行的过程中还需要被合并。

     4、react中如何定义自定义属性,以及限制外部数据的类型

      自定义属性:

        组件名.defaultProps={

          key:val

        }

      限制外部数据的类型:

        ①引入propTypes第三方模块

        ②类型限制

          组件名.propTypes={

            key:propTypes.类型

          }

     5、react路由常用的组件配置项

      BrowserRouter  路由的根组件,根组件下面只能有一个子元素

      HashRouter  路由的根组件,根组件下面只能有一个子元素

      withRouter

      Route  路由路径对应的文件

      Link  进行路由的跳转

      NavLink  进行路由的跳转,选中标签的时候NavLink会加上一个class

      Switch  被Switch包裹的Route渲染的时候只会渲染一个路径,建议:子页面不要放在Switch中,主页面放在Switch中

      Redirect  路由重定向

    6、react路由中Route渲染组件的方法有哪几种?区别是什么

      ①<Route path="/home" component={组件名}></Route>

         通过component进行组件的渲染,这种方式的优点在于可以直接在组件的内部接收到history、location、match,缺点在于如果需要传参的组件,或者渲染jsx语法的时候无法使用。

      ②<Route path="/home" render={()=>{

         return <Home/>

       }}></Route>

         通过render进行渲染组件,优点在于可以进行组件传参,还可以渲染非组件的标签,缺点在于如果需要使用history、location、match的话需要在函数中传递过去。

    7、如何控制路由路径的完全匹配

      给NavLink或Route设置exact属性

      

    8、react中路由传参的方法有哪些

        //方案一:通过params进行传值
        <Router path="/one/:id" render={(history)=>{
            return <One history={history} />
        }}>
        </Router>
        //html跳转
        <NavLink to={"/one/"+1}>one</NavLink>
        //js跳转
        this.props.history.push("/one/"+"1")
        //接收值:在组件内部通过constructor接收
        constructor({history,location,match}){
            super();
            console.log(match.params)
        }
    
        //方案二:通过query进行传值
        <Router path="/one" render={(history)=>{
            return <One history={history} />
        }}></Router>
        //html跳转
        <NavLink to={
            pathname:"/one"
            query:{data:1}
        }>one</NavLink>
        //js跳转
        this.props.history.push({pathname:"/one",query:{data:1}})
        //获取值
        this.props.location.query.data
        注意:如果通过render进行渲染的时候需要在回调中将history的值传递过去,
    如果是component进行渲染的话,只需要通过this.props进行接收

    9、react中的编程式导航有哪些

      this.props.history.push("路径")  跳转路径

      this.props.history.back()  返回

      this.props.history.forward()  前进

      this.props.history.replace()  替换

    10、react的生命周期

      组件创建的过程:

        constructor

        componentWillMount

        render

        componentDidMount

      当props中的数据发生改变后会执行哪些生命周期函数:

        componentWillReceiveProps

        shouldComponentUpdate

        componentWillUpdate

        render

        componentDidUpdate

      组件销毁的时候:

        componentWillUnmount

    11、react中如何强制更新DOM

      this.foreUpdate()

    12、谈谈对react中生命周期shouldComponentUpdate的理解

      shouldComponentUpdate是react性能优化非常重要的一环。组件接收新的state或者props时调用,我们设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会产生相同的DOM树,这样就不需要创造新的DOM树和旧的DOM树进行diff算法对比,节省大量性能,尤其是在DOM结构复杂的时候。

    13、谈谈你对虚拟DOM的理解,以及好处

      虚拟DOM:真实的js对象

      好处:虚拟DOM提高了react性能,每次更新数据后都会重新计算上虚拟DOM,并和上一次的虚拟DOM进行对比,对发生变化的部分进行批量更新。react中也提供了shouldComponentUpdate声明周期的回调,来减少数据变化后不必要的虚拟DOM对比过程,保证性能。

    14、谈谈对flux的理解

      利用单项数据流的方式来组合react的视图组件,它是一种模式,而不是一种框架。

      flux可以帮我们解决非父子组件之间的传值

      flux数据传递流程 https://www.cnblogs.com/nanianqiming/p/9870194.html

      

     15、react17版本废除的生命周期,与新增的生命周期函数

      由于未来采用异步渲染机制,所以即将在17版本中去掉的生命周期钩子函数:

        componentWillMount

        componentWillReceiveProps

        componentWillUpdate

      新增的生命周期:

        static  getDeriveStateFromProps(nextProps,prevState){}

        用于替换componentWillReceiveProps,可以用来控制props更新state的过程,它返回一个对象表示新的state,如果不需要更新,返回null即可。在每次渲染之前都会调用,不管初始挂载还是后面的更新都会调用,这一点和componentWillReceiveProps(只有当父组件造成重新渲染时才调用)不同,每次都应该返回新对象。

        getSnapshotBeforeUpdate(){}  

        用于替换componentWillUpdate,该函数会在update后DOM更新前被调用,用于读取最新的DOM数据,返回值将作为componentDidUpdate的第三个参数,在最新的渲染数据提交给DOM前会立即调用,它让你在组件的数据可能要改变之前调用他们。

        componentDidCatch(error,info){}

        如果一个组件定义了componentDidCatch生命周期,则它将成为一个错误边界。错误边界会捕捉渲染期间,在生命周期中和在它们之下整棵树的构造函数中的错误,就像使用了try catch,不会将错误直接抛出了,保证应用的可能性。

    16、this.setState之后做了哪些操作

      shouldComponentUpdate

      componentWillUpdate

      render

      componentDidUpdate

    17、当组件的key值发生改变后会执行哪些生命周期函数

      componentWillUnmount

      constructor

      componentWillMount

      render

      componentDidMount

     

    18、在react中是否封装过组件?封装组件要注意的地方

      常用封装组件用到的东西

        propTypes  限制外部数据的类型

        defaultProps  设置默认的外部数据

        父传子  子传父  context等传值方式

        高阶组件

      封装组价要注意组件的复用性、灵活性

    19、如何接收组件内部的标签/内容

      this.props.children

    20、说一下对redux的理解,以及使用的方式

      其实redux就是Flux的一种进阶实现,它是一个应用数据流框架,主要作用是应用状态的管理。

      redux的三大原则:

        ①单一的数据源

        ②state是只读的

        ③使用纯函数来进行修改

      redux中常用的三个方法:

        ①createStore()  创建store

        ②combineReducers()  合并多个reducer

        ③applyMiddleware()  使用中间件,处理异步的action

      redux数据传递的流程:

        当组件需要改变store的时候,需要创建一个action,然后通过dispatch(action)传递给store,然后store把action转发给reducers。reducers会拿到previousState(以前的state数据)和action。然后将previousState和action进行结合做新的数据(store)修改。然后生成一个新的数据传递给store。store通过触发subscribe方法来调用函数执行setState使得view的视图发生改变。

     21、请说下在react中如何处理异步的action

      通过applyMiddleware来使用中间件来处理action

      常用的中间件:

        redux-promise-middleware

        redux-thunk

        redux-saga

    22、请说下对redux中间件的理解

      中间件:请求和回复之间的一个应用

      在redux中,中间件是dispatch和reducer之间的一个应用

    23、请说下redux中你对reducers的理解,以及如何合并多个reducers

      在redux中reducer是一个纯函数,其中这个纯函数会接收2个参数,一个是state,一个是action。state用来保存公共的状态,state的特点是只能读不能修改。

      在实际开发中因为会涉及到多人协作开发,所以每个模块都有一个reducer,我们可以通过combineReducers来合并多个reducers。

    24、请说下对高阶组件的理解,以及作用

      高阶组件:它是一个函数,接收一个组件作为参数,返回一个相对增强性的组件。

      高阶组件是一个函数,并不是组件。

      作用:

        ①属性代理----主要进行组件的复用(最常见的高阶组件的使用方式,通过做一些操作,将被包裹组件的props和新生成的props一起传递给此组件)

        ②反向继承----主要进行渲染的劫持(返回的react组件继承了被传入的组件,所以它能访问到的区域、权限更多,想比属性代理的方式,它更像是打入组件内部,对其进行修改)

    25、在react中如何解决单页面开发首次加载白屏现象

      ①通过路由懒加载的方式  react-loadable

      ②首屏服务端渲染

    26、请说下react中key值的理解

      react利用key来识别组件,它是一种身份标识,相同的key值react认为是同一个组件,这样后续相同的key对应的组件都不会被创建。

      有了key属性后,就可以与组件建立一种对应关系,react根据key来决定是销毁重新创建组件还是更新组件。

      key相同,若组件属性有所变化,则react只更新组件对应的属性,没有变化则不更新。

      key值不同,则react先销毁该组件(有状态组件的componentWillUnmount会执行),然后重新创建该组件(有状态组件的constructor和componentWIllUnmount都会执行)。

    27、组件第一次执行的时候会执行哪些生命周期函数

      constructor

      componentWillMount

      render

      componentDidMount

      

    28、哪些声明周期会执行多次

      render

      componentWillReceiveProps

      shouldComponentUpdate

      componentWillUpdate

      componentDidUpdate

    29、当this.state和this.props执行的时候会执行哪些生命周期函数

      this.state

        shouldComponentUpdate

        componentWillUpdate

        render

        componentDidUpdate

      this.props

        componentWillReceiveProps

        shouldComponentUpdate

        render

        componentDidUpdate

      

    30、谈谈对context的理解

      当不想在组件树中通过逐层传递props或state的方式来传递数据时,可以使用context来实现跨层级的组件数据传递,使用context可以实现跨组件传递。

      旧版context的基本使用:

        ①getChildContext根组件中声明,一个函数,返回一个对象,就是context

        ②childContextTypes根组件中声明,指定context的结构类型,如不指定会产生错误

        ③contextTypes子孙组件中声明,指定要接收的context的结构类型,可以只是context的一部分结构。contextTypes没有定义,context将是一个空对象。

        ④this.context在子孙组件中通过此来获取上下文

      新版context的使用:

        ①根组件中引入GlobalContext,并使用GlobalContext.Provider(生产者)

        ②组件引入GlobalContext并调用context,使用GlobalContext.Consumer

    31、谈谈对react中withRouter的理解

      默认情况下必须是经过路由匹配渲染的组件在this.props上拥有路由参数,才能使用编程式导航的写法,withRouter是把不通过路由切换过来的组件,将react-router的history、location、match三个对象传入props对象上。

      简单来说就是:不是路由包裹的组件也可以使用路由的一些方法

    32、说说对puerComponent的理解

      puerComponent表示一个纯组件,可以用来优化react程序,减少render函数渲染的次数,提高性能。

      puerComponent进行的是浅比较,也就是说如果是引用数据类型的数据,只会比较不是同一个地址,而不会比较这个地址里的数据是否一致。

      好处:当组件更新时,如果组件的props或state都没有改变,render函数就不会触发,省去虚拟DOM的生成和对比过程,达到提升性能的目的。具体原因是react自动帮我们做了一层浅比较。

    33、react请求接口数据是在componentDidMount还是componentWillMount周期好

      如果你要获取外部数据并加载到组件上,只能在组件“已经”挂载到真是的网页上才能做这件事,其他情况你是加载不到组件的。componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以保证数据的加载。

      react异步渲染开启的时候,componentWillMount就可能中途被打断,中断之后渲染又要重新做一遍,如果在componentWillMount中做ajax调用,代码里看到只有调用一次,但是实际上可能调用n多次,这个浪费了性能。如果把ajax放在componentDidMount中,因为componentDidMount在第二阶段,所以绝对不会多次重复调用,这里是ajax合适的位置。

       

    34、react性能优化

      一、immutable简介

        Immutable Data是一旦创建,就不能修改的数据。对Immutable对象的任何修改或添加删除操作都会返回一个新的Immutable对象。Immutable实现的原理是Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变,同时为了避免deepCopy把所有的节点都复制一遍带来的性能损耗。

      在js中,引用类型的数据,优点在于频繁的操作数据都是在原对象的基础上修改,不会创建新对象,从而可以有效的利用内存,不会浪费内存,这种特性称为mutable(可变),但恰恰它的优点也是它的缺点,太过于灵活多变在复杂数据的场景下也造成了它的不可控性,假设一个对象在多处用到,在某一处不小心修改了数据,其他地方很难预见到数据是如何改变的,针对这种问题的解决方法,一般就像刚才的例子,会想复制一个新对象,再在新对象上做修改,这无疑会造成更多的性能问题以及内存浪费。

      为了解决这种问题,出现了immutable对象,每次修改immutable对象都会创建一个新的不可变对象,而老的对象不会改变。

      二、react中如何减少render函数渲染的次数

        在react中当this.state、this.props发生改变的时候render函数就会执行,但有些时候this.state、this.props没有发生改变的时候render函数也会执行。那么如何减少render函数的执行次数,可以封装一个BaseComponent来减少react中render函数的执行次数。

    import React,{Component}from 'react';
    import {is} from 'immutable';
    
    class BaseComponent extends Component {
        shouldComponentUpdate(newProps, newState) {
            const thisProps = this.props || {};
            const thisState = this.state || {};
            newState = newState || {};
            newProps = newProps || {};
    
            if (Object.keys(thisProps).length !== Object.keys(newProps).length ||
                Object.keys(thisState).length !== Object.keys(newState).length) {
                return true;
            }
    
            for (const key in newProps) {
                if (!is(thisProps[key], newProps[key])) {
                    return true;
                }
            }
    
            for (const key in newState) {
                if (!is(thisState[key], newState[key])) {
                    return true;
                }
            }
            return false;
        }
    }
    
    export default BaseComponent;

         继承BaseComponent来创建开发中所需要的组件:

    import BaseComponent from  "@common/BaseComponent";
    
    export default class Home extends BaseComponent{
      constructor(){
        super()
      }
      ........
    }

     35、react中key值的作用

      react中的key属性,它是一个特殊的属性,它的出现不是给开发者使用的,而是给react自己使用,有了key属性后,就可以与组件建立一种对应关系。react利用key来识别组件,它是一种身份标识,就像每个人都有身份证一样,每个key对应一个组件,相同的key react认为是同一个组件,这样后续相同的key对应的组件都不会被创建。

      key值相同:如果两个元素的key相同,且满足第一点元素类型相同,若元素属性有所变化,则react只更新组件对应的属性,这种情况下性能开销会相对较小。

      key值不相同:在render函数执行的时候,新旧两个虚拟DOM会进行对比,如果两个元素有不同的key,那么前后两次渲染中就会被认为是不同的元素,这时候旧的那个元素会被销毁,新的元素会被创建。

    //更新前
    render(){
        return(
            <List key="1"/>
        )
    }
    //更新后
    render(){
        return(
            <List key="2"/>
        )
    }

      例子:

      //tree1
      <ul>
          <li key="1">1</li>
          <li key="2">2</li>
      </ul>
      //tree2
      <ul>
          <li key="1">1</li>
          <li key="3">3</li>
          <li key="2">2</li>
      </ul>

      如果没有key值,react并不会执行插入操作,它会直接移除原先的第二个子元素,然后在append进去剩下的子元素,而其实我们这个操作只需要一个insert操作就能完成。为了解决这种问题,react需要我们提供一个key来帮助更新,减少性能开销。

      如果有key值,react就会通过key来发现剩下tree2的第二个子元素不是原先tree1的第二个元素,原先的第二个元素被挪到下面去了,因此在操作的时候就会直接指向insert操作,来减少DOM操作的性能开销。

      不推荐用属性中的index来做key值

        大部分情况下我们要在执行数据遍历的时候会用index来表示元素的key,这样做其实并不是很合理。我们用key的真实目的是为了标识前后两次渲染中元素的对应关系,防止发生不必要的更新操作。那么如果我们用index来标识key,数据在执行插入、排序等操作之后,原先的index并不再对应到原先的值,那么这个key就失去了本身的意义,还会带来其他问题。

      注意事项

        react中的key值必须保证其唯一和稳定性

        下面案例中的key值以Math.random()随机生成而定,这使得数组元素中的每项都重新销毁然后重新创建,有一定的性能开销

      {
          dataList.map((item,index)=>{
              return <div key={Math.random()}>{item.name}</div>
          })
      }

      

      

  • 相关阅读:
    Freemarker中JS取Data-model的值的问题
    Jquery动态添加元素并给元素增加onchange相应
    [算法] 动态规划
    Linux安装mysql.8.0.12
    Linux命令
    [算法] 并查集
    Flume整合Kafka完成实时数据采集
    Kafka 单节点部署
    Spark Streaming——Flume实例
    Spark实战——日志分析
  • 原文地址:https://www.cnblogs.com/wuqilang/p/11594968.html
Copyright © 2011-2022 走看看