React知识集总结
- react基础
- 什么是React?
- 什么是虚拟DOM?
- 什么是JSX?
- 说说React的生命周期有哪些?
- react 中 keys 的作用是什么?
- 在 React 中,refs 的作用是什么
- 怎样解释 React 中 render() 的目的。
- 说说你对“在React中,一切都是组件”的理解
- 何为高阶组件(higher order component)
- 何为纯函数(pure function)
- 什么是 Props?
- React中的状态(state)是什么?它是如何使用的?
- 组件的状态(state)和属性(props)之间有何不同?
- 区分有状态和无状态组件
- react组件间传值(组件间通信方式)
- React中的事件是什么?
- 如何在React中创建一个事件?
- 何为受控组件(controlled component)?
- 受控组件和非受控组件有什么区别?
- 在React如何做性能优化?
- 常见问题
react基础
什么是React?
React 是 Facebook 在 2011 年开发的前端 JavaScript 库。它遵循基于组件的方法,有助于构建可重用的UI组件。它用于开发复杂和交互式的 Web 和移动 UI。尽管它仅在 2015 年开源,但有一个很大的支持社区。
优势
- 实现对虚拟DOM的操作,使得它速度快,提高了应用的性能。
- 组件化,模块化。react里每一个模块都是一个组件,组件化开发,可维护性高。
- 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的 API,甚至在 IE8 中都是没问题。
- 可以方便地在客户端和服务器端使用
- JSX 的引入,使得组件的代码更加可读,也更容易看懂组件的布局,或者组件之间是如何互相引用的。
JSX 是JavaScript XML 的简写。是 React 使用的一种文件,它利用 JavaScript 的表现力和类似 HTML 的模板语法。这使得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能。
render(){
return(
<div>
<h1> Hello World!</h1>
</div>
);
}
不足
- react中只是 MVC 模式的View部分,要依赖引入很多其他模块开发。(可以和其它任何框架一起使用)
- 当父组件进行重新渲染操作时,即使子组件的props或state没有做出任何改变,也会同样进行重新渲染。
特点
- 声明式设计:React采用声明范式,可以轻松描述应用。
- 高效:React使用虚拟DOM 而不是真正的DOM。通过对DOM的模拟,最大限度地减少与DOM的交互。
- 灵活:React可以与已知的库或框架很好地配合,可以进行服务器端渲染。
- 单向数据流:比较有序,有便于管理,它随着React视图库的开发而被 Facebook 概念化。
什么是虚拟DOM?
虚拟DOM(Virturl DOM) 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是真实DOM的内存表示,一种编程概念,一种模式。它会和真实的DOM同步。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。
为什么要使用Virturl DOM,因为操作真实DOM的耗费的性能代价太高,所以react内部使用js实现了一套 dom 结构,在每次操作真实 dom 之前,使用实现好的 diff 算法,对虚拟 dom 进行比较,递归找出有变化的 dom 节点,然后对其进行更新操作。为了实现虚拟DOM,我们需要把每一种节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中,假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点。
为什么虚拟DOM可以提高性能?
当数据变化的时候,无需整体的重新渲染,而是局部刷新。虚拟DOM它是以js的形式存在,计算性能会比较好。而且由于减少对真实DOM的操作次数。性能会有很大提升。
diff算法原理 , 什么是diff算法?(diff算法的理解)
对新旧两棵DOM树进行同层比较。给每层元素添加唯一的 key 值。提高diff算法效率。React只会匹配相同组件名字。调用组件setState 方法的时候, React 将它标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的组件 重新渲染.这样就实现了局部刷新的效果。
真实DOM(Real DOM)和虚拟DOM(Virtual DOM)区别?
Real DOM | Virtual DOM |
---|---|
更新缓慢 | 更新快 |
可以直接更新HTML | 无法直接更新HTML |
元素更新,则创建新DOM | 元素更新,则更新JSX |
DOM操作代价很高 | DOM操作非常简单 |
内存消耗多 | 内存消耗少 |
什么是JSX?
JSX是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力。
为什么浏览器无法读取JSX?
浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX。所以为了使浏览器能够读取 JSX,首先,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。
React为什么要用JSX?
JSX语法糖允许前端开发者使用我们最熟悉的类HTML标签语法来创建虚拟DOM在降低学习成本的同时,也提升了研发效率与研发体验。
如何使用JSX?
- 在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。
const title = 'World'; const element = <h1>Hello, {title}</h1>;
- 在属性中嵌入 JavaScript 表达式时,不要在大括号外面加上引号。
- 使用引号,将属性值指定为字符串字面量
const element = <div tabIndex = "0"></div>;
- 使用大括号,在属性值中插入一个 JavaScript 表达式
const element = <img src = {user.avatarUrl}></img>;
- 因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。
JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex。
- JSX中的标签可以是单标签,也可以是双标签,但必须保证标签是闭合的。
// 单标签
constelement = <img src = {user.avatarUrl }/>;
// 双标签
const element = (<div> <h1> Hello World ! </h1> </div>);
说说React的生命周期有哪些?
- 组件将要挂载时触发的函数:componentWillMount
在渲染之前执行,用于根组件中的应用程序级别配置。
- 组件挂载完成时触发的函数:componentDidMount
在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。
- 是否要更新数据时触发的函数:shouldComponentUpdate
允许我们手动地判断是否要进行组件更新,根据组件的应用场景设置函数的合理返回值能够帮我们避免不必要的更新。
可在该生命周期做性能优化,提高性能的好地方,因为如果组件收到新的道具,它可以防止重新渲染。
- 将要更新数据时触发的函数:componentWillUpdate
在由shouldComponentUpdate确认返回正值的优点和状态更改时,在重新渲染组件之前执行。在这个函数中我们不调用 this.setState()是因为该方法会触发另一个 componentWillUpdate(),如果我们在componentWillUpdate()中触发状态更改,我们将以无限循环。
- 数据更新完成时触发的函数:componentDidUpdate
通常用于更新DOM以响应属性或状态更改
- 组件将要销毁时触发的函数:componentWillUnmount
它将用于取消任何传出的网络请求,或删除与该组件关联的所有事件侦听器。
- 父组件中改变了props传值时触发的函数:componentWillReceiveProps。
react 中 keys 的作用是什么?
Keys是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。
在 React 中,refs 的作用是什么
Refs 是一个有助于存储对特定的 React 元素或组件的引用的属性,它将由组件渲染配置函数返回。用于对 render() 返回的特定元素或组件的引用。当需要进行 DOM 测量或向组件添加方法时,它们会派上用场。
使用Refs情况:
- 需要管理焦点、选择文本或媒体播放时
- 触发式动画
- 与第三方 DOM 库集成
怎样解释 React 中 render() 的目的。
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 、、
说说你对“在React中,一切都是组件”的理解
组件是 React 应用 UI 的构建块。这些组件将整个 UI 分成小的独立并可重用的部分。每个组件彼此独立,而不会影响 UI 的其余部分。
何为高阶组件(higher order component)
高阶组件(HOC)是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。HOC 是纯函数,没有副作用 ------纯函数:输入确定,输出就一定确定。
何为纯函数(pure function)
一个纯函数是一个不依赖于且不改变其作用域之外的变量状态的函数,这也意味着一个纯函数对于同样的参数总是返回同样的结果。
什么是 Props?
Props 是 React 中属性的简写。它们是只读组件,必须保持纯,即不可变。它们总是在整个应用中从父组件传递到子组件。子组件永远不能将 prop 送回父组件。这有助于维护单向数据流,通常用于呈现动态生成的数据。
React中的状态(state)是什么?它是如何使用的?
状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props 不同,它们是可变的,并创建动态和交互式组件。可以通过 this.state() 访问它们。
组件的状态(state)和属性(props)之间有何不同?
- State 是一种数据结构,一般用于组件内部的状态维护,更新组件内部的数据状态,更新子组件的props等。用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
- Props则是组件的配置。一般用于父组件向子组件通信,在组件之间通信使用。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据–回调函数也可以通过 props 传递。
区分有状态和无状态组件
有状态组件(逻辑组件/容器组件) | 无状态组件(UI组件/展示组件) |
---|---|
在内存中存储有关组件状态变化的信息,(其他组件的数据源) | 不会有自身的状态(但当组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态) |
有权改变状态 | 无权改变状态 |
包含过去、现在和未来可能的状态变化情况 | 不包含过去,现在和未来可能发生的状态变化情况 |
提供修改数据源的方法,接受无状态组件状态变化要求的通知,然后将 props 发送给他们。 | 从有状态组件 props接收数据和回调函数 |
关心组件是如何运作的 | 关心组件看起来是什么 |
react组件间传值(组件间通信方式)
- 父子:props传值,父组件通过props向子组件传值,子组件通过回调函数向父组件传值。
- 兄弟:利用redux/mobx跨级通信。
- 通过prop-types的context实现跨级通信。
跨级组件间双向通信:使用 context 对象,根组件和其他所有子孙通信,不太适合组件间通信(可以实现,不好维护)
- 使用事件订阅实现非嵌套组件间通信,也可以实现跨级组件间通信。
React中的事件是什么?
在 React 中,事件是对鼠标悬停、鼠标单击、按键等特定操作的触发反应。处理这些事件类似于处理 DOM 元素中的事件。但是有一些语法差异,如:
- 用驼峰命名法对事件命名而不是仅使用小写字母。
- 事件作为函数而不是字符串传递。
- 事件参数重包含一组特定于事件的属性。每个事件类型都包含自己的属性和行为,只能通过其事件处理程序访问。
对react中事件机制的理解?
React事件是合成事件,不是原生事件。
合成事件是围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同浏览器的行为合并为一个 API。这样做是为了确保事件在不同浏览器中显示一致的属性。
合成事件(React事件)和原生事件的区别:
- 写法不同:合成事件是camal命名法,原生事件是全部小写
- 绑定位置不同:合成事件全部委派到document上,原生事件绑定到真实dom上。所以一般是在componentDidMount中或者ref回调函数中绑定,在componentWillUnmount阶段进行解绑,防止内存泄漏。
- 执行顺序不同:先执行原生事件,事件冒泡至document上,再执行合成事件。
react事件注意点:
- 用驼峰命名法对事件命名而不是仅使用小写字母。
- 事件作为函数而不是字符串传递。
- 事件参数重包含一组特定于事件的属性。每个事件类型都包含自己的属性和行为,只能通过其事件处理程序访问。
如何在React中创建一个事件?
class Display extends React.Component({
show(evt) {
// code
},
render() {
return (
<div onClick={this.show}>Click Me!</div>
);
}
});
何为受控组件(controlled component)?
在 HTML 中,类似 , 和 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一起被发送。但在 React 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state,重新渲染组件。一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为"受控元素"。
受控组件和非受控组件有什么区别?
受控组件 | 非受控组件 |
---|---|
没有维持自己的状态 | 保持着自己的状态 |
数据由父组件控制 | 数据由 DOM 控制 |
通过 props 获取当前值,然后通过回调通知更改 | Refs 用于获取其当前值 |
在React如何做性能优化?
1.给DOM的遍历上加上唯一的key。提高diff算法效率。 尽量不要用index,如果说在DOM中删了某一个节点,index也就会发生变化,这时候 就会重新渲染,所以key值最好使用id。
2. 能用const声明的就用const。
3. 在render里面尽量减少新变量的创建以及函数的指向改变问题。
4. 减少对真实DOM的操作。
5. 如果是用webpack搭建环境的话,当一个包过大加载过慢时,可分成多个包来优化。
6. 使用react-loadable,按需加载路由。
7. 重写shouldComponentUpdate来避免不必要的 dom 操作。
8. 使用 production 版本的react.js。
9. 使用key来帮助React识别列表中所有子组件的最小变化
常见问题
render函数中return如果没有使用()会有什么问题?
我们在使用 JSX 语法书写 react 代码时,babel 会将 JSX 语法编译成 js,同时会在每行自动添加分号(;),如果 return 后换行了,那么就会变成 return;
渲染没有返回任何内容。这通常意味着缺少 return 语句。或者,为了不渲染,返回 null。
为了代码可读性我们一般会在 return 后面添加括号这样代码可以折行书写,否则就在 return 后面紧跟着语句。
怎么阻止组件的渲染
在组件的 render 方法中返回 null 并不会影响触发组件的生命周期方法
setState为什么是异步的
- 保证内部的一致性:因为props是要等到父组件渲染过后才能拿到,也就是不能同步更新,state出于统一性设成异步更新。
- 性能优化:举例说你正在一个聊天窗口输入,如果来了一条新消息又要render,那就会阻塞你的当前操作,导致延迟什么的。
- 支持state在幕后渲染:异步可以使state在幕后更新,而不影响你当前旧的页面的交互,提升用户体验。
React的render中可以写{if else}这样的判断吗?
不可以,可以采用函数返回值或者三元运算符。
class HelloMessage extends React.Component {
render (){
return(
<div>
<h1>
{ this.props.loggedIn ? 'You are logged In' : 'You are not logged In' }
</h1>
</div>
)
}
react如何避免重复渲染
React 官方提供了 PureRenderMixin 插件,它的功能就是在不需要重新渲染的情况下让shouldComponentUpdate 返回 false, 使用这个插件就能够减少不必要的重新渲染,性能得到也得到一些提升。
但是在 React 的新版本里面,提供了 React.PureComponent,而不需要使用这个插件。 所以说一个较大的组件决定重渲染的时候,我们可以在每一个子组件中绑定(新的)shouldComponentUpdate方法,这样可以减少子组件重新渲染的次数。