由 小黑猫 发布于 2025年02月28日 12:19:40
是什么随着前端项目规模越来越大, 原本的开发方式html+script+css开发效率低,需要利用一些约束、规范和工具,降低前端开发的开发成本,提升开发效率随着前端的发展阶段我觉得主要分为以下四个部分吧,四个部分层层递进模块化把代码分割成独立且易管理的部分(esm)。如果没有模块化,js通过script把所有资源引入html,依赖关系不明确,可能引入的资源间也互相有依赖。CommonJS:requireESM:import/export包管理器使用其他开发者写好的包(模块),使用包管理器来管理这些依赖。babel/core.js 处理兼容性问题,比如某些浏览器不支持ESM esm->commonjs虽然手动也可以解决,但随着要转换的文件变多,要求变多,就需要构建工具来提供一套统一的构建流程构建工具随着代码规模增大,需要构建工具来帮开发者打包、压缩、做一些代码分割、资源压缩等优化。构建工具提供一个统一的构建系统,一整套构建的流程Webpack构建流程1. 初始化:加载配置文件创建Compiler实例;过程中注册插件,监听广播事件2. 开始编译,执行compiler.run3. 找到入口Entry,递归解析依赖树,loader加载文件(优化空间:配置规则、oneOf、include/exclude,noParse让loader加载更快),执行构建4. 在所有模块和依赖都通过Loader转换后,将这些模块分块处理,打包成一个或多个输出文件(分块、代码压缩等Plugin在此作用)5. 构建完成,生成文件、index模版,输出写入文件到输出目录中通常dist6. 完成打包,触发done(触发一些通知、日志等)7. 1的补充:在整个过程中 webpack广播一些事件,plugin通过监听这些事件,触发webpack一些特定的api,改变编译的结果Loader、PluginLoader:由于Webpack本身只能加载js和json,所以需要一些加载器在解析模块的时候转换对应的文件,通过配置text、use(loader、option)来让Webpack加载对文件,更多集中于文件加载,作用于文件Plugin:赋予一些Webpack本身不具备的额外功能,通过监听Webpack广播的事件执行Webpack API改变输出结果,作用于Webpack整体,一般用作文件打包时的压缩优化类插件(写在优化配置中)、流程类插件(HTML生成、CSS提取、每次构建前清理构建目录)性能优化(可分为四方面)1. 优化开发体验:源码地图source-map(devtool)2. 提高构建速度:优化匹配规则(include/exculde、oneOf、noParse)(rules)3. 降低打包体积:代码压缩、提取公用模块(optimization)、缓存(cache)、treeshaking4. 优化运行性能:懒加载、按需加载、prefetch预加载5. terserplugin:Js多线程代码压缩(许多脚手架默认支持)(还有其他css压缩,图片无损压缩的插件)脚手架为前端项目提供一个自动化的项目初始模版(常见的构建工具和配置),让开发者专注于功能的开发,减少重复工作。
由 小黑猫 发布于 2025年02月28日 12:11:11
设计理念不同:React:构建用户界面的库,只提供基本的功能,使用其他功能需要使用社区提供的第三方库,但是目前React官网也推荐直接使用React框架来开发React项目。Vue:渐进式框架,提供模版和规范,可以只用基本功能,也可以使用Vue官方提的工具链逐步拓展框架的功能。响应式原理不同:React:UI=f(state),基于不可变数据,状态更新时不会修改原数据,而是创建一个新的数据,组件的代码会在每次状态改变时重新执行(记忆钩子),所以在状态频繁改变或组件数大的情况下会增加性能开销。Vue:Vue的script代码通常只执行一次,并不会在状态改变时重新执行(所以Vue需要有计算属性等的概念来添加追踪触发更新)基于依赖追踪的响应式系统来管理状态更新,采用了观察者的设计理念,将状态定义为可被订阅的JS对象,并跟踪哪些组件依赖这些状态,当状态改变时,Vue的响应式系统会自动通知所有订阅者更新视图,而不需要重新执行组件代码,更高效精细的更新UI。数据绑定方面:React:单项数据绑定,父组件通过props传到子组件,子组件不能直接修改父组件状态,而是通过调用回调函数进行状态更新。Vue:支持双向数据绑定(举例对于input框,Vue可以v-model绑定状态,React则要通过onChange监听+setState),数据和视图之间自动同步,在开发输入框、表单等数据交互场景非常便利。性能:React:Fiber架构,改变状态后通知调度器,运行组件代码,构建Fiber树,通过双缓存机制渲染。Vue:编译时创建虚拟dom构建函数,在代码中留标记,便于依赖追踪,提高性能。使得Vue在数据更新方面更高效,避免了React常见的重复渲染问题。数据传递:React:父子间:函数传参,props接收跨组件:ContextVue:父子间:defineProps、defineEmits、defineModel(Vue3.5新增,之前的父子数据绑定思路参考React调用回调)跨组件:provide/inject#### Diff算法Diff算法是什么:对比算法,找出两个结构中的不同,文件系统、git上其实都有运用Diff优化必要性:树形结构对比复杂,不进行优化不可用,复杂度高 n的三次Diff统一优化思路:1. 同层比较2. tag不同直接删掉重建,不再比较细节3. 子节点通过key区分React:双指针单向遍历,节点仅右移Vue:Vue2采用双端比较,Vue3在此基础上添加了最长递增子序列进一步优化
由 小黑猫 发布于 2025年02月28日 12:05:42
构建过程1. 初始化:加载配置文件创建Compiler实例;过程中注册插件,监听广播事件2. 开始编译,执行compiler.run3. 找到入口Entry,递归解析依赖树,loader加载文件(优化空间:配置规则、oneOf、include/exclude,noParse让loader加载更快),执行构建4. 在所有模块和依赖都通过Loader转换后,将这些模块分块处理,打包成一个或多个输出文件(分块、代码压缩等Plugin在此作用)5. 构建完成,生成文件、index模版,输出写入文件到输出目录中通常dist6. 完成打包,触发done(触发一些通知、日志等)7. 在整个过程中 webpack广播一些事件,plugin通过监听这些事件,触发webpack一些特定的api,改变编译的结果性能优化(可分为四方面)1. 优化开发体验:源码地图source-map(devtool)2. 提高构建速度:优化匹配规则(include/exculde、oneOf、noParse)(rules)3. 降低打包体积:代码压缩、提取公用模块(optimization)、缓存(cache)、treeshaking4. 优化运行性能:懒加载、按需加载、prefetch预加载补充:terserplugin:Js多线程代码压缩(许多脚手架默认支持)(还有其他css压缩,图片无损压缩的插件
由 小黑猫 发布于 2025年02月20日 08:02:59
迭代和遍历的区别:迭代强调依次取数据,不一定取多少也不一定取完;遍历全部依次取出迭代器:对迭代过程的封装,通常为对象迭代模式:一种设计模式用以统一迭代过程,规定了迭代器应有获取下一个数据和判断是否还有后续数据的能力。js规定,如果一个对象具有next方法,并且该方法返回一个对象,格式如下:{value:值done:是否迭代完成} 则该对象为迭代器迭代器创建函数:返回一个迭代器的函数可迭代协议与for..of循环:ES6规定,如果一个对象具有知名符号属性Symbol.iterator,并且属性值是一个迭代器创建函数,则该对象是可迭代的(iterable)for...of循环用于遍历可迭代对象,会帮你迭代value直到down扩展(展开)运算符...除了展开数组,也可以用来展开可迭代对象生成器:什么是生成器?生成器是一个通过构造函数Generator创建的对象,生成器既是一个迭代器,同时又是一个可迭代对象如何创建生成器?生成器的创建不能new,必须通过生成器函数创建如何书写生成器函数?关键词后函数名前加一个星号* 该函数一定返回生成器生成器函数内部如何工作?内部是为了给生成器每次迭代提供数据,每次调用生成器的next方法,将导致生成器函数运行到下一个yield关键字的位置,yield是一个只能在生成器函数内使用的关键字,表达生成一个迭代数据需要注意的细节:1. return的值为第一次down为true时返回的value,如果不设置则为undefinded2. 调用生成器的next方法可以传递参数(生成器特有),传递的参数会交给上一次yield表达式的返回值,也就是说第一个next传递3. 在生成器函数内部可以调用其他生成器函数,但是要在yield后加上* 号相当于把其他生成器的yield cv过来了
由 suzvc 发布于 2025年02月18日 07:35:56
基础所有对象都是通过new创建的,所有的函数也是对象(本质通过new Function创建,Function创建函数直接在内存中不是new创建的),函数中可以有属性,所有对象都是引用类型new创建对象时,如果函数返回值为对象,则结果为该对象,如果没有对象返回值,则返回该构造函数实例对象函数原型prototypeprototype是所有函数都有的属性,称之为函数原型prototype默认情况下是一个普通的Object对象,中有一个constructor属性指向该构造函数本身隐式原型__proto__所有的对象(包括函数)都有的属性,称之为隐式原型隐式原型指向创建该对象的函数原型:obj.__ proto __ === 创建函数.prototype原型链应用简而言之,就是我个人认为当需要一些实例特有的属性时,通过构造函数传递参数与实例绑定,但对于实例通用的方法,存储在prototype上则可以共用降低内存损耗,我个人感觉prototype的作用主要就是在于区分实例私有和公用,需要一个属性值来标定,所以存储在prototype中原型链(个人感觉原型链指的是隐式原型链,函数会将一些公用方法存储到函数原型中供隐式原型链层层查找)任何对象都有原型,原型也是个对象,最终层层嵌套会访问到Object原型,达到继承的效果,Object原型再调用__proto__ 则为null