大家有补充可以留言呀
1、v-for的key作用?
答:目前可以理解为遍历数组或元素中的唯一标识,增加或删减元素时,通过这个唯一标识key判断是否是之前的元素,并且该元素key的值是多少。这个唯一标识是保持不变的。
Vue中为v-for提供了一个属性,key:
key属性可以用z提升v-for渲染的效率!vue不会去改变原有的元素和数据,而是创建新的元素然后把新的数据渲染进去
在使用v-for的时候,vue里面需要我们给元素添加一个key属性,这个key属性必须是唯一的标识
给key赋值的内容不能是可变的
\1. 在写v-for的时候,都需要给元素加上一个key属性
\2. key的主要作用就是用来提高渲染性能的!
3.key属性可以避免数据混乱的情况出现 (如果元素中包含了有临时数据的元素,如果不用key就会产生数据混乱)
2、require和import的区别?
答:区别1:模块的加载时间
Require:运行时加载
Import:编译时加载,效率更高,由于是编译时加载,所以import命令会被提升到头部
区别2:模块的本质
Require:模块就是对象,输入时必须查找对象属性
Import:ES6模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入(这也导致了没法引用 ES6 模块本身,因为它不是对象)。由于 ES6 模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽 JavaScript 的语法,比如引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。(一个是导入整个对象,从对象上去方法,另一个是只取方法)
区别3:严格模式
Commomjs模块默认是非严格模式,输出是值得拷贝
Es6模块默认是严格模式,输出是值得引用
3、三次握手四次挥手?
答:三次握手:
第一次:客户端发送请求到服务器,服务器知道客户端发送,自己接收正常。SYN=1,seq=x
第二次:服务器发给客户端,客户端知道自己发送、接收正常,服务器接收、发送正常。ACK=1,ack=x+1,SYN=1,seq=y
第三次:客户端发给服务器:服务器知道客户端发送,接收正常,自己接收,发送也正常.seq=x+1,ACK=1,ack=y+1
四次挥手:
第一次:客户端请求断开FIN,seq=u
第二次:服务器确认客户端的断开请求ACK,ack=u+1,seq=v
第三次:服务器请求断开FIN,seq=w,ACK,ack=u+1
第四次:客户端确认服务器的断开ACK,ack=w+1,seq=u+1
4、为什么三次握手四次挥手?
答:三次握手时,服务器同时把ACK和SYN放在一起发送到了客户端哪里
四次挥手时,当收到对方得FIN报文时,仅仅表示对方不在发送数据了,但是还能接收数据己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方得ACK和FIN一般都会分开发送。
5、img、inlineblock的底部3像素问题怎么解决?
答:(1)display:block
(2)在img的都标签增加font-size:0
(3)img标签增加float:left
6、Vue实现数据双向绑定的原理:Object.DefineProperty,
答:vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
简便说法: 当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。
7、vuex是什么?怎么使用?哪种功能场景使用她?
答:只用来读取的状态集中放在store中,改变状态的方式是提交mutations,这是个同步的,异步逻辑应该封装在action中
在main.js引入store,将vuex的数据注册到vue全局对象上
应用场景:单页应用中,组件之间的状态,音乐播放,登陆状态,加入购物车
state:Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations:mutations定义的方法动态修改Vuex 的 store 中的状态或数据
getters:类似vue的计算属性,主要用来过滤一些数据。
action:actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action
8、如何让css只在当前组件中起作用?
答:将当前组件的<style>修改为<style scoped>
9、Route和Router的区别?
Route是路由信息对象,包括path、params、query、name等路由信息参数
Router是路由实例对象,包含了路由跳转的方法和钩子函数
10、构建的 vue-cli 工程都到了哪些技术,它们的作用分别是什么?
答:vue.js:vue-cli工程的核心,主要特点是 双向数据绑定 和 组件系统。
vue-router:vue官方推荐使用的路由框架。
vuex:专为 Vue.js 应用项目开发的状态管理器,主要用于维护vue组件间共用的一些 变量 和 方法。
axios( 或者 fetch 、ajax ):用于发起 GET 、或 POST 等 http请求,基于 Promise 设计。
vuex等:一个专为vue设计的移动端UI组件库。
创建一个emit.js文件,用于vue事件机制的管理。
webpack:模块加载和vue-cli工程打包器。
11、timeline工具快速定位组件出现性能问题
12、类的创建和继承?
答:(1)利用function和this关键字
(2)原型方法
利用prototype关键字和this关键字
(3)利用object.create()方法构造
类的继承:
(1) 原型链继承:原型链继承是JavaScript实现继承的主要办法,利用原型让一个引用类型继承另一个引用的类型的属性和方法
(2) 构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类
(3) 组合继承:相当于构造继承和原型链继承的组合体,通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
13、async和await的原理?
答:async和await确实也算是Promise的语法糖,但实际是promise包裹了generator的语法糖。
这个Promise包裹的非常特别,是一个递归一直next直到没有yield才进行resolve的promise,如果下面还有yield,那么就调用Promise.resolve来递归。
async函数就是generator函数的语法糖。
async函数,就是将generator函数的*换成async,将yield替换成await。
【async函数对generator的改进】
(1)内置执行器,不需要使用next()手动执行。
(2)await命令后面可以是Promise对象或原始类型的值,yield命令后面只能是Thunk函数或Promise对象
(3)返回值是Promise。返回非Promise时,async函数会把它包装成Promise返回。(Promise.resolve(value))
14、vue中使用async和await来实现同步和异步?
promise的基本用法:在promise的内部,执行顺序是同步的,等内部执行完成后,调用then或catch方法,
then方法的执行是异步的,每次当`promise`执行完成后,`then`是异步的,所以当执行`then`后,不会等它的结果,会直接执行下面的代码,但是`setTimeout`定时器本身会将执行内容调到`任务队列`尾部,所以会等`then`方法执行完成后才会调用定时器
async:表示异步函数,异步函数也就意味着该函数的执行不会阻塞后面代码的执行,async函数返回的是一个promise 对象
await:表示同步,意思是等待,需要按照顺序执行
15、http1和2协议区别?
\1. Http1.x
缺陷:线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制数目的请求会被阻塞。
\2. Http1.0(短连接)
缺陷:浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接(TCP连接的新建成本很高,因为需要客户端和服务器三次握手),服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求;
解决方案:添加头信息——非标准的Connection字段Connection: keep-alive
\3. Http1.1
改进点:
持久连接(与Http1其它版本的最大区别)
引入了持久连接,即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive(对于同一个域名,大多数浏览器允许同时建立6个持久连接)
管道机制
即在同一个TCP连接里面,客户端可以同时发送多个请求。
分块传输编码
即服务端每产生一块数据,就发送一块,采用”流模式”而取代”缓存模式”。
新增请求方式
PUT:请求服务器存储一个资源;
DELETE:请求服务器删除标识的资源;
OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求;
TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断;
CONNECT:保留将来使用
缺点:
虽然允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个请求,才会接着处理下一个请求。如果前面的处理特别慢,后面就会有许多请求排队等着。这将导致“队头堵塞”
避免方式:一是减少请求数,二是同时多开持久连接
\4. Http/2.0
特点:
采用二进制格式而非文本格式;
完全多路复用,而非有序并阻塞的、只需一个连接即可实现并行;(解决了线头阻塞的问题,与Http1最重要的区别)
使用报头压缩,降低开销
服务器推送
4.1 二进制协议
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”:头信息帧和数据帧。
二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少。
4.2 完全多路复用
HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”。
4.3 报头压缩
HTTP 协议是没有状态,导致每次请求都必须附上所有信息。所以,请求的很多头字段都是重复的,比如Cookie,一样的内容每次请求都必须附带,这会浪费很多带宽,也影响速度。
对于相同的头部,不必再通过请求发送,只需发送一次;
HTTP/2 对这一点做了优化,引入了头信息压缩机制;
一方面,头信息使用gzip或compress压缩后再发送;
另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,产生一个索引号,之后就不发送同样字段了,只需发送索引号。
4.4 服务器推送
HTTP协议通常承载于TCP协议之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS.
15、前后端数据结构json
16、map和object的区别?
Object的键只能是字符串或者Symbol,Map的键值可以是任意值
Map的键值对数量可以通过size属性获取,Object则需要通过Object.keys(obj).length类似的方式获取
json支持object但不支持map
Map 在存储大量元素的时候性能表现更好,特别是在代码执行时不能确定 key 的类型的情况。
map只支持new实例化
map想要访问元素:map.get()
object:.和[]
17、json option?
18、webstorm是什么?
它是一款js开发工具,支持js、es6语言,帮助编写html、css、less等代码,支持node、vue、react等主流框架
代码补全:
WebStorm分析项目,为应用程序中定义的所有方法、 函数、模块、变量和类提供最佳代码补全。 代码辅助是上下文感知的,也可以特定于框架
Live Edit
动态编辑可以立刻在浏览器中看到页面内容更新(仅限于Google Chrome), 无需重现加载,即可看到对HTML和CSS文件的变更。 它作为JavaScript调试会话的一部分
导航
WebStorm强大的导航功能,在处理大型项目时, 提高代码效率并节省时间
对于代码中的任何方法、函数或变量,只需Ctrl+点击或搜索其用途, 即可跳到其定义
通过双击 Shift ,即可进行随处搜索(Search Everywhere ),在整个项目中搜索符号、文件或类名
结构视图可以在当前打开的文件中轻松导航
对项目进行代码分析,任何可能有问题的代码行都标记在编辑器右侧的排水沟中,因此可以轻松地在长文件中发现错误和警告
19、防止用户随意修改地址跳转怎么办?路由守卫?
方法1:在入口文件main.js判断是否存在用户的token,若不存在则跳转到登录页面
通过路由独享守卫,路由判断登录 根据路由配置文件的参数
router.beforeEach((to, from, next) => {
// to,将要访问的路径
// from 从哪个路径跳转过来的
// next 是一个函数,代表放行
let token = sessionStorage.getItem('token')
if(to.path==='/login'){
return next()
}else{
if(!token){
return next('/login')
}else{
next()
}
}
})
一、全局路由守卫:
全局路由守卫有两个,一个全局前置守卫,一个全局后置守卫。
router.beforEach((to,from,next)=>{})
router.afterEach((to,from)=>{})
全局后置守卫没有next回调函数
二、组件内部守卫:
跟methods:{}等同级别 组件路由守卫是写在每个单独的Vue文件里面的路由守卫
beforeRouterEnter(to,from,next){ 在路由进入之前调用这个函数 }
beforeRouterUpdate(to,from,next){ 当路由参数发生改变的时候调用这个函数 }
beforeRouterLeave(to,from,next){ 当路由离开当前路由页面的时候调用 }
三、路由独享守卫
路由独享守卫就是在路由配置页面单独给路由配置一个守卫
只是守卫当前的路由 语法:在路由映射表里面写beforeEnter(to,form,next)
to 到那个路由页面去
from 从哪个路由页面来
next() 回调函数参数配置
20、防止用户刷新数据丢失怎么做?
在做vue项目的过程中有时候会遇到一个问题,就是进行F5页面刷新的时候,页面的数据会丢失,出现这个问题的原因是因为当用vuex做全局状态管理的时候,store中的数据是保存在运行内存中的,页面刷新时会重新加载vue实例,store中的数据就会被重新赋值,因此数据就丢失了,解决方式如下:
最先想到的应该就是利用localStorage/sessionStorage将数据储存在外部,做一个持久化储存,下面是利用localStorage存储的具体方案:
方案一:由于state中的数据是响应式的,而数据又是通过mutation来进行修改,故在通过mutation修改state中数据的同时调用localStorage.setItem()方法来进行数据的存储。在页面加载的时候再通过localStorage.getItem()将数据取出放回到vuex
方案二:通过监听beforeunload事件来进行数据的localStorage存储,beforeunload事件在页面刷新时进行触发,具体做法是在App.vue的created()周期函数
21、vue动态绑定class的最常用的几种方式?
1、绑定单个class
html部分:
<div :class="{'active':isActive}"></div>
js部分:判断是否绑定一个active
data() {
return {
isActive: true
};
}
结果渲染为:
<div class="active"></div>
2、(绑定的数据对象)
<div :class="classObject"></div>
data: {
classObject: {
active: true,
}
}
3、(绑定一个返回对象的计算属性)
<div :class="classObject"></div>
复制代码
export default {
data() {
return {
isActive: true,
};
},
computed: {
classObject: function () {
return {
active: this.isActive,
}
}
}
22、p标签获取第3个以后?
23、一条为0.5px的横线?
24、vuerouter怎么实现按需加载(路由懒加载)?
:当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
1、vue异步组件
2、es提案的import()
没有指定webpackChunkName,每个组件打包成一个js文件。
指定了相同的webpackChunkName,会合并打包成一个js文件。 把组件按组分块
3、webpack的require,ensure()
webpack提供的require.ensure()
vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。
这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
25、js深拷贝,多层嵌套怎么解决?
深拷贝
:修改新变量的值不会影响原有变量的值。默认情况下基本数据类型(number,string,null,undefined,boolean)都是深拷贝。
浅拷贝:修改新变量的值会影响原有的变量的值。默认情况下引用类型(object)都是浅拷贝。
解构赋值,如果所解构的原对象是一维数组或对象,其本质就是对基本数据类型进行等号赋值,那它就是深拷贝;
如果是多维数组或对象,其本质就是对引用类型数据进项等号赋值,那它就是浅拷贝
25、router-link使用要注意什么
26、js的解构?
27、less和scass的区别?
1、Less在JS上运行,Sass在Ruby上使用。
2、编写变量的方式不同。
Sass使用$,而Less使用@。
3、在Less中,仅允许循环数值。
在Sass中,我们可以遍历任何类型的数据。但在Less中,我们只能使用递归函数循环数值。
4、Less与Sass处理机制不一样
前者是通过客户端处理的,后者是通过服务端处理,相比较之下前者解析会比后者慢一点
5、sass有函数的概念;
-@function和@return以及函数参数(还有不定参)可以让你像js开发那样封装你想要的逻辑。
-@mixin类似function但缺少像function的编程逻辑,更多的是提高css代码段的复用性和模块化,这个用的人也是最多的。Sass有Compass,Less有Preboot
Sass和LESS有可用于集成mixins的扩展(在整个站点中存储和共享CSS声明的能力)。
Sass有适用于mixins的Compass,其中包括所有可用的选项以及未来支持的更新。
LESS有Preboot.less,LESSMixins,LESSElements,gs和Frameless。LESS的软件支持比Sass更加分散,导致许多不同的扩展选项可能不会以相同的方式运行。对于项目,我们可能需要所有列出的扩展以获得与Compass类似的性能。
28、jsx的问题?if-else?
1、使用三目运算
2、直接放在render里面
3、从render里面拿出来放进函数中
29、使用histroy路由的方式需要注意什么
1、如果用户考虑url的规范,那么就需要使用history模式,history模式没有#号,符合规范
2、在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要后端配置一下nginx的url的重定向
30、vue中如何监听数组的变化?
31、浏览器如何实现不同标签页的通信?
一:但是由于仅仅从cookie读取信息不能实时更新,需要手动刷新,因此采用setInterval定时器解决,将读取信息的代码封装成一个函数,在定时器内调用即可
缺点:
1)cookie空间有限,容量4k
2)每次http请求都会把当前域的cookie发送到服务器上,浪费带宽
3)setInterval评率设置过大会影响浏览器性能,过小会影响时效性
优点:每个浏览器都兼容
二、websocket协议
websocket是一种网络通信协议,因为http有缺陷,通信只可以由客户端发起,服务器无法主动向客户端发送消息,但如果这时服务器有连续变化的状态,那么就只能使用轮询(每个一段时间,就发出一个询问)的方式来询问。因为websocket拥有全双工(full-duplex)通信自然可以实现多个标签页之间的通信。
发送方先发送消息到WebSocketServer,然后服务端再实时把消息发给接收方
用法:新建webSocket文件夹,在该目录下打开终端,运行npm init (npm安装及配置步骤)初始化一个简单的node项目(因为需要引入ws包),一直按回车到结束就初始了一个简单的node项目。再安装ws包,依旧在当前目录下的终端运行npm i -save ws,在webSocket目录下新建sever.js、send.html、reveive.html文件
三、localstorage
四、html5浏览器新特性——SharedWorker
WebWorker的升级版,webworker只能在一个窗口内使用,而SharedWorker可以在多个窗口之间通信
SharedWorker也是纯客户端的,没有服务端参与
SharedWorker在客户端有一个自己维护的对象worker.js,消息存储在worker.js的data中
SharedWorker不如localStorage的是接收消息不是自动的,也要用定时器实时从worker.js中获取消息
32、Vue 的响应式原理中 Object.defineProperty有什么缺陷?
为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty? Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象。
Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
1.MVVM的理解
MVVM是model-view-viewmodel的缩写。MVVM是一种设计思想。model层代表数据模型,也可以在model中定义数据修改和操作的业务逻辑;view代表UI组件(视图),他负责将数据模型转化成UI展现出来,viewmodel是一个同步view和model的对象
在MVVM架构下,view和model之间并没有直接的联系,而是通过viewmodel进行交互,model和viewmodel之间的交互是双向的,因此view数据的变化会同步到model中,而model数据的变化也会立即反应到view上。
viewmodel通过双向绑定把view层和model层连接了起来,而view和model之间的同步工作完全是自动的,无需人为干涉,因此开发者只需要关注业务逻辑,不需要手动操作dom,不需要关注数据状态的问题,复杂的数据状态维护完全由MVVM来统一管理
2.vue双向绑定的原理
vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
具体步骤:
1.需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,这样的话,给 这个对象的某个值赋值,就会触发setter,那么就能监听到数据的变化
2.compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
3.Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
a.在自身实例化时往属性订阅器(dep)里面添加自己
b.自身必须有一个update()方法
c.待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退
4.MVVM作为数据绑定的入口,整合Observe、Compile和Watcher三者,通过Observe来监听自己的model数据的变化,通过compile来解析编译模板指令,最终利用Watcher搭起Observe和Compile之间的通信桥梁,达到数据变化->视图更新;视图交互变化(input)-> 数据model变更的双向绑定效果
3、Vue组件间的参数传递
1.父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据; 子组件传给父组件:$emit方法传递参数
2.非父子组件间的数据传递,兄弟组件传值
eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适
4、v-show 与 v-if 区别
v-show和v-if的区别:
v-show是css切换,v-if是完整的销毁和重新创建。
使用
频繁切换时用v-show,运行时较少改变时用v-if
v-if=‘false’ v-if是条件渲染,当false的时候不会渲染
5、ES6新特性
1.let、const和块级作用域
2.箭头函数
3.模板字符串
4.对象字面量扩展语法
5.表达式结构
6.函数参数表达、传参
7.新的数据结构
8.类语法
9.生成器
10.Promise
11.代码模块化
12.Symbol
13.Proxy
6、H5和C3新特性
H5新特性
1.拖拽释放(Drap and drop) API ondrop
拖放是一种常见的特性,即抓去对象以后拖到另一个位置。在HTML5中,拖放是标准的一部分,任何元素都能拖放
2.自定义属性的data-id
3.语义化标签 header、nav、footer、aside、article、section
4.音频,视频(audio,video)如果浏览器不支持自动播放,在属性中添加autoplay
5.画布Canvas
6.地理(Geolocation)API
7.本地离线存储localStorage长期存储数据 浏览器关闭后数据不会丢失
8.sessionStorage 的数据在浏览器关闭后自动删除
9.表单控件calendar,date,time,email,url,search,tel,file,number
10.新的技术webworker、websocket、Geolocation
CSS3新特性
1.颜色:新增RGBA,HSLA模式
2.文字阴影(text-shadow)
3.边框:圆角(border-radius) 边框阴影:box-shadow
4.盒子模型 box-sizing
特征:具有content、padding、border、margin4个属性
盒子模型有两种形式:
标准盒子模型:box-sizing: content-box 标准模型会被padding撑开
怪异盒子模型:box-sizing: border-box 怪异模型不会被padding撑开
5.背景 background-size background-origin background-clip
6.渐变: linear-gradient , radial-gradient
7.过渡:transition 可实现动画
8.自定义动画: ainimate @keyfrom
9.媒体查询 多栏布局 @media screen and (width:800px){}
10. border-image
11.2D转换;transform:translate(x,y) rotate(x,y) skew(x,y) scale(x,y)
12.3D转换
13.字体图标 font-face
14.弹性布局flex
7、父子组件生命周期的执行顺序
1.父组件的beforeCreate
2.父组件的created
3.父组件的beforeMount
4.子组件的beforeCreate
5.子组件的created
6.子组件的beforeMount
7.子组件的mounted
8.父组件的mounted
8、vue生命周期
9、vue的优点
1.低耦合。视图view可以独立于model变化和修改,一个viewmodel可以绑定到不同的view上,当view变化的时候model可以不变,当model变化的时候view也可以不变
2.可重用性。你可以把一些试图逻辑放在一个viewmodel里面,让很多view重用这段视图逻辑
3.独立开发。开发人员可以专注于业务逻辑和数据的开发(viewmodel),设计人员可以专注于页面设计
4.可测试。界面素来是比较难于测试的,而现在测试可以针对viewmodel来写
10、vuex相关
1.vuex是什么?怎么使用?哪种功能场景使用它
vuex是vue框架中的状态管理。
在main.js 中引入store,注入。新建一个目录store,。。。。export
一般使用场景有单页应用,组件之间的状态。登录状态、购物车
2.vuex有哪几种属性?
有五种属性,分别是State、Getter、Mutation、Action、Module
3.vuex的State特性
a.vuex就是一个仓库,仓库里面放了很多对象,其中state就是数据源存放地,对应于一般vue对象里面的data
b.state里面存放的数据是响应式的,vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会更新
c.它通过mapState把全局的state和getters 映射到当前组件的computed计算属性中
4.vuex的Getter特性
a.getters可以对State进行计算操作,他就是Store的计算属性
b.虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
c.如果一个状态只在一个组件内使用,是可以不用getters
5.vuex的Mutation特性
Action 类似于 mutation ,不同点在于 :Action 提交是的 mutation ,而不是直接变更状态; Action可以包含任意异步操作
6.不用vuex会带来什么问题
a.可维护性会下降,想修改数据要维护三个地方
b.可读性会下降,因为一个组件里的数据,根本看不出来是从哪里来的
c.增加耦合,大量的上传派发,会让耦合性大大增加,本来vue用component就是为了减少耦合,现在这么用和组件话的初衷相悖
11、性能优化
1.内容方面
a.DNS解析优化(DNS缓存、减少DNS查找、keep-alive、适当的主机域名)
b.减少HTTP请求次数
c.减少DOM操作
d.使用Ajax
2.css方面
a.把css样式放在HTML代码的上端
b.从页面中分离css代码,从外部引入
c.压缩代码
d.不要使用@import
e.避免css表达式
3. js方面
a.脚本放在HTML底部
b.从页面中分离js代码,从外部引入
c.压缩代码
d.减少对DOM的访问
e.移除重复的脚本
4.图片方面
a.优化图片(少用图片用css3新特性代替,使用矢量图代替位图) 矢量图:图标字体 位图:gif、jpg、png
b.不要在HTML中使用缩放图片
c.使用恰当的图片格式
d.按照HTTP协议设置合理的缓存
e.用css或js实现预加载
f.WebP图片格式能给前端带来优化 webp格式:谷歌开发一种旨在加快图片加载速度的图片格式
12、watch和computed的区别
计算属性computed
1.支持缓存,只有当依赖数据发生改变,才会重新进行计算
2.不支持异步,需要return
3.computed属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
4.如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,可以使多个值影响一个值,一般用computed
5.如果computed属性属性值是函数,那么默认会走get方法,函数的返回值就是属性的属性值,在computed中 的属性都有一个set和get方法,当数据变化时,调用set方法
侦听属性watch
1.不支持缓存,数据变化,直接触发相应的操作
2.watch支持异步
3.监听的函数接受两个参数,第一个参数是最新的值,第二个参数是输入之前的值
4.当一个属性发生变化时,需要执行对应的操作,一对多
5.监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数 immediate:组件加载立即触发回调函数执行, deep:深度监听,为了发现对象内部值的变化,复杂类型而定数据时使用,例如数组中的对象内容改变,注意监听数组的变动不需要这么做。 注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到
13、vue中如何解决页面不重新渲染的问题
1.修改对象属性后页面未重新渲染可以使用this.$set(对象名称,'属性名','属性值')
2.使用this.$forceUpdate()方法可以重新渲染页面
```
14、vue中事件的修饰符主要有哪些,分别是什么作用
```tex
.stop 阻止事件冒泡
.native 绑定原生事件
.once 事件只执行一次
.self 将事件绑定在自身身上 相当于阻止事件冒泡
.prevent 阻止默认事件
.caption 用于事件捕获
```
15、什么是keep-alive
```tex
keep-alive是用于做组件缓存的,只会执行一次,不会被销毁。被keep-alive包裹的组件,没有create和beforeDestroyed等方法,但是有active和deactivated方法
```
16、防抖与节流
```tex
防抖:
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
缺点:如果事件在规定的时间间隔内被不断的触发,则调用的方法会被不断的延迟
节流:
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
实现方式:每次触发事件时,如果当前有等待执行的延时函数,则直接return
区别和应用:
函数防抖:将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发
函数节流:使得一定时间内只触发一次函数,原理是通过判断是否有延迟调用函数未执行
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次时间后才触发一次函数。如果在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次ajax请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。如果是在进行搜索的时候,当用户停止输入后调用方法,节约请求资源,这时就适合用防抖。
```
17、vue中路由传值的三种方式
```
通过query属性传值
this.$router.push({path:"/login",query:{} })
跳转后页面获取参数 this.$route.query
通过params属性传值
this.$router.push({name:"login",params:{} )}
跳转后页面获取参数 this.$route.params
通过动态路由的方式
this.$router.push('/detail/' + id )
跳转后页面获取参数 this.$toute.params.id
总结:动态路由和query属性传值 页面刷新参数不会丢失 params会丢失
动态路由一般用来传递一个参数时居多 例如详情页的id, query和params可以传递一个或多个参数
```
18、vuex中的数据传递
```
state存放数据源
cosnt state = ()=>({
goodsList:[]
})
gettres 相当于组件的计算属性 computed
const getters = {
.......
}
在组件中获取getters中的数据
mounted(){
this.$store.getters
}
mutations 修改state中数据一定要用mutations的方法
const mutations = {
setGoodsList(state,data){
state.goodsList = data
}
}
组件中调用mutations内的方法
this.$store.commit("模块名/方法名","传入的值")
actions用来处理异步方法
const actions = {
getGoodsList(store){
//fetch是浏览器原生的方法
fetch("http://localhost:3000/goods").then(res=>
return res.json()
}).then(res => {
store.state.commit("setGoodsList",res)
})
}
}
在组件中调用actions的方法请求数据
mounted(){
//调用actions的方法请求商品列表
this.$store.dispatch("products/getGoodsList")
}
```
19、CSS实现垂直水平居中的方法
```
1.单行文本
line-height 垂直居中
text-align: center 水平居中
2.多行文本
使用position:absolute与transform配合实现
position:absolute
left:50% //使元素距离左边50%
top:50% //使元素距离上边50%
transform:translate(-50%,-50%) //向左-向上平移自身高度和宽度的一半
flex布局
display:flex //定义弹性容器
justify-content:center //垂直居中
align-item:center // 水平居中
3.块级元素
设置父元素为相对定位,给子元素设置绝对定位,top: 0; right: 0; bottom: 0; left: 0; margin: auto;
```
20、写一个简单的ajax请求
```
$ajax({
url:'user1.php', //请求地址
type:'get', //请求方式
data:{id:1}, //请求参数
dataType:'json', //设置响应体类型,一旦设置该项就不再关心服务器的 Content-Type
beforeSend:function(xhr){ //在请求发送前执行的函数,可以用来设置自定义HTTP头信息
console.log('beforeSend',xhr)
},
success:function(res){ //请求成功后的回调函数
console.log(res)
},
error:function(xhr){ //请求失败是执行的函数
console.log(xhr)
},
complete:function(xhr){ // 请求完成后执行的函数(不管请求是否成功,都是完成了请求)
console.log(xhr)
}
})
```
21、web攻击技术
```
1. XSS (Cross-Site Scripting, 跨站脚本攻击):指通过存在安全漏洞的web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击
2.SQL注入攻击
3.CSRF (Cross-Site Request Forgeries, 跨站点请求伪造) :指攻击者通过设置好的陷阱,强制对已完成的认证用户进行非预期的个人信息或设定信息等某些状态更新
```
22、$nextTick()
```
nextTick是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用nextTick,可以在回调中获取更新后的DOM
```
23、图片懒加载的原理
```
为什么需要懒加载:
有时候一个页面里有很多图片,比如京东淘宝这一类,页面图片多,加载的图片就很多,服务器压力就很大,不仅影响渲染速度,还浪费带宽。
为了解决上面的问题,就有了懒加载的方式来减轻服务器的压力,优先加载出现在可视区内的内容,其他部分等进入了可视区再进行加载,从而提高性能
1.懒加载的原理:
浏览器是否发起请求图片是根据<img>的src属性,所以实现懒加载的关键就是,在图片没有进入可视区内的时候,先不给<img>的src赋值,这样浏览器就不会发起请求,等到图片进入了可视区内,再给src赋值。
2.懒加载的实现思路
2.1加载loading图片
2.2判断哪些图片要加载
核心原理:当图片距离顶部的距离 > 可视区域的高度 + 滚动区域的高度 时,表示图片还未进入可视区域
2.3隐形加载图片
2.4替换真图片
```
24、数组的操作方法
```
栈方法 (后进先出)
push() 可以接收任意数量的参数,逐个添加到数组末尾,返回修改后数组的长度 修改原数组
pop() 移除数组中的最后一项 返回被移除的值 修改原数组
队列方法 (先进先出)
shift() 移除数组中的第一项 返回被移除的值 修改原数组
unshift() 在数组前端添加任意项 返回新数组长度 修改原数组
重排序方法
reverse() 翻转数组排序 返回排序后的数组
sort() 比较数组每项大小进行排序 但比较的是数组的第一位 返回排序后的数组 修改原数组
操作方法
concat() 创建当前数组的副本,接受参数添加到副本末尾,返回新构建的数组 不修改原数组
join() 用于把数组中的所有元素放入一个字符串,元素通过指定的分隔符进行分隔,默认使用' , ' 不改变原数组
slice() 相当于截取数组 第一个参数起始项,第二个参数结束项,但不包括结束项 返回新数组 不修改原数组
splice()
删除:可以删除任意数量的项,只需指定2个参数,要删除的第一项的位置和要删除的项数
插入:可以向指定位置插入任意数量的项,只需提供3个参数,起始位置、0(要删除的项数)、要插入的项,如果要插入 多个可以再传入多个项
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,需要3个参数,同上
splice()方法始终会返回一个数组,该数组包含从原始数组中删除的项(如果没有删除任何项则返回空数组) 修改原数组
位置方法
indexOf()、lastIndexOf() 接受两个参数:要查找的项和查找起点位置的索引 indexOf()从数组开头开始查找,lastIndexOf()从数组末尾开始向前查找,两个方法都返回要查找的项在数组中的索引,若没有则返回-1
迭代方法 都包含3个参数 item(数组项的值),index(该项在数组中的索引),array(数组对象本身) 都不会修改原数组
every() 对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
filter() 对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach() 对数组中的每一项运行给定函数,该方法没有返回值
map() 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
some() 对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true
归并方法 包含4个参数 prev(前一个值),cur(当前值),index(索引),array(数组对象)
reduce() 该函数返回的任何值都会作为第一个参数自动传给下一项 从数组第一项开始遍历
reduceRight() 与reduce方法一样,只是方法相反 从数组最后一项开始遍历
es6新增操作数组的方法
find() 传入一个函数,找到数组中符合当前搜索规则的第一个元素,返回它,并终止搜索
findIndex() 传入一个回调函数,找到数组中符合当前搜索规则的第一个元素,返回他的下标,终止搜索
fill(value, start, end) 用新元素替换掉数组内的元素,可以指定替换下标范围
copyWithin() 选择数组的某个下标,从该位置开始复制数组元素,默认从0开始复制。也可以指定要复制的元素范围
from() 将类似数组的对象(array-like-object) 和可遍历(iterable)的对象转为真正的数组
of() 用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数Array()的不足。
entries() 返回迭代器:返回键值对
values() 返回迭代器:返回键值对的value
key() 返回迭代器:返回键值对的key
includes() 判断数组中是否存在该元素,参数:查找的值、起始位置,可以替换es5的indexof。indexof判断元素是否为nan,会 判断错误
Set() 接收一个数组或者是类数组对象,自动去重其中的重复项目,返回一个对象,如果需要得到数组,使用Array.from()
```
25、js的new操作符做了什么事情
```js
function creactPerson (name, age) {
//1. 生成一个新的对象
var o = {}
// call apply 函数执行 call apply 在哪个作用域下执行? 第一个参数就是我们的传递的作用域
//2. 将Person中的this指向o
//Person.call(o,name,age)
Person.apply(o,arguments)
//3. 原型链继承 一旦实例化 实例应该拥有原来的函数的原型属性
o.__proto__ = Person.prototype
//4. 返回这个 o 对象
return o
}
```
26、冒泡事件
冒泡事件是指某个组件上的事件被触发后,事件还会向父级元素传递,父级还会向父级元素传递,一直到页面的顶级元素。
e.stoppagation()取消冒泡
.stop() vue中取消冒泡
.prevent() vue中取消默认事件
27、盒子模型
每个html元素都是一个box。
它包含四个区域:1、内容区域(context),内间距区域(padding),边框区域(border),外边距区域(margin)。
28、箭头函数和普通函数的区别。
箭头函数不能通过new关键词来调用。
箭头函数没有原型。
箭头函数不能改变this的指向。
箭头函数不支持重复命名。
29、vue页面第一次加载会出现那几个钩子函数。
会出现4个:
1、beforecreate
2、created
3、beforemount
4、mounted
30、for in和for of的区别。
首先,for-in是ES5标准,遍历的是key(可遍历对象、数组或字符串的key);for-of是ES6标准,遍历的是value(可遍历对象、数组或字符串的value)。
31、深浅拷贝
浅拷贝:重新在队中创建内存,拷贝前后基本数据类型互不影响,但拷贝前后对象的引用类型共享一块内存,会相互影响。
```js
let a = {name:'gsf',hobby:[1,2,3]}
let b = {}
for(var i in a){
b[i] = a[i] }
b.name = 'atn'
b.hobby[1] = 12
console.log(a)//gsf ,【1,12,3】
console.log(b)//atn,【1,12,3】
```
深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的俩个对象互不影响。
```js
var a = {name:'gsf',hobby:[1,2,3]}
function clone(obj){
let b = {}
if(typeof(obj)!=='object'){
return obj
}else{
for(var i in obj){
b[i]= clone(obj[i])
}
}return b
}
let c = clone (a)
c.name = 'atm'
c.hobby[1] = 0
console.log(c)//name: "atm" hobby:1,0,3
console.log(a)//name: "gsf" hobby:1,2,3
```
32、foreach和map遍历数组的区别
**map方法**
1.map方法**返回一个新的数组**,数组中的元素为原始数组调用函数处理后的值。
2.map方法不会对空数组进行检测,map方法不会改变原始数组。
**forEach方法**
1.forEach方法用来调用数组的每个元素,将元素传给回调函数
2.forEach对于空数组是不会调用回调函数的
33、v-for和v-if的区别
v-for的优先级比v-if的要高。
v-for中的key主要作用是为了更高效的更新虚拟dom。
34、v-on可以绑定多个事件。
35、谈谈你对this指向的看法。
谁调用,this就指向谁
36、vue中的data为什么要写成函数
object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址。只要有一个数据改变了,其他的也会随着改变。只有当data是一个函数时,每个组件都会有自己的作用域,不会相互影响。
37、什么是跨域?怎么解决跨域?
域名、协议、端口任意一个不同都会造成跨域问题。
跨域是指浏览器不能执行其他网站的脚本。
1、通过jsonp的方式。创建一个script标签。通过script里面的src属性来实现。(只能用get请求)
2、跨域资源共享CORS
```js
Access-Control-Allow-Origin//设置请求头
```
3、 nginx代理跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
```js
location / {
add_header Access-Control-Allow-Origin *;
}
```
38、ajax中get和post的区别
GET 请求可被缓存
GET 请求保留在浏览器历史记录中
GET 请求可被收藏为书签
GET 请求不应在处理敏感数据时使用
GET 请求有长度限制
GET 请求只应当用于取回数据
POST 请求不会被缓存
POST 请求不会保留在浏览器历史记录中
POST 请求不能被收藏为书签
POST 请求对数据长度没有要求
39、常见的状态码
200: “OK”
304:该资源在上次请求之后没有任何修改(这通常用于浏览器的缓存机制,使用GET请求时尤其需要注意)。
401 用户没有[访问权限](https://baike.baidu.com/item/访问权限/6533727),
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
408 (请求超时) 服务器等候请求时发生超时。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
40、vue路由的两种模式
1.hash模式
特点:在url地址上有#号
实现的原理:原生的hasChange事件来实现,来监听hash值的变化
window.onhaschange=function(){}
刷新页面的时候:不会去发送请求,页面不会有任何问题,不需要后端来配合
2.history模式
特点:在url地址上没有#号,比较与hash模式看起来好看一些
实现的原理:利用的是history的api 来实现的 popState() 来实现的
刷新页面的时候:会去发送请求然后会导致页面出现找不到的情况,需要后端来配合解决
41、webpack的作用是什么,谈谈你对它的理解?
现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决Scss,Less……新增样式的扩展写法的编译工作。
所以现代化的前端已经完全依赖于webpack的辅助了。
现在最流行的三个前端框架,可以说和webpack已经紧密相连,框架官方都推出了和自身框架依赖的webpack构建工具。
react.js+WebPack
vue.js+WebPack
AngluarJS+WebPack
2、webpack的工作原理?
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。
3、webpack打包原理
把一切都视为模块:不管是 css、JS、Image 还是 html 都可以互相引用,通过定义 entry.js,对所有依赖的文件进行跟踪,将各个模块通过 loader 和 plugins 处理,然后打包在一起。
按需加载:打包过程中 Webpack 通过 Code Splitting 功能将文件分为多个 chunks,还可以将重复的部分单独提取出来作为 commonChunk,从而实现按需加载。把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载
4、webpack的核心概念
Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js
output :出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
5、Webpack的基本功能有哪些?
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
文件优化:压缩 JavaScript、CSS、html 代码,压缩合并图片等
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
6、gulp/grunt 与 webpack的区别是什么?
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。grunt和gulp是基于任务和流(Task、Stream)的。
类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。webpack是基于入口的。
webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
7、webpack是解决什么问题而生的?
如果像以前开发时一个html文件可能会引用十几个js文件,而且顺序还不能乱,因为它们存在依赖关系,同时对于ES6+等新的语法,less, sass等CSS预处理都不能很好的解决……,此时就需要一个处理这些问题的工具。
vue3有静态节点的优化策略,节点没有绑定任何数据时,直接创建dom,不需要额外的计算
8、webpack是什么?
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。
面试题:有哪些常见的Loader?他们是解决什么问题的?
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
eslint-loader:通过 ESLint 检查 JavaScript 代码
面试题:有哪些常见的Plugin?他们是解决什么问题的?
define-plugin:定义环境变量
commons-chunk-plugin:提取公共代码
uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
面试题:Loader和Plugin的不同?
Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
42、事件循环
遇到同步代码,依次推入同步队列并执行
当遇到setTimeout、setInterval,会被推到宏任务队列
如果遇到.then,会被当作微任务,被推入微任务队列
同步队列执行完毕,然后会去微队列取任务,直到微队列清空。然后检查宏队列,去宏队列取任务,并且每一个宏任务执行完毕都会去微队列跑一遍,看看有没有新的微任务,有的话再把微任务清空。这样依次循环
宏:setTimeout, setInterval, DOM渲染, AJAX请求
微:Promise、async/await nextTick
微任务比宏任务执行要早。
宏任务里如果有宏任务,不会执行里面的那个宏任务,而是被丢进任务队列后面,所以会最后执行。
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
当指定的事情完成时,Event Table会将这个函数移入Event Queue。
主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
上述过程会不断重复,也就是常说的Event Loop(事件循环)。