react面试题总结

1、当调用 setState的时候,发生了什么操作?

当调用 setState时, React做的第一件事是将传递给setState的对象合并到组件的当前状态,这将启动一个称为和解( reconciliation)的过程。

和解的最终目标是:根据这个新的状态以最有效的方式更新DOM

为此, React将构建一个新的 React虚拟DOM树(可以将其视为页面DOM元素的对象表示方式)。

一旦有了这个DOM树,为了弄清DOM是如何响应新的状态而改变的, React会将这个新树与上一个虚拟DOM树比较

这样做, React会知道发生的确切变化,并且通过了解发生的变化后,在绝对必要的情况下进行更新DOM,即可将因操作DOM而占用的空间最小化。

2、在 React中元素( element)和组件( component)有什么区别?

简单地说,在 React中元素(虛拟DOM)描述了你在屏幕上看到的DOM元素。

换个说法就是,在 React中元素是页面中DOM元素的对象表示方式。在 React中组件是一个函数或一个类,它可以接受输入并返回一个元素。

注意:工作中,为了提高开发效率,通常使用JSX语法表示 React元素(虚拟DOM)。在编译的时候,把它转化成一个 React. createElement调用方法。

3、在构造函数调用 super 并将 props 作为参数传入的作用

  • 在构造函数里调用super的目的是:保证子类(组件里)有this

        ​ 在ES6中,super()函数就是父类的构造函数。所以,在react里定义类组件时,调用               super就是在调用React.Component的构造函数。

  • ​调用super函数时,把props传入的目的是,保证this有属性props;即:在子类(组件)里能够使用this.props

举例:

  • 传递了props
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    console.log(this.props); // { name: 'sudheer',age: 30 }
  }
}
  • 没传递 props
class MyComponent extends React.Component {
  constructor(props) {
    super();
    console.log(this.props); // undefined
    // 但是 Props 参数仍然可用
    console.log(props); // Prints { name: 'sudheer',age: 30 }
  }
  render() {
    // 构造函数外部不受影响
    console.log(this.props); // { name: 'sudheer',age: 30 }
  }
}

4、什么是 React的refs?为什么它们很重要?

refs允许你直接访问DOM元素或组件实例。为了使用它们,可以向组件添加个ref属性。

如果该属性的值是一个回调函数,它将接受底层的DOM元素或组件的已挂载实例作为其第一个参数。可以在组件中存储它。

export class App extends Component  {
    showResult ( ) {
        console. log(this. input. value)
    }
    render ( ) {
        return (
            <div>
                <input  type="text" ref={input => this .input =input } />
                < button onClick={this. showResult.bind(this)}>展示结果</ button>
            </div>
        );
    }
}

如果该属性值是一个字符串, React将会在组件实例化对象的refs属性中,存储一个同名属性,该属性是对这个DOM元素的引用。可以通过原生的 DOM API操作它。

export class App extends Component {
    showResult(){
        console .log ( this.refs.username.value)
    }
    
    render(){
        return (
            <div>
                <input type="text" ref="username"/>
                < button onClick={this. showResu1t.bind (this)}>展示结果</ button>
            </div>
        );
    }
}

react获取dom,ref(不适用于父组件获取子组件DOM)

6221e0da72df4c4c970233a644e7dc9f.jpg

 React.forwardRef(获取组件的dom)

abc996082a52415e9c5e7294e75907fa.jpg

 1ffd1e8af52a4dd782c198ee0637719d.jpg

586e2d2e0eec446abdb42280464c2454.jpg

useInperativeHandle(通过ref暴露子组件中的方法)

cc320cdd75c841a0a99868ef46d65b7f.jpg

ca5682f39a7149559b57f120d298298f.jpg1b973ec5393348428665077fd3fadace.jpg665c86c790f5456c806fc4b5ddfdb405.jpg 

5、React 中的key是什么?为什么它们很重要?

key可以帮助 React跟踪循环创建列表中的虚拟DOM元素,了解哪些元素已更改、添加或删除。

每个绑定key的虚拟DOM元素,在兄弟元素之间都是独一无二的。在 React的和解过程中,比较新的虛拟DOM树与上一个虛拟DOM树之间的差异,并映射到页面中。key使 React处理列表中虛拟DOM时更加高效,因为 React可以使用虛拟DOM上的key属性,快速了解元素是新的、需要删除的,还是修改过的。如果没有key,React就不知道列表中虚拟DOM元素与页面中的哪个元素相对应。所以在创建列表的时候,不要忽略key。

6、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,
    })

react性能优化是在哪个生命周期函数中

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

组件状态数据或者属性数据发生更新的时候,组件会进入存在期,视图会渲染更新。在生命周期方法 should ComponentUpdate中,允许选择退出某些组件(和它们的子组件)的和解过程。

和解的最终目标是根据新的状态,以最有效的方式更新用户界面。如果我们知道用户界面的某一部分不会改变,那么没有理由让 React弄清楚它是否应该更新渲染。通过在 shouldComponentUpdate方法中返回 false, React将让当前组件及其所有子组件保持与当前组件状态相同

react18中的memo

 React.memo

7fcce1456d4244f7baf1b732b81aa9f8.jpg

a173d46dd2c84d7c9b81316a106d6825.jpg

97206dab3d0c4b27844125ffd3c4c771.jpg

fbdb3e1d627d4ba88fac8ab99da02ea1.jpg

604ca13b15d44288817e5497d30b572d.jpg

7、约束性组件( controlled component)与非约束性组件( uncontrolled  component)有什么区别?

在 React中,组件负责控制和管理自己的状态。

如果将HTML中的表单元素( input、 select、 textarea等)添加到组件中,当用户与表单发生交互时,就涉及表单数据存储问题。根据表单数据的存储位置,将组件分成约東性组件和非约東性组件。

约束性组件( controlled component)就是由 React控制的组件,也就是说,表单元素的数据存储在组件内部的状态中,表单到底呈现什么由组件决定。

如下所示, username没有存储在DOM元素内,而是存储在组件的状态中。每次要更新 username时,就要调用 setState更新状态;每次要获取 username的值,就要获取组件状态值。

class App extends Component {
    //初始化状态
    constructor ( props ) {
        super ( props )
        this .state = {
         username:'有课前端网'
        }
    }
    //查看结果
    showResult ( ) {
    //获取数据就是获取状态值
        console. log ( this .state. username )
    }
    changeUsername (e) {
        //原生方法获取
        var value =e .target .value
        //更新前,可以进行脏值检测
        //更新状态
        this .setState ( {t
            username:value
        } )
    }
    //渲染组件
    render( ) {
        //返回虚拟DOM 
        return (
        <div>
            <p>
            {/*输入框绑定va1ue*/}
                <input type="text" onChange={ this.changeUsername .bind (this ) }
                value= { this .state.username }/>
            </p>
            <p>
                < button onClick={this.showResult.bind (this)}>查看结果</ button>
            </p>
        </div>
        )
    }
}

非约束性组件( uncontrolled component)就是指表单元素的数据交由元素自身存储并处理,而不是通过 React组件。表单如何呈现由表单元素自身决定。

如下所示,表单的值并没有存储在组件的状态中,而是存储在表单元素中,当要修改表单数据时,直接输入表单即可。有时也可以获取元素,再手动修改它的值。当要获取表单数据时,要首先获取表单元素,然后通过表单元素获取元素的值。

注意:为了方便在组件中获取表单元素,通常为元素设置ref属性,在组件内部通过refs属性获取对应的DOM元素。

class App extends Component {
  //查看结果
  showResult ( ) {
    //获取值
    console. log(this. refs. username .value)
   //修改值,就是修改元素自身的值
   this.refs.username.value="专业前端学习平台"
  }
  //渲染组件
  render ( ) {
    //返回虚拟DOM 
    return (
     <div>
      <p>
      {/*非约束性组件中,表单元素通过 defaultvalue定义*/}
        < input type="text"  ref=" username"  defaultvalue="有课前端网"/>
      </p>
      <p>
        < button onClick={this. showResult.bind ( this ) }>查看结果</button>
      </p>
    </div>
   )
 }

虽然非约東性组件通常更容易实现,可以通过refs直接获取DOM元素,并获取其值,但是 React建议使用约束性组件。主要原因是,约東性组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式等。

8、在哪个生命周期中你会发出Ajax请求?为什么?

Ajax请求应该写在组件创建期的第五个阶段,即 componentDidMount生命周期方法中。原因如下。

在创建期的其他阶段,组件尚未渲染完成。而在存在期的5个阶段,又不能确保生命周期方法一定会执行(如通过 shouldComponentUpdate方法优化更新等)。在销毀期,组件即将被销毁,请求数据变得无意义。因此在这些阶段发岀Ajax请求显然不是最好的选择。

在组件尚未挂载之前,Ajax请求将无法执行完毕,如果此时发出请求,将意味着在组件挂载之前更新状态(如执行 setState),这通常是不起作用的。

在 componentDidMount方法中,执行Ajax即可保证组件已经挂载,并且能够正常更新组件。

9、*useMemo和useCallback的区别

React18笔记-CSDN博客

useMemo

755dced30fb341dc8b9a129f815518dd.jpg

41f56c37a9174e049e152fa1f9908534.jpg

 useCallback

16859f17ae6f4a07b57d2ccb132ab64c.jpg

79b49539742d4b438cec794dda158d19.jpg

ab1e568c8a64437ca9073728210549c5.jpg

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

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

可以通过配置package.json中的script中的mode为production

11、为什么要使用 React. Children. map( props. children,( )=>)而不是props. children. map ( (  ) => )?

因为不能保证 props. children将是一个数组

以下面的代码为例。

<Parent>
    <h1>有课前端网</h1>
</Parent>

在父组件内部,如果尝试使用 props.children. map映射子对象,则会抛出错误,因为props. children是一个对象,而不是一个数组。

如果有多个子元素, React会使 props.children成为一个数组,如下所示。

<Parent>
    <h1>有课前端网</h1>
    <h2>前端技术学习平台</h2>
</Parent>
不建议使用如下方式,在这个案例中会抛出错误。
class Parent extends Component {
     render ( ) {
         return (
            <div> { this .props.children.map (obj = > obj ) }</div>
        )    
    } 
}

建议使用如下方式,避免在上一个案例中抛出错误。

class Parent extends Component  {
    render ( ) {
      return (
        <div> { React.Children.map ( this .props.children, obj => obj) }</div>
    )
    }
}

12、在使用 React Router时,如何获取当前页面的路由或浏览器中地址栏中的地址?

在当前组件的 props中,包含 location属性对象,包含当前页面路由地址信息,在 match中存储当前路由的参数等数据信息。可以直接通过 this .props使用它们。

react18中可以使用useLocation获取地址相关信息

13、createElement和 cloneElement有什么区别?

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

14、React- Router有几种形式?

有以下几种形式。

  • HashRouter,通过散列实现,路由要带#,不够美观。
  • BrowerRouter,利用HTML5中 history API实现,需要服务器端支持,兼容性不是很好。

15、React的事件和普通的HTML事件有什么不同?

区别:

  • 对于事件名称命名方式,原生事件为全小写,react 事件采用小驼峰;
  • 对于事件函数处理语法,原生事件为字符串,react 事件为函数;
  • react 事件不能采用 return false 的方式来阻止浏览器的默认行为,而必须要地明确地调用preventDefault()来阻止默认行为。

合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:

  • 兼容所有浏览器,更好的跨平台;
  • 将事件统一存放在一个数组,避免频繁的新增与删除(垃圾回收)。
  • 方便 react 统一管理和事务机制。

事件的执行顺序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为需要冒泡到document 上合成事件才会执行。

16、*react函数组件useState异步,数据不能及时获取到

react函数组件useState异步,数据不能及时获取到_usestate 异步-CSDN博客

17、React中D算法的原理是什么?

原理如下。

(1)节点之间的比较。

节点包括两种类型:一种是 React组件,另一种是HTML的DOM

如果节点类型不同,按以下方式比较:

如果 HTML DOM不同,直接使用新的替换旧的。如果组件类型不同,也直接使用新的替换旧的。

如果 HTML DOM类型相同,按以下方式比较。

在 React里样式并不是一个纯粹的字符串,而是一个对象,这样在样式发生改变时,只需要改变替换变化以后的样式。修改完当前节点之后,递归处理该节点的子节点。

如果组件类型相同,按以下方式比较:

如果组件类型相同,使用 React机制处理。一般使用新的 props替换旧的 props,并在之后调用组件的 componentWillReceiveProps方法,之前组件的 render方法会被调用。

节点的比较机制开始递归作用于它的子节点。

(2)两个列表之间的比较。

一个节点列表中的一个节点发生改变, React无法很妤地处理这个问题。循环新旧两个列表,并找出不同,这是 React唯一的处理方法。

但是,有一个办法可以把这个算法的复杂度降低。那就是在生成一个节点列表时给每个节点上添加一个key。这个key只需要在这一个节点列表中唯一,不需要全局唯一。

(3)取舍

需要注意的是,上面的启发式算法基于两点假设。

类型相近的节点总是生成同样的树,而类型不同的节点也总是生成不同的树

可以为多次 render都表现稳定的节点设置key。

上面的节点之间的比较算法基本上就是基于这两个假设而实现的。要提高 React应用的效率,需要按照这两点假设来开发。

18、概述一下 React中的事件处理逻辑。

为了解决跨浏览器兼容性问题, React会将浏览器原生事件( Browser Native Event)封装为合成事件( Synthetic Event)并传入设置的事件处理程序中。

这里的合成事件提供了与原生事件相同的接口,不过它们屏蔽了底层浏览器的细节差异,保证了行为的一致性。另外, React并没有直接将事件附着到子元素上,而是以单一事件监听器的方式将所有的事件发送到顶层进行处理(基于事件委托原理)。

这样 React在更新DOM时就不需要考虑如何处理附着在DOM上的事件监听器,最终达到优化性能的目的。

19、传入 setstate函数的第二个参数的作用是什么?

第二个参数是一个函数,该函数会在 setState函数调用完成并且组件开始重渲染时调用,可以用该函数来监听渲染是否完成

this .setstate ({ 
  username:'有课前端网'
}, ( ) => console.log ( 're-rendered success. ' ) )

20、React和vue.js的相似性和差异性是什么?

相似性如下:

  • 都是用于创建UI的 JavaScript库。
  • 都是快速和轻量级的代码库(这里指 React核心库)。
  • 都有基于组件的架构。
  • 都使用虚拟DOM。
  • 都可以放在单独的HTML文件中,或者放在 Webpack设置的一个更复杂的模块中。
  • 都有独立但常用的路由器和状态管理库。

区别:

  • react严格上只能算是MVC的view层,vue则是MVVM模式
  • 组件定义方式不同。React使用JSX语法,而Vue可以使用模板或JSX。
  • 虚拟DOM实现不同。React使用虚拟DOM进行DOM的渲染和更新,而Vue也使用虚拟DOM,但它更注重数据绑定和响应式系统。
  • 数据绑定不同。Vue实现了数据的双向绑定,而React则提倡单向数据流。
  • 社区和生态系统不同。React拥有更大的社区和更多的第三方库支持,而Vue也在社区和生态系统方面有着显著的发展。
  • 性能不同。在某些情况下,Vue可能提供更快的渲染速度,因为其在虚拟DOM和编译器方面做了一些优化。
  • 状态管理方式不同。Vue使用Vuex进行状态管理,而React则使用Redux或Context。
  • 设计理念不同。React被设计为可以自底向上逐层应用,而Vue则被设计为可以自顶向下逐层应用

21、生命周期调用方法的顺序是什么?

React生命周期分为三大周期,11个阶段,生命周期方法调用顺序分别如下。

(1)在创建期的五大阶段,调用方法的顺序如下。

  • getDetaultProps:定义默认属性数据。

  • getInitialState:初始化默认状态数据。

  • componentWillMount:组件即将被构建。

  • render:渲染组件。

  • componentDidMount:组件构建完成

(2)在存在期的五大阶段,调用方法的顺序如下。

  • componentWillReceiveProps:组件即将接收新的属性数据。

  • shouldComponentUpdate:判断组件是否应该更新。

  • componnentWillUpdate:组件即将更新。

  • render:渲染组件。

  • componentDidUpdate:组件更新完成。

(3)在销毁期的一个阶段,调用方法 componentWillUnmount,表示组件即将被销毀。

22、使用状态要注意哪些事情?

要注意以下几点。

  • 不要直接更新状态

  • 状态更新可能是异步的

  • 状态更新要合并。

  • 数据从上向下流动

23、说说 React组件开发中关于作用域的常见问题。

在 EMAScript5语法规范中,关于作用域的常见问题如下。

(1)在map等方法的回调函数中,要绑定作用域this(通过bind方法)。

(2)父组件传递给子组件方法的作用域是父组件实例化对象,无法改变。

(3)组件事件回调函数方法的作用域是组件实例化对象(绑定父组件提供的方法就是父组件实例化对象),无法改变。

在 EMAScript6语法规范中,关于作用域的常见问题如下。

(1)当使用箭头函数作为map等方法的回调函数时,箭头函数的作用域是当前组件的实例化对象(即箭头函数的作用域是定义时的作用域),无须绑定作用域。

(2)事件回调函数要绑定组件作用域。

(3)父组件传递方法要绑定父组件作用域。

总之,在 EMAScript6语法规范中,组件方法的作用域是可以改变的。

24、在 Redux中使用 Action要注意哪些问题?

在Redux中使用 Action的时候, Action文件里尽量保持 Action文件的纯净,传入什么数据就返回什么数据,最好把请求的数据和 Action方法分离开,以保持 Action的纯净。

25、在 Reducer文件里,对于返回的结果,要注意哪些问题?

在 Reducer文件里,对于返回的结果,必须要使用 Object.assign()来复制一份新的 state,否则页面不会跟着数据刷新。

return Object. assign ( { }, state, {
  type:action .type,
  shouldNotPaint : true
})

26、React中的setState是同步执行还是异步执行?如果是异步的?怎么拿到执行后的state?

【每天一个知识点】setState 到底是同步的,还是异步的_this.setstate是同步还是异步-CSDN博客

setState是异步的。

如果要拿到修改后的状态,需要使用回调函数的方式,如下:

//改变状态后想做一些事情:
this.setState({
  属性名:属性值
}, () => {
  //一般是用于在setState之后做一些操作
  //this.state == 修改之后的state
})

为什么不能直接用以下办法更新state

​ this.state.msg = “hello”;

​ 因为,这样不会引起组件的重新渲染,所以,数据修改后没法 呈现在页面上。

​ 而调用setState()函数,会引起组件的重新渲染,这样更新的数据就会呈现在页面上

1.react为什么要把setState做成异步方式?
把setState异步化主要是为了减少频繁setState带来的性能损耗,一次真正的setState会render一次页面,如果频繁render这个性能损耗是巨大的。所以react把setState设为了异步。

2.为什么加上setTimeout就会变成同步?
其实并不是setState变成了同步,而是setState逃脱了react对setState的异步管控机制

27、*useState为什么是异步更新,如何变为同步更新

useState为什么是异步更新,如何变为同步更新_usestate是同步还是异步-CSDN博客

28、Redux内部原理 内部怎么实现dispstch一个函数的

redux-thunk中间件作为例子,下面就是thunkMiddleware函数的代码

// 部分转为ES5代码,运行middleware函数会返回一个新的函数,如下:
return ({ dispatch, getState }) => {
    // next实际就是传入的dispatch
    return function (next) {
        return function (action) {
            // redux-thunk核心
            if (typeof action === 'function') { 
                return action(dispatch, getState, extraArgument);
            }
            return next(action);
        };
    };
}

redux-thunk库内部源码非常的简单,允许action是一个函数,同时支持参数传递,否则调用方法不变

  • redux创建Store:通过combineReducers函数合并reducer函数,返回一个新的函数combination(这个函数负责循环遍历运行reducer函数,返回全部state)。将这个新函数作为参数传入createStore函数,函数内部通过dispatch,初始化运行传入的combination,state生成,返回store对象
  • redux中间件:applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回经过中间件处理的新的dispatch函数
  • redux使用:实际就是再次调用循环遍历调用reducer函数,更新state

29、如果创建了类似于下面的 Icketang元素,那么该如何实现 Icketang类?

< Icketang username="雨夜清荷">
    {user = > user ?<Info user={user} />:<Loading />}
</Icketang>
import React, { Component } fromr "react";
 export class Icketang extends Component {
//请实现你的代码
}

在上面的案例中,一个组件接受一个函数作为它的子组件。Icketang组件的子组件是一个函数,而不是一个常用的组件。这意味着在实现 Icketang组件时,需要将props. children作为一个函数来处理。

具体实现如下。

import React,  { Component } from "react";
class Icketang extends Component {
   constructor ( props ){
    super ( props ) 
    this .state = {
     user : props.user 
    }
   }
  componentDidMount( ) {
  //模拟异步获取数据操作,更新状态
    setTimeout ( ( ) => this .setstate ({
      user:'有课前端网'
     }),2000)
  }
  render ( ) {
    return this.props.children ( this .state.user )
  }
}
class Loading extends Component {
  render  ( ) {
   return <p>Loading.</p>
  }
}
class Info extends Component  { 
  render ( ) {
   return <hl> { this .props.user }</h1>
  }
}

调用 Icketang组件,并传递给user属性数据,把 props.children作为一个函数来处理。这种模式的好处是,我们已经将父组件与子组件分离了,父组件管理状态。父组件的使用者可以决定父组件以何种形式渲染子组件。

为了演示这一点,在渲染 Icketang组件时,分别传递和不传递user属性数据来观察渲染结果。

import {render} from  "react-dom";
 render (<Icketang>
    { user = > user ?<Info user = {user} /> :<Loading /> }
   </Icketang> , ickt)

上述代码没有为 Icketang组件传递user属性数据,因此将首先渲染 Loading组件,当父组件的user状态数据发生改变时,我们发现Info组件可以成功地渲染出来。

render(< Icketang user="雨夜清荷">
{ user => user ?<Info user = {user} /> :<Loading />}
</Icketang>, ickt)

上述代码为 Icketang组件传递了user属性数据,因此将直接渲染Info组件,当父组件的user状态数据发生改变时,我们发现Info组件产生了更新,在整个过程中, Loading组件都未渲染。

30、 这段代码有什么问题?

class App extends Component {
  constructor ( props )  {
    super ( props )
      this .state = {
        username:"有课前端网", 
        msg:' '
      }
  }
  render ( ) {
    return (
      <div> { this .state. msg }</div>
    );
  }
  componentDidMount ( )  {
    this .setState ( ( oldState, props ) => {
    return {
      msg:oldState .username + ' - ' + props.intro 
    }
  } )
  }

render ( < App intro=" 前端技术专业学习平台"></App>,ickt )

在页面中正常输出“有课前端网-前端技术专业学习平台”。但是这种写法很少使用,并不是常用的写法。React允许对 setState方法传递一个函数,它接收到先前的状态和属性数据并返回一个需要修改的状态对象,正如我们在上面所做的那样。它不但没有问题,而且如果根据以前的状态( state)以及属性来修改当前状态,推荐使用这种写法。

31、请说岀 React从 EMAScript5编程规范到 EMAScript6编程规范过程中的几点改变。

主要改变如下。

(1)创建组件的方法不同。

EMAScript5版本中,定义组件用 React.createClass。EMAScript6版本中,定义组件要定义组件类,并继承 Component类。

(2)定义默认属性的方法不同。

EMAScript5版本中,用 getDefaultProps定义默认属性。EMAScript6版本中,为组件定义 defaultProps静态属性,来定义默认属性。

(3)定义初始化状态的方法不同。

EMAScript5版本中,用 getInitialState定义初始化状态。EMAScript6版本中,在构造函数中,通过this. state定义初始化状态。

注意:构造函数的第一个参数是属性数据,一定要用 super继承。

(4)定义属性约束的方法不同。

EMAScript5版本中,用 propTypes定义属性的约束。

EMAScript6版本中,为组件定义 propsTypes静态属性,来对属性进行约束。

(5)使用混合对象、混合类的方法不同。

EMAScript5版本中,通过mixins继承混合对象的方法。

EMAScript6版本中,定义混合类,让混合类继承 Component类,然后让组件类继承混合类,实现对混合类方法的继承。

(6)绑定事件的方法不同。

EMAScript5版本中,绑定的事件回调函数作用域是组件实例化对象。

EMAScript6版本中,绑定的事件回调函数作用域是null。

(7)父组件传递方法的作用域不同。

EMAScript5版本中,作用域是父组件。 EMAScript6版本中,变成了null。

(8)组件方法作用域的修改方法不同。

EMAScript5版本中,无法改变作用域。

EMAScript6版本中,作用域是可以改变的。

32、*常用的hooks

useState、useEffect、useMemo、useCallback、useSelector、useLocation、useParams、useSearchParams、useReducer、useDispatch、useContext、useRef、useLayoutEffect。。。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值