# 面试题总结 **Repository Path**: TXM0117/summary-of-interview-questions ## Basic Information - **Project Name**: 面试题总结 - **Description**: 面试题面试题面试题面试题面试题面试题 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2023-03-29 - **Last Updated**: 2024-06-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # HTML+CSS部分 ### H5的新特性有哪些 | 增加了一些新的有语义标签 | header,nav,footer,aside,article,section | | ------------------------------ | ---------------------------------------------- | | **新增一些API** | localStorage和sessionStorage、画布api、地理api | | **input 支持了几个新的类型值** | date, email, url 等等 | | **新增了音频、视频** | 新增了webworker和 websocket | ### css3新增的特性 > 伪元素 弹性布局flex 媒体查询 > > 圆角 平面转换 渐变 、阴影 > > 3D转换 动画 ### 如何让盒子/图片水平垂直居中? > 要使一个盒子水平和垂直居中,最简单的方法是使用 CSS 的 flex 布局。 **方法1:** 首先让父元素使用 display: flex 并设置 align-items: center 和 justify-content: center,然后,将子元素设置为盒子即可。 如果你希望盒子在垂直方向上居中,但在水平方向上靠左或靠右,则可以使用 justify-content: flex-start 或 justifycontent: flex-end。 **方法2:** 如果你想使用其他布局方式来实现居中,也可以使用 position: absolute 和 transform: translate(-50%, -50%)。 ### CSS盒模型 box-sizing属性控制盒模型,默认宽高指内容,设定border=box则包括内边距盒边框。 ### 块级元素和行内元素 块级元素 > 块级元素在文档流中占据一整行。 > > 块级元素可以设置宽度和高度。 > > 块级元素可以设置内外边距和边框。 常见的块级元素包括:div,h1,p,form,header,footer,section等。 行内元素 > 行内元素在文档流中只占据所需的空间。 > > 行内元素不能设置宽度和高度。 > > 行内元素只能设置内边距。 常见的行内元素包括:a,span,button,input,label,select等。 ### H5事件 > onblur失焦事件 onfocus聚焦事件 onchange改变事件 > > onclick点击事件 onerror错误事件 oninput输入事件 > > onkeydown键盘按下事件 onkeyup键盘抬起事件 > > onmousemove鼠标移动事件 onmouseover鼠标进入事件 onmouseout鼠标移出事件等 > ### 回流和重绘 > **回流**和**重绘**是浏览器渲染页面时的两个关键概念。 **回流**:当页面布局结构发生变化;元素的大小、位置或布局发生改变时。 **使用场景**:比如改变节点大小、位置,改变文本内容,修改样式等,就会触发回流操作。 **重绘**:元素的外观进行更新的过程;当页面元素中的元素的颜色、字体改变,不会对布局产生整体的影响。 **使用场景**:当页面的绘制属性发生变化时,比如修改颜色、字体、文本内容等,就会触发重绘操作。 **回流一定会引起重绘,但重绘不一定会引起回流。** ### rem和em rem和em都是字体大小的单位,计算方式不同。 **rem:**根据根元素html的字体大小来计算其他元素的字体大小。 **rem的使用场景:**主要是针对响应式布局,可以通过设置html的字体大小来适应不同尺寸的设备屏幕,使页面元素的大小和布局随着屏幕大小的变化而自适应。 **em:**相对于父元素的字体大小来计算子元素的字体大小。 **em的使用场景:**主要是针对一些相对大小较小的元素,例如文本和图标,用em来控制其字体大小或图标大小,保证它们与其他元素的比例相近,并且随着父元素的字体大小变化而自适应。 ### 响应式布局 响应式布局是一种能够自适应不同设备、不同屏幕尺寸和不同浏览器的页面布局。 响应式布局的基本原理: 1. 使用**媒体查询**来判断浏览器窗口的大小; 2. 使用**弹性网格布局**或**弹性盒子布局**来实现页面的灵活和自适应性; 3. 使用**相对单位**(例如 em 和 rem)来实现字体、图片和其他元素的自适应性。 ### 有没有用过视频组件 视频组件的原理是通过调用浏览器提供的HTML5 video标签. **使用场景:** - 网络直播:视频组件可以用于实现网络直播功能,如在线教育、会议直播等。 - 视频广告:视频组件可以用于播放视频广告,增加网站收入。 - 录像回放:视频组件可以用于回放已录制的视频,如体育比赛、演唱会等。 - 视频教程:视频组件可以用于展示各种视频教程,如语言学习、技术培训等。 ### 点击穿透现象及解决办法 点击穿透指的是,用户点击屏幕上的元素时,点击事件会同时触发下方的元素。 阻止点击穿透,可以监听点击事件,并在回调函数中调用方法来阻止默认点击行为。 event.stopPropagetion()和event.pr eventDefault() # JS部分 ### ES6新增(特性)方法 let ,const 关键字;箭头函数;解构赋值;模板字符串,展开运算符。 **数组的 find,findindex,includes,sort** **对象的Object.keys,Object.values,Object.assign** `let 和 const 关键字`:这两个关键字用于声明变量,其中 let 声明的变量可以被修改,而 const 声明的变量是常量, 不能被修改。 `箭头函数`:这是一种简化函数的语法,它比传统的函数定义更短、更简洁。 `解构赋值`:引入了解构赋值语法,可以轻松地从对象或数组中获取值,并将它们赋值给变量。 `模板字符串`:引入了模板字符串,可以在字符串中使用变量和表达式,语法简单且易于阅读和维护。 `Promise`:引入了 Promise 对象,可以更方便地处理异步操作。 `扩展运算符`:如...array ### ES6中var let const的区别 1.变量提升区别:`var`声明的变量存在变量提升,而`let`和`const`是不存在的。 2.作用域:`var`声明的变量只有全局作用域和函数作用域,没有块级作用域;而`let`和`const`声明的变量具有块级作用域。 3.重复声明:使用 `var` 声明的变量可以重复声明,在同一个作用域内声明多次是没有问题的,而使用 `let` 和 `const` 声明的变量不能重复声明,否则会抛出错误。 4.赋值和修改:使用 `var` 和 `let` 声明的变量可以随意赋值和修改,而使用 `const` 声明的变量必须在声明时就赋值,并且会成为常量不能再修改。 ### JavaScript有哪些数据类型 JavaScript共有八种数据类型 这些数据也可以再细分为**原始数据类型**和**引用数据类型** 栈:原始数据类型(Undefined、Null、Boolean、Number、String、Symbol 、BigInt) 堆:引用数据类型(对象、数组和函数) 分别是 **Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。** 其中 Symbol 和 BigInt 是ES6 中新增的数据类型: - Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。 - BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。 ### JS的数据类型,储存上的差距 数据类型分两大类: 1. 基本数据类型,变量保存的是值 2. 引用数据类型,变量保存的是引用地址 ### isNaN 和 Number.isNaN 区别 > 重点在于判断 是不是NaN,而不是 **数字** 首先说一下isNaN: 函数isNaN接收参数后,会把这个参数转换为数值,如果不能被转换的话值会返回true,并且**非数字**值传入也会返回true,所有会影响NaN的判断 。 函数 Number.isNaN : 只会判断 传入的数据 是不是 一个 `NaN`,并且不会帮你做类型转换。 ### DOM 事件流与事件委托 **事件流**:⼜称为事件传播,是指事件在DOM树中的传播过程。 事件流分为三大阶段: 捕获阶段(**大到小**) - 目标阶段 - 冒泡阶段(**小到大**) **事件委托**: 利用事件冒泡的机制,将事件绑定到该元素的父级上,通过条件判断,执行事件触发后的语句。 好处: 1. 代码简洁 2. 节省内存 3. 提高页面性能和代码可维护性 ### 作用域和作用域链 > 作用域分为**全局作用域**和**局部作用域** 全局作用域:script标签内部 和 js文件 局部作用域:又分为函数作用域和块级作用域。 作用域链:作用域链的底层原理是**变量查找机制** 它的查找规则规则是:优先查找自己的作用域,查不到的情况会依次逐级查找父级作用域直到全局作用域。 ### JS中的垃圾回收机制 JS中的垃圾回收机制指的是在 JS 中一种**自动回收**或 **释放内存**的机制。 JS中的垃圾回收机制分为两种算法: - **引用计数法** 它的弊端是嵌套引用导致内存泄漏变量将无法释放。 - **标记清除法** 标记清除法的方式:判断变量的可达性。 从全局变量出发来判断变量是否可以被访问到,**可以访问到的话,具有可达性,则内存不能被释放;不能被访问到,不具有可达性,那么内存就要被释放。** ### 闭包 - 闭包是一个函数,它有权去访问另一个函数作用域中的变量。它的构造方式是在函数的内部创建另一个函数。使用闭包有它的优势也有弊端。 - 优势:实现数据的私有,保护数据,防止被意外修改,弊端的话就是容易导致内存泄漏。 ### 什么是 JavaScript 中的包装类型 在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台地将基本类型的值转换为对象,这些对象就是包装类型 ### 编程思想 1. **面向过程**:就是按照我们分析好了的步骤,按照步骤解决问题。 2. **面向对象**:是以对象功能来划分问题,而不是步骤。 3. 面向对象的特性: - Ø封装性 - Ø继承性 - Ø多态性 ### 递归 递归就是函数调用自己 本身 的操作。递归是一种非常有用的编程技巧,可以在处理复杂问题时大大简化代码的编写和理解 递归的使用场景非常广泛,特别是在处理树形结构、图形结构、分治算法等问题时,递归是非常有效的解决方案。 ### 深浅拷贝 **浅拷贝:** 浅拷贝只是复制对象的引用,并不会复制对象本身。 如果对象是基本类型,则复制的是值本身;如果被拷贝到属性也是引用类型,那么这个属性只是做了个引用地址的传递,任意一方的修改都会影响另一方。 使用:扩展运算符 ...来事项浅拷贝 **深拷贝:** 深拷贝是完全复制了对象本身,包括对象内部的所有属性和方法。深拷贝后的对象和原对象没有任何关联,对其中一方的修改并不会影响另一方。 PS:**除了 递归克隆对象、JSON.stringify 两种方式做的拷贝,其他方法全部都是浅拷贝** ### 防抖和节流 **防抖:**指的是在规定的时间内,某个动作只能执行一次;如果在规定的时间内多次触发,那么只有最后一次会生效。 **防抖的使用场景**:频繁触发的事件 (搜索框,窗口) **节流:**指的是在规定连续触发的行为中,控制它在某个时间内只能执行一次。 **节流的使用场景**:频繁触发但某些时候可以延迟执行的事件 (轮播图点击效果 、 鼠标移动、页面尺寸缩放 resize、滚动条滚动) ### call、apply、bind的区别 1. 他们三都可以修改this指向 2. call、apply 在修改this指向的同时也会调用原函数、bind只会返回修改this指向后的新函数 3. call和apply接收参数的方式不一样,call类似普通函数一样接收参数、apply接收的参数必须都放在一个数组内。 ### sessionStorage和localStorage的区别 sessionStorage和localStorage都是用于在浏览器端存储数据的方式。 两者的区别主要分为:存储的周期,存储的大小,使用的方式和安全性 1.存储的周期 sessionStorage 数据在当前浏览器窗口关闭后自动删除 localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据 2.存储的大小 localStorage 的容量 通常比 sessionStorage 大一些 3.使用的方式 sessionStorage 和 localStorage 的使用方法基本相同,都可以使用 setItem() 和 getItem() 方法 来存储和获取数据 4.安全性 由于localStorage的数据可以在不同的浏览器窗口和标签页中共享,所以它可能会存在一些安全风险;而sessionStorage的数据只在当前会话中有效,并且不会被其他窗口或标签页所共享,所以相对来说更加安全。 **sessionStorage的使用场景:** - 在处理一次会话过程中需要共享数据,但不需要保留数据,例如在一个表单提交页面和处理页面中传递数据; - 在为用户保留数据时不需要持久化,例如保存用户在一个网站中的购物车数据; - 避免多个标签页或浏览器窗口中的数据冲突,因为每个标签页和窗口都有单独的sessionStorage对象。 **localStorage的使用场景:** - 在不同的浏览器会话之间保存用户设置或其他数据; - 在多个标签页或浏览器窗口中共享数据,因为每个标签页和窗口都共享同一个localStorage对象; - 记录用户的登录信息或其他长期数据,例如用户偏好设置; - 缓存数据或离线时使用。 ### localstrong和cookie的区别 1. 存储容量:Cookie 的存储容量较小,通常限制在几KB,而 LocalStorage 的存储容量较大,通常限制在几MB。这使得 LocalStorage 更适合存储大量数据,而 Cookie 适合存储较小的数据。 2. 客户端与服务器通信:Cookie 在每次 HTTP 请求中都会被发送到服务器,这使得它可以用于与服务器之间进行数据交互。而 LocalStorage 仅存储在客户端,不会随着请求被发送到服务器。因此,如果需要与服务器进行数据交互,Cookie 是更好的选择。 3. 过期时间:Cookie 可以设置一个过期时间,一旦过期,浏览器会自动删除该 Cookie。而 LocalStorage 没有过期时间,存储的数据会一直存在,直到被手动清除。 ### this指向问题 1.全局作用域中的 this:在全局作用域中,this 指向的是全局对象 window。 2.函数中的this:在函数中,this 的指向取决于函数的调用方式。 - 作为函数调用:this 指向全局对象或 undefined(严格模式下) - 作为对象的方法调用:this 指向调用该方法的对象。 - 作为构造函数调用:this 指向新创建的对象。 - 使用 call() 或 apply() 方法调用:this 指向传入的第一个参数。 3.箭头函数没有自己的 this,它的 this 指向的是定义它的函数的 this ### this指向处理 - 箭头函数 - 用变量储存this - 用 api 改变this指向, call / apply / bind ### new操作符具体过程 使用 new 操作符创建一个新对象的过程如下: 1.创建一个新对象。 2.将这个新对象的原型设置为构造函数的原型。 3.将这个新对象的 this 指向这个新对象。 4.如果构造函数返回了对象,则返回这个对象;否则,返回这个新对象。 ### 浏览器/JS的事件循环机制 JavaScript是一种单线程的语言,程序运行时,只有一个线程存在,同一时间只能做一件事。事件循环是一种机制,用于在执行主线程的同时处理异步任务。 主线程执行同步任务。 当遇到异步任务时,将其排入队列中。 当主线程空闲时,从队列中取出第一个任务并执行。 当任务完成时,如果有回调函数,则将其排入队列中。 ### js的继承 JavaScript 中的继承是通过原型链来实现的。在 JavaScript 中,每个对象都有一个原型对象,原型对象又有自己的原型对象,这样就形成了一个原型链。当我们访问对象的一个属性或方法时,如果该对象本身没有这个属性或方法,就会去它的原型对象中查找,如果还没有找到,就会继续向上查找,直到找到 Object.prototype 为止。 JavaScript 中的继承可以通过以下方式实现: 1. 原型链继承:子类的原型对象继承父类的实例。这种方式的缺点是如果父类的属性是引用类型,那么子类的所有实例都会共享这个属性,容易造成数据污染。 2. 构造函数继承:在子类的构造函数中调用父类的构造函数,并使用 call 或 apply 方法将父类的属性绑定到子类上。这种方式的缺点是父类的方法无法被子类继承。 3. 组合继承:将原型链继承和构造函数继承结合起来,既可以继承父类的属性和方法,又可以避免共享引用类型属性和无法继承父类的方法。 4. ES6 的 class 继承:使用 class 和 extends 关键字来实现继承。这种方式只是语法糖,本质上还是使用原型链实现的。 5. 寄生式继承:就是给原型式继承外面套个壳子,没用到原型 6. 寄生组合式继承:通过借用函数来继承属性,通过原型链的混成形式来继承方法(常用) ### 构造函数在被实例化的时候内部发生了什么 1. 创建一个空对象,并将该对象的 `__proto__` 属性指向构造函数的原型对象。 2. 执行构造函数的函数体,将 `this` 关键字指向该空对象。 3. 返回该对象 ### forEach和map的区别 forEach 和 map 是 JavaScript 中常用的数组方法,都可以用来遍历数组中的元素。 **forEach和map的区别:** - 返回值:forEach 没有返回值,而 map 返回一个新的数组; - 使用:forEach 通常用于遍历数组,执行一些操作,而 map 则通常用于对数组中的元素进行处理后,生成一个新的数组。 **使用场景:** - forEach方法:forEach 通常用于遍历数组并执行某些操作,例如输出数组内容、修改数组中的元素等。因为它不会返回新的数组,所以它更适合只需要简单循环遍历的情况。 - map方法:map 通常用于改变数组中的元素,生成一个新的数组。例如将数组中的元素转换成大写或小写字母、筛选出数组中的某些值并且修改这些值的属性。因为它会返回新的数组,所以适用于需要转换数组元素的情况。 ### set和map的区别 Set 和 Map 都是 JS 中的两种常用的数据结构,它们都是用于存储数据的容器。 区别: 1. Set 中的值是按照插入顺序排列的,而 Map 中的键值对是无序的。 2. Set 是一组不重复的值的集合,它的值都是唯一的,可以用来去重。而 Map 是一组键值对的集合,它的键和值都可以是任意类型的。 3. Set 的主要用途是去重,而 Map 的主要用途是存储键值对。 4. Set 可以通过 add、delete、has 等方法来添加、删除和判断值是否存在。Map 可以通过 set、delete、get、has 等方法来添加、删除、获取和判断键值对是否存在。 5. Set 没有提供类似于 forEach 这样的遍历方法,而 Map 提供了 forEach 方法来遍历所有的键值对。 ### for of和 for in的区别 `for...of` 和 `for...in` 都是 JavaScript 中用于迭代对象的语句。 `for...of` :循环遍历数组的值。 `for...in` :循环遍历对象的属性名。 1. 区别: - for...of:用于迭代可迭代对象,例如数组、字符串、Set、Map 等。每次循环返回对象的值,而不是索引。 - for...in:用于迭代对象的属性名,例如对象、数组等。每次循环返回属性名,而不是属性值。 1. 使用场景: - for...of:通常用于需要遍历可迭代对象的情况,例如遍历数组元素、字符串、Set、Map 等。它可以直接返回数组、字符串、Set 或 Map 中的值或键值对,并且代码简洁易懂。 - for...in:通常用于需要遍历对象属性的情况,例如检查对象是否具有某些属性、遍历对象的所有属性等。它可以直接返回对象的属性名,并且在遍历对象时可以使用 hasOwnProperty 方法来过滤继承属性。 ### 数组去重(算法) 先转成 es6 里面的 Set 对象,然后展开成为一个数组,利用 Set 不能重复的特性去重,示例如下const newArr = [...new Set(arr)] ### js 怎么判断类型 typeof: 判断基本类型 instance of: 判断复杂数据类型 Object.property.toString.call(数据): 这个方法兼容基本类型和复杂类型 ### 图片懒加载的底层原理 图片懒加载是一种前端优化技术,它可以延迟加载页面上的图片,直到用户滚动到它们的位置,从而减少页面的初始加载时间和数据传输量。 其底层原理是通过监听窗口的滚动事件,然后判断目标图片是否在可视区域内。如果在可视区域内,则将其真实的src属性设置为图片地址,从而触发图片的加载。如果不在可视区域内,则暂时保持其src属性为空或者设置占位符图片。 ### js各种数组的⽅法 1. **push()**: 将一个或多个元素添加到数组的末尾,并返回新的长度。 2. **pop()**: 删除数组的最后一个元素,并返回被删除的元素。 3. **shift()**: 删除数组的第一个元素,并返回被删除的元素。 4. **unshift()**: 将一个或多个元素添加到数组的开头,并返回新的长度。 5. **concat()**: 连接两个或多个数组,并返回一个新的数组。 6. **slice()**: 从数组中截取一部分元素,返回一个新的数组,不会修改原数组。 7. **splice()**: 从数组中删除、替换或插入元素,并返回被删除的元素组成的数组。 8. **join()**: 将数组中的所有元素按指定的分隔符连接成一个字符串。 9. **indexOf()**: 返回指定元素在数组中首次出现的位置索引。 10. **lastIndexOf()**: 返回指定元素在数组中最后一次出现的位置索引。 11. **forEach()**: 遍历数组的每个元素,并对每个元素执行指定的操作。 12. **map()**: 遍历数组的每个元素,并返回一个新数组,新数组的元素是原数组元素经过指定操作后的结果。 13. **filter()**: 遍历数组的每个元素,根据指定的条件筛选元素,返回一个新的数组。 14. **reduce()**: 从数组的第一个元素开始累计,对数组中的每个元素执行指定的累加操作,返回一个累计值。 15. **sort()**: 对数组的元素进行排序,可以指定排序规则。 16. **reverse()**: 颠倒数组中元素的顺序。 ### 字符串的切割 在 JavaScript 中,可以使用字符串的 `split()` 方法来进行切割(拆分)操作。`split()` 方法将一个字符串分割为一个字符串数组,根据指定的分隔符将原字符串分割成多个部分。 ### 双向绑定的原理 双向绑定是一种数据绑定机制,它能够将数据模型(通常是后端数据)与用户界面(通常是前端界面)的状态进行自动同步。当数据模型发生改变时,界面会相应更新;反之,当用户在界面上做出改变时,数据模型也会相应更新。 ### 原⽣⽂件如何上传 在上面的示例中,我们创建了一个表单和一个文件选择的``元素。当用户点击提交按钮时,通过JavaScript的`uploadFile`函数来处理文件上传操作。 在`uploadFile`函数中,首先通过`document.getElementById`获取文件输入元素,然后通过`files`属性来获取用户选择的文件(这里示例只处理单个文件)。然后,创建一个`FormData`对象,将文件添加到其中,使用`append`方法,并给文件一个键名(这里使用`file`)。 接下来,我们使用XMLHttpRequest对象发起一个POST请求,将`FormData`作为请求体发送。注意,这里的URL(`/upload`)需要替换为实际的服务器端处理文件上传的地址。 最后,我们通过`onreadystatechange`事件处理函数来监控请求的状态,当请求`readyState`变为`4`(完成)且`status`为`200`(成功)时,表示文件上传成功。 需要注意的是,通过原生JavaScript进行文件上传涉及到一些底层的处理,包括创建FormData对象、通过XMLHttpRequest发起请求等。为了简化开发,提高效率,也可以使用一些现代的JavaScript库或框架,如Axios、Fetch等,它们提供了更易用的API来处理文件上传等操作。 # AJAX部分 ### 原型和原型链的理解 **原型**也叫原型对象,是构造函数中的一个属性,在构造函数的原型 所添加的成员可以被实例所共享。 原型对象可以包含属性和方法,这些属性和方法可以被对象继承。这种继承机制被称为原型链 在JavaScript中,每个对象都有一个原型对象(prototype),原型对象也是对象,因此也有自己的原型对象,这样便形成了一条原型链(prototype chain)。原型链的顶端是Object.prototype对象,所有的对象都可以通过原型链访问Object.prototype对象的属性和方法。 ### 原型原型链怎么使⽤ 首先我们定义了一个 `Person` 构造函数,通过给 `Person.prototype` 添加方法,该方法可以被 `Person` 的实例对象共享。我们可以通过 `new Person()` 创建一个 `person` 对象,并调用 `person.sayHello()` 方法。 ### promise的理解 Promise是ES6中新增的一种异步编程的解决方案,它是一个对象,表示一个异步操作的最终完成或失败的结果。Promise对象有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。 当一个Promise对象处于pending状态时,可以通过调用resolve()方法将其状态改为fulfilled,或者通过调用reject()方法将其状态改为rejected。当状态改变后,Promise对象就不可再改变。 **Promise的使用场景:**比如网络请求,文件的读写,定时器等 ### Promise有四种常用的方法 1.then()方法用于指定Promise对象状态改变时的回调函数, then() 的第一个参数为成功时的回调 .then() 的第二个参数为失败时的回调 返回值为一个新的 promise因此可以链式调用。 2.catch()方法用于指定发生错误时的回调函数, 它只接受一个参数,即错误的回调函数。catch()方法也会返回一个新的Promise对象,因此可以链式调用。 Promise对象还有一些静态方法,比如all()方法和race()方法。 3.all()方法接受一个Promise对象数组作为参数,当所有Promise对象都为成功状态时,返回一个新的Promise对象;否则返回失败状态的Promise对象。 4.race()方法也接受一个Promise对象数组作为参数,当其中任意一个Promise对象状态改变时,返回一个新的Promise对象。 总之,Promise是一种更加规范和可靠的异步编程方案,它可以避免回调地狱和错误处理困难等问题,提高代码的可读性和可维护性。 ### 实现异步编程的方式有哪些? 回调函数、Promise、async异步函数 回调函数: - 优点:将函数作为参数传入,并在特定的时机被调用,比较简单 - 缺点:多个回调函数嵌套的时候会造成回调函数地狱,耦合度太高,不利于维护 Promise - 优点:可以将嵌套的回调函数作为链式调用,可维护性增强 - 缺点:有时会造成多个 then 的链式调用,可能会造成代码的语义不够明确 async 异步函数 - 优点:将异步逻辑,转化为同步的顺序书写,更简洁,**推荐使用** - 缺点:当函数内部执行到一个 await 语句的时候,如果语句返回一个 promise 对象,那么函数将会等待 promise 对象的状态变为 resolve 后再继续向下执行 ### async/await的理解 async/await本质上是基于Promise实现的,它可以更简单、更直观地处理异步操作,避免了回调地狱的问题。 async 和 await 用了同步的方式去做异步操作。它使用async用于声明一个函数是异步函数,而await用于等待Promise对象的完成并返回结果。 **使用场景:** 1. 网络请求:使用async/await处理网络请求可以使代码更易读,易于排查,避免了回调地狱的问题。 2. 文件读写:使用async/await可以更加清晰地处理文件读写的异步操作。 3. 定时器:使用async/await处理定时器可以使异步代码看起来更像同步代码,便于理解和维护。 **async/await的优点** 1. 代码结构类似同步代码,更易读、易理解; 2. 代码使用try…catch语句块,更加清晰容易排查异常; 3. 可以使用同步的方式编写异步代码,避免了回调地狱的问题。 **使用async/await的注意事项:** ### async/await与Promise的区别 a. 写法不同:使用async/await可以更直观地表达异步操作的逻辑,代码更加简洁易懂。 b. 错误处理方式不同:使用async/await可以使用try...catch语句捕获异步操作中的异常,而Promise使用catch方法进行错误处理。 c. 返回值不同:使用async/await可以直接返回异步操作的结果,而Promise需要使用.then()方法获取异步操作的结果。 ### 什么是同步异步 在js中同步和异步指的是程序的执行方式。 **同步**:程序按照顺序依次执行,每个操作都必须等上一个操作 执行完毕才能进行下一个操作。如果当前操作需要等待的时间过长的话,会导致程序的堵塞无法执行其他的操作,造成资源浪费和工作效率低。 **异步:**程序不需要安装顺序执行,可以进行异步执行,不需要等待上一个操作完成,可以同时处理多个操作。从而避免了程序的阻塞,提高了程序的效率。 常用的异步操作:定时器,发起网络请求,事件函数等 ### 微任务和宏任务 微任务和宏任务是 JavaScript 中的执行机制,用于处理异步操作。在事件循环中,异步任务可以分为两类:宏任务和微任务。当宏任务执行完毕后,会检查是否有微任务需要执行,并在当前周期内执行完所有的微任务才进入下一个宏任务。 1. 宏任务: 宏任务是指在执行栈中排队等待被执行的任务,例如 setTimeout、setInterval、ajax 等。 宏任务的执行顺序固定,先进先出,各个宏任务之间互不影响。每次事件循环只会从宏任务队列中取出一个宏任务执行。 宏任务的使用场景通常是对于需要耗时较长的、与用户交互无关的操作,例如网络请求、IO 操作、定时器等。 1. 微任务: 微任务是指在当前任务执行结束后立即执行的任务,例如 Promise.then、MutationObserver 等。 与宏任务不同,微任务不需要排队等待,每次事件循环会依次执行所有微任务,直到所有微任务执行完毕才继续执行宏任务。 微任务的使用场景通常是对于需要更新 UI 或需要尽快完成的操作,例如数据更新、状态更改等。 ### 常见的异步方式 1.定时器,setTimeout,setInterval 2.接口调用,axios.get() , axios.post(), axios({}),node中的 readFile(),writeFile() 3.事件函数, dom.addEventLister("click",function(){}) ### 纯函数是什么 ? 纯函数的原理在于它的输出结果只依赖于其输入参数,而不受程序状态、环境变量、时间和随机数等外部因素的影响。 因此,纯函数具有很高的可重用性、可测试性和并发性,可以帮助我们写出更加稳定、健壮、高效的代码。 ### 怎么创建一个文档碎片? 在JS中我们主要是通过document.createDocumentFragment()方法来创建一个文档碎片。 文档碎片有一个很重要的特点:当需要添加多个dom元素时,如果先将这些元素添加到 DocumentFragment(文档碎片)中,再统一将DocumentFragment(文档碎片)添加到页面,会减少页面渲染dom的 次数,效率会明显提升。Vue的底层就充分使用了文档碎片来提升页面渲染性能。 ### 为什么会跨域 ? 跨域指的是在Web浏览器中,一个网页的JavaScript代码试图访问另一个域名下的资源时所出现的问题。本质是浏览器基于同源策略的一种安全手段。 **同源策略:** 同源是指协议、域名和端口号都相同。反之非同源请求,也就是协议、端口、主机其中一项不相同的时候,这时候就会产生跨域 ### 不受同源策略影响的有哪些 1.img> 2.link 3.script ### 跨域怎么处理 ? 1.使用代理服务器:可以在本地搭建一个代理服务器,通过代理服务器转发请求,从而解决跨域问题. 2.使用 CORS:通过在服务器端设置响应头信息,允许指定域名下的页面进行跨域访问。 3.使用 JSONP:通过动态创建Script标签来实现跨域请求,服务器返回一段callback函数调用的JS代码,从而实现数据的传递。 4.使用 WebSocket:WebSocket 是一种基于 TCP 的协议,可以实现双向通信,不存在跨域的限制。 ### 自己有封装过axios吗? 就是封装 个requestjs 有, 创建 request.js 文件引入 axios用 axios.create(创建实例,配置基地址和超时时间配置请求拦截器和响应拦截器,最后默认导出在封装 api 函数的时候就引入这个 request 使用 是的,你可以封装 axios 并使用拦截器来统一处理请求和响应。下面是一个简单的示例: 首先,安装 axios(如果尚未安装): ```ABAP npm install axios ``` 然后,在你的项目中创建一个文件(例如 api.js)来封装 axios: ```js import axios from 'axios'; // 创建一个 axios 实例 const instance = axios.create({ baseURL: 'https://api.example.com', // 设置基本的 API URL timeout: 5000 // 请求超时时间 }); // 请求拦截器 instance.interceptors.request.use( config => { // 在发送请求之前做一些处理,例如添加请求头 config.headers.Authorization = 'Bearer your-token'; return config; }, error => { // 处理请求错误 console.error('请求拦截器发生错误:', error); return Promise.reject(error); } ); // 响应拦截器 instance.interceptors.response.use( response => { // 对响应数据进行处理 return response.data; }, error => { // 处理响应错误 console.error('响应拦截器发生错误:', error); return Promise.reject(error); } ); export default instance; ``` 在上面的示例中,我们首先通过 import 语句引入 axios,然后创建了一个 axios 实例 instance。你可以根据需要设置 baseURL 和 timeout。 接下来,我们使用 instance.interceptors.request.use 方法来添加请求拦截器。这个拦截器会在每个请求发送之前触发。你可以在这里对请求进行处理,例如添加请求头信息。 然后,我们使用 instance.interceptors.response.use 方法来添加响应拦截器。这个拦截器会在每个请求的响应返回之后触发。你可以在这里对响应进行处理,例如提取响应的数据。 最后,我们通过 export default 导出封装好的 axios 实例,使其可以在其他文件中使用。 这样,你就可以在其他文件中引入 api.js ,使用封装好的 axios 进行 API 请求,并享受拦截器提供的统一处理功能。 ```js import api from './api'; api.get('/users') .then(response => { // 处理响应数据 console.log(response); }) .catch(error => { // 处理请求错误 console.error(error); }); ``` 这只是一个简单的示例,你可以根据需要进一步扩展和定制拦截器的功能,例如处理错误、添加身份验证等 ### 前端web登录流程 1首先用户输入信息后点击登录按钮,输入的内容则会发送给后端在数据库中进行比对验证。如果验证成功的话,则会返回一个token给前端,并存到本地存储中以便下次校验,失败则会发送一个错误信息。 ### 自己封装过方法? 1.请求拦截器 2.响应拦截器 3.递归转换公司组织架构数据 4.excel 导入导出时数据对接转换 # 工具类(git&webpack) ### git的常用命令 git add 加入暂存区 git commit 提交记录 git push 推送代码 git pull 拉取代码 git clone 克隆代码 git checkout 签出代码 git checkout -b 签出或创建分支 git merge 合并分支 ### 项目优化打包 减少请求数量,合并 css之类 减小资源大小 压缩图片, 按需加载 之类 优化资源加载 cdn 加载第三方库之类 减少重绘回流,防抖和节流之类 # NodeJS部分 ### Node的三大模块 Node.js是一个基于Chrom e V8引擎的Js运行时环境。 v8 引擎:指的是谷歌浏览器解析和执行js代码的工具 运行时指的是:一个容器,用来运行代码的环境 **node的三大模块:** 核心模块和自定义模块,第三方模块 核心模块指的是node内置的模块 自定义模块是自己封装定义的文件 第三方模块是各路大神封装好的并上传在npm官网的文件 # Vue部分 ### vue的理解 Vue.js是一种流行的JavaScript`渐进式框架 `,用于构建用户交互式Web界面。它采用的了MVVM模式数据驱动视图模式,vue的响应式当模型数据发送变化,视图会自动更新。vue还提供了组件,路由、状态管理等功能。 ### MVVM的理解 MVVM是一种软件架构模式,它将应用程序分成三个主要部分:模型(Model)、视图(View)和视图模型(ViewModel)。 **模型:**是应用程序的数据层,它包含所有业务逻辑和数据访问代码。 **视图:**是应用程序的用户界面,它包含所有用户界面相关的代码和控件。 **视图模型:**相当于是应用程序中的一个桥梁,它将模型和视图连接在一起。数据驱动视图变化的框架。 **优点:**将 UI和业务逻辑分离,易于维护和扩展 **缺点:** 可能会使代码变得复杂。 对于需求变化频繁、用户界面逻辑比较复杂的应用场景,MVVM模式非常适合。比如,高性能界面展示、大数据展示、数据增删改查等。 ### Vue的插槽 vue中的插槽:相当于一个占位符,是用来将父组件中的内容传递到子组件中进行渲染。它允许父组件将任意内容插入到子组件中的指定位置,从而实现更加灵活的组件复用和组合。 插槽又分为两种类型: **具名插槽:**具有名字的插槽;跨域传递多个插槽道子组件中,通过插槽名称进行显示 **匿名插槽:**没有指定名字的插槽; **作用域插槽**:用于将子组件数据回传给父组件插槽内容中,通常用在组件库封装。 使用插槽的优点:可以让组件更加灵活,允许父组件和子组件之间进行更加复杂的数据传递和交互。 **实际应用场景:**在实际应用中,使用插槽可以实现很多有用的功能,比如自定义表格列、自定义弹窗、自定义下拉菜单等等。 ### v-model实现的原理 v-model是Vue.js框架中的一个指令,用于实现表单元素和数据模型之间的双向数据绑定。 v-model 指令的实现原理是基于计算属性和事件绑定。它会将表单元素的 value 属性绑定到一个计算属性上,并且在计算属性的 setter 中触发 input 事件来更新 Vue 实例中的数据。 ### Vue组件中data为什么必须是一个函数 因为多次复用组件时,每个组件实例都应该有自己的状态,如果data不是一个函数返回的新对象,那么所有实例将会共享同一个数据对象,这会导致组件之间的状态相互污染。 ### Vue 数据双向绑定的原理 Vue 数据双向绑定是指,当我们在表单元素中输入数据时,这些数据会自动同步到 Vue 实例中的 data 对象中;反过来,当 data 对象中的属性发生变化时,Vue 会自动更新表单元素的值,这样就实现了数据的双向绑定。 Vue的数据双向绑定是通过劫持属性的 getter 和 setter 方法,利用依赖收集器来自动更新组件视图的机制实现的。当数据发生变化时,自动更新视图;当视图发生变化时,自动更新数据。 ### 单页面应用 单页面应用:使用 JavaScript 操作浏览器的 DOM,通过动态渲染数据来实现页面的更新,使得所有的视图在同一个页面上进行切换,不需要重新加载整个页面。 SPA 的优点包括: 1. 减少需要从服务器端请求的数据量,加快页面的加载速度; 2. 提供更好的用户体验,无需重新载入页面,提供更连贯的交互; 3. 通过前端路由机制实现快速响应,用户感知上让应用程序更快; 4. 通过 MVVM 的通信方式,允许前端和后端分离,使得开发更加灵活。 SPA 的缺点主要包括: 1. 首次页面加载时间相对较长,需要动态加载静态资源; 2. 对搜索引擎的支持相对较弱,对于SEO优化不友好; 3. 网络状况差的情况下,应用程序无法正常运行; 4. 由于所有的资源都在一个HTML文件中,需要特殊的处理,否则代码量可能过大。 **使用场景:**适合于那些数据交互较多的应用,例如社交网络、电子商务网站、在线编辑器等 ### v-for中key的原理 key 的原理是在每个循环项中绑定一个唯一的标识符,这个标识符将会被作为虚拟 DOM 中的一个属性进行存储。当数据发生变化时,Vue.js 会对比新旧节点的 key 值,根据 key 值的变化来判断新旧节点是否相同。如果节点相同,则直接复用旧节点,避免了不必要的更新操作;如果节点不同,则需要执行更新操作,重新渲染页面。 ### 计算属性与watch的区别 **计算属性**:computed是用来计算出来一个值的,会根据依赖进行缓存,依赖不变,计算属性的值不会重新计算 **watch:**watch是通过监听一个或多个数据的变化来触发回调函数执行的,watch可以监听一个数据、一个数组或者一个对象,当监听的数据发生变化时,就会自动执行相应的回调函数。 如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化 1. 计算机属性适用于:当我们要进行数值计算,而且依赖于其他数据, 2. watch适用于: 如果你需要在某个数据变化时做一些事情,来观察这个数据变化 ### nextTick的理解 nextTick 是 Vue.js 中一个用来在下一个事件循环中调用回调函数的方法。这个方法通常用在等待数据或 DOM 元素更新之后执行一些代码。 ### v-model 语法糖 **语法糖**:v-model本质上是 value属性和input事件的一层包装 v-model的作用:提供数据的双向绑定 ①数据发生了改变,页面会自动变 v-bind:value ②页面输入改变 , 数据会自动变化 v-on:input ### v-show和v-if的区别 v-show和v-if是Vue.js中常用的两个指令,用于控制元素的显示和隐藏。 不同:v-if会直接移除添加dom,v-show则只是通过样式隐藏显示 **场景:** 1. v-if:切换不频繁、敏感数据的隐藏(如权限按钮) 2. v-show:切换频繁的场景 ### v-for和v-if为什么不能一起使用 v-for比v-if的优先级更高,会先执行v-for指令,然后再执行v-if指令;每次都要先循环,再判断,消耗很多性能。 对于同一组数据来说,如果我们要先判断再渲染,可以在外层包装一个div,使用v-if做一次判断即可。Vue3 解决了这个问题,将v-if的优先级调整为高于v-for了。 ### Vue组件之间的传递方式 父传子:子组件定义props属性接收 子传父:子组件中使用this.$emit方法 兄弟传值:以父组件为桥梁进行通信,事件总线,vuex。 父传孙:provide和inject方式 ### 兄弟组件的传值 1.在 Vue 中,兄弟组件之间的通信可以通过共同的父组件作为中介来实现。具体来说,可以在父组件中定义一个数据对象,在兄弟组件中通过 `props` 属性将这个数据对象传递给子组件,在子组件中通过 `$emit` 方法触发一个自定义事件,并将需要传递的数据作为参数传递给这个事件,在父组件中监听这个事件,并更新相应的数据对象,从而实现兄弟组件之间的通信。 2.复杂的话可以通过Vuex进行传值 ### vue的生命周期 生命周期:vue从创建到销毁的全过程。 本质:是一堆函数,会在特定时期执行。 Vue的生命周期分为三个阶段 **1.组件创建挂载阶段** - **beforeCreate**:组件创建前 - **created**: 组件已经创建完毕 - **beforeMount**:挂载前 - **mounted**:挂载完毕 **2.组件更新阶段** - **beforeUpdate**: 数据更新前 - **updated:** 数据更新后 **3.组件销毁阶段** - **beforeDestroy**: 组件销毁前调用,(**组件销毁前 取消异步任务 工作!**) - **destroyed**: 组件销毁后调用 ### vue-router的钩子函数 钩子函数有三种 **1.全局守卫** - beforeEach(to, from, next)(全局路由守卫) - afterEach(to, from)(全局后置钩子)在路由跳转后进行一些操作,如页面统计、关闭loading - beforeResolve(全局解析守卫) **2.路由独享守卫** - beforeEnter(to, from, next) 路由独享守卫,可以在路由配置中单独定义,作用和beforeEach一样,但只作用于当前路由 **3.组件内的守卫** - beforeRouteEnter 在渲染该组件的对应路由被验证前调用 - beforeRouteUpdate(to, from, next) 路由更新时调用,可以在不刷新页面的情况下响应路由参数的变化。 - beforeRouteLeave(to, from, next) 导航离开该组件的对应路由时调用,可以在用户离开当前页面时弹出确认框等 ### 拦截器 拦截器是在发送请求或响应数据时,对请求或响应做一些统一的预处理或处理操作的工具。 拦截器中分为两个部分:请求拦截器和响应拦截器 **请求拦截器**:在发送请求之前,对请求做一些处理。我们可以在每个请求体里面注入token等认证信息,或者判断token有没有失效(主动方法)或者对请求进行加密和压缩。 **响应拦截器:**在获取到响应数据之后,对响应数据进行统一的处理。我们可以在响应拦截器中进行token的超时或失效(被动方法),服务器返回的登录状态失效,就跳转到登录页 ### Vuex核心属性: Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 - **state**:(**存数据**)定义需要管理的数据 - **getters**:state派生出来的数据,相当于state的计算属性 - **mutation**:(**改数据**)里面定义的是同步的更新数据方法,每个方法里都有两个参数,一个是state,一个是payload,通过store.commit调用 - **action**:(**异步请求**)里面定义的是异步的方法,每个方法里面有两个参数,一个是store,一个是payload,通过store.dispatch调用,在actions里也可以提交mutation,通过store.commit - **module**:将vuex模块化,可以让每一个模块拥有自己的state、mutation、action、getters,结构清晰,方便管理 ### Vuex?Vuex的使用过程? Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 使用步骤: 1. 安装 Vuex:使用 npm 或 yarn 安装 Vuex。 2. 创建 store:创建一个 store.js 文件,并在文件中定义 store 的状态、getters、mutations 和 actions。 3. 在入口文件中加载 store:在应用的入口文件中引入 store.js 文件,并将 store 实例作为参数传递给 new Vue()。 4. 最后在组件中使用this.$store Vuex包含了以下几个部分: 1. state:存储应用的状态,即定义了应用中需要管理的数据的结构和初始值。 2. mutations:包含了一组方法,用于修改state中的数据。其中每个方法都是一个同步函数,且不允许包含异步操作。 3. actions:包含了一组方法,用于处理异步操作,例如从服务器获取数据。在Action中可以包含任意异步操作,但最终仍需调用mutation方法来更新state状态。 4. getters:用于从store中获取数据,类似于Vue中的计算属性。在Getter中可以对state中的数据进行过滤、排序等操作。 通过Vuex,我们可以将应用的状态集中管理,方便数据的共享和管理。将状态从组件中抽离出来,可以让组件专注于业务逻辑的实现,而不必关心数据的存储和管理。同时,由于状态的修改只能在mutation方法中进行,因此可以保证状态的修改是可追踪的,也避免了多个组件直接修改同一个状态而导致的数据冲突问题。 ### 如何解决跨域问题??? 什么是跨域: 跨域是浏览器基于同源策略的一种安全手段。 代理方法: 不能让本机直接去访问远程地址请求 ### vue路由懒加载 将路由组件抽离出来,打包成单独的 chunk 文件,在需要时进行异步加载。这样可以实现按需加载,减小页面初始化的代码体积,提升网页的加载速度,并且可以避免过多不必要的资源加载,从而提高网页的性能。 **使用场景:** 1. 提升页面加载速度 2. 减小首屏加载体积 3. 优化搜索引擎爬虫 ### Vue路由模式 在 Vue.js 中,路由模式有两种:hash 模式和 history 模式。 1.hash 模式:hash 模式的 URL 中带有 # 符号。 2.history 模式:history 模式的 URL 中没有 # 符号。 ### 路由之间跳转方式 1.声明式导航:使用 `router-link` 组件来创建链接 2.编程式导航:使用 `router` 对象的 `push` 或 `replace` 方法来实现跳转 3.命名路由:为路由定义一个名称,然后可以通过名称来进行跳转 4.重定向:通过路由配置中的 `redirect` 属性来实现重定向 5.back()、go() ### vue-router传参方式有哪些 动态路由传参,是在url上拼接,需要在路由配置时预先配置好参数的名称 通讨this.$route.params 获取url query 查询参数传参,在路径上加上 ?name=tom 的写法 无需预先配置 通过 this.Sroute.querv获取 通过路由参数(params)传参,通过查询参数(query)传参和通过props传参, ### vue-router前置路由守卫 路由跳转之前,会触发的一个函数 叫前置路由守卫 语法: routerbeforeEach((to, from, next) => 0)作用: 通常用来检验token或者权限,防止别人猜到网址直接跳过登录查看页面 3个参数: to:到哪里去 from:从哪里来 next: 放行函数 next0:放行,next(false):不放行 ### keep-alive 使用时跳转页面后返回,原数据还存在吗? 数据还存在,keep-alive 可以缓存页面的数据,在页面回跳的时候不会更新数据 ### 如何封装组件? 步骤: 创建组件vue文件,全局或局部注册组件,最后再以标签的形式使用。 封装组件的好处:可以提升项目开发效率,把页面抽象成多个相对独立的模块,复用性高 。 ### vue的dom更新是异步还是同步的 Vue.js 中的 DOM 更新是异步进行的,通过异步批量更新机制进行优化,以提高性能并减少不必要的计算和重绘。你可以信任 Vue.js 的响应式系统,它会自动处理数据的更新和组件的 DOM 更新。 ### 为什么 token 放在 vuex 1, 用户数据统一存放 2, api 较简单 3, 性能优势 ### token失效处理 第一种方案: 服务器端保存token状态,用户每次操作都会验证,如果超时就报错,前端通过响应拦截器处理 第二种方案:使用refresh token,避免频繁的刷新token,此时服务端只要在token过期的时候反馈给前端,前端使用refresh token申请一个全新的token继续使用即可 ### 页面优化的思路有哪些 ·v-if和v-for不能连用 根据需要选择v-if代替v-show 要保证key值的唯 使用组件懒加载或者图片懒加载 防抖和节流的使用 模块按需导入 使用cdn加载第三方模块 缓存常用信息 精灵图 ### 使用vuex时怎么实现数据的持久化 通常将数据保存到本地存储中,刷新页面后再将vuex中的state 赋值为本地存储中取出的数据,也有插件直接实现这个功能 ### 全局前置守卫的应用,自己举个小例子 路由中的前置守卫可以监听到所有的路由跳转,只有放行后才能真正去加载路由对应的组件渲染出来。 我们可以使用前置守卫来做全局的登录判断,如果在前置守卫中判断没有token或者token失效了则表示没有登录,跳转登录页,否则就是有登录,放行原页面 # Vue3框架 ### vue3和vue2区别 底层实现方面 :vue2的响应式使用的是Object.defineProperty()实现的,Vue3使用的Proxy实现的 - Vue 3.x 引入了 Composition API,这是一种使用函数式编程方式来组织和复用组件逻辑的方式。Composition API 提供了一种更灵活和组合性更强的方式来处理响应式数据。 ### v3的创建响应式数据两个⽅法有什么区别 - `ref` 适用于创建单个简单值的响应式数据,你需要通过 `.value` 访问和修改值。 - `reactive` 适用于创建复杂对象的响应式数据,你可以直接访问和修改对象的属性。 - 在大多数情况下,可以使用 `ref` 来创建响应式数据,只有在需要处理复杂对象时才使用 `reactive`。 - `ref` 的优势在于提供了更直观的语义,更容易理解和使用。 - 当你需要对整个对象进行深层次的响应式追踪时,可以使用 `reactive`。 ### vue3做了哪些更新 1. 更快的渲染:Vue 3 的响应系统经过全面的重写,使用 Proxy 和 Reflect 实现,取代了 Vue 2 中的 Object.defineProperty。 2. 更小的文件体积:Vue 3 的代码体积比 Vue 2 要小得多。 3. Composition API:Vue 3 引入了 Composition API,这是一种新的组合式 API 风格,可以更灵活地组织和复用组件逻辑。 4. 虚拟 DOM 改进:Vue 3 在虚拟 DOM 方面进行了一些改进,包括优化了标记树的渲染和更新算法,提高了性能。 5. TypeScript 支持:Vue 3 对 TypeScript 的支持更加完善。。 6. 更强大的工具链:Vue 3 引入了一些新的开发工具和插件,例如 Vue CLI 5,提供了更好的开发体验和工程化支持。 ### Pinia和vuex的区别,vuex的不足 Pinia 是一个基于 Vue 3 的新一代状态管理库,而 Vuex 则是 Vue 2 中使用的状态管理库。 Pinia没有mutation,他只有state,getters,action【同步、异步】使用它来修改state数据 。 Pinia语法上比vuex更容易理解和使用,灵活。 Pinia没有modules配置,每一个独立的仓库都是definStore生成出来的、 Pinia的state是一个在函数中返回的对象,和vue组件中的data编写方式差不多 vuex的不足 : Pinia和Vuex都是非常好用的数据管理工具,在某些情况下,使用Pinia的web应用程序会比使用Vuex更快,这种性能的提升可以归因于 Pinia的极轻的重量,Pinia体积约1KB。 ### vite和wabpack的区别 ### webpack是什么? Webpack 是一个前端构建工具,可以将多个模块打包成一个或多个静态资源文件,用于在浏览器中运行。Webpack 支持多种模块化方案,并且可以通过各种插件和配置选项进行扩展和定制,使得开发者可以根据自己的需求进行灵活的构建和优化。Webpack 通常用于处理 JavaScript、CSS、图片等静态资源文件,并且可以处理代码中的依赖关系、代码压缩、文件合并、代码分割等任务,从而提高应用程序的性能和可维护性。Webpack 是目前前端构建工具中使用最广泛的一个,被广泛应用于各种前端开发场景中。 ### 服务端渲染和客户端渲染分别是什么? 服务端渲染是指在服务端将页面的 HTML、CSS、JavaScript 等资源渲染成最终的 HTML 后再发送给客户端,客户端只需要展示即可。在服务端渲染中,浏览器只需要请求一次就可以获得完整的 HTML 页面,因此首屏加载速度较快,对 SEO 也更加友好。服务端渲染通常使用 Node.js 等后端技术实现。 客户端渲染是指将页面的 HTML、CSS、JavaScript 等资源发送到客户端后,由客户端的浏览器渲染成最终的 HTML 页面。在客户端渲染中,浏览器需要发送多次请求来获取页面的各个部分,因此首屏加载速度通常较慢。但是客户端渲染可以提供更好的用户体验,例如通过 AJAX 等技术实现无刷新更新页面,提高了页面的动态交互性。 两种渲染方式各有优缺点,需要根据具体的业务场景和性能需求选择合适的渲染方式。 ### ### 请解释Vue.js 3的Composition API是什么?它和Options API有什么不同? ### Vue.js 3中的响应式系统有何改进?请解释Proxy在Vue.js 3中的作用。 ### Vue.js 3中的Teleport组件是用来做什么的?举一个使用Teleport的场景。 ### Vue.js 3中的Suspense组件是什么?它在异步组件加载中的作用是什么? ### 如何在Vue.js 3中使用全局状态管理?它与Vue.js 2中的VueX有何不同? ### Vue.js 3中的Fragments是什么?请解释它的作用和用法。 ### Vue.js 3中的动态组件是如何使用的?请示例说明。 ### 请解释Vue.js 3中的静态提升(Static Inlining)是什么,它如何提高性能? ### Vue.js 3中的自定义指令的语法和用法有何变化? # 小程序部分 ### 小程序扫码进来,一条链接,如何获取其中参数? 在对应的页面中的 onLoad 生命周期方法的形参中,可获取到 url 传入的参数。 ### 小程序的生命周期 ·应用级别: App(中触发 onLaunch: 小程序启启动时 onShow: 小程序前台运行时 onHide: 小程序后台运行时 页面级别: Page()中触发 onLoad: 页面初次加载时触发。可以在onLoad的参数中获取路径参数o onReady: 页面初次渲染完毕,相当于vue的mounted。 onShow: 页面显示/切入前台时触发(跳转、tabBar切换、后台运行o onHide: 页面隐藏/切入后台时触发(跳转、tabBar切换、后台运行) onUnload: 页面卸载销毁时触发。如redirectTo重定向 或 navigateBack后退 到其他页面时 组件级别: Component0中触发 attached 组件进入页面 detached 组件移出页面 ### 小程序的跳转方式 1.wxnavigateTo(:保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面 2.wx.switchTab0:跳转到 TabBar 页面,并关闭其他所有非 tabBar 页面3.wx.navigateBack():关闭当前页面,返回之前的页面 4.wx.redirectTo() 跳转到应用内的某个tabbar页面 ### 小程序的数据绑定和vue有什么区别 直接用大括号插值表达式来绑定,然后如果修改时,一定要用 this.setData() 才会触发渲染 ### ⼩程序的登录和⽀付流程 小程序的登录和支付流程如下: 登录流程: 1. 用户打开小程序,并点击登录按钮。 2. 小程序调用 `wx.login` 接口获取用户的临时登录凭证 `code`。 3. 小程序将 `code` 发送给开发者后台服务器。 4. 开发者后台服务器使用 `code` 调用微信后台接口,验证 `code` 的有效性,并获取用户的唯一标识 `openid` 和会话密钥 `session_key`。 5. 开发者后台服务器将 `openid` 和 `session_key` 返回给小程序前端。 6. 小程序前端将 `openid` 和其他必要用户信息保存在本地,用于后续的用户操作。 支付流程: 1. 用户在小程序中选择商品或服务,并点击支付按钮。 2. 小程序前端调用支付接口,并传递支付相关参数,如商品信息、订单号、支付金额等。 3. 小程序前端将支付参数发送给开发者后台服务器。 4. 开发者后台服务器使用传递的支付参数,调用微信支付接口生成预支付订单,并获取到预支付交易会话标识 `prepay_id`。 5. 开发者后台服务器将 `prepay_id` 返回给小程序前端。 6. 小程序前端调用微信支付接口,传递 `prepay_id` 和其他必要参数进行支付。 7. 微信支付接口进行支付验证和处理,并返回支付结果给小程序前端。 8. 小程序前端根据支付结果进行相应处理,如支付成功后跳转到支付成功页面或显示支付失败提示。 ### ⼩程序有没有做过多端,如果做过怎么实现条件编译的 小程序可以进行多端适配,以满足在不同平台上运行的需求。目前主要有两种方式来实现小程序的多端适配: 1.基于条件编译的多端适配:小程序开发工具提供了条件编译的功能,可以通过在代码中使用特定的条件语句来实现多端适配。在代码中可以使用类似于以下形式的条件语句: ```js #ifdef MP-WEIXIN // 微信小程序端代码 #endif #ifdef MP-ALIPAY // 支付宝小程序端代码 #endif #ifdef MP-TOUTIAO // 头条小程序端代码 #endif // 其他平台的代码 ``` 上述代码中,#ifdef是条件编译指令,根据定义的平台标识符来选择性地编译不同平台的代码。开发者可以根据不同平台的需求,编写对应的代码逻辑,从而实现多端适配。 2.使用框架支持的多端能力:除了条件编译外,小程序框架本身也提供了一些多端适配的能力,开发者可以使用这些能力来实现多端适配。例如,针对不同平台提供不同的组件、API、样式等,或者通过框架提供的条件判断方法来进行不同平台的逻辑处理。此外,还可以在小程序配置文件中配置不同平台的特性和表现。 无论采用哪种方式,多端适配都需要开发者对各个平台的特性和限制有一定的了解,并根据实际需求做出相应的适配。同时,多端适配也需要进行充分的测试和验证,以确保在不同平台上运行的稳定性和一致性。 # uniapp部分 ### uniapp的优缺点? UniApp 是一个基于 Vue.js 的跨平台应用开发框架,可以用于开发同时在多个平台上运行的应用,包括小程序、App、H5 等。下面是 UniApp 的一些优点和缺点: 优点: 1.跨平台开发:UniApp 允许使用相同的代码库构建多个平台上的应用,大大减少了开发人员在不同平台上重复编写代码的工作量,提高了开发效率。 2.一次开发,多端运行:开发者可以通过编写 Vue.js 组件一次性开发多平台应用,减少了学习成本和开发周期,同时还能享受到 Vue.js 的开发乐趣和生态系统。 3.性能优化:UniApp 内部使用了一些性能优化技术,包括基于原生组件渲染、升级 H5 渲染性能等,以提高应用的性能和用户体验。 4.统一的 UI 组件:UniApp 提供了一套统一的 UI 组件,可以在不同平台上保持一致的外观和交互体验,减少了设计和开发的工作量。 5.社区支持和生态系统:UniApp 拥有庞大的开发者社区和活跃的生态系统,有丰富的插件和扩展可供选择,开发者可以在开发过程中获取到丰富的资源和支持。 缺点: 6.平台限制:由于不同平台的差异,UniApp 在跨平台时可能受到一些限制,部分平台特有的功能可能无法完全支持或需要额外的处理。 7.性能和体验妥协:由于要兼顾多个平台,UniApp 可能无法充分发挥每个平台的特性和优化,对于一些对性能和体验要求较高的应用可能不够理想。 8.学习成本和框架限制:如果开发者之前没有接触过 Vue.js 框架,需要花一定的时间学习 Vue.js 的相关知识。另外,UniApp 提供的功能和扩展可能无法完全满足特定项目需求,可能需要额外的自定义开发。 9.社区规模和资源不足:相比于一些主流的跨平台框架,UniApp 的社区规模和资源相对较小,可能在某些方面缺乏特定功能的支持和解决方案。 综上所述,UniApp 是一个方便开发者跨平台应用的框架,具有跨平台开发、一次开发多端运行、性能优化和统一 UI 组件等优点,但也存在平台限制、性能和体验妥协、学习成本和框架限制以及社区规模和资源不足等一些缺点。开发者在选择使用 UniApp 时应根据具体项目需求和限制进行权衡和选择。 ### uniapp常见组件? 1. 视图容器组件: - view:通用视图容器,类似于 HTML 中的 div 元素。 - scroll-view:可滚动的视图容器,适用于展示较长的内容。 - swiper:轮播组件,用于展示图片或其他内容的轮播效果。 1. 基础内容组件: - text:文本内容展示。 - image:展示图片。 - icon:显示图标。 1. 表单组件: - input:输入框。 - textarea:文本域输入框。 - picker:选择器,可用于选择日期、时间、地点等。 - radio:单选框。 - checkbox:复选框。 - switch:开关按钮。 1. 导航组件: - navigator:页面跳转链接。 - tabbar:底部导航栏。 - navbar:顶部导航栏。 1. 列表组件: - list:列表容器。 - cell:列表项容器。 - grid:九宫格布局。 1. 操作反馈组件: - toast:轻提示组件。 - modal:模态框组件,用于展示弹窗内容。 - action-sheet:操作菜单组件。 - loading:加载提示组件。 1. 地图组件: - map:地图组件,用于显示地图和定位信息。 ### uniapp的生命周期? UniApp 的生命周期有三大类:包括 应用生命周期、应用生命周期和组件生命周期 应用生命周期:**小程序规范**(App.vue) onLaunch:当小程序初始化完成时触发,全局只触发一次。 onShow:当小程序启动或从后台进入前台显示时触发。 onHide:当小程序从前台进入后台时触发。 onError:当小程序发生脚本错误或 API 调用失败时触发。 页面生命周期:**小程序规范** onLoad:监听页面加载,页面被创建时触发,只触发一次。 onShow:监听页面显示,页面展示时触发,每次打开页面都会触发。 onReady:监听页面初次渲染完成,页面初次渲染完成时触发。 onHide:监听页面隐藏,页面被隐藏时触发。 onUnload:监听页面卸载,页面被关闭时触发。 onPullDownRefresh:监听用户下拉刷新事件。 13.onReachBottom:监听页面上拉触底事件。 14.onShareAppMessage:监听用户点击右上角转发按钮事件。 15.onPageScroll:监听页面滚动。 16.onTabItemTap:监听 tab 被点击的事件。 组件生命周期:**vue规范** 这些生命周期函数可以在对应的页面或全局配置文件中进行定义和使用。通过生命周期函数,开发者可以在不同的阶段执行相应的操作,实现更精细的控制和交互 ### uini-app打包要进⾏哪些配置 1.选择编译目标平台:根据需要选择目标平台,如小程序、App(Android/iOS)、H5 等。 2.配置应用图标和启动页:根据目标平台的要求,配置应用图标和启动页的设计和尺寸。 3.设置应用名称和版本号:在项目配置文件中设置应用名称和版本号。 4.配置第三方插件和扩展:如果需要使用第三方插件或扩展功能,需要根据文档进行相应的配置和集成。 5.配置打包签名(Android):对于 Android 平台的 App,需要生成并配置签名证书,以便在打包时进行应用签名。 6.配置权限和访问控制:根据需要配置应用的权限和访问控制,以确保应用的安全性和数据保护。 ### uniapp开发app端遇到过哪些兼容性和安全性问题 在开发 App 端时,可能会遇到一些兼容性和安全性问题。以下是一些常见问题: 1.兼容性:由于 Uni-app 是跨平台框架,不同平台之间可能存在一些差异。需要注意处理不同平台的兼容性问题,例如布局、样式、API 的差异等。 2.性能优化:在开发 App 端时,需要关注性能优化,避免页面加载慢、卡顿等问题。可以通过减少请求、合并资源、使用虚拟列表等方式来提升性能。 3.持久化数据安全性:在 App 中,使用本地存储或缓存数据时需要考虑数据的安全性,避免敏感数据泄露或被篡改。可以使用加密算法对敏感数据进行加密存储,并设置访问权限。 4.网络安全性:在进行网络请求时,需要注意网络安全问题,如防止中间人攻击、数据加密传输等。建议使用 HTTPS 协议进行请求,同时使用合适的身份验证和数据加密机制。 5.代码安全性:在开发 App 端时,需要考虑代码的安全性,防止恶意代码注入、数据篡改等安全问题。可以采用代码混淆、加密传输和数据校验等方式来增加代码的安全性。 ### 以下是可能会在uniapp面试中被问到的50个问题和答案: 1. 什么是uniapp? A: uniapp是一款使用Vue.js框架开发跨平台应用的前端框架。 2. uniapp支持哪些平台? A: uniapp支持微信小程序、支付宝小程序、百度小程序、头条小程序、H5、App等多个平台。 3. uniapp的优点是什么? A: uniapp具有多端开发、高效率、简单易用、开发成本低等优点。 4. uniapp的缺点是什么? A: uniapp在一些特定的场景中可能存在一些限制,如不能使用一些原生API等。 5. 如何在uniapp中使用原生API? A: 可以通过uni-app提供的插件机制,或者使用uni-app提供的原生组件来实现。 6. uniapp中的生命周期有哪些? A: uniapp中的生命周期包括onLoad、onReady、onShow、onHide、onUnload、onPullDownRefresh、onReachBottom等。 7. uniapp中的路由如何使用? A: uniapp中的路由可以使用uni-app提供的vue-router插件来实现,具体使用方法与Vue.js中的路由类似。 8. uniapp中如何使用组件? A: uniapp中可以通过引入组件文件或组件库来使用组件,具体使用方法与Vue.js中的组件类似。 9. uniapp中的vuex如何使用? A: uniapp中可以通过引入vuex插件来使用vuex,具体使用方法与Vue.js中的vuex类似。 10. uniapp中如何进行数据绑定? A: uniapp中可以通过Vue.js的数据绑定语法来实现数据绑定,如v-bind、v-model等。 11. uniapp中如何进行条件渲染? A: uniapp中可以通过Vue.js的条件渲染语法来实现条件渲染,如v-if、v-else等。 12. uniapp中如何进行列表渲染? A: uniapp中可以通过Vue.js的列表渲染语法来实现列表渲染,如v-for等。 13. uniapp中如何进行事件绑定? A: uniapp中可以通过Vue.js的事件绑定语法来实现事件绑定,如v-on等。 14. uniapp中如何进行样式绑定? A: uniapp中可以通过Vue.js的样式绑定语法来实现样式绑定,如v-bind:class、v-bind:style等。 15. uniapp中如何进行动态组件渲染? A: uniapp中可以通过Vue.js的动态组件渲染语法来实现动态组件渲染,如component等。 16. uniapp中如何进行数据请求? A: uniapp中可以使用uni.request或uni.requestPomise方法来进行数据请求。 17. uniapp中如何进行文件上传? A: uniapp中可以使用uni.uploadFile或uni.uploadFilePromise方法来进行文件上传。 18. uniapp中如何进行文件下载? A: uniapp中可以使用uni.downloadFile或uni.downloadFilePromise方法来进行文件下载。 19. uniapp中如何进行图片预览? A: uniapp中可以使用uni.previewImage方法来进行图片预览。 20. uniapp中如何进行地图定位? A: uniapp中可以使用uni.getLocation方法来进行地图定位。 21. uniapp中如何进行二维码扫描? A: uniapp中可以使用uni.scanCode方法来进行二维码扫描。 22. uniapp中如何进行音视频播放? A: uniapp中可以使用uni.createVideoContext或uni.createAudioContext方法来进行音视频播放。 23. uniapp中如何进行本地存储? A: uniapp中可以使用uni.setStorageSync或uni.getStorageSync方法来进行本地存储。 24. uniapp中如何进行网络状态监测? A: uniapp中可以使用uni.getNetworkType或uni.onNetworkStatusChange方法来进行网络状态监测。 25. uniapp中如何进行分享功能? A: uniapp中可以使用uni.share方法来进行分享功能。 26. uniapp中如何进行微信支付? A: uniapp中可以使用uni.requestPayment方法来进行微信支付。 27. uniapp中如何进行支付宝支付? A: uniapp中可以使用my.tradePay方法来进行支付宝支付。 28. uniapp中如何进行百度地图API调用? A: uniapp中可以使用swan.request方法来进行百度地图API调用。 29. uniapp中如何进行头条API调用? A: uniapp中可以使用tt.request方法来进行头条API调用。 30. uniapp中如何进行原生组件调用? A: uniapp中可以使用uni.createSelectorQuery或uni.createIntersectionObserver方法来进行原生组件调用。 31. uniapp中如何进行微信登录? A: uniapp中可以使用uni.login方法来进行微信登录。 32. uniapp中如何进行微信授权? A: uniapp中可以使用uni.authorize方法来进行微信授权。 33. uniapp中如何进行微信分享 # 网络部分 ### 对http的了解 HTTP是一种基于请求/响应模型的、无状态的协议,用于在网络中传输超文本文档。 HTTP通常用于在万维网上传输超文本文档(HTML),但是它也可以用于传输其他类型的文档,例如XML和JSON。 HTTP协议使用端口号80和443。端口号80是HTTP协议的默认端口,端口号443是HTTPS协议的默认端口。 HTTP协议包括五个方法,分别是GET、POST、PUT、DELETE和HEAD。每个方法都有其特定用途。 HTTP协议使用状态码表示请求的结果。常见的状态码包括200 OK(请求成功)、301 (永久性 重定向)、401没登录、403权限不足、404 Not Found(未找到)和500(服务器内部错误)。 ### http握手总共有几次 分别是什么 三次握手四次挥手。 HTTP是一种应用层协议,用于在计算机之间传输数据。它使用 TCP 协议来保证数据的可靠传输。 HTTP的三次握手是指在建立TCP连接时,客户端和服务器之间需要进行三次握手确认,以确保数据能够安全可靠地传输。它的过程就像打招呼一样:客户端先向服务器打招呼,服务器回应客户端的招呼,然后客户端再向服务器回应一声。这样,客户端和服务器之间就建立了连接,数据的传输就可以开始了。 HTTP的四次挥手是指在断开TCP连接时,客户端和服务器之间需要进行四次挥手确认,以确保数据能够完整地传输。它的过程就像结束聊天一样:客户端先向服务器说“我要结束了”,服务器回应“好的,我知道了”,然后服务器再向客户端说“我也要结束了”,客户端回应“好的,我知道了”。这样,客户端和服务器之间的连接就断开了,数据的传输也结束了。 ### http连接握手过程 目的是保证数据可靠传输 在传输信息之前,客户端和服务器会发送一些控制报文来确认对方的状态 1,客户端 => 服务器(服务器确认客户端可发送) 2.客户端 <= 服务器(客户端确认服务器可接收可发送) 3.客户端 => 服务器(服务器确认客户端可接收) ### 断开链接的挥手过程 四次挥手是两台计算机终止网络连接 1.客户端发送断开请求 2.服务器发送确认消息,表明收到请求3.服务器发送断开请求 4.客户端发送确认消息,表明收到请求 ### HTTP和HTTPS区别 HTTP和HTTPS都是应用层协议,用于在计算机之间传输数据的协议、 它们两个之间的区别主要分为:安全性,连接的方式,端口号和证书 1.安全性:HTTPS 在传输过程中使用了加密技术,而 HTTP 没有。这意味着,使用 HTTPS 可以保护数据不被窃取或 篡改 2.连接的方式:HTTP使用TCP连接,一次请求对应一次连接;HTTPS在传输数据之前需要进行SSL握手,建立安全连接,需要多次请求和响应,因此速度比HTTP慢。 3.端口号:HTTP默认使用80端口,HTTPS默认使用443端口。 4.证书:HTTPS需要 需要在服务器端安装 SSL 证书,安装证书是需要一定的费用,而HTTP不需要证书。 ### 一个页面从输入 URL 到页面加载显示完成的过程 当用户在浏览器中输入 URL 并按下回车时,浏览器会向服务器发送 HTTP 请求,请求指定的资源。服务器收到请求 后,会根据请求的 URL 返回对应的资源,这通常是一个 HTML 文件。浏览器收到服务器返回的 HTML 文件后,会开始 解析 HTML 代码,并在浏览器中构建 DOM (Document Object Model) 树。 在解析过程中,浏览器会根据 HTML 中的标签引用的外部资源(如 CSS、JavaScript 文件)发送请求,加载这些资 源。浏览器会等待所有这些资源都加载完成,然后再渲染页面。 在渲染过程中,浏览器会使用构建的 DOM 树和加载的 CSS 文件来计算每个元素的布局,并将这些元素绘制到浏览器窗 口中。如果 HTML 中还包含 JavaScript 代码,浏览器会执行这些代码,可能会修改 DOM 结构或者添加新的内容。 当所有的 HTML 代码解析完成,所有的资源加载完成,所有的 JavaScript 代码执行完成后,页面就会显示完成。 ### 常见的 HTTP 状态码 HTTP状态码是指在客户端向服务器发送请求时,服务器会返回一个三位数的状态码,用来表示请求的处理结果。常见的HTTP状态码包括: 1xx:信息提示,表示请求已被接收,继续处理。 2xx:成功处理,表示请求已被成功处理。 - 200 OK:请求成功,服务器已经成功返回相应的数据。 - 201 Created:请求成功,服务器已经成功创建了新的资源。 - 204 No Content:请求成功,但是服务器没有返回任何数据。 3xx:重定向,表示需要进一步的操作以完成请求。 - 301 Moved Permanently:请求的资源已经被永久移动到新的位置。 - 302 Found:请求的资源已经被临时移动到新的位置。 - 304 Not Modified:客户端缓存的资源没有被修改,可以直接使用。 4xx:客户端错误,表示请求包含语法错误或者请求无法被服务器所理解。 - 400 Bad Request:请求的语法错误,服务器无法解析。 - 401 Unauthorized:请求需要身份验证,但是客户端没有提供身份验证信息。 - 403 Forbidden:请求被服务器拒绝,客户端没有访问权限。 - 404 Not Found:请求的资源在服务器上不存在。 5xx:服务器错误,表示服务器在处理请求时发生了错误。 - 500 Internal Server Error:服务器内部错误,无法完成请求。 - 502 Bad Gateway:服务器作为网关或者代理时,从上游服务器接收到无效的响应。 - 503 Service Unavailable:服务器当前无法处理请求,通常是由于过载或者正在维护。 ### 页面优化 1. 减少 HTTP 请求:通过合并或压缩 CSS、JavaScript 文件、图片等资源,减少 HTTP 请求次数,从而提高页面加载速度。 2. 使用缓存:通过浏览器缓存、CDN 缓存等方式,减少重复请求和资源的下载次数,从而提高页面加载速度。 3. 延迟加载:通过懒加载等技术,延迟加载页面中部分内容,从而减少首屏加载时间,提高用户体验。 4. 优化图片:通过压缩、裁剪、选择合适的图片格式等方式,减小图片文件大小,从而提高页面加载速度。 5. 压缩代码:通过压缩 CSS、JavaScript 等代码,减小文件大小,从而提高页面加载速度。 6. 前端性能监控:通过使用前端性能监控工具,了解页面性能瓶颈,并及时进行优化。 7. 使用合适的框架和库:使用合适的框架和库可以减少代码量,提高开发效率,从而提高页面性能和用户体验。 8. v-if和v-for不能连用 更多的情况下,使用v-if代替v-show 要保证key值的唯一 使用组件懒加载或者图片懒加载 防抖和节流的使用 模块按需导入 打包优化,使用cdn加载第三方模块 缓存常用信息 精灵图,base64 ### 动态组件 定义:多个组件使用同一个挂载点,并动态切换 使用:当控制 componentName 改变时就可以动态切换选择组件 # 小程序部分 # 项目部分 ### 人资登录功能逐字稿 首先第一时间要想到:**获取数据渲染页面** 1.使用路由守卫进行判断有没有 `token` 从而进行页面访问权限的拦截 2.在请求拦截器中 ,判断有没有 `token` ,如果有的话注入到请求头上面 3.在 `Vuex`中封装获取用户的信息,在将获取的用户信息存放在 `Vuex` 中 4.路由守卫检测所有页面的用户数据是否存在,存在的话放行;不存在的话再调用`vuex actions `获取数据 5.按流程渲染Vuex中的用户信息到页面中 ### 菜单权限和按钮权限的实现 1. 定义权限数据结构:首先,你需要定义一个权限数据结构,用于表示菜单和按钮的权限信息。可以使用树形结构来组织菜单权限,每个节点可以包含权限名称、图标、路由路径等信息。对于按钮权限,可以使用唯一的标识符来表示不同的按钮。 2. 获取用户权限:在用户登录或刷新页面时,通过后端接口获取当前用户的权限信息。这些权限信息可以包含用户拥有的菜单权限和按钮权限。 3. 菜单权限的实现:在前端应用程序中,可以通过根据用户权限生成动态路由来实现菜单权限控制。根据用户的菜单权限,动态生成对应的路由配置,然后将这些路由配置添加到路由器中。这样,只有用户拥有权限的菜单项才会在菜单中显示,并且点击菜单项会正确渲染对应的页面。 4. 按钮权限的实现:对于按钮权限,可以在组件中通过判断用户是否有对应按钮的权限来决定是否显示或禁用按钮。可以通过在按钮组件上添加 `v-if` 或 `v-show` 指令,并使用权限判断逻辑来控制按钮的显示或隐藏。另外,还可以考虑在处理按钮点击事件时,根据权限决定是否执行相应的操作。 5. 权限验证和路由守卫:为了增强安全性,可以在路由守卫中进行权限验证。在每次路由切换时,可以通过路由守卫中的权限验证逻辑检查用户是否具有访问对应路由的权限。如果用户没有权限,可以重定向到一个无权限页面或给出相应的提示。 6. 后端权限校验:前端权限控制只是表面上的控制,为了确保数据安全性,后端也需要对用户请求进行权限校验。后端应该验证每个请求的权限,并且不允许未经授权的用户执行对应操作。 # 业务场景部分 ### 怎么实现⽆刷新跳转⻚⾯ 1.使用HTML的标签:你可以在标签中设置href属性,将其指向目标页面的URL。当用户点击该链接时,浏览器会自动加载并显示目标页面,实现无刷新跳转。 ```html 跳转到目标页面 ``` 2.使用JavaScript的location对象:你可以使用JavaScript中的location对象来实现无刷新跳转。通过修改location.href属性,将其设置为目标页面的URL,页面将会自动跳转到目标页面。 ```js location.href = "target-page.html" ``` 3.使用JavaScript的window对象的open方法:通过使用window.open方法,你可以在新的浏览器窗口或标签页中打开目标页面。 ```js window.open("target-page.html"); ``` ### 数据劫持 数据劫持(Data Hijacking)是指通过修改或拦截数据传递的过程,对数据进行非法操作或篡改的行为。它常见于前端开发中,特别是在处理用户输入、数据交互和数据传输过程中。 数据劫持可以发生在不同阶段和环境中,例如: 1. 前端数据劫持:在前端开发中,JavaScript提供了许多操作和修改数据的方法,其中包括对输入字段、表单数据、AJAX请求和响应数据等进行修改。通过劫持这些数据,攻击者可以伪造或篡改数据,导致安全漏洞和业务逻辑错误。 2. 数据拦截和篡改:在网络通信中,攻击者可能通过拦截传输的数据,修改其中的内容。例如,通过中间人攻击(Man-in-the-Middle Attack)截获数据包,篡改其中的请求参数或响应内容,从而欺骗用户或者改变应用行为。 3. 后端数据劫持:后端开发中也存在数据劫持的风险。攻击者可以通过各种手段,突破系统的安全防护,修改或篡改数据库中的数据,或者通过未经授权的访问和操作来获取敏感数据。 为了防止数据劫持,可以采取以下措施: 1. 输入验证和过滤:对用户输入的数据进行验证和过滤,防止恶意数据的注入和攻击。 2. 加密和签名:对敏感数据进行加密、签名和校验,确保数据的完整性和真实性。 3. 安全传输:在数据传输过程中,采用安全协议(如HTTPS)来加密数据,避免被拦截和篡改。 4. 权限控制:通过权限管理和访问控制,限制对数据的操作和访问权限,防止未经授权的修改和访问。 ### uniapp打包工具 1. **HBuilderX**:HBuilderX是UniApp官方提供的集成开发环境(IDE),它内置了打包工具,可以使用它进行UniApp项目的打包。HBuilderX提供了一键打包的功能,支持多平台的打包,包括小程序、App、H5等。在HBuilderX中,你可以选择构建目标平台,进行相应的配置,然后点击打包按钮即可生成相应平台的应用程序文件。 2. **CLI命令行工具**:UniApp也提供了命令行工具,用于通过命令行进行打包操作。在终端或命令提示符中,你可以使用uni-cli命令进行打包操作。通过命令行工具,你可以选择不同的打包模式和目标平台,进行灵活的配置和定制。例如,使用命令`uni build`可以进行打包,通过指定命令参数可以选择生成的平台和其他配置。 ## uniapp开发安卓和ios以及h5的流程 UniApp是一个基于Vue.js的跨平台应用开发框架,它可以让你使用一套代码同时开发Android、iOS和H5应用。下面是UniApp开发Android、iOS和H5应用的基本流程: ### 1. 环境搭建: 首先,确保你的开发环境中已经安装了Node.js和HBuilderX。Node.js是UniApp的运行环境,而HBuilderX是UniApp的官方IDE。 ### 2. 创建UniApp项目: 在HBuilderX中创建一个UniApp项目。选择创建新项目时,在模板中选择"uni-app",然后选择支持的平台(Android、iOS、H5)。 ### 3. 开发页面和组件: UniApp使用Vue.js语法进行开发。你可以在`pages`目录下创建页面,使用Vue.js编写页面逻辑,同时可以使用CSS、Less或者Sass编写样式。UniApp也支持自定义组件,可以将页面拆分成多个组件进行开发。 ### 4. 调试和预览: 在HBuilderX中,你可以使用内置的调试工具,在模拟器或真机上预览你的应用。UniApp还提供了HBuilderX Companion App,你可以在手机上实时查看应用效果。 ### 5. 数据交互和网络请求: UniApp支持使用Vue.js的异步请求方法(例如axios、uni.request)进行数据交互和网络请求。你可以与后端API进行交互,获取数据并在应用中展示。 ### 6. 打包和发布: - **Android应用**:在HBuilderX中选择App发布,生成APK文件,然后将APK文件上传到Google Play商店或其他Android应用市场。 - **iOS应用**:在HBuilderX中选择App发布,生成Xcode工程,然后使用Xcode进行进一步的构建和发布到App Store。 - **H5应用**:在HBuilderX中选择H5应用发布,生成静态文件,然后将这些文件部署到Web服务器上。 ### 7. 测试和优化: 在各个平台的真机和模拟器上测试应用,确保应用在不同设备和屏幕尺寸上正常运行。针对性能进行优化,确保应用响应迅速、流畅运行。 ### 8. 发布和推广: 将应用发布到应用商店(Google Play、App Store等)或者Web服务器上,然后进行推广,吸引用户下载和使用你的应用。 ### 9. 持续维护: 定期更新应用,适配新的操作系统版本和设备,修复bug,添加新功能,提高用户体验。 以上是UniApp开发Android、iOS和H5应用的基本流程,具体的开发过程会根据项目需求和复杂度有所不同。在开发过程中,可以参考UniApp官方文档和社区,获取更详细的开发指南和解决方案。