前端react相关总结

491 阅读13分钟

1.react的原理?

包括这几方面 diff算法,数据驱动,合成事件,组件更新机制

diff算法:

  1. 是虚拟dom的必然产物,通过新旧虚拟dom作对比(即diff),将变化的地方更新到真实的dom上面,另外也需要 diff高效的执行对比过程,从而降低时间复杂度O(n)。
  2. vue2.x中为了降低watcher粒度,每个组件只有一个watcher 与之对应,只有引入diff才能精确找到发生变化的地方。
  3. vue中diff执行的时刻 是组件实例 执行其更新函数时,它会对比上一次渲染结果oldVnode和新的渲染结果newVnode,此过程称为patch。
  4. diff过程整体遵循深度优先,同层比较的策略,俩个节点之间比较会根据他们是否拥有子节点或文本节点做不同的操作,比较两组子节点是算法的重点,首先假设头尾节点可能相同做4次比对尝试,如果没有找到相同节点,才按照通用方式 遍历查找,查找结束再按情况处理剩下节点,借助key通常可以非常精确查找找到相同节点,因此整个patch过程非常高效。

数据驱动::this.setState()会将变化的数据首先映射到虚拟的dom中,最后一并进行挂载使页面数据更新

合成事件:

  1. react把事件委托到document对象上。
  2. 当真实dom元素触发事件,先处理原生事件,然后冒泡到document对象后,再处理react事件。
  3. react事件绑定的时刻是调和阶段,会在原生事件的绑定前执行。
  4. 目的和优势:进行浏览器兼容,react采用的是顶层事件代理机制,能够保证冒泡的一致性。事件对象可能被频繁创建和回收,因此react引入事件池,在事件池中获取和释放事件对象。(react17被抛弃)

react 16.x版本中,react 事件委托到document上

截屏2021-06-12 下午5.38.33.png

截屏2021-06-12 下午5.33.41.png react 17.x版本中,react 事件委托到root上

截屏2021-06-12 下午5.37.53.png

stopPropagation(); 阻止向上冒泡,但是本元素剩下的监听函数还是会执行, stopImmediatePropagation(); 阻止向上冒泡,但是本元素剩下的监听函数不执行, 组件更新机制

2.前端性能优化?

一.更快的网络通信

1.让服务器和用户更近用cdn:

  • 1)全局负载均衡
  • 2)缓存系统 2.服务器通信层面
  • 1)资源合并 雪碧图
  • 2)域名分片 多域名 (一个域名可以发6-8个请求) 3.数据传输层面 - 缓存
  1. 先根据这个资源的一些 http header 判断它是否命中强缓存,如果命中,则直接从本地获取缓存资源,不会发请求到服务器;
  2. 当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些request header验证这个资源是否命中协商缓存,称为http再验证,如果命中,服务器将请求返回,但不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就会从缓存中获取资源;
  3. 强缓存和协商缓存共同之处在于,如果命中缓存,服务器都不会返回资源; 区别是,强缓存不对发送请求到服务器,但协商缓存会。
  4. 当协商缓存也没命中时,服务器就会将资源发送回客户端。
  5. 当 ctrl+f5 强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;
  6. 当 f5刷新网页时,跳过强缓存,但是会检查协商缓存;
  • 1)强缓存 Expires(该字段是 http1.0 时的规范,值为一个绝对时间的 GMT 格式的时间字符串,代表缓存资源的过期时间) Cache-Control:max-age(该字段是 http1.1的规范,强缓存利用其 max-age 值来判断缓存资源的最大生命周期,它的值单位为秒)

  • 2)协商缓存 Last-Modified(值为资源最后更新时间,随服务器response返回,即使文件改回去,日期也会变化) If-Modified-Since(通过比较两个时间来判断资源在两次请求期间是否有过修改,如果没有修改,则命中协商缓存) ETag(表示资源内容的唯一标识,随服务器response返回,仅根据文件内容是否变化判断) If-None-Match(服务器通过比较请求头部的If-None-Match与当前资源的ETag是否一致来判断资源是否在两次请求之间有过修改,如果没有修改,则命中协商缓存)

使用ETag而不使用Last-Modified为唯一标识的原因 有些特定的场合下,一些静态的文件,可能会被频繁的更新, 但是文件内容没有变化,这时候如果使用Last-modified,服务器端始终返回最新的内容给浏览器,而Etag是根据文件内容来的,如果内容没有变化的话,始终会让浏览器使用本地缓存的文件。所以,使使用ETag可以更好的避免一些不必要的服务器相应

此处引入 链接:juejin.cn/post/694822…

4.数据传输层面 - 压缩

  • 1)数据压缩 gzip 新的br
  • 2)代码文件压缩 html/css/js 注释、 空格、长变量名 等等
  • 3)静态资源 字体图标 去除元数据 缩小尺寸及分辨率,使用jpg或者webp格式 5.头与报文
  • 1)http1.1中减少不必要的头
  • 2)减少cookie数据量 6.通信协议层面 1)http2头部压缩 臃肿的请求头 平均460字节的首部 专门的HPACK压缩算法
  • 索引表
  • 霍夫曼编码 2)二进制帧 3)链路复用

二.更高效的数据处理 工具测试 ab 三.代码上优化 1.html语义化标签加强dom解析 2.能用html/css实现的效果 就不要用js 3.多使用伪元素,减少js多dom的查找遍历 4.逻辑和展示解耦,避免不必要的js引擎启动 5.减少作用域查找和闭包,避免== 使用块级作用域 四.服务端渲染 ssr 解决方案:next.js nuxt.js

概念: 使用户觉得页面加载快!
思路:分析一个页面从输入 URL 到页面加载显示完成的所有步骤,采用分治法逐步优化。
	1.优化DNS查询
	减少域名:尽量把所有的资源放在一个域名下。一个域名同时可以发4IE8)或8个请求
        (Chrome)。请求文件少,用1个域名,文件多用多个域名。与3权衡。

	2.优化TCP协议
	1TCP连接复用,使用keep-alive:连接回复加上请求头:keep-alive。第一次请求不断
        开,第二次请求复用。
	2)使用http 2.0版本:多路复用,连接复用率会更高

	3.优化发送HTTP请求
	1)合并JSCSS文件
	2)inline image:使用data:url scheme来内连图片
	3)减小cookie体积,每个请求都会附带cookie,所以不要滥用cookie。
	4)合理使用CasheControl代替发送HTTP请求
	5)同时发送多个请求(浏览器自带)IE8可以同时请求下载4个的css文件,Chrome可以同时
        请求下载8个 。

	4.优化接受响应
	1)设置Etags:浏览器重复与请求服务器一样的文件,ETag响应3042Gzip压缩大文件 使用macos gzip,npm server gzip gzip 文件名
	其响应头为Content-Encodinging:gzip,先压缩接收到再解压缩。缺点:耗费浏览器CPU,权衡

	5.优化DOCTYPE
	不能不写,不能写错

	6.优化CSSJS请求
	1)使用CDN:用CDN请求静态资源同时可以增大同时下载数量,内容分发网络(CDN)可以使请
        求总时间降低,也可以减少cookie
	2CSS放在head里:使其尽早下载,因为chrome需要下载完所有的css后才渲染页面
	3JS放在body里的最后:尽早显示整个页面,获取节点。

	7.使用懒加载
	1)组件懒加载
	const xxx =()=>import('./components/xxx.vue')
	2)路由懒加载

	8.优化用户体验
	1)用户看到哪些内容就请求哪些内容
	2)加一个loading动画用户会感觉时间变快

	9.减少监听器,使用事件委托
    <body>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
        <script>
            let liList = document.querySelectorAll('li')

            // liList[0].onclick = ()=>console.log(1)
            // liList[1].onclick = ()=>console.log(2)
            // liList[2].onclick = ()=>console.log(3)
            // liList[3].onclick = ()=>console.log(4)
            //法一:监听太多

            let ul = document.querySelector('ul')

            ul.onclick = (e) => {
                if (e.target.tagName === 'LI') {
                    console.log(e.target.innerText)

                }
            }//法二:减少监听,采用事件委托
        </script>
    </body>

	10.优化图片大小
	图片压缩网站

	11.减少或合并DOM操作或使用虚拟DOM
	// 不好的方式
	var elem = $('#elem');
	for (var i = 0; i < 100; i++) {
 	elem.append('<li>element '+i+'</li>');
	}

	// 好的方式
	var elem = $('#elem' ),
	arr = [];
	for (var i = 0;  i < 100; i++) {
  		arr.push('<li>element ' +i+'</li>' );
	}
	elem.append(arr. join(''));

	12.对大量数据计算使用缓存
	// data.length === 100000
   	for(var i = 0;i < data.length;i++){
     	// do something...
   	}
   	//上面的代码没有下面的好
   	for(var i = 0,len = data.length;i < len;i++){
     	// do something...
   	}

	13.使用setTimeout降低调用接口频率

1.hash模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

2.history 模式

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。history 模式需要后台配置支持

3.WebSocket

  1. http协议是短链接,因为请求之后,都会关闭连接,下次重新请求数据,需要再次打开连接。
  2. WebSocket协议是一种长连接,只需要通过一次请求来初始化链接,然后所有的请求和响应都是通过这个TCP链接进行通信。WebSocket是真正实现了全双工通信的服务器向客户端推的互联网技术,是一种在单个TCP连接上进行全双工通讯协议

特点:

(1)握手阶段采用HTTP协议,默认端口是80和443

(2)建立在TCP协议基础之上,和http协议同属于应用层

(3)可以发送文本,也可以发送二进制数据。

(4)没有同源限制,客户端可以与任意服务器通信。

(5)协议标识符是ws(如果加密,为wss),如ws://localhost:8023

4.纯函数

一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数 举个例子:

函数的返回结果只依赖于它的参数。
函数执行过程里面没有副作用。

const foo = (a,b) => a + b
foo(1,2) // => 3

blog.csdn.net/c_kite/arti…

5.什么是虚拟dom

是一个js对象 用来描述真实的dom,

Virtual DOM 是一种编程概念。在这个概念里, UI 以一种理想化的,或者说“虚拟的”表现形式被保存于内存中,并通过如 ReactDOM 等类库使之与“真实的” DOM 同步。这一过程叫做协调。 “Virtual DOM” 通常与 React 元素关联在一起,因为它们都是代表了用户界面的对象。而 React 也使用一个名为 “fibers” 的内部对象来存放组件树的附加信息。

6.什么是 “React Fiber”

Fiber 是 React 16 中新的协调引擎。它的主要目的是使 Virtual DOM 可以进行增量式渲染:一种将渲染工作分解为多个区块并将其分散到每一帧里面。

其他核心功能还包括随着程序中新的update引起的暂定、终止和继续等;以及为不同任务分配优先级;和最新的并发性

7.this.setState 什么时候是同步?什么时候是异步的?

原生事件与setTimeout中是同步的

setState本身的执行过程是同步的,只是因为在react的合成事件与钩子函数中执行顺序在更新之前,所以不能直接拿到更新后的值,形成了所谓的异步;

8.react性能优化

1.请确保你正在使用压缩后的生产版本。 2.单文件构建,在生产环境使用的单文件版 React 和 React DOM:注意:.production.min.js 为结尾的 React 文件适用于生产 3.使用 Chrome Performance 标签分析组件 4.虚拟化长列表 :虚拟滚动”技术。这项技术会在有限的时间内仅渲染有限的内容,降低重新渲染组件消耗的时间,以及创建 DOM 节点的数量。 4.shouldComponentUpdate 5.不可变数据的力量

9.redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理,应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。 惟一改变 state 的办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你需要编写 reducers,只有一个单一的 store 和一个根级的 reduce 函数(reducer),。随着应用不断变大,你应该把根级的 reducer 拆成多个小的 reducers,分别独立地操作 state 树的不同部分,而不是添加新的 stores。这就像一个 React 应用只有一个根级的组件,这个根组件又由很多小组件构成。

10.高阶组件

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 具体而言,高阶组件是参数为组件,返回值为新组件的函数。 组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件

实际应用案例:Redux 的 connect

11.jsx

JSX 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

编译成:

React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)

12.Time Slice 和Suspense?

Time Slicing (时间分片)

React 在渲染(render)的时候,不会阻塞现在的线程 如果你的设备足够快,你会感觉渲染是同步的。如果你设备非常慢,你会感觉还算是灵敏的、 虽然是异步渲染,但是你将会看到完整的渲染,而不是一个组件一行行的渲染出来 同样书写组件的方式

Suspense 悬停(也可以叫做暂停)

  • 在render函数中,我们可以写入一个异步请求,请求数据
  • react会从我们缓存中读取这个缓存
  • 如果有缓存了,直接进行正常的render
  • 如果没有缓存,那么会抛出一个异常,这个异常是一个promise
  • 当这个promise完成后(请求数据完成),react会继续回到原来的render中(实际上是重新执行一遍render),把数据render出来
  • 完全同步写法,没有任何异步callback之类的东西

13.观察者模式和发布订阅模式最大的区别?

观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。

5262488-291da39f66dbc28a.webp 从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

14.暂时性死区

在代码块内,使用const let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

15.二叉查找树特性

1.左子树上所有结点的值均小于或等于它的根结点的值. 2.右子树上所有结点的值均大于或等于它的根结点的值. 3.左、右子树也分别为二叉排序树. blog.csdn.net/Strangerrai…

16.transform动画和直接使用left、top改变位置有什么优缺点

1.left、top

会隐约觉得动画的运行并不流畅,动画有些停顿的感觉。这时因为top和left的改变会触发浏览器的 reflow和 repaint 。然后整个动画过程都在不断触发浏览器的重新渲染,这个过程是很影响性能的

2.transform动画

在动画移动的过程中也没有发生repaint和reflow。理由:ransform 动画由GPU控制,支持硬件加速。 zhuanlan.zhihu.com/p/78230297

17.JavaScript中 如何判断两个对象是否相等

blog.csdn.net/weixin_4379…

18 当调用setState时,React render 是如何工作的?

  • 虚拟 DOM 渲染:当render方法被调用时,它返回一个新的组件的虚拟 DOM 结构。当调用setState()时,render会被再次调用,因为默认情况下shouldComponentUpdate总是返回true,所以默认情况下 React 是没有优化的。

  • 原生 DOM 渲染:React 只会在虚拟DOM中修改真实DOM节点,而且修改的次数非常少——这是很棒的React特性,它优化了真实DOM的变化,使React变得更快。