美文网首页
前端基础之React(二)

前端基础之React(二)

作者: 若雨千寻 | 来源:发表于2023-12-11 09:09 被阅读0次

    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

    相关文章

      网友评论

          本文标题:前端基础之React(二)

          本文链接:https://www.haomeiwen.com/subject/wiedgdtx.html