react理论总结1

 

1)对react的理解(特点)

1, Jsx js+xml ,是对js语法的扩张,需要通过babel.js的编译转化成浏览器可以解析的普通js对象,浏览器解析不了js对象中jsx。

2, 虚拟dom , 相当于在js和真实dom之间的缓存, state改变 调用render函数会重新生成新的虚拟dom树,通过diff算法计算出新旧dom差异  只将差异部分更新到真实的dom,减少了对真实dom的操作,提高了性能

3, 单项数据流 , 数据只能通过父组件传给子组件 对于子组件来说只能使用propos不能修改;如果需要修改 需要在父组件定义函数,通过propos传递给子组件,在子组件中调用此函数,在父组件里面修改props(实现双向绑定的原理)

4, 组件化思想,将整个ui按照功能解构成各个小组件  小组件嵌套组合成大组件  大组件构成页面,组件可以重复使用。

 

2)react 性能优化

1,性能优化是在shouldComponentUpdata 钩子里面是实现的

2,数据更新时立即执行这个函数  判断是否需要调用render函数,如果返回false就跳过此次更新 不再执行后面的生命周期钩子;如果返回true 才会调用render方法重新绘制dom,减少dom渲染的次数从而提高了性能。

3,但是组件的shouldcomponentUpdate()默认返回true,,需要自己重写这个钩子,增加判断,如果数据有变化,用新的state替换旧的state返回true, 否则返回false

4,pureComponent里面实现了重写shouldComponentUpdate(),对新旧state,props进行浅层对比,

【如果组件内部的state为对象或数组格式,当该对象或数组内部发生改动时,不能直接获取setState,这里必须使用解构赋值,将对象或数组内部展开,再重新赋值,才会改动】

 

3react keys 的作用是什么?

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

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。

在 react Diff 算法中 react 会借助元素的 Key 值来判断该元素是新创建的还是被移动而来的元素,从而减少不必要的元素重渲染

4react refs 的作用是什么?

访问 DOM 元素或者某个组件实例从而调用组件实例的方法和属性

5)调用setState 之后发生了什么?(必会)

调用 setState ,setstate是异步的,新的 state 并不会马上生效渲染组件。

而是先看执行流中有没有在批量更新中,如果有就等待试图合并称成一次更新;

无则调用shouldcomponentUpdate()函数看其返回true的话

->render(进行 diff 运算,与上一次的虚拟 DOM 相比较,进行有效的渲染更新组件)

->react更新真实的dom和ref

->componentDidUpdate 获取到最新的 state 或 props

 

 

6)除了在构造函数中绑定 this,还有其它方式吗?(必会)

1 在constructor 中绑定this

2 在事件属性绑定时传入的函数用bind绑定

3 在事件属性绑定时将事件放入箭头函数回调中(每次组件渲染时都会创建一个新的回调)

4在定义事件阶段使用箭头函数绑定---推荐

7setState 第二个参数的作用?(必会)

第一个参数是要改变的 state 对象,

第二个参数是 state 导致的页面变化完成后的回调(箭头函数),等价于 componentDidUpdate

8)在构造函数中调用 super(props)的目的是什么?

调用super的原因:在ES6中,在子类的constructor中必须先调用super()才能引用this  

在 JavaScript 子类的构造函数中 super 指的是父类(即超类)的构造函数。子类中显式定义了constructor的方法中必须在其最顶层调用super,否则新建实例时会报错。

这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。
如果不调用super方法,子类就得不到this对象。所以必须先调用super才可以使用this。如果子类没有定义constructor方法,这个方法会被默认添加。

super(props)的目的:在constructor中可以使用this.props

9)受控组件 与非受控组件之间的区别是什么?

受控组件:通过截获控件 onChange 方法,从而将value 控制于组件;

非受控组件: 会维护自身的状态,并基于用户的输入来更新;不截获控件的值,而是通过 Ref 函数,获取到控件 DOM,每次取值时直接从 DOM 中取

10)展示组件和容器组件之间有何不同?

展示组件:展示专门通过 props 接受数据回调,并且几乎不会有自身的状态。

容器组件:展示组件或者其他容器组件提供容器和行为;并调用 actions,将其作为回调提供给展示组件,容器组件经常是有状态的

11)类组件和函数式组件之间有何不同?

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

函数式组件:当组件仅是接收 props,并将组件自身渲染到页面时,是一个无状态组件,可以使用一个纯函数来创建这样的组件

12)组件的状态(state)和属性(props)之间有何不同?

state 是一种数据结构,用于组件挂载时所需数据的默认值。State 可以改变,但多数时候是作为用户事件行为的结果。

props则是组件的配置,props 由父组件传递给子组件,并且就子组件而言,props 是不可变的,组件不能改变自身的 props,但是可以把其子组件的 props 放在一起统一管理

13)何为高阶组件?

高阶组件是一个以组件为参数并返回一个新组件的函数,主要做劫持、 扩展组件

使用场景:

1 共享 react 组件之间的行为---抽取公共逻辑,最常见的可能是 Redux 的 connect 函数,自定义导航

2 组件组合

14)react 渲染机制

1、当页面一打开,就会调用 render 构建一棵 DOM 树

2、当数据发生变化( state | props )时,就会再渲染🎧一棵 DOM 树

3、此时,进行 diff 运算,两棵 DOM 树进行差异化对比,找到更新的地方进行批量改动

 

15)解释 react 中 render()的目的

每个 react 组件强制要求必须有一个 render()。它返回一个 react 元素,是原生 DOM 组件的表示,

如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如<form>、<group>、<div>等,此函数必须保持纯净,即必须每次调用时都返回相同的结果

16)react 性能优化的方案

减少 render 方法的调用; 避免使用状态提升来共享 state,此时应该使用 redux 解决方案; 保持稳定的 dom 结构,尽量避免 dom 节点跨层级移动操作; 使用 css 来隐藏节点,而不是真的移除或添加 DOM 节点等

17)为什么我们需要使用 react 提供的 ChildrenAPI 而不是 JavaScript 的 map?

props.children 是对象(object)而不是数组(array),如果我们使用 props.children.map 函数来遍历时会受到异常提示

18)为什么虚拟 DOM 会提高性能?说下他的原理

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom 的 diff 算法避免了没有必要的 dom 操作,从而提高性能

VirtualDOM 工作过程有三个简单的步骤

1、每当底层数据发生改变时,整个 UI 都将在 VirtualDOM 描述中重新渲染

2、然后计算之前 DOM 表示与新表示的之间的差异

3、完成计算后,将只用实际更改的内容更新 realDOM

 

19)setState 何时同步何时异步?

1、setState 只在合成事件(react 为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在 jsx 中常见的 onClick、onChange 这些都是合成事件)和钩子函数(生命周期)中是“异步”的,

在原生事件和 setTimeout 中都是同步的

2、setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更

 新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState,callback)中的 callback 拿到更新后的结果

3、setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和 setTimeout 中不会批量更新,

在“异步”中如果对同一个值进行多次 setState,setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新

 

20)调用 render 时,DOM 一定会更新吗,为什么?

不一定更新,react 组件中存在两类 DOM(真实dom和虚拟dom)

render 函数被调用后, react 会根据 props 或者 state重新创建一棵 virtual DOM 树(虽然每一次调用都重新创建,但因为创建是发生在内存中,所以很快不影响性能)

而 virtual dom 的更新并不意味着真实 DOM 的更新,react 采用 diff 算法将 virtual DOM 和 Real DOM 进行差异比较,找出需要更新的最小的部分,这时 Real DOM 才可能发生修改

所以每次 state 的更改都会使得 render 函数被调用,但是页面 DOM 不一定发生修改

 

21)在哪些生命周期中可以修改组件的 state?

componentDidMount 和 componentDidUpdate

constructor、componentWillMount 中 setState 会发生错误:setState 只能在 mounted 或 mounting组件中执行。

componentWillUpdate 中 setState 会导致死循环(state一旦改变就自动调用shouldComponentUpdate循环了)

 

22)connect()前两个参数是什么?

mapStateToProps(state, ownProps)

允许我们将 store 中的数据作为 props 绑定到组件中,只要store 更新了就会调用 mapStateToProps 方法,mapStateToProps 返回的结果必须是 object 对象,该对象中的值将会更新到组件中

mapDispatchToProps(dispatch, [ownProps])

允许我们将 action 作为 props 绑定到组件中,如果不传这个参数 redux 会把 dispatch 作为属性注入给组件,可以手动当做 store.dispatch 使用

mapDispatchToProps 希望你返回包含对应 action 的 object 对象

 

23)react 的 diff 原理

diff(翻译差异):计算一棵树形结构转换成另一棵树形结构的最少操作 1、把树形结构按照层级分解,只比较同级元素

2、给列表结构的每个单元添加唯一的 key 属性,方便比较

3、react 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)

4、合并操作,调用 component 的 setState 方法的时候, react 将其标记为 dirty.到每一个事件循环结束, react 检查所有标记 dirty 的 component 重新绘制

5、选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能

 

24)为什么建议传递给 setState 的参数是一个 callback 而不是一个对象

因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state

 

 

 

 

 

posted @ 2024-05-08 17:52  青橙娃娃  阅读(5)  评论(0编辑  收藏  举报