前言
本系列主要整理博主2023秋招的面试情况。本节介绍20220713兴业数金前端一面。
1. 自我介绍
2. 为什么要学习vue?
答:首先因为vue是当前前端较为流行的框架,使用vue的公司较多,也证明了这是一个非常成功的框架;第二是因为这个框架是国人编写的,简单易学,上手较快;第三因为这个框架使用了双向数据绑定,数据和视图的交互更加方便;最后因为它含有组件化、视图数据结构分离、虚拟DOM、运行速度快等特点。
3. 双向数据绑定和单向数据绑定的区别,以及双向数据绑定的优缺点?
答:双向数据绑定就是当我们采用MV模式时,就是模型-视图模式时,通常,我们需要编写代码,将从服务器获取的数据进行“渲染”,展现到视图上。每当数据有变更时,我们会再次进行渲染,从而更新视图,使得视图与数据保持一致。而另一方面,页面也会通过用户的交互,产生状态、数据的变化,这个时候,我们则编写代码,将视图对数据的更新同步到数据,以致于同步到后台服务器。而单向数据绑定只有模型----->视图的一个方向的数据传递。
双向数据绑定的优缺点:
①优点:用户在视图上的修改会自动同步到数据模型中去,数据模型中值的变化也会立刻同步到视图中去;无需进行和单向数据绑定的那些相关操作,会简化大量业务无关的代码。
②缺点:增加了出错时的debug的难度、消耗较大,部署很大网站的时候会出现问题。
4. 双向数据绑定报错的话要怎么寻找问题?
答:可以打开开发者模式,会有相应的报错,比如props不存在、期待一个Object你传入了一个Array之类的,可以直接从报错中找到。
5. 解释一下防抖和节流?
- 防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发,只会执行最后一次;
- 节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
6. 项目用什么打包的?
答:webpack。
7. 说一下webpack里做了哪些前端优化?
- 压缩代码:删除多余的代码、注释、简化代码的写法等等?式。可以利?webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 来压缩JS?件, 利? cssnano (css-loader?minimize)来压缩css
- 利?CDN加速: 在构建过程中,将引?的静态资源路径修改为CDN上对应的路径。可以利?webpack对于 output 参数和各loader的 publicPath 参数来修改资源路径
- Tree Shaking: 将代码中永远不会?到的?段删除掉。可以通过在启动webpack时追加参数 --optimize-minimize 来实现
- Code Splitting: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利?浏览器缓存
- 提取公共第三?库: SplitChunksPlugin插件来进?公共模块抽取,利?浏览器缓存可以?期缓存这些?需频繁变动的公共代码
8. 对一个绝对定位的盒子怎么水平垂直居中?
①绝对定位+margin:auto ②绝对定位+margin负值 ③绝对定位+translate
9. 隐藏元素的方法?
(1)dispaly:none 消失+重排+重绘+绑定事件不触发+无过渡;
(2)visibility:hidden 存在+不重排+重绘+绑定事件不触发+有过渡;
(3)opacity:0 存在+不重排+不一定重绘+触发自身绑定+有过渡;
(4)position:absolute 移除视线;
(5)z-index:负值 使用其他元素遮盖;
(6)transform:scale(0,0) 缩放元素为0 存在+绑定事件不触发。
10. Promise().then()返回的也是Promise对象,要怎么判断这个Promise对象的状态?
let p1 = new Promise(function(){})
let p2 = p1.then((resolve,reject)=>{})
-
如果p1的状态的pending,那么p2的状态也是pending; -
如果p1的状态的resolved,then会执行resolve,那么p2的状态由resolve的返回值决定;
- 如果resolve()的返回值不是一个promise对象,那么p2的状态是resolved,且p2的值就是resolve()的return值。
- 如果resolve()的返回值是一个promise对象,那么p2的状态以及值由这个promise对象为准。
- 如果resolve()的返回值内部出现了错误(或者是用户抛出错误),那么p2的状态是rejected,且p2的值就是错误对象。
-
如果p1的状态是rejected,then会去执行reject(),那么p2的状态由reject()的返回值决定。
- 如果reject()的返回值不是一个promise对象,那么p2的状态是resolved,且p2的值就是resolve()的return值。
- 如果reject()的返回值是一个promise对象,那么p2的状态以及值由这个promise对象为准。
- 如果resolve()的返回值内部出现了错误(或者是用户抛出错误),那么p2的状态是rejected,且p2的值就是错误对象。
11. import 和 export的都是什么?
- export方式导出对象、方法、引用,但是导入的时候不可直接指定对象、方法,需要通过大括号"{}"来指定属性、变量名,如下:
import axios from 'axios'
export function get({url,params = {}}) {
return new Promise((resolve,reject) => {
axios.get(url,{
params:params
}).then( response =>{
landing(url, params, response.data);
resolve(response.data);
}).catch(error =>{
reject(error)
})
})
}
import { get } from '../utils/http';
- export default导出可不必须指定函数名、类名等,在一个文件或模块中,export、import 可以有多个,export default 仅有一个,export default 向外暴露的成员,可以使用任意变量来接收且import时不需要用大括号嵌套,也不能用大括号嵌套,如:
export default function HttpData (fecth,url, parm) {
let _data = "";
return new Promise((resolve, reject) => {
switch (fecth){
case "get":
get(url, parm).then(function (response) {
resolve (response);
}).catch(function (error) {
console.log("get request failed.",error);
});
break;
case "post":
post(url, parm).then(function (response) {
resolve (response);
}).catch(function (error) {});
break;
default:
break;
}
});
}
import http from '../utils/http';
12. 解释一下项目中的菜单权限的实现?
答:由于不同用户登录以后应该有不同的权限,可以看到不同的内容,因此需要给不同的用户在菜单上分配不同的权限。菜单权限最重要的一点就是:**当获取用户信息的时候,服务器会把响应的用户拥有菜单的权限信息返回,需要根据用户身份对比出,当前这个用户需要展示哪些菜单。**本项目中,服务器会返回给用户拥有的菜单权限信息,在vuex中可以获取到,然后通过提取路由、对比路由、重组路由就可以得到当前用户用户的异步路由+常量路由,进一步修改路由的渲染数组,就能最终展示出菜单权限。
13. 登录中的token是怎么存储的?
答:服务器下发的token,是用户唯一的标识符,token不应该存在vuex中,因为如果存在vuex中,刷新页面token就会消失,因此要把token放在本地存储中,这样在导航守卫的过程中就可以获取token,进而判断是否还能点击登录页面。
同学问到的一些通用问题:
1. 良好的编码习惯有什么?
- 善于用语义化标签给网页布局,如header , footer , aside , content ,nav等;
- 将HTML标签和CSS样式表分割开来;
- 注意文件的命名规范,如global.css , layout.css 等;
- CSS中class与id不重名,书写样式的时候遵循布局定位属性–>自身属性–>文本属性–>其他属性的顺序;
- 为复杂的代码逻辑编写注释。
2. Promise()中的race和all的区别?
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。Promise.race()将里面返回最快的结果返回,不管结果本身是成功状态还是失败状态。当要做一件事,超过多长时间就不做了,可以用这个方法来解决:
Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
3. 解释一下组件化?
- 组件是独立和可复用的代码组织单元。组件系统是Vue核心特性之一,它使开发者使用小型、独立和通常可复用的组件构建大型应用;
- 组件化开发能大幅提高应用开发效率、测试性、复用性等;
- 组件使用按分类有:页面组件、业务组件、通用组件;
- vue的组件是基于配置的,我们通常编写的组件是组件配置而非组件,框架后续会生成其构造函数,它们基于VueComponent,扩展于Vue;
- vue中常见组件化技术有:属性prop,自定义事件,插槽等,它们主要用于组件通信、扩展等;
- 合理的划分组件,有助于提升应用性能;
- 组件应该是高内聚、低耦合的;
- 遵循单向数据流的原则。
4. 解释一下微任务和宏任务?
答:JS是一门单线程语言,JS实现单线程非阻塞的方法就是事件循环。JS把任务分为同步任务和异步,当执行遇到同步任务时,则立即执行,如果遇到异步任务,则挂起任务,异步任务也分为宏任务和微任务,微任务比如Promise.then、nextTick、await/async、MutonObserver、Object.observe,微任务要在主函数执行结束、当前宏任务结束之前执行,而宏任务包括执行script标签内部代码、setTimeout/setInterval、ajax请求、postMessageMessageChannel、setImmediate,I/O。
5. 解释一下深浅拷贝?
答:深拷贝和浅拷贝是针对引用数据类型来说的。浅拷贝就是只拷贝一层,深层次的引用类型则共享内存地址。通过浅拷贝得到的引用数据,如果修改第一层的数据,那么新数据改变不会影响原数据;如果修改第二层的引用类型数据,则新旧数据会一起改变。存在浅拷贝现象的有:①Object.assign ;②Array.prototype.slice()、Array.prototype.concat();③使用拓展运算符实现的复制。
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。常见的深拷贝方式有:①_.cloneDeep()、②jQuery.extend()、JSON.stringify()、手写循环递归。
|