前端基础之React(二)

1.11 setState到底是异步还是同步

有时表现出异步,有时表现出同步

  1. setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。

  2. setState 的异步并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback)中的 callback 拿到更新后的结果。

  3. setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。

1.12 redux异步中间件之间的优劣?

redux-thunk优点:

  • 体积小: redux-thunk的实现方式很简单,只有不到20行代码

  • 使用简单: redux-thunk没有引入像redux-saga或者redux-observable额外的范式,上手简单

redux-thunk缺陷:

  • 样板代码过多: 与redux本身一样,通常一个请求需要大量的代码,而且很多都是重复性质的

  • 耦合严重: 异步操作与redux的action偶合在一起,不方便管理

  • 功能孱弱: 有一些实际开发中常用的功能需要自己进行封装

redux-saga优点:

  • 异步解耦: 异步操作被被转移到单独 saga.js 中,不再是掺杂在 action.js 或 component.js 中

  • action摆脱thunk function: dispatch 的参数依然是一个纯粹的 action (FSA),而不是充满 “黑魔法” thunk function

  • 异常处理: 受益于 generator function 的 saga 实现,代码异常/请求失败 都可以直接通过try/catch 语法直接捕获处理

  • 功能强大: redux-saga提供了大量的Saga 辅助函数和Effect 创建器供开发者使用,开发者无须封装或者简单封装即可使用

  • 灵活: redux-saga可以将多个Saga可以串行/并行组合起来,形成一个非常实用的异步flow

  • 易测试,提供了各种case的测试方案,包括mock task,分支覆盖等等

redux-saga缺陷:

  • 额外的学习成本: redux-saga不仅在使用难以理解的 generator function,而且有数十个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是rxjs和一整套思想

  • 体积庞大: 体积略大,代码近2000行,min版25KB左右

  • 功能过剩: 实际上并发控制等功能很难用到,但是我们依然需要引入这些代码

  • ts支持不友好: yield无法返回TS类型

redux-observable优点:

  • 功能最强: 由于背靠rxjs这个强大的响应式编程的库,借助rxjs的操作符,你可以几乎做任何你能想到的异步处理

  • 背靠rxjs: 由于有rxjs的加持,如果你已经学习了rxjs,redux-observable的学习成本并不高,而且随着

  • rxjs的升级redux-observable也会变得更强大

redux-observable缺陷:

  • 学习成本奇高: 如果你不会rxjs,则需要额外学习两个复杂的库

  • 社区一般: redux-observable的下载量只有redux-saga的1/5,社区也不够活跃,在复杂异步流中间件

  • 这个层面redux-saga仍处于领导地位

1.13 state props 区别是啥?

props和state是普通的 JS 对象。虽然它们都包含影响渲染输出的信息,但是它们在组件方面的功能是不同的。即

  • state 是组件自己管理数据,控制自己的状态,可变
  • props 是外部传入的数据参数,不可变;
  • 没有state的叫做无状态组件,有state的叫做有状态组件;
  • 多用 props,少用 state,也就是多写无状态组件。

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

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

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

1.15 hooks

Hooks简介

React的组件创建方式,一种是类组件,一种是纯函数组件

  • 纯函数组件没有状态
  • 纯函数组件没有生命周期
  • 纯函数组件没有this

使用Hooks的优点:

  • 告别难以理解的Class( this 和 生命周期 的痛点)
  • 解决业务逻辑难以拆分的问题
  • 使状态逻辑复用变得简单可行
  • 函数组件从设计思想上来看更加契合React的理念

Hooks并非万能:

  • Hooks暂时还不能完全的为函数组件补齐类组件地能力(如生命周期的getSnapshotBeforeUpdate、componentDidCatch方法暂时还未实现)
  • 将类组件的复杂变成函数组件的轻量,可能使用者并不能很好地消化这种复杂
  • Hooks在使用层面有着严格地规则约束

Hook函数(9种)

  1. useState():状态钩子
  2. useContext():共享状态钩子
  3. useEffect():副作用钩子
  4. useReducer():Action钩子
  5. userRefef():Ref Hook可以在函数组件中存储、查找组件内的标签或任意其它数据
  6. useMemo(): 主要用来解决使用React hooks产生的无用渲染的性能问题
  7. useCallback(): 主要是为了性能的优化
  8. useLayoutEffect() :和useEffect相同,都是用来执行副作用,但是它会在所有的DOM变更之后同步调用effect。useLayoutEffect和useEffect最大的区别就是一个是同步,一个是异步。
  9. useImperativeHandle(): 可以在使用 ref 时自定义暴露给父组件的实例值。

自定义Hooks

自定义 Hooks:是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook

自定义Hooks:可以封装状态,能够更好的实现状态共享

打包工具

1.1 前端为什么要进行打包和构建

  1. 体积更小(Tree-Shaking、压缩、合并),加载更快
  2. 编译高级语言和语法(TS,ES6+,模块化,scss)
  3. 兼容性和错误检查(Polyfill、postcss、eslint)
  4. 统一、高效的开发环境
  5. 统一的构建流程和产出标准
  6. 集成公司构建规范(提测、上线等)

1.2 如何提高webpack的构建速度

  1. 优化babel-loader 开启缓存
  2. 使用module中的Noparse,不去解析属性值代表的库的依赖(需要在webpack.config.js的module节点添加noParse配置,使用|分割)
  3. 可以使用webpack内置插件lgnorePlugin插件(作用:忽略第三方包指定目录,让这些指定目录不要被打包进去)
  4. 使用happyPack多进程打包(需要下载)
  5. 使用parallelUgligyPlugin多进程压缩js(默认使用uglifyJs来压缩代码,单进程)

1.3 代码分割的本质是什么?

  1. 代码分割的本质就是在源代码直接上线和达成唯一脚本main.bundle.js这两种极端方案之间的一种更适合实际场景的中间状态。
  2. 源码直接上线:虽然过程可控,但是http请求多,性能开销大。
  3. 打包成唯一脚本:服务器压力小,但是页面空白期长,用户体验不好。

1.4webpack的基本功能有哪些?

名称 内容
代码转换 typescript编译成JavaScript、scss编辑成css
文件优化 压缩JavaScript、css、html、压缩合并图片
代码分割 提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并 采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新 监听本地源代码的变化,自动构建,刷新浏览器
代码校验 在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
自动发布 更新完代码后,自动构建出线上发布代码并传输给发布系统

1.5 文件指纹是什么?

文件指纹是打包之后的文件后缀名。

    chunkhash:和webpack打包的chunk有关,不同的entry会生出不同的chunkhash。

            js后缀名:filename:'\[name]\[chunkhash:8].js',

    contenthash:根据文件内容来定义hash,文件内容不变,则其不变。

            css后缀名:filename:'\[name]\[contenthash:8].css',

    hash:和整个项目构建有关,只要项目文件有修改,整个构建的hash值就会修改。

            img后缀名:name:'\[name]\[hash:8].\[ext]'

1.6 为什么说vite比webpack更快?

  1. webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
  2. vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。
  3. vite在启动的时候不需要打包,意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快。
  4. 当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。
  5. 在HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
  6. 当需要打包到生产环境时,vite使用传统的rollup进行打包,因此,vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS

1.7 vite工作原理

vite是一种现代化的前端开发工具,其工作原理主要分为以下几个步骤

  1. 基于ESM构建:Vite作为一款基于ESM的前端构建工具,通过ES模块提供的动态导入功能来实现快速的开发和构建。
  2. 零配置开发:Vite允许开发者在不需要任何配置的情况下启动一个服务器进行开发,通过对文件的即时编译和缓存,来提高开发效率。
  3. 基于浏览器原生的ESM加载:Vite将所有文件视为ES模块,并且在开发时会直接从源代码加载模块,而不是打包后的文件,从而可以避免打包的过程带来的性能损失。
  4. 按需编译和缓存:Vite会按需编译和缓存依赖项,只有当需要更新时才会进行重新编译,缓存让开发者可以忽略无关的代码变化。
  5. 插件化架构:Vite的插件化架构可以方便地扩展其功能,例如使用插件来处理CSS、处理图片、压缩源代码等等。

1.8 vite核心原理

  • Vite其核心原理是利用浏览器现在已经支持ES6的import,碰见import就会发送一个HTTP请求去加载文件。
  • Vite整个过程中没有对文件进行打包编译,做到了真正的按需加载,所以其运行速度比原始的webpack开发编译速度快出许多!

特点:

  1. 快速的冷启动:基于Esbuild的依赖进行预编译优化 (Esbuild 打包速度太快了,比类似的工具快10~100倍 )
  2. 增加缓存策略:源码模块使用协商缓存,依赖模块使用强缓;因此一旦被缓存它们将不需要再次请求
  3. HMR(热更新):当修改代码时,HMR 能够在不刷新页面的情况下,把页面中发生变化的模块,替换成新的模块,同时不影响其他模块的正常运作
  4. 基于 Rollup 打包:生产环境下由于esbuild对css和代码分割并使用Rollup进行打包
  5. 高效的热更新:基于ESM实现,同时利用HTTP头来加速整个页面的重新加载

1.9 Vite 冷启动为什么快

vite 运行 Dev 命令后只做了两件事情

  1. 启动本地服务器并注册了一些中间件
  2. 使用 ESbuild 预构建模块

1.10 vite生产环境缺点

  1. Vite 在是直接把转化后的 es module 的JavaScript,扔给浏览器,让浏览器根据依赖关系,自己去加载依赖

  2. 那有人就会说了,那放到 生产环境 时,是不是可以不打包,直接在开个 Vite 服务就行,反正浏览器会自己去根据依赖关系去自己加载依赖。答案是不行的,为啥呢:

    1、你代码是放在服务器的,过多的浏览器加载依赖肯定会引起更多的网络请求

    2、为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割、CSS处理,这些优化操作,目前 esbuild 还不怎么完善

1.11 vite和webpack优缺点对比

  • 更快的启动时间和更新速度
  • 更好的开发体验:自动打开浏览器、自动刷新页面 配置简单。
  • 不需要过多的配置就可以搭建基本的开发环境 更少的依赖。
  • 借助原生的ES模块
  • 避免了过多的额外依赖

缺点:

  • vite的构建技术主要用于中小型项目,对于大型项目的支持不如webpack
  • vite主要是针对vue3的单页面应用,对于多页面应用、ssr应用、自定义流程应用不如webpack
  • 开发环境首屏加载慢,懒加载慢
  • vite由于基于原生ES模块,不支持commonJs;webpack关注兼容性,vite关注浏览器端的开发体验,vite的生态还不如webpack
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容