ES6面试点
- ES6新增功能有哪些?
- 变量定义 let/const
- 箭头函数
- 模板字符串
- 解构赋值
- 展开运算符
- Set对象
- async/await 【async[ə'zɪŋk]】
- promise
- symbol
- 模块(import/export)
- 类(class)
- promise是什么?
- 是ES6提出的异步编程的一种解决方案,语法上讲,是一个构造函数,功能上讲,它封装了一个未来的关于成功或者失败的事件结果。
- 用Promise来解决什么问题?
- 支持链式调用,可以解决回调地狱的问题。
- 支持多个并发请求
- Promise有几种状态?有什么特点?
- pending(等待态),fulfiled(成功态),rejected(失败态)
- 状态不受外界影响,状态一旦改变,就不会再变
- 什么是回调地狱?
- 回调函数里面嵌套调用回调函数
- promise和callback(回调函数)的区别?
- promise是ES6异步编程的一种方案,解答如上
- callback是js最基础的异步调用方式,它把A函数当成参数传递给另外一个B函数,在B函数内部某个特定的点执行函数A,那么A函数就是回调函数。
- promise和async/await
- async 用于申明一个异步的 function。async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值
- await 用于等待一个异步方法执行完成。await 也是一个修饰符,只能放在async定义的函数内。
- 同步和异步的区别?
- 同步会造成线程阻塞,但是异步执行不会造成自己的线程阻塞;
- 同步需要等待所有步骤执行完了才能继续往下执行,异步只需要发起调用后就可以继续其他逻辑
- 箭头函数有什么特点?
- 没有arguments对象
- 没有自己的this,不能当构造函数
- this值取决外部非箭头函数的this指向,不能改变this的指向
- 不能用new关键字声明
- 没有原型prototype属性
HTML
- HTML是什么?
- Html是超文本标记语言,是用来描述web文档的一种标记语言
- HTML5是什么?
- HTML5是构建以及呈现互联网内容的一种语言方式
- HTML5是Web中核心语言HTML的规范
- HTML5和html4的区别
- DOCTYPE简化
- html新增了许多标签
- DOCTYPE的作用?
- DOCTYPE是document type (文档类型) 的缩写。声明位于文档的最前面,处于标签之前,它不是html标签。主要作用是告诉浏览器的解析器使用哪种HTML规范或者XHTML规范来解析页面。
- HTML5 为什么只需要写 ?
- HTML5不基于 SGML,因此不需要对 DTD 进行引用,但是需要 doctype 来规范浏览器的行为(让浏览器按照它们应该的方式来运行)
- HTML4.01 基于 SGML,所以需要对 DTD 进行引用,才能告知浏览器文档所使用的文档类型。
- 严格模式和混杂模式?
- 严格模式: 又称标准模式,是指浏览器按照W3C标准来解析代码,呈现页面
- 混杂模式: 又称为怪异模式或者兼容模式,是指浏览器按照自己的方式来解析代码,使用一种比较宽松的向后兼容的方式来显示页面。
- HTML有哪些标签?
- html,meta,body,script
- div,span, a
- 说一说HTML语义化?
- 代码可读高
- 有利于SEO
- 利于页面内容结构化 常见的语义化标签:header、footer、aside、main、h1-h6、input、textarea、video、aduio
- HTML的行内和块级元素
- 块级元素:独占一行,对宽高的属性值生效;如果不给宽度,块级元素就默认为浏览器的宽度,即就是100%宽;
- 行内元素:可以多个标签存在一行,对宽高属性值不生效,完全靠内容撑开宽高!
- 行内元素有?
- p、div、ul、ol、li、dl、dt、dd、h1~h6、form;
- 块级元素有?
- a、span、em、strong、b、i、u、label、br;
- HTML5新增了哪些标签?
- 语义化标签,header,nav,footer,article,section
- audio,video
- canvas
- HTML5新特性?
- Canvas绘图以及SVG绘图。
- 拖放(Drag and drop)API
- 语义化标签(header、nav、footer、article、section)
- 音频、视频(audio、video)API
- 本地离线存储(localStorage),长期存储数据,关闭浏览器后不丢失
- 会话储存(sessionStorage),数据在关闭浏览器后自动删除
- 表单控件(calendar、date、time、email、url、search)
- 新技术如Web Worker、Web Socket
- 点击一个input,会依次触发哪些事件?
- onmouseenter,
- onousedown,
- onfocus,
- onclick
- 如何解决a标签点击后hover事件失效的问题?
- 改变a标签css属性的排列顺序:link→visited→hover→active
- a标签伪类的顺序?
- link→visited→hover→active
- 如何实现元素的拖拽?
- 用H5的新API dataTransfer,将元素设置为可拖拽,设置元素拖拽的目标容器和drop事件。
- 使用原生的js,按下鼠标获取当前鼠标的元素,以及当前元素距离左边界和上边界的距离,松开鼠标,获取当前鼠标信息,然后,再计算元素的相对距离,赋予样式。
css
- 盒模型
- css的盒模型由里到外包括:content(内容)、padding(内边距)、border(边框)、margin(外边距)四个部分。
- css盒模型有两种:标准模型(浏览器默认)+ IE模型
- 标准模型(浏览器默认)+ IE模型的区别?
- IE盒模型与W3C标准盒模型的唯一区别就是元素的宽度
- IE盒模型(border-box):边框才是边界。宽度= 内容+padding+border
- 标准盒模型(conteng-box):内容就是边界。宽度= 内容
- css如何设置两种盒模型?
- box-sizing属性,有两个值content-box,border-box;
- css3特性有哪些?
- css3选择器
- css3边框与圆角
- 背景和渐变
- 过渡
- 变化
- 动画
- 说一说样式优先级的规则是什么?
- !important > 内联样式(style) > ID选择器(id) > 类选择器(class) > 标签选择器
- css选择器
- CSS 元素选择器
- 类选择
- id选择器
- 属性选择器(需要元素+属性使用),例如
a[href] - 子元素选择器 > 符号
- 用到的场景: 某个元素下的子元素样式都需要一致
- 相邻兄弟选择器 +
- 用到的场景:当前元素和下一个相邻元素的样式需要保持一致
- 实现水平居中的方式?
- 行内元素:text-aligin,文本居中
- 块级元素:margin:0 auto,元素一定要有宽度
- flex布局:justify-contet:center;
- transform+position属性
- 实现水平垂直居中的方式?
- flex布局设置居中,justify-contet+align-items
- transform+position属性
- tabel-cell实现垂直居中
- 容器设置
display: table-cell; vertical-align: middle属性设置元素的垂直对齐方式
- 容器设置
- 实现左右布局,左边固定,右边自适应的方式?
- flex布局,左边flex-basis固定,右边flex-grow:1;
- position:
- 内容main,宽高100%,使用relative定位,left,right使用absolute定位。内容main必须设置高度,否则left和right无法撑开。
- left宽度固定,高度100%
- right宽度100%需要减去左边固定宽度,高度100%
- 使用float浮动
- left设置浮动
- right设置宽度100%;
- display取值?
- flex
- block
- inline-blcok
- none
- table-cell
- flex?
- 弹性布局,是css的一种新的布局模式。
- 属性
- flex-direction:指定盒子中子元素的排列方式,纵向/横向
- flex-wrap:指定子元素超出父元素时,是否换行
- flex-flow: flex-direction,flex-wrap两个属性的缩写
- justify-content:横轴对齐
- align-items:纵轴对齐
- order: 子元素排列顺序
- flex:元素如何分配空间
- flex-grow:设置盒子的扩展比率
- flex-shrink:盒子的收缩比率
- flex-basis: 盒子伸缩的基准值
- 属性
- 弹性布局,是css的一种新的布局模式。
- css预处理使用哪种?less怎样定义变量?
- 使用符号@
- px和em的区别?
- px表示像素 ,是绝对单位,不会因为其他元素的尺寸变化而变化;简单点就是根据屏幕分辨率来的。
- em表示相对于父元素的字体大小。em是相对单位 ,没有一个固定的度量值,而是由其他元素尺寸来决定的相对值。
- position的值有哪些?
- static 默认值
- fixed 固定,相对于浏览器窗口进行定位
- relative 相对定位,不影响元素本身特性,不会使元素脱离文档流
- absolute 绝对定位,使元素完全脱离文档流
- sticky,粘性定位 ,可以被认为是相对定位和固定定位的混合。
- inherit 继承父属性
浏览器
- DOM是什么?
- DOM代表文档对象模型,是 HTML 和 XML 文档的接口(API)。
- 介绍一下虚拟DOM是什么?
- 虚拟dom就是将真实的节点dom用js模拟出来。
- 为什么要用虚拟DOM?
- 首先,一个dom节点是很庞大的,它有很多属性,每次操作dom是一个相当耗时的过程。
- 第二,当更新一个dom节点的时候,很有可能会触发回流操作,导致浏览器会重新渲染部分或全部文档。
- 第三,当对多个dom进行更新的时候,每一次都要重新计算dom节点的坐标信息,会造成性能的浪费。
- 什么是重绘与回流?
- 重绘
- 简单来说就是重新绘画,当给一个元素更换颜色、更换背景,虽然不会影响页面布局,但是颜色或背景变了,就会重新渲染页面,这就是重绘。
- 重绘不会引起dom结构和页面布局的变化,只是样式的变化,有重绘不一定有回流。
- 回流
- 当增加或删除dom节点,或者给元素修改宽高时,会改变页面布局,那么就会重新构造dom树然后再次进行渲染,这就是回流。
- 回流则是会引起dom结构和页面布局的变化,有回流就一定有重绘。
- 重绘
- 怎样减少回流和重绘?
- 批量修改元素样式
- 避免使用css表达式
- 避免使用table布局
- 对于复杂动画效果,使用绝对定位让其脱离文档流
- 避免设置多层内联样式
- 创建多个dom节点时,使用documentfragment创建
- 缓存DOM,减少DOM深度及DOM数量
- 避免循环读取offsetLeft等属性,在循环之前把它们存起来
- 兼容产生的原因?
- 不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况
- 遇到过哪些兼容问题?
- iE不兼容new File()
- iE和其他浏览器的盒模型不一样
- 原生select选择标签的问题,它在安卓端,苹果,浏览器上的样式不一样
- IE的添加事件和移除事件,在IE中添加事件使用
attachEvent,detachEvent,非IE中使用,addEventListener,removeEventListener, - ajax的实现方式不一样,非IE是XMLHttpRequest,IE是activeXObject
- IE获取目标元素,标准浏览器是event.target,而IE下是event.srcElement
- 说一下你所知道的缓存方案/缓存策略?
- 强制缓存
- 浏览器加载资源时,会通过http首部字段判断是否强制缓存,如果强制缓存,直接读取缓存中的文件,不会发请求到服务器
- 协商缓存
- 如果没有强制缓存,浏览器发送请求到服务。,服务器根据请求的http首部字段作比较,是否命中协商缓存,如果有协商缓存,则返回消息, 告诉浏览器可直接用缓存
- 强制缓存
- 输入URL到页面呈现的一个过程?
- 在地址栏输入url,回车
- 浏览器判断是否有缓存,如果有缓存,直接显示页面内容。
- 没有缓存,对URL进行DNS解析,获取IP地址。
- 浏览器发起TCP请求,建立三次握手。
- 握手成功,浏览器向服务器发送HTTP请求。
- 服务器响应请求,并返回数据
- 浏览器收到相应数据,开始渲染页面
- 浏览器把获取到的文档解析成DOM树
- 浏览器构建css树。
- 将DOM树和css树合并成一个渲染树
- 浏览器开始布局,为渲染树的每个节点确定一个精确的坐标
- 通过渲染树的每个节点坐标,浏览器开始绘制
- script放在body头部就一定会阻塞加载吗?
- 动态加载,放在head头部,不会阻塞
- 异步加载不会阻塞
- script与css及页面的渲染顺序?
- 渲染顺序从上到下
- link标签的加载阻塞后续代码执行,但不影响外部文件(link,script,可以同时加载。)
- 外部文件加载后进行解析,解析过程,会阻塞加载
- js的加载会阻塞下载,防止出现JS修改DOM树,需要重新构建DOM树的情况,一般js放置在body底部。
- 添加async属性的script,异步加载,不会被阻塞,但可能读取dom节点失败
- 为什么说script标签建议放在body下面?
- 因为浏览器在渲染HTML的时候是从上到下依次执行, 遇到script标签则会停止DOM树的渲染,优先下载js文件, 如果文件很大,则导致页面加载时间过长,影响用户体验
- 说一说defer和async区别?
- defer和async在网络读取(下载)这一阶段是一样的,相对于html解析来说都是异步的
- 两者之间的差别是script脚本下载完后何时执行。defer是最接近我们对于应用脚本加载和执行要求的。
- 对async而言,脚本的加载和执行是紧挨着的,不管声明顺序如何,只要加载完就会立即执行。
- html文件都是按顺序执行的,script标签中没有加defer和async时,浏览器在解析文档时遇到script标签就会停止解析阻塞文档解析,先加载JS文件,加载完之后立即执行,执行完毕后才能继续解析文档。
- async是js文件加载完毕后立即执行js脚本,阻塞文档解析;defer是js文件加载完毕后解析文档,文档解析完毕后再执行js脚本。
- 说一说跨域是什么?
- 跨域是指浏览器的同源策略是不允许执行其他网站上的脚本,只要协议,主机地址,端口其中之一不同就算跨域。
- 如何解决跨域问题?
- 跨域一般的解决方法是Jsonp,script标签不受同源策略影响;
- 前台还可以设置代理proxy;
- 后端也可以设置CROS,Access-Control-Allow-Origin;
- 此外还有nginx的反向代理。
- websocket
性能
- 为什么要新能优化?
- 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更 为友好的体验。
- 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
- 首页加载缓慢的原因
- 加载的资源多
- 请求过多
- 资源在第三方站点上,且资源过大
- 后台数据查询缓慢
- 前端js代码阻塞,script脚本会阻塞后面代码执行,css不会阻塞dom解析,但会阻塞dom渲染,阻塞link后面js代码执行
- 网络差,或者设备硬件配置低
- 如何进行网站性能优化?
- 减少HTTP请求
- 合并css,js,图片
- 简单的图片可以用div+css或者base64代替
- 图片可以用懒加载
- 减少cookie大小
- 压缩资源
- 减少资源体积:JavaScript 压缩和模块打包
- 可以在服务器启用Gzip压缩
- 缓存
- 浏览器缓存,缓存不经常改变的JS、CSS、图片
- cdn缓存,使用cdn,缓存第三方库,如vue
- 渲染优化方案
- 脚本尽量放置body底部,以防阻塞代码
- 减少dom结构的层级
- 避免重绘和回流
- 资源预加载
- 按需加载
- 减少HTTP请求
- ssr,服务器渲染的优点?
- 更好的SEO
- 解决首屏渲染问题(更快的首屏到达时间)
- ssr,服务器渲染的优点?
- 配置过程复杂,需要配置2个入口文件,即 服务端首屏渲染所需和前端激活所需的。
- 相比于SPA,服务端渲染加重了服务器的负担。
- SPA是单例模式,SSR需要服务端返回Vue实例,一次首屏就需要创建一个实例,代码是工厂模式返回的实例,即多实例。所以更浪费性能
网络
- TCP三次握手?
- 客户端发送syn包,等待服务器确认
- 服务器收到syn包,确定客户端标识,发送syn+ack包响应
- 客户端收到syn+ack包,向服务器发送确认包,发送完毕,三次握手建立。
- 为什么TCP要三次握手而不是两次?
- 解决网络延迟的问题,防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
- HTTP是什么?
- (HyperText Trransfer Protocol 超文本传输)客户端与服务端的通信协议,HTTP协议的通信过程,简单来说就是请求和响应的过程。
- 基于TCP/IP通信协议传递数据
- HTTP和TCP的不同?
- HTTP协议是建立在TCP协议上的应用
- TCP只是建立连接,HTTP收发数据
- TCP是底层通讯协议,HTTP是应用层协议
- TCP定义数据传输和连接方式的规范,HTTP定义传输数据内容的规范。
- HTTP消息/报文的结构组成有哪些?
- 请求行
- 请求方法、
- get,post,options,delete
- URL、
- http协议版本
- 请求方法、
- 请求头header,包含许多字段
- accept: 接受的响应类型
- user-agent:用户浏览器类型
- Content-Type、
- Date、
- Expires、过期日期
- cache_control
- Set-Cookie,由服务器下发
- token,由服务器下发
- 请求正文,比如数据
- 请求行
- 一次完整的HTTP事务流程?
- 域名解析,从网址到IP地址的转换,称为DNS解析
- 发起TCP三次握手
- 发起HTTP请求
- 服务器响应,浏览器得到资源
- 浏览器渲染
- HTTP常见的状态码?
- 200请求成功
- 301请求的资源已经移动到新的URL
- 302临时移动到新的URL
- 304未修改,请求资源未修改
- 400客户端请求错误
- 401缺少用户身份验证
- 403服务器拒绝客户端请求
- 404服务器找不到客户端的请求资源
- 500服务器内部错误
- 503服务器处于维护中
- 304有没有了解,返回304的时候浏览器做了什么?
304状态码是当浏览器请求未改变且已缓存的资源时,服务器会返回304,告知浏览器,该资源从某个时间之后没有再改变,可以直接读取在浏览器端缓存的资源。
- token一般会放在哪里?
- localstorage
- cookie
- token会不会被伪造?
- token放入header之后,是无法被直接伪造的
- 前端如何验证一个用户是否下线了?
- cookie中存储用户信息,下线后,后端会删除信息
- TCP和UDP的区别?
- TCP面向连接,UDP是无连接的
- TCP是可靠的,传输数据不会丢失,UDP不可靠性。
- UDP更简单,更快速,具有实时性
- HTTPS是什么?
- HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer,安全套接字超文本传输协议)
- 为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS,依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
- HTTP和HTTPS的区别?
- HTTPS协议需要申请证书
- HTTP是超文本,明文传输,HTTPS是加密传输
- 链接方式不一样,使用的端口不一样,HTTP是80,HTTPS是443
- 在项目中如何把http的请求换成https?
- 利用meta标签
- 为什么说HTTPS比HTTP安全呢?
- HTTPS是加密传输
安全
- 常见的 web 前端攻击方式?
- XSS Cross Site Script:跨站脚本攻击
- 指攻击者在网站上注入恶意的客户端代码,通过恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
- CSRF Cross Site Request Forgery:跨站请求伪造
- 窃取用户的cookie,骗取服务器信任,伪造请求给服务器,在并未授权的情况下,执行需要权限的操作
- XSS Cross Site Script:跨站脚本攻击
- 如何预防CSRF?
- 验证码,因为用户是在不知情的情况下构造请求,如果该请求需要验证码,用户必须与应用进行交互,从而有效阻止攻击
- Referer Check,HTTP 头中的字段,它记录了该 HTTP 请求的来源地址,判断请求是否来自合理的“源”
- 添加 token 验证
- 攻击者窃取的是cookie,token存在于请求头,不能被伪造
- 增加一个随机产生的 token放置在请求头中,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
- 如何预防XSS?
- 防止劫取cookie
- 输入检查,不要相信用户的任何输入
- 输出检查,服务端的输出也需要检查
前端打包框架 - webpack/glup
- webpack是什么?
- 压缩打包工具
- webpack如何把没有用到的文件删除掉?
- useless-files-webpack-plugin
- webpack用的什么版本?同上一个版本有什么区别?
- loader做什么用的?和plugin有什么区别?
- loader加载器,plugin是插件
- 了oader它只专注于转化文件(transform)这一个功能,比如css-loader,style-loader,letss-loader等,完成压缩,打包,语言翻译
- plugin不仅只局限在打包,资源的加载上,还可以打包优化和压缩,重新定义环境变量等
- Plugin可以扩展webpack的功能,让webpack具有更多的灵活性
- vue打包后的js文件有哪些?文件包含的内容大概是什么?
手撕代码
- 获取两个数字之间的随机数?
getBetweenNum(min,max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
- 手写一个闭包
function fn() {
let a = 0;
return function() {
return a++;
}
}
let b = fn()
console.log(b())//0
console.log(b())//1
console.log(b())//2
- 手写深拷贝
function deepClone(){
// 如果不是引用数据类型,返回原值
if(checkType(target) !== 'Array' && checkType(target) !== 'Object'){
return target
}
// 利用构造函数,创建一个该类型的对象
var result = new target.constructor
for(var i in target){
var val = target[i]
// 递归拷贝
result[i] = deepClone(val)
}
// 返回拷贝后的值
return result
}
- 手写节流
- 思路:传入一个要执行的函数和规定时间,用闭包返回函数,闭包外层函数定义一个最后执行时间的变量,内层函数判断当前时间和最后时间是否可以执行函数,同步最后执行时间,最后注意修正this指向。
function throttle(fn,delay){
let lastTime = 0
return function() {
let newTime = Date.now()
if(newTime - lastTime > delay) {
fn.call(this)
lastTime = newTime
}
}
}
- 手写防抖
- 思路:传入一个要执行的函数和规定时间,用闭包返回函数,闭包外层函数定义一个定时器,内层函数清除定时器并重新定义一个延迟的定时器
function debounce(fn,delay){
let timer = null
return funciton() {
clearTimeout(timer);
timer = setTimeout(() => {
fn.call(this)
}, delay)
}
}
- 手写模拟new关键字
- 定一个构造函数,这里用数组
- 创建一个空对象,提取出构造函数,将新对象的原型链指向构造函数的原型 ,执行构造函数改变this,返回新对象
// 定义一个构造函数
function _Array() {
if(arguments.length > 1) {
for(let i of arguments) {
this.splice(this.length,0,i)
}
} else {
this.length = arguments[0]
}
}
// 模拟new
function _new(){
// 第一步:创建一个空对象
let obj = [];
// 第二步:
let [constructor,...args] = [...arguments];
// 第三步:
obj.__proto__ = constructor.propotype;
// 第四步:执行构造函数中的代码,传入参数,对新对象初始化
constructor.apply(obj,args)
// 第五步:返回新对象
return obj
}
// 实现
let arr = _new(_Array, 1, 2)
console.log(arr) // [1,2]
- 手写排序
快速排序
冒泡排序
- 手写数组去重
- 解析url
//第一种,使用API,可以获取单个参数
function query_api(name) {
let search = location.search
let res = new URLSearchParams(search)
return res.get(name)
}
// 第二种,拆分循环
function query_split(url) {
let string = location.search.substr(1)
let obj = {}
string.split('&').forEach(v => {
let itemArr = v.split('=')
obj[itemArr[0]] = itemArr[1]
})
return obj
}
- 手写一个trim函数,去除字符串开头和结尾的空格?
function trim(str) {
let start = 0;
let end = str.length - 1;
let hasStart = false;
let hasEnd = false;
while(start < end && (!hasStart || !hasEnd)) {
if(!hasStart && str[start] === ' ') {
start++;
} else {
hasStart = true
}
if(!hasEnd && str[end] === ' ') {
end--
} else {
hasEnd = true
}
}
return str.substring(start, end + 1)
}
- 把‘hello-world-my-name’字符串变成大驼峰‘HelloWorldMyName’?
function upper(str) {
let strArr = str.split('-').map(v => {
return v.charAt(0).toUpperCase() + v.substring(1)
})
return strArr.join('')
}
- 手机号或身份证中间段星号隐藏?
// 后面用\w是匹配身份证的字母问题
function idCard(card) {
return card.replace(/^(\d{3})\d+(\w{4})$/, "$1****$2")
}
项目问题
- 最近做的项目?担任的职责?
- 自答。
- 遇到过的bug?
- vue版本和ui组件版本冲突,ui组件依赖的vue版本升级,但项目中用的vue是比较低一点版本,因为这两个vue版本相差不大,可以把项目里的vue版本升级,同时通知其他同事。
- vue2到vue3的迁移,vue2和vue3的底层写法不一样,有些组件和插件不支持vue3,迁移的时候就遇到插件迁移不过去,那这种情况要么自己写,要么找别的代替。
- 本地环境和流水线环境打的包不一样,同样的代码,后来找到原因是版本问题,vue中有个package.json的文件,里面记录所有依赖的版本,同时还有一个package-lock.json文件,这个lock文件是不会上传到代码库的,这个文件的作用就是锁定项目依赖的版本,因为流水线环境没有这个文件,它就会按照package.json的通配符,尖号,波浪号去升级最新的版本,导致两个环境里有一个依赖的版本不一样,最终的解决结果,就是本地更新依赖版本,就是说一些重要依赖的版本,需要固定,不要让它自动升级。
- 兼容问题,IE和其他浏览器,图片上传,IE无法创建new file对象,解决办法就是转成blob对象让后端接收。
- 怎么看待你做的这几个项目?
- 项目中有什么难点?
- 项目有什么亮点?
- 项目中的数据权限是怎么做的?
- 项目中做过哪些优化?