2026/1/2 5:02:17
网站建设
项目流程
哪里有专业网站建设公司,哈尔滨seo关键词优化,新增备案网站要关闭吗,世界知名网站目录
一、HTML篇
1、HTML5 新增那些标签?#xff08;⭐#xff09;
2、块元素、行内元素、行内块元素#xff0c;三者有何不同以及区别#xff1f;#xff08;⭐#xff09;
3、HTML4、HTML5、XML、XHTML它们之间有什么区别#xff1f;#xff08;⭐#xff09; …目录一、HTML篇1、HTML5 新增那些标签?⭐2、块元素、行内元素、行内块元素三者有何不同以及区别⭐3、HTML4、HTML5、XML、XHTML它们之间有什么区别⭐4、DOCTYPE(⽂档类型) 的作⽤⭐5、localStorage、sessionStorage、cookie 三者区别对比⭐⭐⭐6、网站TDK三大标签以及SEO优化 ⭐7、img标签的title属性与alt属性的区别是什么⭐8、src 和 href 的区别⭐9、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别 ⭐10、iframe的基本介绍与使用 ⭐⭐⭐11、BFC 是什么 ⭐二、CSS篇1、说一下 link 与 import 的区别和用法⭐2、rgba和opacity的透明效果有什么不同⭐⭐3、display:none与visibility:hidden的区别⭐⭐4、定位布局 position中的relative、absolute、fixed、sticky它们之间的区别⭐⭐⭐5、如何用CSS3画一条0.5px的直线⭐6、如何用CSS3画一个三角形⭐7、CSS3盒子模型标准盒模型、怪异盒模型⭐⭐⭐8、浮动float)以及清除浮动的方法⭐⭐9、Flex布局⭐⭐⭐10、CSS3中 transform 属性~平面转换⭐11、CSS3中 “子绝父相” 定位布局⭐⭐⭐12、盒子居中的几种方法“子绝父相”、“Flex布局”、“transform”⭐⭐⭐13、CSS3中有哪些新特性⭐14、CSS3选择器及其优先级⭐15、CSS3中 “transition” 过渡属性⭐16、结构伪类选择器伪元素选择器⭐17、display的block、inline和inline-block的区别⭐18、定位堆叠顺序z-index⭐19、如何实现双飞翼圣杯布局 ⭐20、伪元素和伪类的区别和作用⭐三、JavaScript篇1、JS基础类型和复杂类型⭐⭐⭐2、箭头函数与普通函数的区别⭐⭐⭐⭐3、JS中null和undefined的判断方法和区别⭐⭐⭐4、原型链⭐⭐⭐5、v-show 与 v-if 的区别⭐⭐6、keep-alive 的作用是什么?⭐⭐7、闭包的理解?⭐⭐⭐⭐⭐8、JS垃圾回收机制⭐⭐⭐⭐⭐9、nextTick的实现⭐⭐10、混入mixin的原理⭐⭐11、js列举和数组操作相关的方法(常用)⭐⭐⭐⭐⭐12、typeof和instanceof的区别是什么 ⭐⭐13、JS中 ““和““的区别详解⭐⭐14、如何用原生 JS给一个按钮绑定两个 onclick 事件⭐⭐15、var、let和const的区别⭐⭐⭐16、讲解js的call、apply和bind区别⭐⭐⭐17、谈谈你对webpack的理解⭐⭐⭐18、 const定义的对象属性是否可以改变⭐⭐19、栈溢出及解决方法⭐⭐⭐20、JS如何实现多线程⭐⭐⭐21、浅拷贝和深拷贝区别概念常见情况⭐⭐⭐⭐22、事件循环Promise和async/await的详解⭐⭐⭐⭐23、JS中数组常用方法详解 ⭐⭐⭐⭐24、JS 防抖和节流概念代码示例⭐⭐⭐25、JS图片懒加载的原理⭐⭐⭐四、Vue2篇1、什么是前端构建工具?比如Vue2的webpackVue3的Vite⭐⭐2、Vue 组件之间的通信方式⭐⭐⭐⭐⭐3、Vuex的理解及使用场景⭐⭐⭐4、vue 的生命周期 八个阶段⭐⭐⭐⭐5、简述Vue每个周期具体适合哪些场景⭐⭐⭐6、简述MVVM 和MVC的原理以及区别⭐⭐⭐7、vue常见指令⭐⭐⭐8、vue中的data为什么是一个函数起到什么作用 ⭐⭐⭐9、vue中ref的作用 ⭐⭐⭐10、Vue中hash和history的区别 ⭐⭐⭐五 、Vue3篇1、Vue2和Vue3的区别⭐⭐⭐⭐2、Vue2和Vue3的生命周期⭐⭐⭐⭐⭐3、Vue2和vue3的响应式原理⭐⭐⭐⭐⭐4、Vue3常用 Composition API⭐⭐⭐⭐⭐5、Vue3 组件通信 (父传子、子传父、父子双向绑定、跨层级通信、全局状态管理) ⭐⭐⭐⭐⭐6、Vue 3 的 setup() 函数的作用是什么⭐⭐⭐7、ref 和 reactive 的区别是什么⭐⭐⭐六、React篇1、讲讲什么是 JSX ⭐⭐⭐2、React 的生命周期方法有哪些⭐⭐⭐3、React的Hooks详解⭐⭐⭐⭐⭐4、React和Vue.js的相似性和差异性是什么⭐⭐5、React的功能是什么 ⭐⭐6、React的一些主要优点是⭐⭐7、React的局限性是什么⭐⭐8、如何理解React State不可变性的原则⭐⭐9、React的特点和关键版本区别⭐⭐10、React Fiber的深入理解⭐⭐七、uniapp篇1、uniapp优缺点⭐⭐2、uniapp目录结构⭐3、跨端适配—条件编译 ⭐⭐4、uniapp 常用的指令语句⭐⭐5、uniapp 应用的生命周期、页面的生命周期、组件的生命周期⭐⭐八、Webpack篇1、Webpack是什么⭐⭐2、Webpack的打包过程/打包原理/构建流程 ⭐⭐3、Webpack中loader的作用/ loader是什么⭐⭐4、常见的loader有哪些⭐⭐5、Plugin有什么作用Plugin是什么⭐⭐6、常见的Plugin有哪些⭐⭐7、Webpack中Loader和Plugin的区别⭐⭐8、如何利用webpack来优化前端性能⭐⭐9、Webpack如何配置压缩代码压缩了什么⭐⭐10、如何提高webpack的构建速度 ⭐⭐九、Git/SVN篇1、Git是什么⭐⭐2、简述Git中如何将一个新增文件添加到本地仓库⭐⭐3、Git常用命令⭐⭐⭐4、Git和SVN有什么区别?⭐⭐十、B站开源视频大汇总前端从入门到精通1、web 入门HTML5CSS32、jsJavaScriptjQueryAjax3、Vue 开发Vue2Vue3实战项目4、React 微信小程序开发uniapp5、华为鸿蒙进阶6、ssrNuxtNext.js7、工程化webpackvite8、可视化echarts 9、源码虚拟DOM和diff算法10、移动App跨端开发Uni-App11、桌面应用开发Electron12、网络知识网络概述结构算法13、浏览器底层原理一、HTML篇1、HTML5 新增那些标签?⭐1布局标签语义化标签: 头部标签: 导航标签: 内容标签: 定义文档某个区域: 侧边栏标签: 底部标签图形结合记忆法2视频标签(video)属性描述示例autoplay布尔属性若存在则视频在加载完成后自动播放。video autoplay/videocontrols布尔属性若存在则显示视频控制控件如播放按钮、进度条、音量控制等。video controls/videoloop布尔属性若存在则视频播放完毕后自动循环播放。video loop/videomuted布尔属性若存在则视频默认静音。video muted/videoposter指定视频加载时显示的预览图片 URL若未设置则显示视频第一帧。video posterpreview.jpg/videopreload定义视频的预加载方式可选值-auto自动预加载视频-metadata仅加载视频元数据如时长、尺寸-none不预加载视频video preloadmetadata/videosrc指定视频文件的 URL。video srcvideo.mp4/videowidth设置视频的宽度像素值。video width800/videoheight设置视频的高度像素值。video height450/videoplaysinline布尔属性主要用于移动端若存在则视频在浏览器内播放不进入全屏模式需配合浏览器兼容性设置。video playsinline/videocontrolslist自定义控制控件的显示 / 隐藏可选值用空格分隔-nodownload隐藏下载按钮-nofullscreen隐藏全屏按钮-noremoteplayback禁止远程播放video controlslistnodownload nofullscreen/videocrossorigin配置视频的跨域请求策略可选值-anonymous匿名跨域-use-credentials带凭证跨域video crossoriginanonymous/videomediagroup将多个视频元素分组用于同步控制如多个视频同时播放 / 暂停。video mediagr3音频标签(audio)属性描述示例autoplay布尔属性若存在则音频在加载完成后自动播放。audio autoplay/audiocontrols布尔属性若存在则显示音频控制控件如播放按钮、进度条、音量控制等。audio controls/audioloop布尔属性若存在则音频播放完毕后自动循环播放。audio loop/audiomuted布尔属性若存在则音频默认静音。audio muted/audiopreload定义音频的预加载方式可选值-auto自动预加载音频-metadata仅加载音频元数据如时长、采样率-none不预加载音频audio preloadmetadata/audiosrc指定音频文件的 URL。audio srcmusic.mp3/audio4图片标签imgsrc指定图片文件的 URL是标签的必需属性。img srcimage.jpgalt图片的替代文本当图片无法加载或需要无障碍访问时显示。img alt风景图片width设置图片的宽度像素值或百分比。img width800height设置图片的高度像素值或百分比建议与width配合使用以避免图片变形。img height450loading定义图片的加载时机可选值-eager立即加载-lazy延迟加载浏览器视口外的图片暂不加载img loadinglazysrcset提供多个不同分辨率的图片 URL浏览器会根据设备屏幕尺寸自动选择最佳图片。img srcsetimg-320.jpg 320w, img-640.jpg 640wsizes配合srcset使用定义不同屏幕尺寸下应加载的图片尺寸格式为(媒体条件) 图片宽度, 默认宽度。img sizes(max-width: 600px) 100vw, 600pxcrossorigin配置图片的跨域请求策略可选值-anonymous匿名跨域-use-credentials带凭证跨域img crossoriginanonymousdecoding定义图片的解码优先级可选值-async异步解码不阻塞页面渲染-sync同步解码-auto浏览器自动决定img decodingasyncclass/id为图片添加 CSS 类名或唯一标识符用于样式控制或 JavaScript 操作。img classgallery-img idmain-imgusemap关联图片映射map标签用于定义图片上的可点击区域。img usemap#image-mapismap布尔属性若存在则图片为服务器端映射点击图片会向服务器发送点击坐标。img ismap srcmap.jpg5新的 API音视频audio 和 video 元素绘图图形canvas 元素本地存储localStoragesessionStorage多线程操作Web Worker Web Worker 是HTML5 新特性允许我们在 js 主线程之外开辟新线程并将一段 js 脚本运行其中它赋予了开发者利用 js 操作多线程的能力 更多HTML5新属性W3Cschool官网开始学习HTML5_w3cschool语义化的优点如下在没有CSS样式情况下也能够让页面呈现出清晰的结构有利于SEO和搜索引擎建立良好的沟通有助于爬虫抓取更多的有效信息爬虫是依赖于标签来确定上下文和各个关键字的权重方便团队开发和维护语义化更具可读性遵循W3C标准的团队都遵循这个标准可以减少差异化2、块元素、行内元素、行内块元素三者有何不同以及区别⭐本质区别分类布局特性典型标签块级元素独占一行默认宽度 100%可设置宽高、内外边距div,p,h1,ul行内元素不独占行宽度由内容决定无法直接设置宽高边距部分生效span,a,em,strong行内块元素不独占行但可设置宽高兼具行内元素和块级元素的特性img,input,button,select1块元素空间占据默认占据父容器 100% 宽度垂直方向与其他块级元素堆叠排列尺寸可控可通过 CSS 自由设置width、height、margin、padding布局基石常用于构建页面框架如导航栏、内容区、页脚嵌套规则通常可包含块级元素和行内元素但p等少数标签例外2行内元素行内排列多个行内元素在同一行排列直到父容器宽度不足时换行尺寸限制无法通过 CSS 设置width、height仅内容撑开盒子边距特性margin-left/right有效margin-top/bottom无效padding全方向生效但不影响布局嵌套规则只能包含文本或其他行内元素不能包含块级元素a标签可嵌套行内元素但需注意嵌套规范3行内块元素行内排列可与其他行内 / 行内块元素在同一行排列尺寸可控可设置width、height、margin、padding基线对齐默认基于文本基线对齐可通过vertical-align调整空白间隙多个行内块元素之间的 HTML 空白空格、换行会渲染为间距3、HTML4、HTML5、XML、XHTML它们之间有什么区别⭐技术核心应用场景当前趋势HTML4老旧网页、兼容性要求极高的 legacy 系统逐步淘汰仅在历史项目中使用HTML5现代网页开发、响应式设计、Web 应用如单页应用、移动端 H5 页面主流标准持续迭代新特性如 WebGPU、WebAssemblyXML配置文件如 Android manifest、企业级数据交换SOAP、RSS、后端系统集成在数据交换中仍有应用但部分场景被 JSON 取代XHTML1.0早期移动设备网页、需严格 XML 解析的场景极少新建项目使用主要用于历史兼容4、DOCTYPE(⽂档类型) 的作⽤⭐DOCTYPE文档类型的核心作用与机制解析一、DOCTYPE 的本质与核心功能DOCTYPEDocument Type Declaration文档类型声明是 HTML 文档的 “身份标识”其核心作用是告知浏览器解析规则声明当前文档遵循的 HTML 或 XML 标准如 HTML4、HTML5、XHTML让浏览器以对应模式渲染页面避免因规则不明确导致的显示异常。触发浏览器的渲染模式标准模式Standard Mode严格遵循 W3C 标准解析 CSS 和布局。怪异模式Quirks Mode兼容旧浏览器的非标准解析方式仅在 DOCTYPE 缺失或格式错误时触发。二、不同 DOCTYPE 的声明格式与作用对比文档类型DOCTYPE 声明示例作用与浏览器行为HTML5!DOCTYPE html- 最简声明告诉浏览器按 HTML5 标准解析触发标准模式。- 无需引用 DTD语法简化兼容现代浏览器。HTML4.01 严格型!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01//EN http://www.w3.org/TR/html4/strict.dtd- 强制使用 HTML4 严格规范禁止表现层标签如font和框架frameset。- 触发标准模式适合规范严格的网页。HTML4.01 过渡型!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd- 允许使用表现层标签和过时特性兼容旧项目。- 触发标准模式但对语法宽松度更高。XHTML 1.0 严格型!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd- 遵循 XML 语法标签小写、必须闭合等禁止表现层标签。- 需配合 XML 声明?xml version1.0 encodingUTF-8?触发标准模式。无 DOCTYPE 声明无- 浏览器触发 “怪异模式”按旧版本规则解析如 IE6 的盒模型计算方式。- 可能导致布局错乱现代开发中必须避免。5、localStorage、sessionStorage、cookie 三者区别对比⭐⭐⭐特性CookielocalStoragesessionStorage存储大小4KB 左右5MB 或更大5MB 或更大数据有效期可设置失效时间默认浏览器关闭后失效。除非被手动清除否则永久保存。仅在当前会话期间有效关闭页面或浏览器后被清除。与服务器通信每次 HTTP 请求都会携带 cookie 数据因此会带来额外的性能开销。仅在客户端存储不参与服务器通信。仅在客户端存储不参与服务器通信。可见范围在所有同源窗口中都是共享的。在所有同源窗口中都是共享的。在不同浏览器窗口中不共享即使是同源的。应用场景用于身份验证如登录状态、跟踪用户会话等。用于长期保存网站的配置信息、缓存数据等。用于临时保存同一窗口或标签页的数据在关闭窗口或标签页后数据不需要保留的场景。读写 API需要手动解析和设置 document.cookie操作繁琐。简单的 APIsetItem (key, value)、getItem (key)、removeItem (key)、clear ()。与 localStorage 相同setItem (key, value)、getItem (key)、removeItem (key)、clear ()。浏览器支持所有主流浏览器都支持包括 IE6。HTML5 新特性IE8 支持。HTML5 新特性IE8 支持。6、网站TDK三大标签以及SEO优化 ⭐标签定义SEO 优化要点常见误区Title标题网页的标题显示在浏览器标签栏和搜索结果标题位置是搜索引擎判断页面主题的核心依据。1. 长度控制在 55-60 字符避免被搜索引擎截断2. 核心关键词前置自然融入品牌名3. 避免重复每个页面唯一4. 用「-」「」分隔关键词增强可读性。1. 堆砌关键词如 “SEO 优化SEO 公司SEO 服务”2. 标题过长或过短3. 所有页面标题相同如统一使用 “首页”。Description描述网页的内容摘要显示在搜索结果标题下方用于引导用户点击并简述页面价值。1. 长度控制在 150-160 字符2. 包含核心关键词自然扩展为语句3. 突出页面优势如服务、内容、优惠等4. 避免堆砌保持语句通顺。1. 重复关键词如 “专注 SEO 优化SEO 优化服务提供专业 SEO 优化”2. 描述与页面内容无关3. 照搬 Title 内容。Keywords关键词早期用于标注页面核心关键词但目前主流搜索引擎如百度、谷歌已弱化其权重。1. 仅保留 3-5 个核心关键词与 Title、内容强相关2. 避免使用宽泛词如 “互联网”“软件”3. 不强制填写若填写需与内容高度匹配。1. 堆砌大量无关关键词如 “SEO, 淘宝京东拼多多”2. 使用竞争对手品牌词3. 过度依赖 Keywords 标签忽略内容本身优化。7、img标签的title属性与alt属性的区别是什么⭐特性title 属性alt 属性定义为元素提供额外的提示信息为无法显示图像的用户提供替代文本显示时机鼠标悬停在元素上时显示图像无法加载时显示屏幕阅读器朗读搜索引擎抓取内容必要性可选必须无障碍标准要求内容侧重点补充说明图像的细节或背景信息简明扼要地描述图像内容和功能对 SEO 的影响权重较低辅助理解权重较高影响搜索排名示例代码img srclogo.png title公司LogoXX科技img srclogo.png altXX科技公司Logo8、src 和 href 的区别⭐特性srcSourcehrefHypertext Reference定义指向需要嵌入当前文档的资源如图片、脚本、视频等。指向与当前文档相关的外部资源如样式表、链接等建立当前文档与目标资源的关联。作用替换当前元素或引入外部资源到文档中成为文档的一部分。建立超链接关系不替换当前元素仅表示关联。加载行为浏览器会暂停对当前文档的解析优先下载并处理 src 指向的资源同步加载。如img src、script src。浏览器继续解析文档并行下载 href 资源异步加载。如link href、a href。应用场景- 图片img srcimage.jpg- 脚本script srcscript.js/script- 视频video srcvideo.mp4/video。- 样式表link hrefstyle.css relstylesheet- 超链接a hrefpage.html链接/a- 外部资源link hreffavicon.ico relicon。9、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别⭐1title与h1的区别特性titleHTML 标签h1HTML 标题标签定义定义整个 HTML 文档的标题显示在浏览器标签栏。定义页面的主标题通常是页面最重要的标题。位置必须放在head标签内headtitle页面标题/title/head。放在body标签内bodyh1页面主标题/h1/body。SEO 权重高搜索引擎判断页面主题的核心依据。高页面内容的核心主题。用户可见性仅显示在浏览器标签栏、历史记录和书签中。直接显示在网页内容中。最佳实践每个页面的 title 需唯一包含核心关键词和品牌名。每个页面只能有一个 h1 标签通常与 title 相关但更具体。示例titleSEO优化服务-专业网站排名提升-XX科技/title。h1专业SEO优化解决方案/h1。2b与strong 的区别特性bBoldstrongStrong Importance语义仅表示文本 “加粗显示”无特殊语义。表示文本具有 “重要性”强调内容的关键性。无障碍性屏幕阅读器可能忽略 b 标签的语义。屏幕阅读器会强调 strong 标签的内容如朗读时加重语气。SEO 影响无明确权重提升。可能被搜索引擎视为重要内容略微提升关键词相关性。最佳实践用于纯装饰性加粗如产品名称、UI 元素。用于强调重要信息如警告、关键说明、结论。示例biPhone 15/b 现已上市。strong注意/strong 此操作不可逆。3i 与 em 的区别特性iItalicemEmphasis语义仅表示文本 “斜体显示”无特殊语义。表示文本具有 “强调” 语气通常译为 “着重”。无障碍性屏幕阅读器可能忽略 i 标签的语义。屏幕阅读器会强调 em 标签的内容如朗读时提高音调。SEO 影响无明确权重提升。可能被搜索引擎视为重要内容略微提升关键词相关性。最佳实践用于斜体装饰如书籍标题、外来词、分类名称。用于强调句子中的特定词汇如突出对比、重要术语。示例《iJavaScript高级程序设计/i》第4版。你应该使用 emconst/em 而不是 var。总结语义化优先优先使用 strong 和 em因为它们携带语义信息有助于无障碍访问和 SEO。装饰性需求仅在无强调语义时使用 b 和 i如纯视觉效果。SEO 建议title 和 h1 需精准匹配页面主题strong 和 em 用于突出关键词但避免滥用。10、iframe的基本介绍与使用⭐⭐⭐介绍iframe内嵌框架是 HTML 中一种用于将一个网页嵌入到另一个网页中的标签它可以在一个页面中显示来自其他页面的内容。在网页中使用iframe标签可以将一个网页嵌套在另一个网页中实现网页间的互联互通。使用举例iframe的缺点页面样式调试麻烦出现多个滚动条浏览器的后退按钮失效过多会增加服务器的HTTP请求小型的移动设备无法完全显示框架产生多个页面不易管理不容易打印代码复杂无法被一些搜索引擎解读。搜索引擎的检索程序无法解读这种页面不利于SEO;iframe的优点iframe能够原封不动的把嵌入的网页展现出来。如果有多个网页引用iframe那么你只需要修改iframe的内容就可以实现调用的每一个页面内容的更改方便快捷。网页如果为了统一风格头部和版本都是一样的就可以写成一个页面用iframe来嵌套可以增加代码的可重用。如果遇到加载缓慢的第三方内容如图标和广告这些问题可以由iframe来解决。重载页面时不需要重载整个页面只需要重载页面中的一个框架页(减少了数据的传输增加了网页下载速度)总而言之运维性网站或继承性开发的网站可以使用iframe销售内官网、展示性网站等建议不使用iframe标准的网页设计是不使用iframe的嵌入的网页必须与主页面同源否则会受到浏览器的安全限制嵌入的网页可能会影响页面性能和加载速度特别是当嵌入的网页包含大量的资源如图片、CSS 和 JavaScript时嵌入的网页可能会被恶意攻击者用于钓鱼或注入恶意代码的攻击因此需要谨慎使用11、BFC 是什么⭐定义BFC (Block formatting context)直译为“块级格式化上下文”。它是一个独立的渲染区域只有 Block-level box 参与它规定了内部的 Block-level Box 如何布局并且与这个区域外部毫不相干。布局规则1、内部的 Box 会在垂直方向一个接一个地放置2、Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin会发生重叠3、每个元素的 margin box 的左边 与包含块 border box 的左边相接触(对于从左往右的格式化否则相反)。即使存在浮动也是如此4、BFC 的区域不会与 float box 重叠5、BFC 就是页面上的一个隔离的独立容器容器里面的子元素不会影响到外面的元素。反之也如此6、计算 BFC 的高度时浮动元素也参与计算哪些元素会生成 BFC1、根元素2、float 属性不为 none3、position 为 absolute 或 fixed4、display 为 inline-block table-cell table-caption flex inline-flex5、overflow 不为 visible**二、**CSS篇1、说一下 link 与 import 的区别和用法⭐页面导入外部css文件的方法通常有两种一种在网页中直接link标签加入另一种在页面中import引入css文件。两种引入形式如下link引入形式link hrefstyles.css typetext/css /import引用形式style typetext/css import url(styles.css); /style1、适用范围不同import可以在网页页面中使用也可以在css文件中使用用来将多个css文件引入到一个css文件中而link只能将css文件引入到网页页面中。2、功能范围不同link属于XHTML标签而import是CSS提供的一种方式link标签除了可以加载CSS外还可以定义rel连接属性定义RSS等import就只能加载CSS。3、加载顺序不同页面被加载的时候link引用的CSS会同时被加载而import引用的CSS会等到页面全部被下载完再被加载。所以有时候浏览import加载CSS的页面时开始会没有样式就是闪烁4、兼容性由于import是css2.1提出的所以老的浏览器不支持import只有在IE5以上的才能识别而link标签无此问题。5、控制样式时的差别使用link方式可以让用户切换CSS样式.现代浏览器如Firefox,Opera,Safari都支持rel”alternate stylesheet”属性(即可在浏览器上选择不同的风格),当然你还可以使用Javascript使得IE也支持用户更换样式。6、使用DOM控制样式时的差别当使用JavaScript控制DOM去改变样式的时候只能使用link标签因为import不是DOM可以控制的。2、rgba和opacity的透明效果有什么不同⭐⭐opacityopacity是一个属性。opacity属性的值可以被其子元素继承给父级div设置opacity属性那么所有子元素都会继承这个属性并且该元素及其继承该属性的所有子元素的所有内容透明度都会改变。rgba0000.5rgba是一个属性值。rgba设置的元素只对该元素的背景色有改变并且该元素的后代不会继承该属性。补冲rgba只是一个属性值在background 里用改变背景色在color里是改字体颜色shadow里是改阴影色不止是能够改元素的背景色要看具体是在哪个属性上用3、display:none与visibility:hidden的区别⭐⭐这两个属性都是让元素隐藏不可见。两者区别如下1在渲染树中display: none 会让元素完全从渲染树中消失渲染时不会占据任何空间visibility: hidden不会让元素从渲染树中消失渲染的元素还会占据相应的空间只是内容不可见。2是否是继承属性display: none 是非继承属性子孙节点会随着父节点从渲染树消失通过修改子孙节点的属性也无法显示visibility: hidden 是继承属性子孙节点消失是由于继承了hidden通过设置visibility: visible可以让子孙节点显示3修改常规文档流中元素的 display 通常会造成文档的重排但是修改visibility属性只会造成本元素的重绘4如果使用读屏器设置为display:none的内容不会被读取设置为visibility:hidden的内容会被读取。5displaynone 隐藏对应的元素在文档布局中不再给它分配空间它各边的元素会合拢就当他从来不存在。6visibilityhidden 隐藏对应的元素但是在文档布局中仍保留原来的空间。4、定位布局 position中的relative、absolute、fixed、sticky它们之间的区别⭐⭐⭐1relative: 相对定位相对于自己本身在正常文档流中的位置进行定位。2absolute: 生成绝对定位相对于最近一级定位不为static的父元素进行定位。3fixed: 生成绝对定位相对于浏览器窗口或者frame进行定位。老版本IE不支持4static: 默认值没有定位元素出现在正常的文档流中。很少用5sticky: 生成粘性定位的元素容器的位置根据正常文档流计算得出。很少用5、如何用CSS3画一条0.5px的直线⭐height: 1px; transform: scale(0.5);6、如何用CSS3画一个三角形⭐style .up{ width:0; height:0; border: 100px solid transparent; border-top: 100px solid red;/*红色*/ } .down{ width:0; height:0; border: 100px solid transparent; border-bottom: 100px solid blue;/*蓝色*/ } .left{ width:0; height:0; border: 100px solid transparent; border-left: 100px solid pink;/*黑色*/ } .right{ width:0; height:0; border: 100px solid transparent; border-right: 100px solid pink;/*黄色*/ } /style body div classup/div div classdown/div div classleft/div div classright/div /body实现效果7、CSS3盒子模型标准盒模型、怪异盒模型⭐⭐⭐盒子模型分为两种:第一种是 W3C 标准的盒子模型标准盒模型第二种 IE 标准的盒子模型怪异盒模型标准盒模型与怪异盒模型的表现效果的区别之处1、标准盒模型中 width 指的是内容区域 content 的宽度height 指的是内容区域 content 的高度标准盒模型下盒子的大小 content border padding margin2、怪异盒模型中的 width 指的是内容、边框、内边距总的宽度content border paddingheight 指的是内容、边框、内边距总的高度怪异盒模型下盒子的大小 widthcontent border padding margin除此之外我们还可以通过属性 box-sizing 来设置盒子模型的解析模式可以为 box-sizing 赋两个值1、box-sizing: content-box默认值border 和 padding 不算到 width 范围内可以理解为是 W3c 的标准模型(default)。总宽widthpaddingbordermargin2、box-sizing: border-boxborder 和 padding 划归到 width 范围内可以理解为是 IE 的怪异盒模型总宽widthmargin相邻块元素垂直外边距的合并嵌套块元素垂直外边距的塌陷8、浮动float)以及清除浮动的方法⭐⭐(1) 脱标(2) 清除浮动(3) 清除浮动的方法清除浮动 ——额外标签法清除浮动 —— 父级添加 overflow清除浮动 —— :after 伪元素法清除浮动 —— 双伪元素清除浮动9、Flex布局**⭐⭐⭐**1、主轴对齐方式使用 justify-content 调节元素在主轴的对齐方式2、侧轴对齐方式使用 align-items 调节元素在侧轴的对齐方式3、换轴使用 flex-direction 改变元素排列方向4、弹性盒子换行目标使用 flex-wrap 实现弹性盒子多行排列效果10、CSS3中 transform 属性~平面转换**⭐****1位移**transform: translate(水平移动距离, 垂直移动距离)2旋转transform: rotate(角度); 注意角度单位是deg 取值为正, 则顺时针旋转 Ø 取值为负, 则逆时针旋转3缩放**transform: scale(x轴缩放倍数, y轴缩放倍数);** **transform: scale(缩放倍数);** **scale值大于1表示放大, scale值小于1表示缩小****4**transition的基本用法transition[属性名] [持续时间] [速度曲线] [延迟时间]我们可以很方便的用这个过渡来给某一个属性加上好看的动效。例如高度属性的值改变时延迟 0.5 秒后以 ease 曲线进行过渡持续2秒transition:height 2s ease 0.5s或者一个属性不够想要监听所有属性。transition: all 2s ease .5s11、CSS3中 “子绝父相” 定位布局**⭐⭐⭐**弄清楚这个口诀就明白了绝对定位和相对定位的使用场景。这个“子绝父相”太重要了是我们学习定位的口诀是定位中最常用的一种方式这句话的意思是子级是绝对定位的话父级要用相对定位。① 子级绝对定位不会占有位置可以放到父盒子里面的任何一个地方不会影响其他的兄弟盒子。② 父盒子需要加定位限制子盒子在父盒子内显示。③ 父盒子布局时需要占有位置因此父亲只能是相对定位。这就是子绝父相的由来所以相对定位经常用来作为绝对定位的父级。总结 因为父级需要占有位置因此是相对定位 子盒子不需要占有位置则是绝对定位当然子绝父相不是永远不变的如果父元素不需要占有位置子绝父绝也会遇到。12、盒子居中的几种方法“子绝父相”、“Flex布局”、“transform”⭐⭐⭐1利用定位子绝父相、margin-left、margin-top实现2利用定位子绝父相、transform属性实现3利用flex布局实现盒子居中13、CSS3中有哪些新特性⭐新增各种CSS选择器 : not(.input)所有 class 不是“input”的节点圆角 border-radius:8px多列布局 multi-column layout阴影和反射 Shadoweflect文字特效 text-shadow文字渲染 Text-decoration线性渐变 gradient旋转 transform增加了旋转,缩放,定位,倾斜,动画,多背景14、CSS3选择器及其优先级**⭐**对于选择器的优先级标签选择器、伪元素选择器1类选择器、伪类选择器、属性选择器10id 选择器100内联样式1000注意事项!important声明的样式的优先级最高如果优先级相同则最后出现的样式生效继承得到的样式的优先级最低通用选择器*、子选择器和相邻同胞选择器并不在这四个等级中所以它们的权值都为 0 样式表的来源不同时优先级顺序为内联样式 内部样式 外部样式 浏览器用户自定义样式 浏览器默认样式。15、CSS3中 “transition”过渡属性⭐transition: 要过渡的属性 花费时间 运动曲线 何时开始属性想要变化的css属性宽度高度/背景颜色/内外边距都可以如果想要所有的属性都变化过渡写一个all 就可以花费时间单位是 秒必须写单位比如0.5s运动曲线何时开始单位是 秒必须写单位可以设置延迟出发时间默认是0s(可以省略)举例transitionwidth .5s ease 1s16、结构伪类选择器伪元素选择器**⭐**1、结构伪类选择器可方便的选取一个或多个特定的元素:first-child 选取属于其父元素的首个子元素:last-child 选取属于其父元素的最后一个子元素:nth-child(n) 选择第n个子元素neven / 2n 选取偶数孩子nodd / 2n1 选取奇数孩子2、伪元素选择器::first-letter / line: 文本第一个单词 / 第一行::selection: 改变选中文本的样式::before ::after这两兄弟特性一样1.必须要带content属性可以为空2.属于行内盒子3、属性选择器div[classxx]: 选择类名为xx的divdiv[class^xx]: 选择以类名为xx开头的divdiv[class$xx]: 选择类名是以xx结束的divdiv[class*xx]: 选择类名带有xx的div1结构伪类选择器2伪元素选择器17、display的block、inline和inline-block的区别⭐1block 会独占一行多个元素会另起一行可以设置width、height、margin和padding属性2inline 元素不会独占一行设置width、height属性无效。但可以设置水平方向的margin和padding属性不能设置垂直方向的padding和margin3inline-block 将对象设置为inline对象但对象的内容作为block对象呈现之后的内联对象会被排列在同一行内。对于行内元素和块级元素其特点如下行内元素设置宽高无效可以设置水平方向的margin和padding属性不能设置垂直方向的padding和margin不会自动换行块级元素可以设置宽高设置margin和padding都有效可以自动换行多个块状默认排列从上到下。18、定位堆叠顺序z-index⭐在使用定位布局时可能会出现盒子重叠的情况。此时可以使用 z-index 来控制盒子的前后次序 (z轴)语法 选择器 { z-index: 1; }数值可以是正整数、负整数或 0, 默认是 auto数值越大盒子越靠上如果属性值相同则按照书写顺序后来居上数字后面不能加单位只有定位的盒子才有 z-index 属性19、如何实现双飞翼圣杯布局⭐1、利用定位实现两侧固定中间自适应父盒子设置左右 padding 值 给左右盒子的 width 设置父盒子的 padding 值,然后分别定位到 padding 处. 中间盒子自适应2、利用 flex 布局实现两侧固定中间自适应父盒子设置 displayflex 左右盒子设置固定宽高 中间盒子设置 flex120、伪元素和伪类的区别和作用⭐伪元素在内容元素的前后插入额外的元素或样式但是这些元素实际上并不在文档中生成。它们只在外部显示可见但不会在文档的源代码中找到它们因此称为“伪”元素。例如p::before {content:第一章;} p::after {content:Hot!;} p::first-line {background:red;} p::first-letter {font-size:30px;}伪类将特殊的效果添加到特定选择器上。它是已有元素上添加类别的不会产生新的元素。例如a:hover {color: #FF00FF} p:first-child {color: red}总结伪类是通过在元素选择器上加⼊伪类改变元素状态⽽伪元素通过对元素的操作进⾏对元素的改变。**三、**JavaScript篇1、JS基础类型和复杂类型⭐⭐⭐JS数据基础类型有String、Number、Boolean、Null、undefined五种基本数据类型加上新增的两种ES6的类型Symbol、BigIntJS有三种 复杂类型 引用数据类型Object对象、Array数组、function函数2、箭头函数与普通函数的区别⭐⭐⭐⭐(1) 箭头函数比普通函数更加简洁如果没有参数 , 就直接写一个空括号即可 , 如果只有一个参数 , 可以省去参数的括号 如果有多个参数 , 用逗号分割 , 如果函数体的返回值只有一句 , 可以省略大括号。(2) 箭头函数没有自己的this箭头函数不会创建自己的this, 所以它没有自己的this, 它只会在自己作用域的上一层继承this。所以箭头函数中this的指向在它在定义时已经确定了, 之后不会改变。(3) 箭头函数继承来的this指向永远不会改变(4) call()、apply()、bind()等方法不能改变箭头函数中this的指向(5) 箭头函数不能作为构造函数使用由于箭头函数时没有自己的this且this指向外层的执行环境且不能改变指向所以不能当做构造函数使用。(6) 箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是它外层函数的arguments值。(7) 箭头函数没有prototype(8) 补充箭头函数的this指向哪⾥箭头函数不同于传统JavaScript中的函数箭头函数并没有属于⾃⼰的this它所谓的this是捕获其所在上下⽂的 this 值作为⾃⼰的 this 值并且由于没有属于⾃⼰的this所以是不会被new调⽤的这个所谓的this也不会被改变。3、JS中null和undefined的判断方法和区别⭐⭐⭐1.undefined 的判断(1) undefined表示缺少值即此处应该有值但是还没有定义(2) 变量被声明了还没有赋值就为undefined(3) 调用函数时应该提供的参数还没有提供该参数就等于undefined(4) 对象没有赋值的属性该属性的值就等于undefined(5) 函数没有返回值默认返回undefined2.null 的判断(1) null表示一个值被定义了但是这个值是空值(2) 作为函数的参数表示函数的参数不是对象(3) 作为对象原型链的终点 Object.getPrototypeOf(Object.prototype)(4) 定义一个值为null是合理的但定义为undefined不合理var name null3.typeof 类型不同typeof null; // object typeof undefined; // undefined4.Number() 转数字也不同Number(null); // 0 Number(undefined); // NaN4、原型链**⭐⭐⭐**前提须知(1)prototype所有的函数都有原型prototype属性这个属性指向函数的原型对象。(2)__proto__这是每个对象(除null外)都会有的属性叫做__proto__这个属性会指向该对象的原型。(3)constructor: 每个原型都有一个constructor属性指向该关联的构造函数。**原型链**获取对象时如果这个对象上本身没有这个属性时它就会去它的原型__proto__上去找如果还找不到就去原型的原型上去找…一直直到找到最顶层Object.prototype为止Object.prototype对象也有__proto__属性值为null此外每一个prototype原型上都会有一个constructor属性指向它关联的构造函数。5、v-show 与 v-if 的区别⭐⭐**v-show**指令是通过修改元素的display的CSS属性让其显示或者隐藏**v-if**指令是直接销毁和重建DOM达到让元素显示和隐藏的效果使用v-show会更加节省性能上的开销当只需要一次显示或隐藏时使用v-if更加合理。6、keep-alive 的作用是什么?⭐⭐官网解释包裹动态组件时会缓存不活动的组件实例主要用于保留组件状态或避免重新渲染。**作用**实现组件缓存保持这些组件的状态以避免反复渲染导致的性能问题。 需要缓存组件 频繁切换不需要重复渲染。**场景**tabs标签页 后台导航vue性能优化。原理Vue.js内部将DOM节点抽象成了一个个的VNode节点keep-alive组件的缓存也是基于VNode节点的而不是直接存储DOM结构。它将满足条件pruneCache与pruneCache的组件在cache对象中缓存起来在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。7、闭包的理解?⭐⭐⭐⭐⭐**概念**有权访问另一个函数内部变量的函数。**本质**是指有权访问另一个函数作用域中变量的函数创建闭包的最常见的方式就是在一个函数内创建另一个函数通过另一个函数访问这个函数的局部变量利用闭包可以突破作用链域将函数内部的变量和方法传递到外部。面试什么是闭包通俗的来说闭包是在一个函数内部在定一个函数然后内部函数访问外部函数的一个变量就会形成闭包闭包的话会形成一个私有空间然后避免全局变量的一个污染然后会持久化存储数据到内存中但是闭包也有弊端它会导致内存泄漏拓展内存泄漏怎么解决首先避免它的使用其次的话就是变量执行完以后可以让它赋值为null最后利用JS的一个垃圾回收机制进行回收闭包用处读取内部函数的变量这些变量的值始终会保持在内存中不会在外层函数调用后被自动清除闭包优点变量会一直在内存中避免全局变量的污染私有变量的存在闭包缺点变量长期储存在内存中会增大内存的使用量使用不当会造成内存泄露判断闭包的3个特点1.函数嵌套函数2.内部函数一定操作了外部函数的局部变量3.外部函数一定将内部函数返回到外部并保存在一个全局变量中判断闭包的执行结果1.外部函数被调用了几次就有几个受保护的局部变量的副本2.来自一个闭包的函数被调用几次受保护的局部变量就变化几次闭包特性函数嵌套函数内部函数可以直接使用外部函数的局部变量变量或参数不会被垃圾回收机制回收8、JS垃圾回收机制**⭐⭐⭐⭐⭐**标记清除Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。JS中最常见的垃圾回收方式是标记清除。工作原理是当变量进入环境时将这个变量标记为“进入环境”。当变量离开环境时则将其标记为“离开环境”。标记“离开环境”的就回收内存。工作流程垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。去掉环境中的变量以及被环境中的变量引用的变量的标记。再被加上标记的会被视为准备删除的变量。垃圾回收器完成内存清除工作销毁那些带标记的值并回收他们所占用的内存空间。引用计数工作原理跟踪记录每个值被引用的次数。工作流程声明了一个变量并将一个引用类型的值赋值给这个变量这个引用类型值的引用次数就是1。同一个值又被赋值给另一个变量这个引用类型值的引用次数加1.当包含这个引用类型值的变量又被赋值成另一个值了那么这个引用类型值的引用次数减1.当引用次数变成0时说明没办法访问这个值了。当垃圾收集器下一次运行时它就会释放引用次数是0的值所占的内存。**总结归纳**但是循环引用的时候就会释放不掉内存。循环引用就是对象A中包含另一个指向对象B的指针B中也包含一个指向A的引用。因为IE中的BOM、DOM的实现使用了COM而COM对象使用的垃圾收集机制是引用计数策略。所以会存在循环引用的问题。解决手工断开js对象和DOM之间的链接。赋值为null。IE9把DOM和BOM转换成真正的JS对象了所以避免了这个问题。V8引擎中新生代和老生代的垃圾回收机制详解JavaScript中的内存堆Heap被划分为两个区域新生代存储新创建的、声明周期较短的对象老生代存储生命周期较长的对象提高新生代的回收次数处理的内存区域校老生代回收频率低这样就提高了程序的运行连贯性。9、nextTick的实现⭐⭐nextTick是Vue提供的一个全局API,是在下次DOM更新循环结束之后执行延迟回调在修改数据之后使用$nextTick则可以在回调中获取更新后的DOM。Vue在更新DOM时是异步执行的。只要侦听到数据变化Vue将开启1个队列并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发只会被推入到队列中-次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。nextTick方法会在队列中加入一个回调函数确保该函数在前面的dom操作完成后才调用比如我在干什么的时候就会使用nextTick传一个回调函数进去在里面执行dom操作即可。简单了解nextTick的实现它会在callbacks里面加入我们传入的函数然后用timerFunc异步方式调用它们首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。**实现原理**在下次 DOM 更新循环结束之后执行延迟回调在修改数据之后立即使用 nextTick 来获取更新后的 DOM。 nextTick主要使用了宏任务和微任务。 根据执行环境分别尝试采用Promise、MutationObserver、setImmediate如果以上都不行则采用setTimeout定义了一个异步方法多次调用nextTick会将方法存入队列中通过这个异步方法清空当前队列。10、混入mixin的原理⭐⭐mixin 项目变得复杂的时候多个组件间有重复的逻辑就会用到mixin多个组件有相同的逻辑抽离出来其实mixin并不是完美的解决方案会存在一些问题如vue3提出的Composition API旨在解决这些问题【追求完美是要消耗一定的成本的如开发成本】场景PC端新闻列表和详情页一样的右侧栏目可以使用mixin进行混合劣势1. 变量来源不明确不利于阅读2. 多mixin可能会造成命名冲突3. mixin和组件可能出现多对多的关系使得项目复杂度变高11、js列举和数组操作相关的方法(常用)⭐⭐⭐⭐⭐在JavaScript中数组操作是编程的常见任务之一。JavaScript提供了一系列与数组操作相关的方法这些方法可以用来操纵数组如添加、删除、查找、排序和遍历元素等。以下是一些常用的数组方法添加元素push(): 在数组的末尾添加一个或多个元素并返回新的长度。unshift(): 在数组的开头添加一个或多个元素并返回新的长度。删除元素pop(): 删除数组的最后一个元素并返回那个元素。shift(): 删除数组的第一个元素并返回那个元素。splice(): 通过删除、替换或添加新元素来改变数组的内容。查找元素indexOf(): 查找元素在数组中的索引。lastIndexOf(): 从数组的末尾开始查找元素。find(): 查找第一个满足测试函数的元素。findIndex(): 查找第一个满足测试函数的元素的索引。排序和翻转sort(): 对数组元素进行排序。reverse(): 颠倒反转数组中元素的顺序。遍历和过滤forEach(): 对数组的每个元素执行一次提供的函数。map(): 创建一个新数组其结果是该数组中的每个元素都调用一次提供的函数后的返回值。filter(): 创建一个新数组包含通过所提供函数实现的测试的所有元素。reduce(): 对数组中的每个元素执行一个由您提供的reducer函数升序执行将其结果汇总为单个返回值。reduceRight(): 类似reduce()但是从数组的末尾开始累加。归并数组concat(): 合并两个或多个数组。slice(): 提取原数组的一部分返回一个新数组。其它方法join(): 将数组或一个类数组对象的所有元素连接成一个字符串并返回这个字符串。toString(): 返回一个表示数组内容的字符串。split(): 把字符串转换成数组。toLocaleString(): 返回一个表示数组内容的本地化字符串。这些方法可以在日常编程中大大简化数组操作的复杂性。使用这些方法时需要注意它们的返回值和副作用。例如push和pop方法会改变原数组而concat方法则会返回一个新数组。在编写代码时了解这些方法的特性对于避免不必要的错误和优化性能至关重要。12、typeof和instanceof的区别是什么⭐⭐1typeof 的返回值是一个字符串用来说明变量的数据类型typeof用于数据类型的判断返回值有number、string、boolean、function、undefined、object 六个。但是在其中你会发现typeof判断null、array、object以及函数的实例new 函数时它返回的都是object。这就导致在判断这些数据类型的时候得不到真实的数据类型。所以typeof 存在的弊端——它虽然可以判断基本数据类型null 除外但是引用数据类型中除了function 类型以外其他的也无法判断。2instanceof的返回值是布尔值用于判断一个变量是否属于某个对象的实例。instanceof 可以准确地判断复杂引用数据类型但是不能正确判断基础数据类型。13、JS中 ““和““的区别详解**⭐⭐**区别三个等号我们称为等同符当等号两边的值为相同类型的时候直接比较等号两边 的值值相同则返回 true若等号两边的值类型不同时直接返回 false。也就是说三个等号既要判断值也要判断类型是否相等。两个等号我们称为等值符当等号两边的值为相同类型时比较值是否相同类型不同时会发生类型的自动转换转换为相同的类型后再作比较。也就是说两个等号只要值相等就可以。14、如何用原生 JS给一个按钮绑定两个 onclick 事件⭐⭐button idbtn点击/button script //通过事件监听 绑定多个事件 let btn document.getElementById(btn) btn.addEventListener(click, one) btn.addEventListener(click, two) function one() { alert(第一个) } function two() { alert(第二个) } /script15、var、let和const的区别⭐⭐⭐区别varletconst块级作用域❌✔️✔️是否存在变量提升✔️❌❌是否添加全局属性✔️❌❌重复声明同名变量✔️❌❌是否存在暂时性死区❌✔️✔️是否必须设置初始值❌❌✔️能否改变指针方向✔️✔️❌1块级作用域块作用域由 { }包括let和const具有块级作用域var不存在块级作用域。块级作用域解决了 ES5 中的两个问题内层变量可能覆盖外层变量用来计数的循环变量泄露为全局变量2变量提升 var存在变量提升let和const不存在变量提升即在变量只能在声明之后使用否在会报错。3给全局添加属性 浏览器的全局对象是windowNode的全局对象是global。var声明的变量为全局变量并且会将该变量添加为全局对象的属性但是let和const不会。4重复声明 var声明变量时可以重复声明变量后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。5暂时性死区 在使用let、const命令声明变量之前该变量都是不可用的。这在语法上称为暂时性死区。使用var声明的变量不存在暂时性死区。6初始值设置 在变量声明时var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。7指针指向 let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向可以重新赋值。但const声明的变量是不允许改变指针的指向。16、讲解js的call、apply和bind区别⭐⭐⭐首先call apply bind三个方法都可以用来改变函数的this指向具体区别如下call( ) 是接收一个及其以上的参数第一个参数表示this要指向的对象其余参数表示调用函数需要传入的参数返回调用函数的返回结果属于立即执行函数apply( ) 是接收两个参数第一个参数表示this要指向的对象第二参数表示调用函数需要传入的参数所组成的数组返回调用函数的返回结果属于立即执行函数bind( ) 是接收一个及其以上的参数和call(一致但是其返回是一个函数而不是调用函数的返回结果call、apply、bind相同点都是改变this的指向传入的第一个参数都是绑定this的指向在非严格模式中如果第一个参数是nul或者undefined会把全局对象浏览器是window作为this的值要注意的是在严格模式中null 就是 nullundefined 就是 undefinedcall和apply唯一的区别是call传入的是参数列表apply传入的是数组也可以是类数组bind和call、apply的区别 bind返回的是一个改变了this指向的函数便于稍后调用不像call和apply会立即调用bind和call很像传入的也是参数列表但是可以多次传入不需要像call一次传入值得注意当 bind 返回的函数 使用new作为构造函数时绑定的 this 值会失效this指向实例对象但传入的参数依然生效 new调用的优先级 bind调用17、谈谈你对webpack的理解⭐⭐⭐1、谈谈你对Webpack的理解Webpack是一个模块打包工具可以使用它管理项目中的模块依赖并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件图片字体等让开发更高效。对于不同类型的依赖Webpack有对应的模块加载器而且会分析模块间的依赖关系最后合并生成优化的静态资源。2、Webpack的基本功能有哪些代码转换TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等文件优化压缩 JavaScript、CSS、HTML 代码压缩合并图片等代码分割提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载模块合并在采用模块化的项目有很多模块和文件需要构建功能把模块分类合并成一个文件自动刷新监听本地源代码的变化自动构建刷新浏览器代码校验在代码被提交到仓库前需要检测代码是否符合规范以及单元测试是否通过自动发布更新完代码后自动构建出线上发布代码并传输给发布系统。3、Webpack构建过程从entry里配置的module开始递归解析entry依赖的所有module每找到一个module就会根据配置的loader去找对应的转换规则对module进行转换后再解析出当前module依赖的module这些模块会以entry为单位分组一个entry和其所有依赖的module被分到一个组Chunk最后Webpack会把所有Chunk转换成文件输出在整个流程中Webpack会在恰当的时机执行plugin里定义的逻辑4、有哪些常见的Loader?optimize-css-assets-plugin压缩cssfile-loader把文件输出到一个文件夹中在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)url-loader与 file-loader 类似区别是用户可以设置一个阈值大于阈值会交给 file-loader 处理小于阈值时返回文件 base64 形式编码 (处理图片和字体)css-loader加载 CSS支持模块化、压缩、文件导入等特性style-loader把 CSS 代码注入到 JavaScript 中通过 DOM 操作去加载 CSSjson-loader: 加载 JSON 文件默认包含ts-loader: babel-loader把 ES6 转换成 ES5ts-loader: 将 TypeScript 转换成 JavaScriptless-loader将less代码转换成CSSeslint-loader通过 ESLint 检查 JavaScript 代码vue-loader:加载 Vue单文件组件5、有哪些常见的Plugin1、html-webpack-plugin用途自动创建一个 HTML 文件并将打包好的 JavaScript 文件插入到这个 HTML 文件中。配置示例const HtmlWebpackPlugin require(html-webpack-plugin); module.exports { plugins: [ new HtmlWebpackPlugin({ template: ./src/index.html, // 使用现有的 HTML 文件作为模板 filename: index.html, // 输出的 HTML 文件名 inject: body }) ] };2、uglifyjs-webpack-plugin用途压缩 JavaScript 文件。需要注意的是UglifyJS 不支持 ES6 代码压缩。如果你需要压缩 ES6 代码可以考虑使用 terser-webpack-plugin配置示例 (Webpack 4 及以前)const UglifyJsPlugin require(uglifyjs-webpack-plugin); module.exports { optimization: { minimizer: [new UglifyJsPlugin()] } };3、mini-css-extract-plugin用途: 在构建过程中将 CSS 代码从 JavaScript 打包文件中抽离出来单独生成一个或多个 CSS 文件。这样可以提高页面加载性能因为浏览器可以并行加载 CSS 和 JavaScript 文件。配置示例:const MiniCssExtractPlugin require(mini-css-extract-plugin); module.exports { module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, css-loader ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: [name].css, chunkFilename: [id].css }) ] };4、clean-webpack-plugin:用途: 在每次构建之前清理输出目录删除整个输出文件夹下的内容。这有助于避免旧的文件干扰新的构建结果确保每次构建都是基于最新的源代码。配置示例:const { CleanWebpackPlugin } require(clean-webpack-plugin); module.exports { plugins: [ new CleanWebpackPlugin() ] };5、copy-webpack-plugin用途: 用于将项目中的文件或文件夹复制到构建输出目录中。配置示例:const CopyWebpackPlugin require(copy-webpack-plugin); module.exports { plugins: [ new CopyWebpackPlugin({ patterns: [ { from: src/assets, to: assets } // 将 src/assets 文件夹复制到输出目录的 assets 文件夹中 ] }) ] };6、webpack-bundle-analyzer用途: 可视化 Webpack 输出文件的体积帮助你分析业务组件和依赖的第三方模块的大小。配置示例:const { BundleAnalyzerPlugin } require(webpack-bundle-analyzer); module.exports { plugins: [ new BundleAnalyzerPlugin() ] };7、optimize-css-assets-plugin用途: 压缩 CSS 文件减少文件大小。配置示例:const OptimizeCSSAssetsPlugin require(optimize-css-assets-webpack-plugin); module.exports { optimization: { minimizer: [new OptimizeCSSAssetsPlugin()] } };6、那你再说一说Loader和Plugin的区别Loader 本质就是一个函数在该函数中对接收到的内容进行转换返回转换后的结果。 因为 Webpack 只认识 JavaScript所以 Loader 就成了翻译官对其他类型的资源进行转译的预处理工作。Plugin 就是插件基于事件流框架 Tapable插件可以扩展 Webpack 的功能在 Webpack 运行的生命周期中会广播出许多事件Plugin 可以监听这些事件在合适的时机通过 Webpack 提供的 API 改变输出结果。Loader 在 module.rules 中配置作为模块的解析规则类型为数组。每一项都是一个 Object内部包含了 test(类型文件)、loader、options (参数)等属性。Plugin 在 plugins 中单独配置类型为数组每一项是一个 Plugin 的实例参数都通过构造函数传入。7、如何优化 Webpack 的构建速度1使用高版本的 Webpack 和 Node.js2压缩代码通过 uglifyjs-webpack-plugin 压缩JS代码通过 mini-css-extract-plugin 提取 chunk 中的 CSS 代码到单独文件通过 css-loader 的 minimize 选项开启 cssnano 压缩 CSS。3多线程/多进程构建thread-loader, HappyPack4压缩图片: image-webpack-loader5缩小打包作用域exclude/include (确定 loader 规则范围)resolve.modules 指明第三方模块的绝对路径 (减少不必要的查找)resolve.mainFields 只采用 main 字段作为入口文件描述字段 (减少搜索步骤需要考虑到所有运行时依赖的第三方模块的入口文件描述字段)resolve.extensions 尽可能减少后缀尝试的可能性noParse 对完全不需要解析的库进行忽略 (不去解析但仍会打包到 bundle 中注意被忽略掉的文件里不应该包含 import、require、define 等模块化语句)ignorePlugin (完全排除模块)8、说一下 Webpack 的热更新原理吧Webpack 的热更新又称热替换Hot Module Replacement缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。HMR的核心就是客户端从服务端拉去更新后的文件准确地说是 chunk diff (chunk 需要更新的部分)实际上 WDS 与浏览器之间维护了一个 Websocket当本地资源发生变化时WDS 会向浏览器推送更新并带上构建时的 hash让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash)这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。后续的部分(拿到增量更新之后如何处理哪些状态该保留哪些又需要更新)由 HotModulePlugin 来完成提供了相关 API 以供开发者针对自身场景进行处理像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。9、什么是bundle什么是chunk什么是modulebundle是webpack打包后的一个文件chunk代码块一个chunk 可能有很多的模块组成用于合并和分割代码module模块在webpack中一切都是模块一个文件就是一个模块她从入口开始查找webpack依赖的所有模块10、webpack和grunt以及gulp有什么不同grunt和gulp是基于任务处理的工具我们需要把我们要做的事分配成各种各样的任务grunt和gulp会自动执行各种分配的任务像流水线一样把资源放上去通过不同的插件进行加工他的插件非常丰富能够为我们打造各种工作流webpack是模块化打包工具把所有文件都当作模块进行处理也就是说webpack和grunt和gulp是两种完全不一样的东西18、 const定义的对象属性是否可以改变⭐⭐**情况一**const定义的变量存在块级作用域且不存在变量提升一般用于定义常量定义的时候必须初始化。答不可以const定义的如果是基本数据类型stringnumberbooleannullundifinedsymbol定义后就不可再修改如果修改会报错。**情况二**那么如果是const定义的对象呢是否可以修改对象中的属性答案可以原因对象是引用类型的const定义的对象t中保存的是指向对象t的指针这里的“不变”指的是指向对象的指针不变而修改对象中的属性并不会让指向对象的指针发生变化所以用const定义对象对象的属性是可以改变的。19、栈溢出及解决方法⭐⭐⭐栈溢出(stack Overflow)缓冲区溢出是由于C语言系列设有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小因此当这个数据足够大的时候将会溢出缓冲区的范围。栈溢出就是缓冲区溢出的一种。 由于缓冲区溢出而使得有用的存储单元被改写, 往往会引发不可预料的后果。程序在运行过程中为了临时存取数据的需要一般都要分配一些内存空间通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据以致于缓冲区无法容纳就会造成缓冲区以外的存储单元被改写这种现象就称为缓冲区溢出。缓冲区长度一般与用户自己定义的缓冲变量的类型有关。由于缓冲区溢出而使得有用的存储单元被改写往往会引发不可预料的后果。向这些单元写入任意的数据一般只会导致程序崩溃之类的事故对这种情况我们也至多说这个程序有Bug。但如果向这些单元写入的是精心准备好的数据就可能使得程序流程被劫持致使不希望的代码被执行落入攻击者的掌控之中这就不仅仅是bug而是漏洞(exploit)了。栈溢出的解决方法减少栈空间的需求不要定义占用内存较多的auto变量应该将此类变量修改成指针从堆空间分配内存。函数参数中不要传递大型结构/联合/对象应该使用引用或指针作为函数参数。减少函数调用层次慎用递归函数例如A-B-C-A环式调用。20、JS如何实现多线程⭐⭐⭐什么是JavaScript的多线程JavaScript本身是单线程的但是可以通过实现多线程来提高性能和用户体验。多线程允许JavaScript在等待用户交互或网络请求时执行其他任务从而提高页面加载速度和响应速度。JavaScript中有哪些实现多线程的方式JavaScript有多种实现多线程的方式包括Web Workers、SharedArrayBuffer、WebAssembly等。其中Web Workers允许在后台线程中运行JavaScript代码而SharedArrayBuffer和BufferSource API则允许在多个线程之间共享数据。如何使用Web Workers实现多线程使用Web Workers实现多线程需要创建一个新的worker线程并将需要执行的代码作为字符串传递给worker。worker线程可以访问全局对象messageChannel的postMessage方法来发送消息主线程可以使用onmessage方法来接收消息并执行相应的操作。如何保证多线程安全多线程环境下的安全问题主要包括数据竞争和死锁等。为了解决这些问题需要使用同步机制如使用Promise、async/await等异步编程方式或者使用事件循环、共享内存等机制来保证数据的一致性和安全性。描述一个实际的多线程应用场景。在实际应用中多线程可以用于提高页面加载速度和响应速度例如在电商网站中可以使用Web Workers在后台线程中加载和处理商品图片从而提高页面加载速度和用户体验。同时多个并发请求也可以使用Web Workers并行处理提高系统性能和响应速度。21、浅拷贝和深拷贝区别概念常见情况⭐⭐⭐⭐浅拷贝浅拷贝创建一个新的对象但是只复制原始对象的基本数据类型的字段或引用地址而不复制引用指向的对象。这意味着新对象和原始对象中的引用指向相同的对象。如果原始对象中的字段是基本数据类型那么这些字段会被复制到新对象中而如果字段是引用类型则新对象和原始对- 象的对应字段将引用同一个对象。因此对新对象所做的修改可能会影响到原始对象因为它们共享相同的引用。深拷贝深拷贝创建一个新的对象并且递归地复制原始对象的所有字段和引用指向的对象而不仅仅是复制引用本身。深拷贝会递归复制整个对象结构包括对象内部的对象确保新对象和原始对象之间的所有关系都是独立的。这意味着对新对象所做的修改不会影响到原始对象因为它们拥有彼此独立的副本。1、基本类没有问题因为基本类型赋值时赋的是数据所以不存在深拷贝和浅拷贝的问题。例如1var x 100;var y x; //此时x和y都是100;如果要改变y的值x的值不会改变。2、引用类型有问题因为引用类型赋值时赋的值地址就是引用类型变量在内存中保存的内容例如2var arr1 new Array(12,23,34)var arr2 arr1; //这就是一个最简单的浅拷贝如果要改变arr2所引用的数据arr2[0]100时那么arr1[0]的值也是100。原因就是 arr1和arr2引用了同一块内存区域以上的第二点中有体现。这是最简单的浅拷贝因为只是把arr1的地址拷贝的一份给了arr2并没有把arr1的数据拷贝一份。所以拷贝的深度不够。一、常见的 “浅” 拷贝方法除了上面我们演示的对于赋值操作下面将介绍一些开发中可能会用到当然也可以会被面试官问到的实现深浅拷贝的方法。1. Object.assign()方法解释方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象,它将返回目标对象可以实现一个浅拷贝的效果。参数一目标对象参数二源对象var obj1 { a: 1, b: 2, c: [c, t, r] } var obj2 Object.assign({}, obj1); obj2.c[1] 5; obj2.b 3 console.log(obj1); // {a:1,b:2,c:[c, 5, r]} console.log(obj2); // {a:1,b:3,c:[c, 5, r]} console.log(obj1.c); // [c, 5, r] console.log(obj2.c); // [c, 5, r]注意可见Object.assign()方法对于一维数据是深拷贝效果但是对于多维数据是浅拷贝效果。Object.assign是一个浅拷贝,它只是在根属性(对象的第一层级)创建了一个新的对象但是对于属性的值是仍是对象的话依然是浅拷贝2. slice()方法解释数组进行截取如果不传参数,会使用默认值,得到一个与原数组元素相同的新数组。参数一截取的起始位置参数二截取的结束位置var a [1, [1, 2], 3, 4]; var b a.slice(); a[0] 99 b[1][0] 2; console.log(a); // [99,[2,2],3,4] console.log(b); // [1,[2,2],3,4]注意可见slice()方法也只是对一维数据进行深拷贝但是对于多维的数据还是浅拷贝效果。3. concat()方法方法解释数组的拼接(将多个数组或元素拼接形成一个新的数组)不改变原数组如果不传参数,会使用默认值得到一个与原数组元素相同的新数组 (复制数组)。var a [1, 2, [3, 4]] var c []; var b c.concat(a); a[0] 99 b[2][1] 88 console.log(a); // [99,2,[3,88]] console.log(b); // [1,2,[3,88]]注意可见concat()方法也只对一维数据具有深拷贝效果对于多维的数据任然只是浅拷贝4. ES6拓展运算符var a [1, 2, [3, 4]] var b [...a]; a[2][1] 88 b[1] 99 console.log(a); // [1,2,[3,88]] console.log(b); // [1,99,[3,88]]注意: 可见ES6的展开运算符对于一维数据是深拷贝效果但是对于多维数据任然是浅拷贝效果。二、实现 “深” 拷贝常见方法1. JSON.parse(JSON.stringify(obj))JSON.stringify()是目前前端开发过程中最常用的深拷贝方式原理是把一个对象序列化成为一个JSON字符串将对象的内容转换成字符串的形式再保存在磁盘上再用JSON.parse()反序列化将JSON字符串变成一个新的对象JSON.stringfy() 将对象序列化成json对象JSON.parse() 反序列化——将json对象反序列化成js对象function deepCopy(obj1){ let _obj JSON.stringify(obj1); let obj2 JSON.parse(_obj); return obj2; } var a [1, [1, 2], 3, 4]; var b deepCopy(a); b[1][0] 2; console.log(a); // 1,1,2,3,4 console.log(b); // 1,2,2,3,4注意它会抛弃对象的constructor深拷贝之后不管这个对象原来的构造函数是什么在深拷贝之后都会变成Object类型这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象也就是说只有可以转成JSON格式的对象才可以这样用像function没办法转成JSON。2. 使用第三方库实现对象的深拷贝比如lodash、jQueryimport lodash from lodash var objects [1,{ a: 1 }, { b: 2 }]; var deep lodash.cloneDeep(objects); deep[0] 2; deep[1].a 2; console.log(objects); // [1,{ a: 1 }, { b: 2 }] console.log(deep); //[2,{ a: 2 }, { b: 2 }]3. 递归这里简单封装了一个deepClone的函数for in遍历传入参数的值如果值是引用类型则再次调用deepClone函数并且传入第一次调用deepClone参数的值作为第二次调用deepClone的参数如果不是引用类型就直接复制var obj1 { a:{ b:1 } }; function deepClone(obj) { var cloneObj {}; //在堆内存中新建一个对象 for(var key in obj){ //遍历参数的键 if(typeof obj[key] object){ cloneObj[key] deepClone(obj[key]) //值是对象就再次调用函数 }else{ cloneObj[key] obj[key] //基本类型直接复制值 } } return cloneObj } var obj2 deepClone(obj1); obj1.a.b 2; console.log(obj2); //{a:{b:1}}但是还有很多问题首先这个deepClone函数并不能复制不可枚举的属性以及Symbol类型这里只是针对Object引用类型的值做的循环迭代而对于Array,Date,RegExp,Error,Function引用类型无法正确拷贝对象循环引用成环了的情况22、事件循环Promise和async/await的详解**⭐⭐⭐⭐**事件循环event loop它的执行顺序一开始整个脚本作为一个宏任务执行执行过程中同步代码直接执行宏任务进入宏任务队列微任务进入微任务队列当前宏任务执行完出队检查微任务列表有则依次执行直到全部执行完执行浏览器UI线程的渲染工作检查是否有Web Worker任务有则执行执行完本轮的宏任务回到2依此循环直到宏任务和微任务队列都为空微任务包括MutationObserver、Promise.then()或catch()、Promise为基础开发的其它技术比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。宏任务包括script、setTimeout、setInterval、setImmediate、I/O、UI rendering。注意⚠️在所有任务开始的时候由于宏任务中包括了script所以浏览器会先执行一个宏任务在这个过程中你看到的延迟任务(例如setTimeout)将被放到下一轮宏任务中来执行。Promise和async/await是JavaScript中处理异步操作的两种方式。Promise是一种用于处理异步操作的对象。它可以表示一个异步操作的最终完成或失败并返回相应的结果或错误信息。Promise有三种状态pending进行中、fulfilled已完成和rejected已拒绝。通过调用Promise的then()方法可以注册回调函数来处理异步操作的结果。async/await是ES8引入的一种更加简洁的处理异步操作的方式。async函数是一个返回Promise对象的函数其中可以使用await关键字来等待一个Promise对象的解决。await关键字可以暂停async函数的执行直到Promise对象解决为止并返回解决后的结果。区别- 语法上Promise使用then()和catch()方法来处理异步操作的结果而async/await使用async函数和await关键字来等待异步操作的结果。- 可读性上async/await更加直观和易于理解代码结构更加清晰而Promise则需要通过链式调用then()方法来处理多个异步操作。- 错误处理上Promise使用catch()方法来捕获错误而async/await可以使用try-catch语句来捕获错误。详细解答JavaScript的异步机制包括以下几个步骤1所有同步任务都在主线程上执行行成一个执行栈 2主线程之外还存在一个任务队列只要异步任务有了结果就会在任务队列中放置一个事件 3一旦执行栈中的所有同步任务执行完毕系统就会读取任务队列看看里面还有哪些事件哪些对应的异步任务于是异步任务结束等待状态进入执行栈开始执行 4主线程不断的重复上面的第三步promise的用法Promise,简单来说就是一个容器里面保存着某个未来才会结束的时间(通常是一个异步操作的结果)基本语法let obj new Promise((resolve,reject) { //... resolve(success) }); obj.then(result { console.log(result); //success });promise共有三个状态pending执行中、resolve成功、rejected失败链式调用Promise 链式调用是一种编程模式允许在异步操作之间顺序执行多个操作。在每个操作中可以使用 .then() 方法返回一个新的 Promise从而在异步流程中继续执行下一个操作。这样可以避免回调函数地狱提高代码的可读性和可维护性。链式调用的基本步骤包括创建一个新的 Promise 对象并调用 resolve 或 reject 来变更其状态。在 then 或 catch 方法中处理成功或失败的状态。在 then 方法中可以使用 return 关键字返回一个新的 Promise 对象或者直接返回普通值。继续在下一个 then 方法中处理返回的 Promise 对象或者直接处理返回的普通值。例如以下代码展示了如何使用 .then() 和 .catch() 方法进行链式调用let promise1 new Promise((resolve, reject) { resolve(new promise111111); }); promise1.then(res { console.log(res); // 输出: new promise111111 return 链式调用的方式; }).then(value { console.log(value); // 输出: 链式调用的方式 });在这个例子中promise1 被成功地 resolve 并返回了一个值然后 then 方法被调用返回了一个新的 Promise 对象并返回了 ‘链式调用的方式’。这个新的 Promise 对象又被继续 .then 处理最终返回了 ‘链式调用的方式’。需要注意的是每次 .then 方法调用都会返回一个新的 Promise 对象因此链式调用的结果取决于最后 .then 方法中返回的值或新的 Promise 对象。错误捕获Promise.prototype.catch用于指定Promise状态变为rejected时的回调函数可以认为是.then的简写形势返回值跟.then一样let obj new Promise((resolve,reject) { reject(error); }); obj.catch(result { console.log(result); })async、await的用法特点简洁异步编程的最高境界就是不关心它是否是异步。async、await很好的解决了这一点将异步强行转换为同步处理。async/await与promise不存在谁代替谁的说法因为async/await是寄生于PromiseGenerater的语法糖。用法async用于申明一个function是异步的而await可以认为是async wait的简写等待一个异步方法执行完成。规则1 async和await是配对使用的await存在于async的内部。否则会报错2 await表示在这里等待一个promise返回再接下来执行3 await后面跟着的应该是一个promise对象也可以不是如果不是接下来也没什么意义了…写法async function demo() { let a await sleep(100); //上一个await执行之后才会执行下一句 let b await sleep(a 100); let c await sleep(b 100); return c; // console.log(c); } demo().then(result { console.log(result); });错误捕获如果是reject状态可以用try-catch捕捉let obj new Promise((resolve,reject) { setTimeout(() { reject(error); },1000); }); async function demo(item) { try { let result await obj; } catch(e) { console.log(e); } } demo();两者区别1、promise是ES6async/await是ES8补充(async/await 实际上是在 ES2017即 ES8 中正式标准化的发布于 2017 年。async/await 的提案在 ES72016阶段已经处于讨论和开发中但最终并没有在 ES7 中正式定稿。它直到 ES8 才完成标准化流程成为 ECMAScript 标准的一部分)2、async/await相对于promise来讲写法更加优雅3、reject状态1promise错误可以通过catch来捕捉建议尾部捕获错误2async/await既可以用.then又可以用try-catch捕捉推荐一篇Promise文章https://juejin.cn/post/684490418162778112823、JS中数组常用方法详解⭐⭐⭐⭐顺序方法名功能返回值是否改变原数组版本1push()(在结尾)向数组添加一或多个元素返回新数组长度YES5-2unshift()在开头)向数组添加一或多个元素返回新数组长度YES5-3pop()删除数组的最后一位返回被删除的数据YES5-4shift()移除数组的第一项返回被删除的数据YES5-5reverse()反转数组中的元素返回反转后数组YES5-6sort()以字母顺序(字符串Unicode码点)对数组进行排序返回新数组YES5-7splice()在指定位置删除指定个数元素再增加任意个数元素 实现数组任意位置的增删改)返回删除的数据所组成的数组YES5-8concat()通过合并连接现有数组来创建一个新数组返回合并之后的数组NES5-9join()用特定的字符,将数组拼接形成字符串 (默认,)返回拼接后的新数组NES5-10slice()裁切指定位置的数组被裁切的元素形成的新数组NES5-11toString()将数组转换为字符串新数组NES5-12valueOf()查询数组原始值数组的原始值NES5-13indexOf()查询某个元素在数组中第一次出现的位置存在该元素,返回下标,不存在 返回 -1NES5-14lastIdexOf()反向查询数组某个元素在数组中第一次出现的位置存在该元素,返回下标,不存在 返回 -1NES5-15forEach()(迭代) 遍历数组,每次循环中执行传入的回调函数无/(undefined)NES5-16map()(迭代) 遍历数组, 每次循环时执行传入的回调函数,根据回调函数的返回值,生成一个新的数组有/自定义NES5-17filter()(迭代) 遍历数组, 每次循环时执行传入的回调函数,回调函数返回一个条件,把满足条件的元素筛选出来放到新数组中满足条件的元素组成的新数组NES5-18every()(迭代) 判断数组中所有的元素是否满足某个条件全都满足返回true 只要有一个不满足 返回falseNES5-19some()(迭代) 判断数组中是否存在,满足某个条件的元素只要有一个元素满足条件就返回true,都不满足返回falseNES5-20reduce()(归并)遍历数组, 每次循环时执行传入的回调函数,回调函数会返回一个值,将该值作为初始值prev,传入到下一次函数中最终操作的结果NES5-21reduceRight()(归并)用法同reduce,只不过是从右向左同reduceNES5-22includes()判断一个数组是否包含一个指定的值.是返回 true否则falseNES623Array.from()接收伪数组,返回对应的真数组对应的真数组NES624find()遍历数组,执行回调函数,回调函数执行一个条件,返回满足条件的第一个元素,不存在返回undefined满足条件第一个元素/否则返回undefinedNES625findIndex()遍历数组,执行回调函数,回调函数接受一个条件,返回满足条件的第一个元素下标,不存在返回-1满足条件第一个元素下标,不存在-1NES626fill()用给定值填充一个数组新数组YES627flat()用于将嵌套的数组“拉平”变成一维的数组。返回一个新数组NES628flatMap()flat()和map()的组合版 , 先通过map()返回一个新数组,再将数组拉平( 只能拉平一次 )返回新数组NES61.push在数组最后一位_添加_一个或多个元素,并返回新数组的长度,改变原数组.(添加多个元素用逗号隔开)语法:**数组名.push(**数据)作用:就是往数组末尾添加数据返回值:就是这个数组的长度//push var arr [10, 20, 30, 40] res arr.push(20) console.log(arr);//[10,20,30,40,20] console.log(res);//52. pop 末尾出删除数据**语法:**数组名.pop()作用:就是从数组的末尾删除一个数据返回值:就是你删除的那个数据//pop var arr [10, 20, 30, 40] res arr.pop() console.log(arr);//[10,20,30] console.log(res);//403.unshift 头部添加数据语法:**数组名.unshift(**数据)作用:就是在数组的头部添加数据返回值:就是数组的长度//pop var arr [10, 20, 30, 40] resarr.unshift(99) console.log(arr);//[99,10,20,30,40] console.log(res);//54.shift 头部删除数据语法:数组名.shift()作用:头部删除一个数据返回值:就是删除掉的那个数据//shift var arr [10, 20, 30, 40] resarr.shift() console.log(arr);[20,30,40] console.log(res);105.reverse 翻转数组语法:数组名.reverse()作用:就是用来翻转数组的返回值:就是翻转好的数组//reverse var arr [10, 20, 30, 40] resarr.reverse() console.log(arr);//[40,30,20,10] console.log(res);//[40,30,20,10]6.sort 排序语法一:数组名.sort()会排序 会按照位排序语法二:数组名.sort(function (a,b) {return a-b})会正序排列语法三:数组名.sort(function (a,b) {return b-a})会倒序排列//sort() var arr [2, 63, 48, 5, 4, 75, 69, 11, 23] arr.sort() console.log(arr); arr.sort(function(a,b){return(a-b)}) console.log(arr); arr.sort(function(a,b){return(b-a)}) console.log(arr);打印结果7.splice 截取数组语法一:**数组名.splice(****开始索引,**多少个)作用:就是用来截取数组的返回值:是一个新数组 里面就是你截取出来的数据语法二:**数组名.splice(****开始索引,****多少个,**你要插入的数据)作用:删除并插入数据注意:从你的开始索引起返回值:是一个新数组 里面就是你截取出来的数据//splice() 语法一 var arr [2, 63, 48, 5, 4, 75] res arr.splice(1,2) console.log(arr); // [2, 5, 4, 75] console.log(res); // [63, 48] //****************************** //splice() 语法二 var arr [2, 63, 48, 5, 4, 75] res arr.splice(1,1,99999,88888) console.log(arr); //[2, 99999, 88888, 48, 5, 4, 75] console.log(res); // [63]二、不改变原数组的方法1.concat 合并数组功能 数组的拼接(将多个数组或元素拼接形成一个新的数组),不改变原数组如果拼接的是数组 则将数组展开,之后将数组中的每一个元素放到新数组中.如果是其他类型, 直接放到新数组中另外如果不给该方法任何参数将返回一个和原数组一样的数组复制数组var arr1 [1, 2, 3]; var arr2 [a, b, c]; var arr3 [A, B, C]; var rel arr1.concat(arr2, arr3); console.log(arr1); //原数组 console.log(rel); //新数组打印结果2.join 数组转字符串 语法:数组名.join(‘连接符’) 作用: 就是把一个数组转成字符串功能用特定的字符,将数组拼接形成字符串 (默认,)var list [a, b, c, d]; // a-b-c-d var result list.join(-); //a-b-c-d var result list.join(/); //a/b/c/d var result list.join(); //abcd var result list.join(); // a,b,c,d console.log(result);find()返回匹配的元素findIndex()返回匹配元素的索引find()如果没有匹配到元素则返回undefined, 而findIndex()返回-11、数组方法find()返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。find方法对数组中的每一项元素执行一次 callback 函数直至有一个 callback 返回 true。当找到了这样一个元素后该方法会立即返回这个元素的值否则返回 undefined。注意 callback 函数会为数组中的每个索引调用即从 0 到 length - 1而不仅仅是那些被赋值的索引这意味着对于稀疏数组来说该方法的效率要低于那些只遍历有值的索引的方法。callback函数带有3个参数当前元素的值、当前元素的索引以及数组本身。如果提供了 thisArg参数那么它将作为每次 callback函数执行时的this 如果未提供则使用 undefined。find方法不会改变数组。实战举例var arr [ {name: 张三, age: 18}, {name: 李四, age: 20}, ] var arrTest arr.find((item, index, array) { console.log(当前值: JSON.stringify(item), 当前值的索引 index, 当前数组 array) return item.age 18 }) console.log(arrTest)打印结果当前值:{name:张三,age:18} 当前值的索引0 当前数组[object Object],[object Object] {name: 张三, age: 18}2、数组方法findIndex()返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。findIndex方法对数组中的每个数组索引0..length-1包括执行一次callback函数直到找到一个callback函数返回真实值强制为true的值。如果找到这样的元素findIndex会立即返回该元素的索引。如果回调从不返回真值或者数组的length为0则findIndex返回-1。与某些其他数组方法如Array#some不同在稀疏数组中即使对于数组中不存在的条目的索引也会调用回调函数。回调函数调用时有三个参数元素的值元素的索引以及被遍历的数组。如果一个 thisArg 参数被提供给 findIndex, 它将会被当作this使用在每次回调函数被调用的时候。如果没有被提供将会使用 undefined。findIndex不会修改所调用的数组。实战举例var arr [ {name: 张三, age: 18}, {name: 王二, age: 20}, ] var arrTest arr.findIndex((item, index, array) { console.log(当前值: JSON.stringify(item), 当前值的索引 index, 当前数组 array) return item.name 张三 }) console.log(arrTest)打印结果当前值:{name:张三,age:18} 当前值的索引0 当前数组[object Object],[object Object] 03、JSON.stringify( ) 和 JSON.parse( )JSON.stringify()将对象、数组转换成字符串JSON.parse()将字符串转成json对象JSON.parse(JSON.stringify(obj))我们一般用来深拷贝其过程说白了 就是利用JSON.stringify 将js对象序列化JSON字符串再使用JSON.parse来反序列化(还原)js对象序列化的作用是存储(对象本身存储的只是一个地址映射如果断电对象将不复存在因此需将对象的内容转换成字符串的形式再保存在磁盘上 )应用场景a、浏览器创建、获取sessionStorage、localStorage数组内容b、路由浏览器地址传参、获取数组内容创建、传参的时候使用JSON.stringify()深拷贝(如果不使用JSON.stringify()存进去的将是[object object]所以如果我们开发中遇到了获取内容的时候是[object object]不妨试试JSON.stringify())4、instanceof( )instanceof运算符返回一个布尔值如下var array [1, 2, 3]; var obj {}; console.log( array instanceof Array ) // true console.log( obj instanceof Object) // true5、every()方法的定义与用法every()方法用于检测数组中的所有元素是否都满足指定条件该条件为一个函数。every()方法会遍历数组的每一项如果有有一项不满足条件则表达式返回false,剩余的项将不会再执行检测如果遍历完数组后每一项都符合条则返回true。标准用法array.every(function(currentValue,index,arr), thisValue)参数说明第一个参数为一个回调函数必传数组中的每一项都会遍历执行该函数。currentValue必传当前项的值index选传当前项的索引值arr选传当前项所属的数组对象第二个参数thisValue为可选参数回调函数中的this会指向该参数对象。Tips:every() 不会对空数组进行检测every() 不会改变原始数组代码实例var arr [1000, 2000, 3000] var flag arr.every(function (a, b, c) { console.log(a b c) //100001000,2000,3000 return a 2000;//数组中的每个元素的值都要大于2000的情况,最后才返回true }) console.log(flag) //false6、数组some方法作用判断数组中是否有满足条件的元素语法array.some( function ( item, index, arr) {} ,thisValue)function 必须,数组中的每个元素都会执行这个函数第一个参数:item,必须,当前元素的值第二个参数:index,可选,当前元素在数组中的索引值第三个参数:arr,当前元素属于的数组对象thisValue 可选对象作为该执行回调时使用传递给函数用作 “this” 的值。如果省略了 thisValue “this” 的值为 “undefined”some方法特点(1)函数执行次数 ! 数组长度(2)函数内部的returnreturn true : 循环结束,找到了满足条件的元素 return false : 循环继续,没找到循环继续,如果所有元素全部遍历还是没找到,最终结果为false(3) some()方法不会对空数组进行检测(4) some()方法不会改变原始数组应用场景 : 这个方法与every()方法极为相似但又有所不同every要求每一项都要符合函数里面的条件而some只要求有数组中的某一项符合即可这点类似于或与和。返回的是布尔值使用事例如下var num [1,2,3,4,5]; var eve num.some(function(item, index, arr){ return (item 2); }); console.log(eve); //true7、数组filter()方法filter()方法的回调函数接受三个参数当前元素、当前元素的索引和数组本身。其中当前元素是必需的而索引和数组是可选的。过滤数组中符合条件的元素并返回一个新的数组const people [ { name: Alice, age: 25 }, { name: Bob, age: 17 }, { name: Charlie, age: 30 }, { name: David, age: 16 }, { name: Eva, age: 18 } ]; const adults people.filter(person person.age 18); console.log(adults); // [{ name: Alice, age: 25 }, { name: Charlie, age: 30 }, { name: Eva, age: 18 }]24、JS 防抖和节流概念代码示例⭐⭐⭐防抖Debounce概念当事件被触发后等待指定时间后再执行回调函数。如果在等待期间再次触发该事件则重新计算等待时间。适用于输入验证、搜索联想等场景。代码示例function debounce(fn, delay) { let timer null; return function(...args) { // 清除之前的定时器 if (timer) clearTimeout(timer); // 重新设置定时器 timer setTimeout(() { fn.apply(this, args); timer null; }, delay); }; } // 使用示例 const handleSearch debounce(function(keyword) { console.log(搜索:, keyword); }, 500); // 模拟输入框连续输入 handleSearch(a); handleSearch(ab); handleSearch(abc); // 只有最后一次会在500ms后执行节流Throttle概念规定一个单位时间在这个单位时间内只能有一次触发事件的回调函数执行。如果在同一个单位时间内多次触发只有第一次生效。适用于滚动事件、窗口调整等场景。代码示例function throttle(fn, interval) { let lastTime 0; return function(...args) { const now Date.now(); // 如果当前时间与上次执行时间的间隔大于指定时间则执行 if (now - lastTime interval) { fn.apply(this, args); lastTime now; } }; } // 使用示例 const handleScroll throttle(function() { console.log(滚动位置:, window.scrollY); }, 1000); // 监听滚动事件 window.addEventListener(scroll, handleScroll);区别总结防抖多次触发合并为最后一次执行等待空闲后执行节流固定间隔内只执行一次按频率执行防抖是 “等停止触发后再执行”节流是 “按固定节奏执行”25、JS图片懒加载的原理⭐⭐⭐JavaScript 实现图片懒加载的核心原理是延迟加载非可视区域的图片仅当图片即将进入用户视口时才加载从而减少初始加载资源、提升页面性能。具体具体具体具体实现逻辑如下1.初始状态处理页面初始化时不直接在img标签的src属性中设置真实图片地址避免浏览器立即加载而是将真实地址存放在自定义属性中如data-src或data-lazy。img classlazy-img>**四、**Vue2篇1、什么是前端构建工具?比如Vue2的webpackVue3的Vite⭐⭐①首先要明白浏览器它只认识html, css, js企业级项目里都可能会具备哪些功能typescript:·如果遇到ts文件我们需要使用tsc将typescript代码转换为js代码React/Vue:安装react-compiler / vue-complier将我们写的jsx文件或者.vue文件转换为render函数less/postcss/component-style:我们又需要安装less-loader, sass-loader等一系列编译工具4. 语法降级:babel —将es的新语法转换旧版浏览器可以接受的语法体积优化:uglifyjs —将我们的代码进行压缩变成体积更小性能更高的文件②前因后果因为稍微改一点点东西非常麻烦将App.tsx —tsc —· App.jsx —React-complier —js文件但是有一个东西能够帮你把tsc,react-compiler, less, babel,uglifyjs全部集成到一起我们只需要关心我们写的代码就好了我们写的代码变化–有人帮我们自动去tsc, react-compiler,less, babel, uglifyjs全部挨个走一遍–js这个东西就叫做 前端构建工具③前端构建工具的工作打包: 将我们写的浏览器不认识的代码交给构建工具进行编译处理的过程就叫做打包打包完成以后会给我们一个浏览器可以认识的文件。一个构建工具他到底承担了哪些脏活累活:1.模块化开发支持支持直接从node_modules里引入代码多种模块化支持2.处理代码兼容性比始babel语法降级less,ts 语法转换(**不是构建工具做的构建工具将这些语法对应的处理工具集成进来自动化处理)3.提高项目性能压缩文件**代码分割*4.优化开发体验:1构建工具会帮你自动监听文件的变化当文件变化以后自动帮你调用对应的集成工具进行重新打包然后再浏览器重新运行整个过程叫做热更新, hot replacement2开发服务器:跨域的问题用react-cli create-react-element-vue-cli·解决跨域的问题,④构建工具总结构建工具它让我们可以不用每次都关心我们的代码在浏览器如何运行我们只需要首次给构建工具提供一个配置文件(这个配置文件也不是必须的如果你不给他他会有默认的帮你去处理)有了这个集成的配置文件以后我们就可以在下次需要更新的时候调用一次对应的命令就好了如果我们再结合热更新我们就更加不需要管任何东西这就是构建工具去做的东西。构建工具它让我们不用关心生产的代码也不用去关心代码如何在浏览器运行只需要关心我们的开发怎么写的爽怎么写就好了2、Vue 组件之间的通信方式**⭐⭐⭐⭐⭐**1父组件向子组件传值//App.vue父组件 template div idapp users :usersusers/users//前者自定义名称便于子组件调用后者要传递数据名 /div /template script import Chilren from ./components/chilren export default { name: App, data(){ return{ users:[HelloKK] } }, components:{ Chilren:Chilren } }//chilren子组件 template div classhello ul li v-foruser in users{ {user}}/li//遍历传递过来的值然后呈现到页面 /ul /div /template script export default { name: chilren, props:{ users:{ //这个就是父组件中子标签自定义名字 type:Array, required:true } } } /script2子组件向父组件传值// 子组件 template header h1 clickchangeTitle{ {title}}/h1//绑定一个点击事件 /header /template script export default { name: app-header, data() { return { title:Vue.js Demo } }, methods:{ changeTitle() { this.$emit(titleChanged,子向父组件传值);//自定义事件 传递值“子向父组件传值” } } } /script// 父组件 template div idapp app-header v-on:titleChangedupdateTitle /app-header //与子组件titleChanged自定义事件保持一致 // updateTitle($event)接受传递过来的文字 h2{ {title}}/h2 /div /template script import Header from ./components/Header export default { name: App, data(){ return{ title:传递的是一个值 } }, methods:{ updateTitle(e){ //声明这个函数 this.title e; } }, components:{ app-header:Header, } } /script3、Vuex的理解及使用场景**⭐⭐⭐**Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store仓库。Vuex 的状态存储是响应式的当 Vue 组件从 store 中读取状态的时候若 store 中的状态发生变化那么相应的组件也会相应地得到高效更新 2. 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation 这样使得我们可以方便地跟踪每一个状态的变化 Vuex主要包括以下几个核心模块**1.State**定义了应用的状态数据**2.Getter**在 store 中定义“getter”可以认为是 store 的计算属性就像计算属性一样getter 的返回值会根据它的依赖被缓存起来 且只有当它的依赖值发生了改变才会被重新计算**3. Mutation**是唯一更改 store 中状态的方法且必须是同步函数**4. Action**用于提交 mutation而不是直接变更状态可以包含任意异步操作**5. Module**允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中4、vue 的生命周期 八个阶段**⭐⭐⭐⭐**1.beforeCreate在实例创建之间执行数据是未加载状态。创建一个Vue实例此时实例上只有一些生命周期函数和默认的事件此时data computed watch methods上的方法和数据均不能访问2.created在实例创建、数据加载后能初始化数据DOM渲染之前执行。可以对data数据进行操作可进行一些请求请求不易过多避免白屏时间太长。3.beforeMount虚拟DOM已创建完成在数据渲染前最后一次更改数据。el未挂载。判断el的挂载方式判断是否有template设置将template进行渲染保存到内存当中还未挂载在页面上4.mounted页面、数据渲染完成。el挂载完毕。可以访问DOM节点。将内存中的模版挂载到页面上此时可以操作页面上的DOM节点此时组件从创建阶段进入运行阶段5.beforeUpdate重新渲染之前触发。不会造成重渲染。页面显示的数据是旧的此时data里面的数据是最新页面数据和data数据暂未同步6.updated数据已经更新完成DOM也重新render完成更改数据会陷入死循环。根据data里的最新数据渲染出最新的DOM树然后将最新的DOM挂载到页面此时data和页面数据一致都是最新的7.beforeDestroy实例销毁前执行实例仍然完全可用。此时组件从运行阶段进入到销毁阶段组件上的data和methods以及过滤器等都出于可用状态销毁还未执行8.Destroyed实例销毁后执行这时候只剩下DOM空壳。组件已经被完全销毁组件中所有的数据、方法、指令、过滤器等都已不可用5、简述Vue每个周期具体适合哪些场景**⭐⭐⭐**beforeCreate 在new一个vue实例后只有一些默认的生命周期钩子和默认事件其他的东西都还没创建。在beforeCreate生命周期执行的时候data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法created data 和 methods都已经被初始化好了如果要调用 methods 中的方法或者操作 data 中的数据最早可以在这个阶段中操作beforeMount 执行到这个钩子的时候在内存中已经编译好了模板了但是还没有挂载到页面中此时页面还是旧的mounted 执行到这个钩子的时候就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段进入到了运行阶段。如果我们想要通过插件操作页面上的DOM节点最早可以在和这个阶段中进行beforeUpdate 当执行这个钩子时页面中的显示的数据还是旧的data中的数据是更新后的 页面还没有和最新的数据保持同步updated 页面显示的数据和data中的数据已经保持同步了都是最新的beforeDestory Vue实例从运行阶段进入到了销毁阶段这个时候上所有的 data 和 methods 指令 过滤器 ……都是处于可用状态。还没有真正被销毁destroyed 这个时候上所有的 data 和 methods 指令 过滤器 ……都是处于不可用状态。组件已经被销毁了。6、简述MVVM 和MVC的原理以及区别⭐⭐⭐MVVM视图模型双向绑定是Model-View-ViewModel的缩写1、MVVM的优点低耦合。视图View可以独立于Model变化和修改一个Model可以绑定到不同的View上当View变化的时候Model可以不变化当Model变化的时候View也可以不变可重用性。你可以把一些视图逻辑放在一个Model里面让很多View重用这段视图逻辑。独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel)设计人员可以专注于页面设计。可测试。2、什么是MVC?MVC是应用最广泛的软件架构之一,一般MVC分为:Model(模型),View(视图),Controller(控制器)。 这主要是基于分层的目的,让彼此的职责分开.View一般用过Controller来和Model进行联系。Controller是Model和View的协调者,View和Model不直接联系。基本都是单向联系。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。MVC是单向通信。也就是View跟Model必须通过Controller来承上启下。Model模型表示应用程序核心如数据库。View视图显示效果HTML页面。Controller控制器处理输入业务逻辑。MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。Model模型是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据)View视图是应用程序中处理数据显示的部分。(通常视图是依据模型数据创建的)Controller控制器是应用程序中处理用户交互的部分。(通常控制器负责从视图读取数据控制用户输入并向模型发送数据优点:1、低耦合2、重用性高3、生命周期成本低4、部署快5、可维护性高6、有利软件工程化管理3、MVC与MVVM的区别MVC和MVVM的区别并不是VM完全取代了CViewModel存在目的在于抽离Controller中展示的业务逻辑而不是替代Controller其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。MVC中Controller演变成MVVM中的ViewModelMVVM通过数据来显示视图层而不是节点操作MVVM主要解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验7、vue常见指令**⭐⭐⭐**v-model 多用于表单元素实现双向数据绑定v-bind简写为冒号“”动态绑定一些元素的属性类型可以是字符串、对象或数组。v-on:click 给标签绑定函数可以缩写为“”例如绑定一个点击函数 函数必须写在methods里面v-for 格式 v-for“字段名 in(of) 数组json” 循环数组或json记得加上keyv-show 显示内容v-if 指令取值为true/false控制元素是否需要被渲染v-else 指令和v-if指令搭配使用没有对应的值。当v-if的值falsev-else才会被渲染出来v-else-if 必须和v-if连用v-text 解析文本v-html 解析html标签 一般常见的解决后台的富文本内容v-bind:class 三种绑定方法对象型 “{redisred}”三元型 isred“red”“blue”数组型 [{red“isred” }{blue“isblue”}] v-once 进入页面时 只渲染一次 不在进行渲染v-cloak 防止闪烁v-pre 把标签内部的元素原位输出8、vue中的data为什么是一个函数起到什么作用⭐⭐⭐在Vue组件中data选项必须是一个函数而不能直接是一个对象。这是因为Vue组件可以同时存在多个实例如果直接使用对象形式的data选项那么所有的实例将会共享同一个data对象这样就会造成数据互相干扰的问题。因此将data选项设置为函数可以让每个实例都拥有自己独立的data对象。当组件被创建多次时每个实例都会调用该函数并返回一个新的data对象从而保证了数据的隔离性。另外data选项作为一个函数还具有一个重要的特性就是它可以接收一个参数这个参数是组件实例本身。这个特性在一些场景下非常有用例如在定义组件时需要使用组件实例的一些属性或方法来计算初始数据。因此为了避免数据共享和保证数据隔离性以及方便使用组件实例的属性和方法Vue组件中的data选项必须是一个函数。以下是一个简单的Vue组件示例其中data被定义为一个函数template div p{ { message }}/p button clickincrement{ { count }}/button /div /template script export default { data() { return { message: Hello, Vue!, count: 0 } }, methods: { increment() { this.count } } } /script在这个例子中data函数返回一个包含message和count两个属性的对象。每次创建组件实例时Vue都会调用该函数返回一个新的数据对象确保每个组件实例都有它自己的数据对象。9、vue中ref的作用 ⭐⭐⭐1、获取DOM元素的引用。ref 加在普通的元素上用this.ref.name 获取到的是dom元素vue给我们提供一个操作dom的属性ref绑定在dom元素上时用起来与id差不多通过this.$refs来调用template div idapp div reftestDom11111/div button clickgetTest获取test节点/button /div /template script export default { methods: { getTest() { console.log(this.$refs.testDom) } } }; /script2、获取子组件的引用。在Vue组件中使用ref可以获取子组件的引用从而可以在父组件内部调用子组件的方法或访问其数据。在父组件中将子组件引入并在子组件标签上添加ref属性然后就可以通过this.$refs.myChild获取子组件的引用在父组件内部调用子组件的sayHello方法。template div child refmyChild/child /div /template script import Child from ./Child.vue; export default { components: { Child }, mounted() { // 使用this.$refs获取子组件的引用 this.$refs.myChild.sayHello(); } } /script3、利用 v-for 和 ref 获取一组数组或者dom 节点注意事项ref需要在dom渲染完成后应用在使用时确保dom已经渲染完成。比如在生命周期mounted(){}钩子中调用或者在this.$nextTick((){})中调用。如果ref是循环出来的有多个重名那么ref值会是一个数组 此时要拿到单个ref只需要循环就可以。**10、**Vue中hash和history的区别 ⭐⭐⭐在Vue.js中hash和history是Vue Router的两种路由模式它们在URL结构、浏览器兼容性、服务器配置、SEO优化、用户体验等方面存在显著差异。Vue 路由的 Hash 模式和 History 模式是前端路由的两种实现方式以下是两者的核心区别Vue 路由的 Hash 模式和 History 模式是前端路由的两种实现方式以下是两者的核心区别一、URL 形态Hash 模式URL 中包含 # 符号如 http://example.com/#/home# 后的内容为前端路由不会发送至服务端。History 模式URL 无 #如 http://example.com/home形态更接近传统 URL 结构美观性更高。二、实现原理Hash 模式基于 location.hash 和 hashchange 事件实现路由切换通过监听 URL 中 # 后的变化更新页面内容。History 模式利用 HTML5 的 History API如 pushState、replaceState修改浏览器历史记录栈并通过 popstate 事件监听路由变化。三、服务端配置Hash 模式无需服务端特殊配置直接部署即可正常使用。History 模式需服务端支持如 Nginx 配置路由重定向避免直接访问子路由时返回 404 错误。四、兼容性Hash 模式兼容所有浏览器包括 IE8。History 模式依赖 HTML5 History API仅支持 IE10 及现代浏览器。五、SEO 优化Hash 模式后的内容可能被搜索引擎忽略对 SEO 不友好。History 模式完整 URL 更易被搜索引擎抓取但需配合服务端渲染实现 SEO 优化。六、适用场景选择 Hash 模式对 SEO 无要求、需兼容老旧浏览器的小型应用或快速开发场景。选择 History 模式追求 URL 美观性、需 SEO 优化的项目且具备服务端配置能力。通过对比可见Hash 模式简化了部署和维护但牺牲了 URL 规范性和 SEOHistory 模式提供了更专业的用户体验但需额外服务端支持。开发者应根据项目需求权衡选择。五 、Vue3篇1、Vue2和Vue3的区别⭐⭐⭐⭐特性Vue 2Vue 3响应式系统Object.definePropertyProxy架构单一源码模块化架构Tree-shakableComposition API❌✅Fragment❌✅Suspense 组件❌✅自定义渲染器支持有限更灵活支持 TypeScript❌需额外配置✅ 原生支持1. 核心响应式机制不同Vue2基于**Object.defineProperty**实现需要提前遍历对象属性存在天然局限无法监听对象新增 / 删除的属性需用this.$set手动处理无法监听数组通过索引修改的元素如arr[0] 1初始化时要递归遍历所有属性大对象性能损耗明显Vue3改用 **Proxy**代理整个对象解决了上述问题自动监听对象新增 / 删除属性原生支持数组索引修改和length变化懒代理机制只有访问属性时才会递归性能更优2. 代码组织方式差异Vue2主要用选项式 APIOptions API代码按data、methods、computed等选项划分逻辑分散export default { data() { return { count: 0 } }, methods: { increment() { this.count } }, computed: { double() { return this.count * 2 } } }Vue3新增组合式 APIComposition API可按业务逻辑聚合代码适合复杂组件import { ref, computed } from vue export default { setup() { const count ref(0) const increment () count.value const double computed(() count.value * 2) return { count, increment, double } } }3. 性能优化编译层面Vue3 的模板编译会标记静态节点更新时只处理动态内容减少 DOM 操作体积优化支持 Tree-shaking未使用的 API如watch、computed不会打包核心库体积减少约 40%渲染优化新增Fragment多根节点避免不必要的根元素嵌套4. 其他重要变化生命周期Vue3 的生命周期需从vue导入如onMounted替代 Vue2 的mounted且setup替代了beforeCreate和created模板语法支持多根节点、动态指令参数如v-bind:[key]、更灵活的v-slot语法移除特性删除filter推荐用计算属性替代、$on/$off移除实例事件 APITypeScript 支持Vue3 源码用 TS 重写类型定义更完善开发时类型提示更友好简单总结Vue3 是对 Vue2 的全面升级底层机制更先进性能更好代码组织更灵活尤其适合中大型项目开发但学习成本略有增加。2、Vue2和Vue3的生命周期**⭐⭐⭐⭐⭐**Vue2-生命周期Vue3-生命周期Vue3中可以继续使用Vue2中的生命周期钩子但有有两个被更名beforeDestroy改名为 beforeUnmountdestroyed改名为 unmountedVue3也提供了 Composition API 形式的生命周期钩子与Vue2中钩子对应关系如下beforeCreatesetup()createdsetup()beforeMount onBeforeMountmountedonMountedbeforeUpdateonBeforeUpdateupdated onUpdatedbeforeUnmount onBeforeUnmountunmounted onUnmounted3、Vue2和vue3的响应式原理**⭐⭐⭐⭐⭐**Vue2 和 Vue3 的响应式原理在实现方式和功能上有本质区别核心都是为了实现「数据变化时自动更新视图」但具体机制不同Vue2 的响应式原理基于Object.defineProperty实现这是 ES5 中的一个方法作用是给对象的属性添加 getter 和 setter 拦截器。工作流程初始化时Vue 会递归遍历 data 中的所有属性给每个属性添加 getter 和 setter。** getter **当属性被访问时触发用来收集依赖记录这个属性被哪些组件 / 视图使用。** setter **当属性被修改时触发会通知所有依赖该属性的地方如视图、计算属性进行更新。局限性只能监听对象已有的属性新增属性或删除属性不会触发更新需要用this.$set手动处理。无法监听数组通过索引修改的元素如arr[0] 1或直接修改数组长度如arr.length 0需要用数组方法如push、splice才会触发更新。初始化时需要递归遍历所有属性对于大型对象性能损耗较大。Vue3 的响应式原理基于Proxy实现这是 ES6 新增的特性能够创建一个对象的代理拦截对对象的各种操作。工作流程初始化时Vue 会用Proxy对 data 对象创建一个代理对象Proxy 实例。拦截操作Proxy 能拦截对象的几乎所有操作包括属性的读取、修改、新增、删除以及数组的索引修改、长度变化等。依赖收集与更新当代理对象被访问时收集依赖当被修改时触发依赖更新流程和 Vue2 类似但拦截能力更强。优势原生支持监听对象的新增 / 删除属性无需手动调用特殊方法。完美支持数组的索引修改、长度修改如arr[0] 1、arr.length 0都会触发更新。采用「懒代理」模式只有当属性被访问时才会递归处理嵌套对象性能更优。可以监听 Map、Set 等复杂数据结构的变化。总结Vue2 用Object.defineProperty拦截属性功能有限需要手动处理边缘情况。Vue3 用Proxy代理整个对象拦截能力更强支持更多数据类型和操作是更现代、更完善的实现。4、Vue3常用 Composition API**⭐⭐⭐⭐⭐**Vue3 的 Composition API 是一套基于函数的 API主要用于组织和复用组件逻辑。常用的 Composition API 可以分为以下几类1. 响应式相关ref创建基本类型字符串、数字等的响应式数据返回一个包含value属性的对象import { ref } from vue const count ref(0) // 初始值 console.log(count.value) // 访问值 count.value 1 // 修改值必须通过 .valuereactive创建对象 / 数组类型的响应式数据返回一个代理对象import { reactive } from vue const user reactive({ name: 张三, age: 20 }) user.age 21 // 直接修改属性即可响应toRef将响应式对象的某个属性转为ref类型保持响应式关联const ageRef toRef(user, age) // 关联 user.agetoRefs将响应式对象的所有属性转为ref类型常用于解构响应式对象const { name, age } toRefs(user) // 解构后仍保持响应式isRef/isReactive判断数据是否为ref或reactive创建的响应式数据2. 计算属性与监听computed创建计算属性支持只读和可写两种模式import { computed } from vue // 只读 const doubleCount computed(() count.value * 2) // 可写 const fullName computed({ get: () ${firstName.value} ${lastName.value}, set: (val) { /* 处理赋值逻辑 */ } })watch监听数据变化类似 Vue2 的watch选项import { watch } from vue // 监听 ref watch(count, (newVal, oldVal) { ... }) // 监听多个数据 watch([count, user.age], ([newCount, newAge], [oldCount, oldAge]) { ... })watchEffect自动追踪依赖依赖变化时执行回调无需手动指定监听源watchEffect(() { // 自动监听 count 和 user.name 的变化 console.log(count: ${count.value}, name: ${user.name}) })3. 生命周期钩子需要从vue中导入在setup中使用名称以on开头onMounted组件挂载后对应 Vue2 的mountedonUpdated组件更新后对应 Vue2 的updatedonUnmounted组件卸载后对应 Vue2 的destroyed其他onBeforeMount、onBeforeUpdate、onErrorCaptured等import { onMounted, onUnmounted } from vue setup() { onMounted(() { console.log(组件挂载完成) }) onUnmounted(() { console.log(组件已卸载) }) }4. 依赖注入provide/inject跨组件传递数据替代 Vue2 的provide/inject选项// 父组件提供数据import { provide } from ‘vue’provide(‘theme’, ‘dark’)// 子组件获取数据import { inject } from ‘vue’const theme inject(‘theme’, ‘light’) // 第二个参数是默认值5. 其他常用 APIsetup组件的入口函数在创建组件实例时执行所有 Composition API 在此使用getCurrentInstance获取当前组件实例类似 Vue2 的this谨慎使用templateRef获取模板中元素的引用替代 Vue2 的ref属性这些 API 可以按需组合使用核心优势是能将相关逻辑聚合在一起避免 Options API 中逻辑分散的问题尤其适合复杂组件和逻辑复用。5、Vue3 组件通信 (父传子、子传父、父子双向绑定、跨层级通信、全局状态管理)⭐⭐⭐⭐⭐Vue3 组件通信方式在 Vue2 基础上有所扩展既保留了传统方式也新增了 Composition API 相关的方法。以下是常用的组件通信方式1. 父传子Props最基础的通信方式父组件通过属性向子组件传递数据。父组件template ChildComponent :messageparentMsg :useruserInfo / /template script setup import { ref, reactive } from vue import ChildComponent from ./ChildComponent.vue const parentMsg ref(来自父组件的消息) const userInfo reactive({ name: 张三, age: 20 }) /script子组件template div{{ message }}/div div{{ user.name }}/div /template script setup import { defineProps } from vue // 定义接收的 props两种方式 // 方式1仅声明类型 const props defineProps([message, user]) // 方式2带类型校验推荐 const props defineProps({ message: String, user: { type: Object, required: true } }) // 使用 props无需 .value直接访问 console.log(props.message) /script2. 子传父Emits子组件通过触发事件向父组件传递数据。子组件template button clickhandleClick发送数据/button /template script setup import { defineEmits } from vue // 定义可触发的事件两种方式 const emit defineEmits([sendData, update]) // 或带类型校验 const emit defineEmits({ sendData: (data) typeof data string, // 验证数据格式 update: (num) num 0 }) const handleClick () { // 触发事件并传递数据 emit(sendData, 来自子组件的消息) emit(update, 100) } /script父组件template ChildComponent sendDataonReceive updateonUpdate / /template script setup const onReceive (data) { console.log(收到子组件数据, data) } const onUpdate (num) { console.log(收到更新值, num) } /script3. 父子双向绑定v-model简化「父传子 子传父」的语法糖实现数据双向同步。父组件template !-- 等价于ChildComponent :valuecount inputcount $event / -- ChildComponent v-modelcount / /template script setup import { ref } from vue const count ref(0) /script子组件template button clickhandleAddcount: {{ modelValue }}/button /template script setup import { defineProps, defineEmits } from vue // 接收父组件的 valuev-model 默认绑定 modelValue const props defineProps([modelValue]) // 触发更新事件默认触发 input 事件 const emit defineEmits([update:modelValue]) const handleAdd () { emit(update:modelValue, props.modelValue 1) } /script多值双向绑定!-- 父组件 -- ChildComponent v-model:nameuserName v-model:ageuserAge / !-- 子组件 -- emit(update:name, newName) emit(update:age, newAge)4. 跨层级通信Provide / Inject适用于祖孙组件、深层级组件间通信无需逐层传递。顶层组件提供数据script setup import { provide, ref } from vue // 提供普通值 provide(theme, dark) // 提供响应式数据子组件会同步更新 const user ref({ name: 张三 }) provide(currentUser, user) /script深层子组件接收数据script setup import { inject } from vue // 接收数据第二个参数为默认值 const theme inject(theme, light) const currentUser inject(currentUser) // 使用响应式数据 console.log(currentUser.value.name) /script5. 全局状态管理PiniaVue3 推荐的状态管理库替代 Vuex适用于任意组件间共享状态。安装npm install pinia定义仓库store// stores/counter.js import { defineStore } from pinia export const useCounterStore defineStore(counter, { state: () ({ count: 0 }), actions: { increment() { this.count } } })任意组件使用script setup import { useCounterStore } from ./stores/counter const counter useCounterStore() // 访问状态 console.log(counter.count) // 修改状态 counter.count // 或调用 action counter.increment() /script6. 其他方式refs 访问子组件父组件通过ref获取子组件实例直接调用方法或访问数据谨慎使用耦合度高。事件总线EventBusVue3 中可通过mitt库实现替代 Vue2 的$on/$off适用于简单场景。总结父子通信优先用Props Emits或v-model跨层级通信用Provide/Inject全局共享状态用Pinia根据场景选择合适的方式避免过度设计。6、Vue 3 的setup()函数的作用是什么⭐⭐⭐在 Vue 3 中setup()函数是 Composition API 的入口点主要作用是在组件实例创建前执行用于设置组件的状态、方法、生命周期钩子等逻辑并将需要暴露给模板或其他组件的内容返回。具体作用可归纳为替代 Vue 2 的选项式 API不再需要data、methods、computed等选项可在setup()中通过 Composition API如ref、reactive、computed等直接定义响应式数据和方法。前置执行时机在组件的beforeCreate钩子之前执行此时组件实例尚未完全创建this为undefined避免了选项式 API 中this指向的混淆问题。整合逻辑方便按功能维度组织代码如将某一功能相关的状态、方法、监听逻辑放在一起解决了大型组件中选项式 API 逻辑分散的问题。接收参数第一个参数props组件接收的 props 数据响应式需通过props.xxx访问。第二个参数context包含attrs、slots、emit等组件上下文信息替代了 Vue 2 中this.$attrs、this.$slots、this.$emit。返回值用途返回对象对象中的属性和方法会暴露给模板供模板直接使用。返回渲染函数可直接通过h()函数定义组件的渲染逻辑替代模板。template button clickincrement{{ count }}/button /template script import { ref } from vue export default { setup() { // 定义响应式数据 const count ref(0) // 定义方法 const increment () { count.value } // 暴露给模板 return { count, increment } } } /script7、ref 和 reactive 的区别是什么⭐⭐⭐在 Vue 3 的 Composition API 中ref和reactive是创建响应式数据的核心 API二者的核心区别体现在适用场景、内部实现、访问方式等方面具体分析如下适用数据类型不同ref更适合基本类型也支持复杂类型主要用于包装基本数据类型string、number、boolean、null、undefined等使其具备响应式。也可以接收复杂类型对象、数组但内部会自动将复杂类型转换为reactive代理对象即对复杂类型的处理是 “语法糖”。reactive仅适用于复杂类型只能接收对象或数组等复杂数据类型无法直接处理基本类型若传入基本类型会报错或失去响应式。内部实现原理不同ref的实现内部会创建一个包装对象RefImpl实例该对象包含一个value属性响应式的核心逻辑就围绕value展开。对于基本类型直接通过Object.defineProperty拦截value的get和set操作实现依赖收集和触发更新。对于复杂类型当ref接收对象 / 数组时会自动调用reactive对其进行代理此时ref.value等价于reactive创建的代理对象。reactive的实现基于Proxy直接代理整个对象通过拦截对象的get、set、deleteProperty等操作包括动态新增 / 删除属性、数组索引 / 长度变化等实现响应式。只能代理对象且代理是 “深层的”递归代理所有嵌套属性访问与修改方式不同ref需通过.value访问 / 修改无论基本类型还是复杂类型在JavaScript 代码中必须通过.value访问或修改值模板中使用时会自动解包无需.value六、React篇1、讲讲什么是 JSX ⭐⭐⭐当Facebook第一次发布 React 时他们还引入了一种新的 JS 方言JSX将原始 HTML 模板嵌入到 JS 代码中。JSX 代码本身不能被浏览器读取必须使用Babel和webpack等工具将其转换为传统的JS。很多开发人员就能无意识使用 JSX因为它已经与 React 结合在一直了。class MyComponent extends React.Component { render() { let props this.props; return ( div classNamemy-component a href{props.url}{props.name}/a /div ); } }JSX的特点可以将HTML语言直接写在JavaScript语言之中不加任何引号这就是JSX的语法它允许HTML与JavaScript的混写。JSX允许直接在模板插入JavaScript变量。如果这个变量是一个数组则会展开这个数组的所有成员。防注入攻击在JSX中嵌入用户输入是安全的React DOM在渲染之前默认会过滤所有传入的值。它可以确保应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止XSS(跨站脚本攻击)Babel转译器会把JSX转换成一个名为React.createElement()的方法调用。如果在普通的html里面要写jsx语法要将script的type改成text/jsx这是因为React独有的JSX语法跟JavaScript不兼容。凡是使用JSX的地方都要加上type“text/jsx”。其次React提供俩个库:react.js和JSXTransformer.js它们必须首先加载。其中JSXTransformer.js的作用是将JSX语法转为JavaScript语法。这一步很消耗时间实际上线的时候应该把它放到服务器完成。2、React 的生命周期方法有哪些⭐⭐⭐React的生命周期方法有很多并且在不同的React版本中可能会有一些变化。为了更好地理解React的生命周期我将它们按照React 16版本及其之后的版本进行整理以帮助你更好地理解。在React 16版本及其之后React的生命周期方法可分为三个阶段挂载阶段、更新阶段和卸载阶段。以下是React 16版本及其之后的生命周期方法列表挂载阶段constructor组件实例化时调用用于初始化状态和绑定方法。static getDerivedStateFromProps在渲染之前调用用于根据新的属性值计算并返回一个新的状态。render渲染组件的内容。componentDidMount组件挂载后调用可以进行异步操作、订阅事件等。更新阶段static getDerivedStateFromProps在渲染之前调用用于根据新的属性值计算并返回一个新的状态。shouldComponentUpdate在渲染之前调用用于决定是否重新渲染组件默认返回true。render渲染组件的内容。getSnapshotBeforeUpdate在最终将内容渲染到DOM之前调用用于获取DOM更新前的快照。componentDidUpdate组件更新后调用可以进行DOM操作、发起网络请求等。卸载阶段componentWillUnmount组件卸载前调用可以进行清理操作如取消订阅、清除定时器等。另外React 16.3版本后引入了以下生命周期方法static getDerivedStateFromError在子组件渲染过程中如果发生错误会调用该方法返回一个新的状态。componentDidCatch在子组件渲染过程中如果发生错误会调用该方法用于记录错误信息或上报错误。需要注意的是React 17版本之后一些生命周期方法被标记为过时并推荐使用其他替代方法来实现相应的功能。在使用React时可以根据具体的需求和React版本来选择合适的生命周期方法。同时React还提供了钩子函数的方式如useEffect钩子来完成与生命周期相关的操作这也是React 16.8版本及其之后的新特性。3、React的Hooks详解**⭐⭐⭐⭐⭐**Hook是什么Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。React 内置了一些像 useState 这样的 Hook。你也可以创建你自己的 Hook 来复用不同组件之间的状态逻辑。React提供了多个常用的Hooks用于在函数组件中管理状态、处理副作用和访问React的上下文等。以下是React所有的常用Hooks列表useState用于在函数组件中添加状态。useEffect用于在函数组件中执行副作用操作。useContext用于在函数组件中访问React的上下文。useReducer用于在函数组件中使用Reducer模式来管理状态。useRef用于在函数组件中创建可变的引用。useMemo用于在函数组件中缓存计算的值。useCallback用于在函数组件中缓存函数。useLayoutEffect类似于useEffect但在DOM更新之后同步执行。useImperativeHandle用于在函数组件中自定义外部组件实例的暴露。useDebugValue用于在自定义Hooks中显示自定义的调试值。这些Hooks可以帮助你更方便地编写和管理React函数组件。同时你还可以根据需要自定义自己的Hooks来封装和复用逻辑。React的Hooks特性在React 16.8版本及其之后引入它们提供了一种更简洁、灵活的方式来编写可复用的React组件逻辑。4、React和Vue.js的相似性和差异性是什么⭐⭐相似性如下。1都是用于创建UI的 JavaScript库。2都是快速和轻量级的代码库这里指 React核心库。3都有基于组件的架构。4都使用虚拟DOM。5都可以放在单独的HTML文件中或者放在 Webpack设置的一个更复杂的模块中。6都有独立但常用的路由器和状态管理库。它们最大的区别在于 Vue. js通常使用HTML模板文件而 React完全使用 JavaScript创建虚拟DOM。 Vue. js还具有对于“可变状态”的“ reactivity”的重新渲染的自动化检测系统。React一般适用于大型项目5、React的功能是什么⭐⭐React的主要功能如下它使用虚拟DOM而不是真实DOM。它使用服务器端渲染。它遵循单向数据流或数据绑定。6、React的一些主要优点是⭐⭐它提高了应用程序的性能它可以方便地在客户端和服务器端使用由于有了JSX代码的可读性提高了React易于与其他框架如MeteorAngular等集成使用React编写UI测试用例变得非常容易7、React的局限性是什么⭐⭐React只是一个库而不是一个成熟的框架它的图书馆很大需要花费一些时间来理解对于新手程序员而言理解起来可能有点困难由于使用内联模板和JSX编码变得复杂8、如何理解React State不可变性的原则**⭐⭐**在 React 中不可变性是指数据一旦被创建就不能被修改。React 推崇使用不可变数据的原则这意味着在更新数据时应该创建新的数据对象而不是直接修改现有的数据。以下是理解 React 中不可变性原则的几个关键点**数据一旦创建就不能被修改**在 React 中组件的状态state和属性props应该被视为不可变的。一旦创建了状态或属性对象就不应该直接修改它们的值。这样可以确保组件的数据在更新时是不可变的从而避免意外的数据改变和副作用。**创建新的数据对象**当需要更新状态或属性时应该创建新的数据对象。这可以通过使用对象展开运算符、数组的 concat()、slice() 等方法或者使用不可变数据库如Immutable.js、Immer 等来创建新的数据副本。**比较数据变化**React 使用 Virtual DOM 来比较前后两个状态树的差异并仅更新需要更新的部分。通过使用不可变数据React 可以更高效地进行比较因为它可以简单地比较对象引用是否相等而不必逐个比较对象的属性。**性能优化**使用不可变数据可以带来性能上的优势。由于 React 可以更轻松地比较前后状态的差异可以减少不必要的重新渲染和组件更新提高应用的性能和响应性。不可变性的原则在 React 中有以下好处**简化数据变更追踪**由于数据不可变可以更轻松地追踪数据的变化。这样可以更好地理解代码的行为和数据的流动。**避免副作用**可变数据容易引发副作用和难以追踪的 bug。通过使用不可变数据可以避免许多与副作用相关的问题。**方便的历史记录和回滚**不可变数据使得记录和回滚应用状态的历史变得更容易。可以在不改变原始数据的情况下创建和保存不同时间点的数据快照9、React的特点和关键版本区别⭐⭐react的关键版本React16之前对virtural dom的更新和渲染是同步的。就是当一次更新或者一次加载开始以后diff virtual dom并且渲染的过程是一口气完成的。如果组件层级比较深相应的堆栈也会很深长时间占用浏览器主线程一些类似用户输入、鼠标滚动等操作得不到响应。React16开始用了分片的方式解决上面的问题就是把一个任务分成很多小片当分配给这个小片的时间用尽的时候就检查任务列表中有没有新的、优先级更高的任务有就做这个新任务没有就继续做原来的任务。这种方式被叫做异步渲染(Async Rendering)。React的特点1. React速度很快与其他框架相比React采取了一种独特操作DOM的方式。它并不直接对DOM进行操作。它引入了一个叫虚拟DOM的概念安插在JavaScript逻辑和实际的DOM之间。这一概念提高了Web性能。在UI渲染过程中React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。将视图与数据进行单向绑定绝大部分操作都可以不再直接操作DOM而是通过改变数据来更新视图这对于前端是具有里碑意义的。2. 跨浏览器兼容虚拟DOM帮助我们解决了跨浏览器问题它为我们提供了标准化的API甚至在IE8中都是没问题的。3. 模块化为程序编写独立的模块化UI组件并且它们可以引入其他组件。这等同于提高了代码的可维护性。4. 单向数据流让事情一目了然Flux是一个用于在JavaScript应用中创建单向数据层的架构它随着React视图库的开发而被Facebook概念化。它只是一个概念而非特定工具的实现。它可以被其它框架吸纳。例如Alex Rattray有一个很好的Flux实例在React中使用了Backbone的集合和模型。5. 纯粹的JavaScript现代Web应用程序与传统的Web应用有着不同的工作方式。例如视图层的更新需要通过用户交互而不需要请求服务器。因此视图和控制器非常依赖彼此。许多框架使用Handlebars或Mustache等模板引擎来处理视图层。但React相信视图和控制器应该相互依存在一起而不是使用第三方模板引擎而且最重要的是它是纯粹的JavaScript程序。6. 同构的JavaScript单页面JS应用程序的最大缺陷在于对搜索引擎的索引有很大限制。React对此有了解决方案。React可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。因为搜索引擎的爬虫程序依赖的是服务端相应而不是JavaScript的执行预渲染你的应用有助于搜索引擎优化。7. React与其他框架/库相比兼容性好比如使用RequireJS来加载和打包而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。8. 相比于其他的框架【vue】更灵活没有那么多的条条框框提供了一系列基础api自己随意组合。如果要我把他比作积木的话那么react提供的就是小型的积木vue提供的是大型的积木。这就势必造成了react会比vue更加的灵活。10、React Fiber的深入理解**⭐⭐**React Fiber 是 React 16 引入的核心算法重构旨在解决大型应用中渲染阻塞导致的性能问题实现更流畅的用户体验。以下是对 React Fiber 的系统性解析1. 核心目标**增量渲染Incremental Rendering**将渲染任务拆分为可中断、可分片的小任务单元避免长时间占用主线程。任务优先级调度根据任务类型如用户交互、动画分配优先级优先处理高优先级更新。**支持异步渲染Concurrent Mode**允许中断低优先级任务确保关键操作的响应速度。2. Fiber 节点结构每个组件对应一个 Fiber 节点形成链表树结构包含以下关键信息组件类型函数组件、类组件、宿主组件DOM 节点等。状态与 Props当前组件的状态如state和props。指针关系child指向第一个子节点。sibling指向下一个兄弟节点。return指向父节点。副作用标记标识节点是否需要更新、插入或删除如effectTag。**双缓冲Double Buffering**每个 Fiber 节点有两个版本current当前已渲染的树。workInProgress正在构建的新树完成后替换current。**3. 协调机制Reconciliation**分为两个阶段**a. 渲染阶段Render Phase**可中断通过循环遍历 Fiber 链表逐个处理节点而非递归每完成一个单元后检查剩余时间。对比更新通过 Diff 算法生成副作用列表如 DOM 更新。生命周期调整废弃componentWillMount等可能不安全的生命周期因异步渲染可能多次调用。引入getDerivedStateFromProps和getSnapshotBeforeUpdate等静态方法。**b. 提交阶段Commit Phase**不可中断一次性执行所有副作用如 DOM 操作确保 UI 一致性。触发生命周期执行componentDidMount、componentDidUpdate等。4. 调度机制优先级模型任务分为六种优先级如 Immediate、UserBlocking、Normal 等通过调度器Scheduler管理。**时间切片Time Slicing**使用requestIdleCallback的 polyfill 在浏览器空闲期执行任务避免阻塞渲染。任务中断与恢复高优先级任务可中断低优先级任务的渲染后续从断点恢复。5. 关键优势流畅交互确保用户输入、动画等高优先级任务即时响应。高效更新增量渲染减少卡顿提升 FPS帧率。**错误边界Error Boundaries**通过 Fiber 节点链路捕获子组件错误降级 UI 展示。**6. 异步渲染Concurrent Mode**并发更新允许多个任务并发执行根据优先级动态调整处理顺序。Suspense 机制支持异步加载组件或数据在等待期间展示 fallback UI。7. 示例Fiber 工作流程// 组件树 App Header / Content / /App // Fiber 链表结构 App Fiber → child → Header Fiber ↓ sibling → Content Fiber从根节点开始处理AppFiber。依次处理其子节点Header完成后通过sibling处理Content。若时间不足暂停并让出主线程后续恢复处理剩余节点。8. 总结React Fiber 通过重新设计协调算法实现了可中断的任务调度、优先级驱动更新和异步渲染能力显著提升了复杂应用的性能与用户体验。其核心在于将同步递归转换为异步循环处理并利用双缓冲技术实现无缝切换。开发者可通过理解 Fiber 架构优化组件设计如减少渲染阻塞充分发挥 React 的并发特性。七、uniapp篇1、uniapp优缺点⭐⭐uniapp官网组件使用的入门教程 | uni-app官网优点一套代码可以生成多端学习成本低,语法是vue的,组件是小程序的拓展能力强使用HBuilderX开发,支持vue语法突破了系统对H5调用原生能力的限制缺点问世时间短,很多地方不完善社区不大官方对问题的反馈不及时在Android平台上比微信小程序和iOS差文件命名受限2、uniapp目录结构**⭐**一个uni-app工程默认包含如下目录及文件┌─uniCloud 云空间目录阿里云为uniCloud-aliyun,腾讯云为uniCloud-tcb详见uniCloud │─components 符合vue组件规范的uni-app组件目录 │ └─comp-a.vue 可复用的a组件 ├─utssdk 存放uts文件 ├─pages 业务页面文件存放的目录 │ ├─index │ │ └─index.vue index页面 │ └─list │ └─list.vue list页面 ├─static 存放应用引用的本地静态资源如图片、视频等的目录注意静态资源只能存放于此 ├─uni_modules 存放[uni_module](/uni_modules)。 ├─platforms 存放各平台专用页面的目录详见 ├─nativeplugins App原生语言插件 详见 ├─nativeResources App端原生资源目录 │ └─android Android原生资源目录 详见 ├─hybrid App端存放本地html文件的目录详见 ├─wxcomponents 存放小程序组件的目录详见 ├─unpackage 非工程代码一般存放运行或发行的编译结果 ├─AndroidManifest.xml Android原生应用清单文件 详见 ├─main.js Vue初始化入口文件 ├─App.vue 应用配置用来配置App全局样式以及监听 应用生命周期 ├─manifest.json 配置应用名称、appid、logo、版本等打包信息详见 ├─pages.json 配置页面路由、导航条、选项卡等页面类信息详见 └─uni.scss 这里是uni-app内置的常用样式变量pages.json配置文件全局页面路径配置应用的状态栏、导航条、标题、窗口背景色设置等main.js入口文件主要作用是初始化vue实例、定义全局组件、使用需要的插件如 vuex注意uniapp无法使用vue-router路由须在pages.json中进行配置。如果开发者坚持使用vue-router可以在插件市场找到转换插件。App.vue是uni-app的主组件所有页面都是在App.vue下进行切换的是页面入口文件。但App.vue本身不是页面这里不能编写视图元素。除此之外应用生命周期仅可在App.vue中监听在页面监听无效。pages页面管理部分用于存放页面或者组件应用配置 manifest.json文件是应用的配置文件用于指定应用的名称、图标、权限等HBuilderX 创建的工程此文件在根目录CLI 创建的工程此文件在 src 目录。我们也可以在这里为Vue 为H5设置跨域拦截处理器package.json文件用来对 uni-app 进行全局配置决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。pages数组中第一项表示应用启动页参考官网pages.json 页面路由 | uni-app官网3、跨端适配—条件编译⭐⭐开发者按照 uni-app 规范开发即可保证多平台兼容大部分业务均可直接满足。但每个平台有自己的一些特性因此会存在一些无法跨平台的情况。因此就有了条件编译这个模式不仅是js逻辑代码template和css样式都可以设置成在某个环境中生效在其他环境不生效。更多详细信息及平台适配请看官方文档//template !-- #ifdef MP-WEIXIN -- !-- 只在小程序中生效 -- view我是微信小程序/view !-- #endif -- !-- #ifdef APP-PLUS -- !-- 只在 app 中生效 -- view我是 app /view !-- #endif -- //js // #ifndef H5 // 表示只有 h5 不使用这个 api uni.createAnimation(OBJECT) // #endif //css /* #ifdef MP-WEIXIN */ /* 只在小程序中生效 */ .header { color:red } /* #endif */4、uniapp 常用的指令语句**⭐⭐**v-for循环渲染 注意加keyv-if 控制元素的删除添加v-show控制元素的显示隐藏v-model双向数据绑定v-on事件绑定简写v-bind属性绑定简写5、uniapp 应用的生命周期、页面的生命周期、组件的生命周期**⭐⭐**应用的生命周期onLaunch——当uni-app 初始化完成时触发全局只触发一次onShow——当 uni-app 启动或从后台进入前台显示onHide——当 uni-app 从前台进入后台onError——当 uni-app 报错时触发onUniNViewMessage——对 nvue 页面发送的数据进行监听可参考 nvue 向 vue 通讯onUnhandledRejection——对未处理的 Promise 拒绝事件监听函数2.8.1onPageNotFound——页面不存在监听函数onThemeChange——监听系统主题变化页面的生命周期onInit——监听页面初始化其参数同 onLoad 参数为上个页面传递的数据参数类型为 Object用于页面传参触发时机早于 onLoadonLoad——监听页面加载其参数为上个页面传递的数据参数类型为 Object用于页面传参参考示例onShow——监听页面显示。页面每次出现在屏幕上都触发包括从下级页面点返回露出当前页面onReady——监听页面初次渲染完成。注意如果渲染速度快会在页面进入动画完成前触发onHide——监听页面隐藏onUnload——监听页面卸载onResize——监听窗口尺寸变化组件的生命周期uni-app 组件支持的生命周期与vue标准组件的生命周期相同beforeCreate——在实例初始化之后被调用。created——在实例创建完成后被立即调用。beforeMount——在挂载开始之前被调用。mounted——挂载到实例上去之后调用。详见 注意此处并不能确定子组件被全部挂载如果需要子组件完全挂载之后在执行操作可以使用$nextTickVue官方文档beforeUpdate——数据更新时调用发生在虚拟 DOM 打补丁之前。updated——由于数据更改导致的虚拟 DOM 重新渲染和打补丁在这之后会调用该钩子。beforeDestroy——实例销毁之前调用。在这一步实例仍然完全可用。destroyed——Vue 实例销毁后调用。调用后Vue 实例指示的所有东西都会解绑定所有的事件监听器会被移除所有的子实例也会被销毁。八、Webpack篇1、Webpack是什么⭐⭐webpack 是一个静态模块打包器当 webpack 处理应用程序时会递归构建一个依赖关系图其中包含应用程序需要的每个模块然后将这些模块打包成一个或多个 bundle。webpack 就像一条生产线,要经过一系列处理流程(loader)后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。2、Webpack的打包过程/打包原理/构建流程⭐⭐webpack 的运行流程是一个串行的过程它的工作流程就是将各个插件串联起来。命令行执行npx webpack打包命令开始1.初始化编译参数:从配置文件和shell命令中读取与合并参数2.开始编译:根据上一步得到的参数初始化Compiler对象加载所有配置的Plugin执行对象的 run 方法开始执行编译。3.确定入口:根据配置中的 entry 找出所有的入口文件4.编译模块:从入口文件触发调用所有配置的Loader对模块进行翻译再找出该模块依赖的模块然后递归本步骤直到所有入口依赖的文件都进行翻译。5.完成模块编译:在经过第4步使用 Loader 翻译完所有模块后得到了每个模块被翻译后的最终内容以及它们之间的依赖关系图。6.输出资源根据依赖关系图组装成一个个包含多个模块的Chunk再把每个Chunk转化成一个单独的文件加入到输出列表根据配置确定输出的路径和文件名输出。在以上过程中Webpack 会在特定的时间点广播出特定的事件插件在监听到感兴趣的事件后会执行特定的逻辑。总结归纳初始化:从配置文件和shell命令中读取与合并参数根据参数初始化Compiler实例加载Plugin(注册所有配置的插件)调用Compiler实例的run方法开始执行编译。Compiler编译对象掌控者webpack生命周期不执行具体的任务只是进行一些调度工作。比如执行模块创建、依赖收集、分块、打包等调用run之后创建Compiltation实例每次构建都会新创建一个Compiltation实例包含了这次构建的基本信息Webpack 会在特定的时间点广播出特定的事件插件在监听到感兴趣的事件后会执行特定的逻辑。编译:从entry 触发对每个Module 串行调用对应的 Loader对模块进行翻译再找出该模块依赖的模块递归进行编译处理。从配置文件 webpack.config.js 中指定的 entry 入口开始解析文件构建 AST 语法树根据依赖关系图组装成包含多个模块的Chunk将个Chunk转换成文件输出。不同entry生成不同chunk动态导入也会生成自己的chunk3、Webpack中loader的作用/ loader是什么⭐⭐Loader 是webpack中提供了一种处理多种文件格式的机制因为webpack只认识JS和JSON所以Loader相当于翻译官将其他类型资源进行预处理。用于对模块的源代码进行转换。loader支持链式调用原型调用的顺序是从右往左。原型链中的每个loader会处理之前已处理过的资源最终变为js代码。可以通过 loader 的预处理函数为 JavaScript 生态系统提供更多能力。4、常见的loader有哪些⭐⭐less-loader: 将less文件编译成css文件开发中我们常常会使用less预处理器编写css样式使开发效率提高css-loader: 将css文件变成commonjs模块加载到js中模块内容是样式字符串style-loader: 创建style标签将js中的样式资源插入标签内并将标签添加到head中生效ts-loader: 打包编译Typescript文件5、Plugin有什么作用Plugin是什么⭐⭐Plugin功能更强大主要目的就是解决loader 无法实现的事情比如打包优化和代码压缩等。Plugin加载后在webpack构建的某个时间节点就会触发plugin定义的功能帮助webpack做一些事情。实现对webpack的功能扩展。6、常见的Plugin有哪些⭐⭐html-webpack-plugin 处理html资源默认会创建一个空的HTML自动引入打包输出的所有资源js/cssmini-css-extract-plugin 打包过后的css在js文件里该插件可以把css单独抽出来clean-webpack-plugin 每次打包时候CleanWebpackPlugin 插件就会自动把上一次打的包删除7、Webpack中Loader和Plugin的区别**⭐⭐**webpack 就像一条生产线,要经过一系列处理流程(loader)后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。8、如何利用webpack来优化前端性能⭐⭐代码压缩按需加载代码分割 splitChunks - 在optimization配置项中配置1.可以将node__mudules中代码单独打包成一个chunk输出比如使用了jqury2.会自动分析多入口chunk中有没有公共的文件如果有会打包成单独的一个chunk不会重复打包使用Dll进行分包正常情况下node_module会被打包成一个文件使用dll技术对可以将那些不常更新的框架和库进行单独打包生成一个chunk使用路由懒加载在代码中所有被 import()函数引用的模块都将打成一个单独的包放在 chunk 存储的目录下。在浏览器运行到这一行代码时就会自动请求这个资源实现异步加载。9、Webpack如何配置压缩代码压缩了什么⭐⭐在optimization配置项中来配置该插件作为压缩器进行压缩。在plugins里使用该插件进行压缩js压缩:利用terser-webpack-plugincss压缩:利用了optimize-css-assets-webpack-plugin 插件删除了console、注释、空格、换行、没有使用的css代码等10、如何提高webpack的构建速度⭐⭐思路1减少需要构建的文件或代码HMR(Hot Module Replacement) 模块热替换只重新构建发生变化的模块 – 开发环境中缩小处理范围:合理利用这两个属性exclude不需要处理的文件 和 include需要处理的文件babel缓存 第二次构建时会读取之前的缓存只重新构建变化的文件使用Dll进行分包 -- 分包方便按需加载正常情况下node_module会被打包成一个文件使用dll技术对可以将那些不常更新的框架和库进行单独打包生成一个chunk项目源代码也需要拆分可以根据路由来划分打包文件 -- 怎么实现路由懒加载webpack中如何实现组件异步加载思路2多进行进行构建多进程打包 thread-loader,将其放在费时的loader之前进程启动和进程通信都有开销工作时间比较长才需要多进程打包九、Git/SVN篇1、Git是什么⭐⭐Git是目前世界上最先进的分布式版本控制系统旨在快速高效地处理从小型到大型项目的所有事务特性易于学习占用内存小具有闪电般快速的性能使用Git和Gitlab搭建版本控制环境是现在互联网公司最流行的版本控制方式2、简述Git中如何将一个新增文件添加到本地仓库⭐⭐git config --global user.name 开发人员名称 git add 文件名称/* //将当前文件或当前文件夹下未添加到栈存区的文件添加栈存区 git commit 文件名称/* -m 完善的注释 //将栈存区当前文件或当前文件夹下的全部文件添加到版本本地仓库 git log //查看文件版本号3、Git常用命令**⭐⭐⭐**文字整理(可直接复制使用)1、git config - - 可以配置git的参数可以使用 git config --list查看已经配置的git参数。其中有三个级别的保存位置–system本系统–global当前用户全局–local本地配置当前目录默认使用–local配置用户名及邮箱git config --global user.name “****”git config --global user.email 1********qq.com2、git init - - 初始化代码仓库3、git clone - - 克隆远程仓库PS:如果希望在克隆的时候自己定义要新建的项目目录名称可以在上面的命令末尾指定新的名字$ git clone git://github.com/schacon/grit.git mygrit4、git add - - 把需要提交的所有修改放到暂存区Stagegit add file – 提交指定文件git add . || git add -A – 提交所有文件git add *.js – 提交所有.js格式文件git add -f file – 强制添加5、git diff - - 查看当前目录的所有修改(#当暂存区中没有文件时git diff比较的是工作区中的文件与上次提交到版本库中的文件。#当暂存区中有文件时git diff则比较的是当前工作区中的文件与暂存区中的文)git diff HEAD - - file – 比较工作区中的文件与版本库中文件的差异。HEAD指向的是版本库中的当前版本而file指的是当前工作区中的文件。6、git commit -m “message” - - 提交代码7、git rm - - 会把文件从当前目录删除不会保存删除的文件。如果需要从Git仓库中删除但保留在当前工作目录中亦即从跟踪清单中删除可以使用git rm -r --cached readme.mdPS:如果一个文件已经被提交到版本库那么你永远不用担心误删但是要小心你只能恢复文件到最新版本你会丢失最近一次提交后你修改的内容。8、git log - - 查看历史记录git log命令显示从最近到最远的提交日志git log --graph – 查看分支合并图9、git reflog - - 用来记录你的每一次命令10、git remote - - 查看当前的远程库11、git remote -v - - 可以显示对应的克隆地址对于多个远程仓库很有用12、git remote add [short_name][url] - - 可以添加新的远程仓库13、git remote add origin address - - 关联一个远程库14、git fetch [remote-name] - - 可以从远程仓库抓取数据到本地。【git fetch origin release/sprint-70】15、git pull - - 更新数据16、git push [remote_name] [branch_name] - - 推送数据到远程仓库 默认使用origin和master17、git push -u origin master [-f] - - 第一次将本地库的所有内容推送到远程库上18、git remote show origin - - 查看远程仓库信息19、git remote rename [old_name][new_name] - - 远程仓库重命名20、git remote rm [remote_name] - - 删除远程仓库21、git branch -d name - - 删除本地分支22、git tag - - 显示当前库中的标签23、git branch - - 可显示当前所有分支。可以使用–merged和–no-merged查看已经合并、未合并的分支。24、git branch branch_name - - 创建新分支25、git branch -r - - 查看远程仓库分支26、git checkout branch_name - - 切换到指定的分支27、git checkout -b branch_name - - 创建新分支并切换到该分支28、git merge 合并分支举例将hotfix分支合并到master上需要git checkout mastergit merge hotfix合并之后可以使用git branch -d hotfix删除分支。如果合并时存在冲突需要手工修改合并分支时加上—no-ff参数就可以用普通模式合并合并后的历史有分支能看出来曾经做过合并而fast forward合并就看不出来曾经做过合并。29、git checkout . --恢复上次提交状态git checkout --file - - 文件在工作区的修改全部撤销一种是file修改后还没有被放到暂存区现在撤销修改就回到和版本库一模一样的状态一种是file已经添加到暂存区后又作了修改现在撤销修改就回到添加到暂存区后的状态。30、git status – 用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了, 哪些没有, 哪些文件没有被Git tracked到。git status不显示已经commit到项目历史中去的信息。31、git reset --hard HEAD^ - - #版本回退git reset --hard commitId - - 取消回退commitId为你想要回到的未来版本号PS:Git必须知道当前版本是哪个版本在Git中用HEAD表示当前版本上一个版本就是HEAD上上一个版本就是HEAD^当回退版本较早时可以写成HEAD~100。32、git stash - - 储藏可以获取你工作目录的中间状态——也就是你修改过的被追踪的文件和暂存的变更——并将它保存到一个未完结变更的堆栈中随时可以重新应用。现在你想切换分支但是你还不想提交你正在进行中的工作所以你储藏这些变更。为了往堆栈推送一个新的储藏只要运行git stash。把所有未提交的修改包括暂存的和非暂存的都保存起来用于后续恢复当前工作目录。PS:需要说明一点stash是本地的不会通过git push命令上传到git server上。33、git stash list - - 查看现有的所有储藏此命令显然暗示了git stash可以多次保存工作进度并用在恢复时候选择。34、git stash pop [–index] [ stash ] - - 重新应用已经实施的储藏删除储藏如果不使用任何参数会恢复最新保存的工作进度并将恢复的工作进度从存储的工作进度列表中清除。如果提供 stash参数来自git stash list显示的列表则从该 stash中恢复。恢复完毕也将从进度列表中删除 stash。选项–index除了恢复工作区的文件外还尝试恢复暂存区。35、git stash drop [ stash ] - - 删除一个存储的进度。默认删除最新的进度36、git stash clear - - 清空当前所有的stash37、git stash branch branchname stash - - 基于储藏进度创建分支。4、Git和SVN有什么区别?⭐⭐git是分布式版本控制svn是集中式版本控制核心区别git相对于svn的优势就是不需要网络即可版本控制git把内容按数据方式存储而svn是按文件git可以是公用的可以分享svn基本是公司内部才能访问网外不方便访问git不依赖中央服务器即使服务器有问题也不受影响svn依赖服务器一旦服务器有问题就会受影响git没有一个全局的版本号svn有十、B站开源视频大汇总前端从入门到精通分享一些开源优秀的视频HTML5CSS3JSVue2Vue3React微信小程序uniappElectronJQueryAjaxHarmonyOSwebpackecharts底层原理等等欢迎大家一起学习进步学无止境哦~1、web 入门HTML5CSS3Html5css前端Web开发HTML5CSS3移动web视频教程前端web入门首选黑马程序员_哔哩哔哩_bilibiliweb 进阶黑马程序员web前端进阶教程前端html5css3移动端项目实战含华为新闻b站移动端等_哔哩哔哩_bilibili2、jsJavaScriptjQueryAjaxJavaScript黑马程序员前端JavaScript入门到精通全套视频教程javascript核心进阶ES6语法、API、js高级等基础知识和实战教程_哔哩哔哩_bilibiliDOM BOM黑马程序员JavaScript核心教程前端基础教程JS的DOM BOM操作教程_哔哩哔哩_bilibilijQuery黑马程序员前端基础教程|jQuery网页开发案例精讲_哔哩哔哩_bilibiliAjax黑马程序员前端AJAX入门到实战全套教程包含学前端框架必会的ajaxnode.jswebpackgit一套全覆盖_哔哩哔哩_bilibili3、Vue 开发Vue2Vue3实战项目Node.js: 黑马程序员Node.js全套入门教程nodejs新教程含es6模块化npmexpresswebpackpromise等_Nodejs实战案例详解_哔哩哔哩_bilibiliVUE项目实战:https://www.bilibili.com/video/BV1Vf4y1T7bw/Vue2Vue3前端最新Vue2Vue3基础入门到实战项目全套教程自学前端vue就选黑马程序员一套全通关_哔哩哔哩_bilibiliVue3小兔鲜电商项目黑马程序员前端Vue3小兔鲜电商项目实战vue3全家桶从入门到实战电商项目一套通关_哔哩哔哩_bilibili4、React 微信小程序开发uniapp微信小程序https://www.bilibili.com/video/BV1834y1676Puni-app : 实战https://www.bilibili.com/video/BV1BJ411W7pXReacthttps://www.bilibili.com/video/BV1wy4y1D7JT/TypeScript黑马程序员前端TypeScript教程TypeScript零基础入门到实战全套教程_哔哩哔哩_bilibili5、华为鸿蒙进阶HarmonyOS华为开发者学堂B站鸿蒙2.0黑马程序员鸿蒙开发系统教程HarmonyOS 2.0鸿蒙应用开发实战教程_哔哩哔哩_bilibili6、ssrNuxtNext.jsNuxthttps://www.bilibili.com/video/BV13Z4y1T74J/Next.js入门教程https://www.bilibili.com/video/BV13441117KK7、工程化webpackvitewebpack5尚硅谷Webpack5入门到原理面试开发一条龙_哔哩哔哩_bilibiliwebpack高级https://www.bilibili.com/video/BV1cv411C74Fwebpack面试 面试官问webpack怎么做性能优化该怎么回答_哔哩哔哩_bilibilivite:https://www.bilibili.com/video/BV1BS4y1P7mU/Prettier和ESLint使用https://www.bilibili.com/video/BV183411r7YKESLint基础入门https://space.bilibili.com/390120104/search/video?keywordESLint8、可视化echarts 数据可视化项目echarts vue3 千锋EchartsVue3.0数据可视化项目构建_入门必备前端项目实战教程_哔哩哔哩_bilibili前端可视化大屏: https://www.bilibili.com/video/BV1v7411R7mp/9、源码虚拟DOM和diff算法Vue源码解析之虚拟DOM和diff算法: https://www.bilibili.com/video/BV1v5411H7gZ/Vue源码解析之mustache模板引擎 :https://www.bilibili.com/video/BV1EV411h79m/React18源码级剖析https://www.bilibili.com/video/BV1qS4y1m7GY10、移动App跨端开发Uni-AppReactNatvie基础https://www.bilibili.com/video/BV1e5411L7VV/Uni-App从入门到实战https://www.bilibili.com/video/BV1BJ411W7pX/Flutterhttps://www.bilibili.com/video/BV1S4411E7LY/鸿蒙项目实操 千锋教育_从零编写一个HarmonyOS App_开发鸿蒙项目实操_哔哩哔哩_bilibili11、桌面应用开发ElectronElectronhttps://www.bilibili.com/video/BV1FP4115739/12、网络知识网络概述结构算法计算机网络概述https://www.bilibili.com/video/BV1LK4y1b7cj/数据结构预算法https://www.bilibili.com/video/BV1Cz411B7qd/10分钟带你了解互联网是如何运作的:https://www.bilibili.com/video/BV1Rz4y197Jd/13、浏览器底层原理浏览器是如何运作的: https://www.bilibili.com/video/BV1x54y1B7RE/JS运行原理: https://www.bilibili.com/video/BV1vh411Z7QG/V8: https://www.bilibili.com/video/BV1zV411z7RX/文章来源于网上如有侵权请联系博主删除题外话学习资源网上虽然也有很多的学习资源但基本上都残缺不全的这是我们和网安大厂360共同研发的的网安视频教程内容涵盖了入门必备的操作系统、计算机网络和编程语言等初级知识而且包含了中级的各种渗透技术并且还有后期的CTF对抗、区块链安全等高阶技术。总共200多节视频100多本网安电子书最新学习路线图和工具安装包都有不用担心学不全。这些东西我都可以免费分享给大家需要的可以点这里自取:网安入门到进阶资源