vue,小程序,前端 面试题结合项目

261 阅读18分钟

00. 后端返回10万条数据,前端如何优雅的去处理

juejin.cn/post/703192…

01. requestAnimationFrame

requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:

1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

requestAnimationFrame 动画原理:

  假设某图像正在以每秒60次的频率刷新,由于刷新频率很高,因此你感觉不到它在刷新。而动画本质就是要让人眼看到图像被刷新而引起变化的视觉效果,这个变化要以连贯的、平滑的方式进行过渡。 那怎么样才能做到这种效果呢?

  刷新频率为60Hz的屏幕每16.7ms刷新一次,我们在屏幕每次刷新前,将图像的位置向左移动一个像素,即1px。这样一来,屏幕每次刷出来的图像位置都比前一个要差1px,因此你会看到图像在移动;由于我们人眼的视觉停留效应,当前位置的图像停留在大脑的印象还没消失,紧接着图像又被移到了下一个位置,因此你才会看到图像在流畅的移动,这就是视觉效果上形成的动画。

setTimeOut卡顿的原因:

1、setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。

2、刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

  以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致,从而引起丢帧现象。 那为什么步调不一致就会引起丢帧呢?

  原因:setTimeout的执行只是在内存中对图像属性进行改变,这个变化必须要等到屏幕下次刷新时才会被更新到屏幕上。如果两者的步调不一致,就可能会导致中间某一帧的操作被跨越过去,而直接更新下一帧的图像。

原文链接:blog.csdn.net/weixin_4298…

02. 事件循环中包含:【微任务、宏任务】

03. 为什么typeof null 是object?

不同的数据类型在底层都是通过二进制表示的,二进制前三位为000则会被判断为object类型,

而null底层的二进制全都是0,那前三位肯定也是000,所以被判断为object

04. Ajax、Axios、Fetch有啥区别?

  • Ajax:是对XMLHttpRequest对象(XHR)的封装
  • Axios:是基于Promise对XHR对象的封装
  • Fetch:是window的一个方法,也是基于Promise,但是与XHR无关,不支持IE

05. BOM 和 DOM 的关系

BOM全称Browser Object Model,即浏览器对象模型,主要处理浏览器窗口和框架。

DOM全称Document Object Model,即文档对象模型,是 HTML 和XML 的应用程序接口(API),遵循W3C 的标准,所有浏览器公共遵守的标准。

JS是通过访问BOM(Browser Object Model)对象来访问、控制、修改客户端(浏览器),由于BOM的window包含了document,window对象的属性和方法是直接可以使用而且被感知的,

因此可以直接使用window对象的document属性,通过document属性就可以访问、检索、修改XHTML文档内容与结构。因为document对象又是DOM的根节点。

可以说,BOM包含了DOM(对象),浏览器提供出来给予访问的是BOM对象,从BOM对象再访问到DOM对象,从而js可以操作浏览器以及浏览器读取到的文档。

06. map、object和set的区别

map:对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。构造函数Map可以接受一个数组作为参数。

object:

一个Object 的键只能是字符串或者 Symbols,但一个Map 的键可以是任意值。
Map中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
Map的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
set:对象允许你存储任何类型的值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。

总结:

初始化需要的值不一样,Map需要的是一个二维数组,而Set 需要的是一维 Array 数组
Map 和 Set 都不允许键重复
Map的键是不能修改,但是键对应的值是可以修改的;Set不能通过迭代器来改变Set的值,因为Set的值就是键。
Map 是键值对的存在,值也不作为健;而 Set 没有 value 只有 key,value 就是 key;\

07. 函数的length是多少?

可以看出,function有多少个形参,length就是多少;

但是如果有默认参数,就是第一个具有默认值之前的参数个数;剩余参数是不算进length的计算之中的

function fn1 (name) {}

function fn2 (name = '仙人掌') {}

function fn3 (name, age = 22) {}

function fn4 (name, age = 22, gender) {}

function fn5(name = '仙人掌', age, gender) { }

console.log(fn1.length) // 1
console.log(fn2.length) // 0
console.log(fn3.length) // 1
console.log(fn4.length) // 1
console.log(fn5.length) // 0
//剩余参数
function fn6(name, ...args) {}
console.log(fn6.length) // 1

08. 判断元素是否在可视区域内

使用getBoundingClientRect

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。返回的是一个对象,

对象里有这8个属性:left,right,top,bottom,width,height,x,y

09. webpack性能优化

10. loader和plugin的区别

两者都是扩展webpack的功能,loader只专注于转化文件,完成压缩、打包和语言翻译;而plugin只局限在打包,资源加载上,还可以打包优化和压缩,重新定义环境变量等 loader是运行在打包文件之前,plugins在整个编译周期都起作用 一个loader的职责是单一的,只需要完成一种转换,一个loader其实就是一个node.js模块。当需要多个loader去转换一个文件时,每个loader会链式的顺序执行 webpack运行的生命周期中广播出许多事件,plugins会监听这些事件,在合适的时机通过webpack提供的API改变输出结果   原理:

    loader loader 的作用是用来处理非js文件,它是一个函数,实现原理是:将所需处理的文件内容使用相应的转换插件转成AST(抽象语法树),然后按照loader规则对于这个 AST 进行处理,处理之后再转成原本的内容格式,然后输出,达到了处理内容的效果

    plugin plugin 的作用是拓展webpack的打包功能。它是一个类,使用方式是new Plugin(option),这个类内部有一个apply方法,打包时会执行这个方法,且这个apply方法接收的参数中有一个plugin方法,此方法中有许多钩子函数,使用这些钩子函数可以在不同的打包阶段做一些事,例如修改文件,新增文件,删除文件等等 ———————————————— 版权声明:本文为CSDN博主「前端技术栈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

11. 修改Element-UI样式的几种方式

1.新建全局样式表

新建global.css全局样式文件,并在main,js中进行引用

import './style/global.css' 在全局样式下的样式会覆盖vue中单页面中element-ui样式。

2.在当前vue页面下新建style标签 在当前style下不要使用scoped属性,在写有scoped属性不会覆盖element-ui样式

3.使用/deep/进行深度修改样式 找到需要修改的样式的标签名的类名,在类名前加/deep/,这种方式可以强制修改element-ui样式,,可直接用到加了scoped属性的style节点下。

// 修改级联选择框的默认宽度
/deep/ .el-cascader {
  width: 100%;
}

4.通过内联样式 或者 绑定样式覆盖默认样式 不是用通用 例如

<el-button :style="selfstyle">默认按钮</el-button>
   <script>
       export default {
         data() {
           return {
               selfstyle: {
                   color: "white",
           marginTop: "10px",
           width: "100px",
           backgroundColor: "cadetblue"
               }
           };
         }
       }
   </script>

扩展:

第一种全局引入css文件的方式,适合于对elementUI整体的修改,比如整体配色的修改;
第二种添加一个style标签的形式,也能够实现修改默认样式的效果,但实际上因为是修改了全局的样式,因此 在不同的vue组件中修改同一个样式有可能会有冲突。
第三种方式通过 /deep/ 的方式可以很方便的在vue组件中修改默认样式,也不会于其他页面有冲突。
第四种方式局限性比较大,可以使用,但不推荐使用。

原文链接:blog.csdn.net/qq_56989560…

11. 前端常见的浏览器兼容问题

不同浏览器的内核不尽相同,所以各个浏览器对网页的解析存在一定的差异。
浏览器内核主要分为两种,一是渲染引擎,另一个是js 引擎
所以浏览器兼容性问题一般指:css兼容、js兼容

一、样式初始化

由于各大浏览器会有自身的默认样式,并且不尽相同,所以为了尽可能的保证样式的统一性,前端在开发项目之前都会先进行样式格式化,最常见的分为以下几个方面。

1.pandding 值和 margin 值均设置为 0 将html、body、a、li、ol、input、textarea、select、button 等标签的 padding 值和 margin 值设置为 0。

2.html 标签 设置统一的字体,如果使用 rem 单位,则 html 需要设置合适的字号。

3.a 标签 设置统一的颜色,将 text-decoration 属性设置为 none。

4.ol 和 li 标签 list-style 统一设置为 none。

5.input、textarea、select、button 等标签初始化 border 设置为 none;

根据需要设置颜色和背景色。

二、使用不同类型的浏览器内核前缀

1.Chrome(谷歌浏览器) 与 Safari(苹果浏览器) 内核:Webkit (中译无) 前缀:-webkit-

2.IE (IE浏览器) 内核:Trident (中译三叉戟) 前缀:-ms-

3.Firefox (火狐浏览器) 内核:Gecko(中译壁虎) 前缀:-moz-

4.Opera (欧朋浏览器) 内核:Presto(中译迅速) 前缀:-o-

例:

-webkit-border-radius: 10px; /谷歌浏览器/
-ms-border-radius: 10px; /IE浏览器/
-moz-border-radius: 10px; /火狐浏览器/
-o-border-radius: 10px; /欧朋浏览器/
border-radius: 10px;

三、针对IE浏览器不同版本的解决方案

1.对于低版本的 IE 浏览器使用 CSS hack( 即给特点前缀) 注:以下符号是写在属性名前面。

兼容 IE6 的 hack 符号:- 或 _

兼容 IE6 、7 的 hack 符号:` ~ ! @ # $ % ^ & * ( ) + = [ ] | < > , . 任意一个符号

兼容 IE6、7、8 的 hack 符号:.

注:以下符号是写在属性值与分号直接,中间不留空格。

兼容 IE8 的 hack 符号:\0/

兼容 IE8、9、10 的 hack 符号:\0

兼容 IE6、7、8、9、10 的 hack 符号:\9

例:

/hack符号在前/
_border-radius: 10px; /IE6/
+border-radius: 10px; /IE6\7/
.border-radius: 10px; /IE6\7\8/

/hack符号在后/
border-radius: 10px\0/; /IE8/
border-radius: 10px\0; /IE8\9\10/
border-radius: 10px\9; /IE6\7\8\9\10/

2.为不同的版本编写独立的样式,其他浏览器识别不到。 例:大于 IE9 的浏览器使用这个单独的 style9.css 样式

例:只有 IE6 浏览器使用的 style6.css 样式

四、其他特殊样式

1.cursor 属性的 hand 值和 pointer 值 问题:firefox 浏览器不支持 hand 值,但其他浏览器均支持 pointer 值。 解决: 统一使用 cursor 属性的 pointer 值。

2.水平居中 问题:IE8 及IE8 以下版本浏览器不可通过设置 margin:0 auto 实现水平居中。

解决: 可通过设置父级 text-align:center 实现。

3.属性值 “inherit” 问题:IE8 及IE8 以下版本浏览器不支持属性值 “inherit”。

解决:谨慎使用属性值 “inherit”。

五、JS兼容性

1.ES6语法

问题:IE11 不支持箭头函数、class 语法等(报 SCRIPT1002: 语法错误),不支持 Set 和 Map 数据结构(不报错)及 Promise 对象,支持 let 和 const,IE10 及以下不支持任何 ES6 语法。

解决:如果要兼容IE浏览器的项目请使用 ES5 语法或者使用 Babel 进行转换。

2.操作 tr 标签

问题:IE9 及 IE9 以下版本浏览器,不能操作 tr 标签的 innerHTML 属性。

解决:可以操作 td 标签的 innerHTML 属性。

3.Ajax

问题:IE9 及 IE9 以下版本浏览器无法使用 Ajax 获取接口数据。

解决:在使用 Ajax 请求之前设置 jQuery.support.cors=true。

4.event 对象的 srcElement 属性

问题:IE8 及 IE8 以下版本浏览器 event 对象只有 srcElement 属性,没有 target 属性。

解决:obj = event.target?event.target:event.srcElement。

5.DOM 事件绑定

问题:IE8 及 IE8 以下版本浏览器是用 attachEvent() 方法,而其他浏览器是 addEventListener() 方法。

解决:判断 IE 浏览器版本,如果是 IE8 及以下 事件绑定则使用 attachEvent() 方法,注意 attachEvent() 方法的用法,第一个参数为“onclick” 而不是“click”。并且没有第三个参数。

常见的兼容性问题:

1、不同浏览器的标签默认的外边距( margin )和内边距(padding)不同 解决方案: css 里增加通配符 * { margin: 0; padding: 0; }

2、IE6双边距问题;在 IE6中设置了float , 同时又设置margin , 就会出现双边距问题 解决方案:设置display:inline;

3、当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度 解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度

4、图片默认有间距 解决方案:使用float 为img 布局

5、IE9一下浏览器不能使用opacity 解决方案:

opacity: 0.5;filter: alpha(opacity = 50);filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);

6、边距重叠问题;当相邻两个元素都设置了margin 边距时,margin 将取最大值,舍弃最小值; 解决方案:为了不让边重叠,可以给子元素增加一个父级元素,并设置父级元素为overflow:hidden;

7、cursor:hand 显示手型在safari 上不支持 解决方案:统一使用 cursor:pointer

8、两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出; 解决方案:父级元素设置position:relative

原文链接:blog.csdn.net/efew212efe/…

12. 前端项目性能优化

1、HTML性能优化

  1. 把js移到HTML后加载,因为JS会阻塞后面的页面的显示。
  2. 减少iframe的使用,因为iframe会增加一条http请求。
  3. 避免图片和iframe等的空Src。空Src会重新加载当前页面,影响速度和效率。
  4. 减少不必要的嵌套,避免代码纵深层次过深,尽量扁平化,因为当浏览器遇到一个开始标签时就会寻找它的结束标签,直到匹配上才会显示它的内容,所以当嵌套很多时打开页面就会特别慢。
  5. 代码要结构化、语义化,因为这样可以增加代码的可读性,比如说使用header、footer、section等标签

2、css性能优化

  1. 尽量减少重绘重排的次数

  2. 动画效果的实现,需开启独立的图层,减少重绘重排
    1) 定位: position: absolute/relative

  3. 多个小图标,使用CSS sprite来处理,减少请求次数

  4. 多利用继承,多个子元素公用的样式,如果该样式能继承的话就写在父元素身上

    相信经常可以看到,一个元素的样式,会存在许多被覆盖的情况,大多是子元素本身的样式覆盖了继承自父元素身上的样式。这样的话,页面可能就会出现被多次重绘的现象

  5. 使用子选择器、后代选择器时,不要嵌套过深,加深解析的难度。

3、JS性能优化

  1. 合并压缩js
  2. 不要反复去获取相同的dom节点,查找节点是非常消耗性能的

如何减少dom操作:
1、对dom查询做缓存,
2、多个操作尽量合并在一起执行
3、用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
4、避免全局查询

  1. 减少http请求的次数,节省网络资源
  2. 少用全局变量
  3. 慎用闭包,防止内存泄漏

  1. 更新频率不高的资源做缓存,减轻服务器压力的同时也能够提高响应速率
  2. 对于调用频率比较高的方法,通过函数节流,函数防抖等方法,降低回调频率。

函数防抖:简单的说,当一个动作连续触发,则只执行最后一次
函数节流:简单的说,当一个动作连续触发,则限制该方法在一定时间内只能执行一次。减少执行的频率

函数节流、函数防抖的参考链接:
https://blog.csdn.net/yiyueqinghui/article/details/108711456


  1. 移动端使用touch事件代替click事件
  2. 非核心代码异步加载,实现方法是,script标签中使用defer 、async实现延迟或异步加载

defer是在html解析完之后才会执行,如果是多个,按照加载的顺序依次进行。
async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关。

4、Vue/React框架开发项目的优化

参考链接:https://blog.csdn.net/yiyueqinghui/article/details/122056448

\

原文链接:blog.csdn.net/efew212efe/… 原文链接:blog.csdn.net/weixin_4298… 原文链接:blog.csdn.net/weixin_4298…

13. Vue项目遇到的一些难点

1、使用axios.js 处理异步加载时发现请求时传递参数会直接发送js对象到后端 而不是发送Form Data 而且post 请求 会发送两次请求 第一次是 method是options 第二次才是post。

解决方法:配合qs插件使用 也就是将对象格式化成 Form Data 类似jquery中的serialiZeArray()方法

2、使用vue-router时 URL模式引发的问题?

Vue-router 提供一个mode参数 用来控制 URL 格式 默认使用的是 hash格式 而我在项目中使用的是history格式

对比:使用history 后发现手动切换页面一切正常 但刷新页面是会提示页面不存在(404) 原因就是后端把URL解析了,使用hash模式 URL中会有一个#号分割 后端默认不会解析#后面的参数

3、Vue 项目中 用v-for循环本地图片 图片不显示

解决方法:使用require动态引入图片 或者将图片放static文件夹里

4、elementui中 防止错误提示框多个弹出 可以直接调用(Message as any).colseAll() ; 也可从新 Message()方法

原文链接:blog.csdn.net/weixin_5627…

14. 优雅降级和渐进增强

渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。

优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。

其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中, 经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。

原文链接:blog.csdn.net/weixin_4298…

15. 怎样添加、移除、移动、复制、创建和查找节点?

(1)创建新节点

createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点

(2)添加、移除、替换、插入

appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入

(3)查找

getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性

16. Vue 项目 打包 部署 上线

开发完功能,分阶段将代码直接提交到不同的环境

提交到开发环境:前后端联调
提交到测试环境:测试进行验证
提交到生产环境:向用户提供服务
前端项目部署:nginx代理\

17.还原ui设计稿使用的工具

snipaste

原文链接:blog.csdn.net/weixin_4298…