一、组件实例核心---Refs
通过定义 ref 属性可以给标签添加标识
字符串形式的Refs
这种形式已经不再推荐使用,官方不建议使用
https://zh-hans.legacy.reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
回调形式的Refs
javascript
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
const { input1 } = this
alert(input1.value)
}
render() {
return (
<div>
<input
ref={(c) => {
this.input1 = c
}}
type="text"
placeholder="点击按钮提示数据"
/>
<button onClick={this.showData}>点我提示左侧的数据</button>
</div>
)
}
}
ReactDOM.render(<Demo />, document.getElementById('test'))
</script>
关于回调函数形式的Refs的执行次数,官方描述如下:
TIP
如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
即内联函数形式,在更新过程中 ref 回调会被执行两次,第一次传入 null ,第二次传入 DOM 元素。若是下述形式,则只执行一次。但是对功能实现没有影响,因此一般也是用内联函数形式。
createRef API
该方式通过调用 React.createRef 返回一个容器用于存储节点,且一个容器只能存储一个节点
事件处理
- React 使用自定义事件,而非原生 DOM 事件,即 onClick、onBlur :为了更好的兼容性
- React 的事件通过事件委托方式进行处理:为了高效
- 通过 event.target 可获取触发事件的 DOM 元素:勿过度使用 ref
当触发事件的元素和需要操作的元素为同一个时,可以不使用 ref
二、组件通信
-
组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。
-
在组件化过程中,我们将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据。
-
为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通,这个过程就是组件通讯。
组件生命周期
生命周期钩子函数存在于类组件中,详细生命周期介绍请查看官方文档
-
意义:组件的生命周期有助于理解组件的运行方式,完成更复杂的组件功能、分析组件错误原因等
-
组件的生命周期: 组件从被创建到挂载到页面中运行,再到组件不在时卸载的过程
-
生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
-
钩子函数的作用:为开发人员在不同阶段操作组件提供了实际
生命周期的三个重要的钩子函数
- render :初始化渲染和更新渲染
- componentDidMount :进行初始化,如开启定时器、发送网络请求、订阅消息
- componentWillUnmount :进行收尾,如关闭定时器、取消订阅消息
组件复用
复用的是组件操作state的逻辑方法
props模式
-
render 是一个函数,当做 props 传递到组件当中,并在此组件中调用此函数拿到render 返回的内容
-
把 prop 是一个函数并且告诉组件要渲染什么内容的技术叫做 render props 模式
高阶函数(HOC)
-
目的:实现状态逻辑复用
-
采用包装/装饰模式
-
手机:获取保护功能
-
手机壳:提供保护功能
-
高阶组件就相当于手机壳,通过包装组件,增强组件功能
作用:
复用逻辑:高阶组件更像是一个加工 react 组件的工厂,批量对原有组件进行加工,包装处理。我们可以根据业务需求定制化专属的 HOC,这样可以解决复用逻辑。
强化 props:这个是 HOC 最常用的用法之一,高阶组件返回的组件,可以劫持上一层传过来的 props,然后混入新的 props,来增强组件的功能。代表作 react-router 中的 withRouter。
赋能组件:HOC 有一项独特的特性,就是可以给被 HOC 包裹的业务组件,提供一些拓展功能,比如说额外的生命周期,额外的事件,但是这种 HOC,可能需要和业务组件紧密结合。典型案例 react-keepalive-router 中的 keepaliveLifeCycle 就是通过 HOC 方式,给业务组件增加了额外的生命周期。
控制渲染:劫持渲染是 hoc 一个特性,在 wrapComponent 包装组件中,可以对原来的组件,进行条件渲染,节流渲染,懒加载等功能,后面会详细讲解,典型代表做 react-redux 中 connect 和 dva 中 dynamic 组件懒加载。
三、严格模式
strictMode
-
用来突出显示应用程序潜在问题的工具
-
与 Fragment 一样,StrictMode 不会渲染任何可见的 UI
-
它为其后代元素触发额外的检查和警告
-
严格模式检查仅在开发模式下运行;他们不会影响生产环境
-
可以为应用程序的任何部分开启严格模式,用
React.StrictMode
包起来即可,会对所有的后代生效
四、虚拟DOM和Diff算法
Virtual DOM 是以对象的方式来描述真实 dom 对象的,那么在做一些 update 的时候,可以在内存中进行数据比对,减少对真实 dom 的操作减少浏览器重排重绘的次数,减少浏览器的压力,提高程序的性能,并且因为 diff 算法的差异比较,记录了差异部分,那么在开发中就会帮助程序员减少对差异部分心智负担,提高了开发效率。
虚拟 dom 好多这么多,渲染速度上是不是比直接操作真实 dom 快呢?并不是。虚拟 dom 增加了一层内存运算,然后才操作真实 dom,将数据渲染到页面上。渲染上肯定会慢上一些。虽然虚拟 dom 的缺点在初始化时增加了内存运算,增加了首页的渲染时间,但是运算时间是以毫秒级别或微秒级别算出的,对用户体验影响并不是很大。
key的作用
key是虚拟dom对象的标识,可以提高页面更新渲染的效率
当状态中的数据发生变化时,React 会根据新数据生成新的虚拟 DOM ,接着对新旧虚拟 DOM 进行 Diff 比较,规则如下:
- 旧虚拟 DOM 找到和新虚拟 DOM 相同的 key:
-
- 若内容没变,直接复用真实 DOM
- 若内容改变,则生成新的真实 DOM ,替换页面中之前的真实 DOM
-
旧虚拟 DOM 未找到和新虚拟 DOM 相同的 key:根据数据创建新的真实 DOM ,渲染到页面
-
使用 index 作为 key 可能引发的问题:
-
若对数据进行逆序添加、逆序删除等破坏顺序的操作,会进行没有必要的真实 DOM 更新。界面效果没问题,但效率低下。
-
如果结构中包含输入类的 DOM(如 input 输入框) ,则会产生错误的 DOM 更新。
-
若不存在对数据逆序添加、逆序删除等破坏顺序的操作,则没有问题。
有不明白的或者有其他问题的可以评论区留言噢
今天的知识分享就到这里啦~希望大家在这能学到知识一起分享一起进步,成为更好的自己!