Vuex重要核心属性包括?
State:Vuex使用单一状态树,即每个应用将仅仅包含一个store实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。(用来存储变量)
Mutations:mutations定义的方法动态修改Vuex的store中的状态或数据。(提交更新数据的方法)
Action:actions可以理解为通过将mutations里面处理数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view层通过store.dispath来分发action。(用来解决异步流程来改变state数据)
Getters:类似vue的计算属性,主要用来过滤一些数据。(对state里面的变量进行过滤)
Modules:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
为什么vuex的mutation中不能做异步操作?
每个mutation执行完成后都会对应一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现time-travel了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。
router和route的区别?
router为Vuerouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如:router.push()(可以实现返回上一页)、router.replace()(不可以返回上一页)、router.back()(返回上一页)。
route是一个跳转路由的对象(相当于正在跳转的路由对象),每一个路由都会有一个route对象,是一个局部对象,可以获取对应的name、path、params、query等。
vue-router有几种钩子函数?
全局路由:前置守卫(beforeEach)、解析守卫(beforeReslove)、后置钩子(afterEach)
路由独享的钩子:beforeEnter 单个路由独享的导航钩子,它是在路由配置上直接进行定义的。
组件内的导航钩子:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。它们是直接在路由组件内部直接进行定义的。
axios是什么,其特点和常用语法是什么?
Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中,是前端最流行的ajax请求库,react/vue官方都推荐使用axios发ajax请求
特点:1. 基于promise的异步ajax请求库,支持promise所有的API
2. 浏览器端/node端都可以使用,浏览器中创建XMLHttpRequests
3. 支持请求/响应拦截器
4. 可以转换请求数据和响应数据,并对响应回来的内容自动转换成JSON类型的数据
5. 批量发送多个请求
6. 支持请求取消
7. 安全性高,客户端支持防御XSRF
常用语法:1. axios.get(url[,config]) 发get请求
2. axios.delete(url[,config]) 发delete请求
3. axios.post(url[,data,config]) 发post请求
4. axios.put(url[,data,config]) 发put请求
5. axios.spread() 用来制定接收所有成功数据的回调函数的方法
6. axios.all(promise) 用于批量执行多个异步请求
7. axios.interceptors.request.use() 添加请求拦截器
8. axios.interceptors.response.use() 添加响应拦截器
token一般存放在哪里?为什么不存放在cookie内?
token一般放在本地存储(localStorage)中,token的存在本身只关心请求的安全性,而不关心token本身的安全,因为token是服务器端生成的,可以理解为一中加密技术,但如果存在cookie内的话,浏览器的请求默认会自动在请求头中携带cookie,所以容易受到CSRF(跨站请求伪造)攻击
forEach、for...in、for...of三者区别
forEach更多的用来遍历数组
for...in 一般常用来遍历对象或者json
for...of 数组对象都可以遍历,遍历对象需要通过Object.keys()
for...in 循环出的是key,for...of循环出的是value
keep-alive组件
概念:keep-alive是Vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它。和transition相似,keep-alive是一个抽象组件:它自身不会渲染成一个DOM元素,也不会出现在父组件链中
作用:在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性
各组件传值
父传子:父组件里面定义自定义属性,子组件内用props接收
子传父:子组件里使用$emit定义自定义事件,父组件里发出这个事件来获取所传的值
兄弟组件传值:通过EventBus全局事件总线来传值
使用url拼接字符串的形式传值: 使用$route.query接收
使用友好url传值:使用$route.params接收
使用命名路由params字段传值:使用$route.params接收
使用query对象传值:使用$route.query接收
组件传值:父传子,通过props属性或slot插槽传递,子传父,通过$emit发射自定义事件传递,非父子,通过bus总线传递
路由传值:可通过url路径传值和编程式导航对象传值
vuex状态管理传值
Vue路由的几种模式
hash模式:1. vue-router默认是hash模式
2. url中有 # 号
3. hash值(# 后面的值) 不会被包含在http请求中,改变hash值不会引起页面的重新加载
4. hash兼容到IE8以上
5. hash改变会触发hashChange事件,会被浏览器记录下来,可以使用浏览器的前进和后退
6. 会创建hashHistory对象,在访问不同的路由的时候,会发生两件事
HashHistory.push() 将新的路由添加到浏览器访问的历史的栈顶
HashHistory.replace() 替换到当前栈
history模式:1. url不带参数
2. history兼容IE10以上
3. 在history模式需要后端配合将所有访问都指向index.html,否则用户刷新页面会导致404错误
4. 在HTML4中常用的方法
history.forward() 在历史记录中前进一步
history.back() 在历史记录中后退一步
history.go(n) 在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页
5. HTML5中新增了
history.pushState(data,title,url):在浏览器中新增一条历史记录
history.replaceState(data,title,url):在浏览器中替换当前历史记录
data会在onpopstate事件触发时作为参数传递过去,title为页面标题,url为页面地址;
总结:一共三种模式:hash模式和histor模式,abstract模式如果没有设置浏览器API路由会自动被强制进入此模式
hash和history的区别:hash模式带 # 号 history模式不带 # 号
hash模式:使用url的hash值来作为路由,支持所有浏览器。缺点:只能改变 # 后面的来实现路由跳转
history模式:表示当前窗口的浏览历史。当发生改变时,只会改变页面的路径,不会刷新页面
缺点:怕刷新 如果后端没有配置支持,这个时候前端刷新就是实实在在的请求服务器这样消耗的时间很多还很慢。
abstract模式:适用于所有JavaScript环境,例如服务器端使用Node.js,如果没有浏览器API,路由器将自动被强制进入此模式。
重绘和重排是什么?如何避免?
重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,所以重绘跳过了创建布局树和分层的阶段
重排:当DOM的变化影响了元素的位置和尺寸大小,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确为止,这个过程叫做重排
重排需要重新计算布局树,重绘不需要,重排必定发生重绘,但是涉及到重绘不一定要重排,涉及到重排对性能的消耗更多一些
触发重排的方法:页面初始渲染、添加/删除可见的DOM元素、改变元素位置、改变元素尺寸、改变元素字体大小、改变浏览器窗口尺寸、设置style属性的值等
避免重排的方式:样式集中改变,使用absolute或fixed脱离文档流
解释一下什么是闭包?
闭包:闭包就是在一个函数内部创建另一个函数,让你可以在一个内层函数中访问到其外层函数的作用域。又或者说,闭包就是能够读取其他函数内部变量的函数
闭包需要满足三个条件:1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部嵌套函数中的变量
3. 外部函数返回值必须是内嵌函数
优点:1. 保证函数不受外界干扰,实现封装,避免命名冲突
2. 可以在内存中保存函数变量,充当缓存
3. 可以重复使用变量,并且不会造成变量污染
缺点:内存消耗很大,容易造成内存泄漏
函数的节流和防抖?
节流:节流是指当一个事件触发的时候,为防止事件的连续频繁触发,设置定时器,达到一种一段事件内只触发一次的效果,在当前事件内不会再次触发,当前事件结束以后再次触发才有效
防抖:防抖是指当一个事件触发的时候,为防止频繁触发事件,设置定时器,以达到一种频繁触发期间不处理,只有当最后一次连续触发结束以后才处理
解释一下原型和原型链?
原型:原型就是一个为对象实例定义了一些公共属性和公共方法的对象模板
原型链:每一个实例对象上有一个__proto__属性,指向构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找的过程就形成了原型链,通俗讲:原型链是原型对象创建过程的历史记录,在js中,所有的对象都拥有一个__proto__属性指向该对象的原型(prototype)
JS常见的6种继承方式?
原型链继承
构造函数继承(借用all)
组合继承(组合原型链继承和借用构造函数继承)
原型式继承
寄生式继承
class类实现继承
什么是promise
Promise是异步编程的一种解决方案:从语法上讲,promise是一个对象,它可以获取异步操作的消息
promise有三种状态:pending(等待状态),fulfilled(成功状态),rejected(失败状态),状态一旦改变,就不会在变,promise可以解决异步的问题,但不能说promise是异步的
promise有哪些个API?
promise.resolve()
promise.reject()
当resolve或reject修改promise对象状态之后,通过检测promise对象的状态,决定执行then还是catch回调方法,在这个过程中:resolve和reject起到的作用是修改对象状态,通知回调函数以及传递回调函数可能需要的参数。这样做的好处就是:把逻辑判断和回调函数分开处理
promise.all() 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完成后才执行回调
promise.race([p1,p2,p3]) 就是说括号里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败
promise中reject和catch处理上有什么区别?
reject是用来抛出异常,catch是用来处理异常
reject是promise的方法,而catch是promise实例的方法
reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
网络异常(比如断网),会直接进入catch而不会进入then的第二个回调
promise和async/await的区别和使用?
函数前面多了一个async关键字,await关键字只能用在async定义的函数内,async函数会隐式的返回一个promise,该promise的resolve值就是函数return的值
1. async和await是配对使用的,await存在于async的内部,否则会报错
2. await表示在这里等待一个promise返回,再接下来执行
3. await后面跟着的应该是一个promise对象
cookie、localStorage、sessionStorage的区别?
cookie:自身有一个过期属性,并且在每次的通信过程中国会传送向服务端
localStorage:永久存储,除非手动删除就一直存在
sessionStorage:只存在一个页面周期内,页面关闭就清除了
1. 存储大小限制不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有大小储存的限制,但比cookie大很多,可以达到5M
2. 数据有效期不同,sessionStorage,仅在当前浏览器窗口关闭之前有效,localStorage始终有效,窗口或者浏览器关闭也一直保存,除非手动删除,cookie只在设置的cookie过期时间之间有效,即使窗口关闭或浏览器关闭
3. 作用域不同,sessionStorage不能在不同的浏览器中共享,即使是同一个页面,localStorage在所有的同源窗口中都是共享的,cookie也是在所有同源窗口中共享的
for循环与forEach的区别?
1. for循环可以使用break跳出循环,但forEach不能
2. for循环可以控制循环起点(i初始化的数字决定循环的起点),forEach只能默认从索引0开始
3. for循环过程中支持修改索引,但forEach做不到(底层控制index自增,无法左右它)
什么是深浅拷贝?
深拷贝:两者的地址不同,只是内部保存的数据相同,更改一个数据另一个数据不会变化
浅拷贝:只拷贝引用数据类型的地址,两者指向的是同一个数据,更改一个的值,另一个会跟着变
Js中对于引用类型的数据,默认进行的都是浅拷贝。
数组方法forEach和map的区别?
相同:1. 都是循环遍历数组中的每一项
2. 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)
3. 匿名函数中的this都是指向window
4. 只能遍历数组
不同:1. map()会分配内存空间存储新数组并返回,forEach()不会返回数据,map()遍历后的数组通常都是生成一个新的数组,新的数组的值发生变化,当前遍历的数组不会变化
2. forEach()允许callback更改原始数组的元素,map()返回新的数组,forEach遍历通常都是直接引入当前遍历数组的内存地址,生成的数组的值发生变化,当前遍历的数组对应的值也会变化
介绍Set、Map的区别?
应用场景:Set用于数据重组,Map用于数据储存Set
Set:1. 成员不能重复
2. 只有键值没有键名,类似数组
3. 可以遍历,方法有add、delete、has
Map:1. 本质上是键值对的集合,类似集合
2. 可以遍历,可以跟各种数据格式转换
对http的理解?
HTTP协议是超文本传输协议,是客户端浏览器或其他程序"请求"与Web服务器响应之间的应用层通信协议
HTTPS主要是由HTTP+SSL构建的可进行加密传输,身份认证的一种安全通信通道
http和https的区别?
1. https协议需要申请证书,一般免费证书较少,因而需要一定费用
2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议
3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443
4. http的连接很简单,是无状态的:HTTPS协议是由SSL+HTTP协议构建的可进行加密传输,身份认证的网络协议,比http协议安全
http常见的响应状态码?
201-----提示知道新文件的URL
202-----接收和处理、但处理未完成
203-----返回信息不确定或不完整
204-----请求收到,但返回信息为空
205-----服务器完成了请求,用户代理必须复位当前已经浏览过的文件
400-----错误请求,如语法错误
401-----请求授权失败
402-----保留有效ChargeTo头响应
403-----请求不允许
404-----没有发现文件,查询或URI
405-----用户在Request-Line字段定义的方法不允许
500-----服务器产生内部错误
501-----服务器不支持请求的函数
502-----服务器暂时不可用,有时是为了防止发生系统过载
503-----服务器过载或暂停维修
http常用的几种请求方式?
常见的五种分别是get、post、put、delete、options
GET:请求指定的页面信息,并返回实体主题
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件),数据被包含在请求体中
PUT:从客户单向服务器传送的数据取代指定的文档内容
DELETE:请求服务器删除指定的页面
OPTIONS:允许客户端查看服务器的性能
数据类型的判断有哪些方法?他们的优缺点及区别是什么?
typeof:优点:使用简单,缺点:只能检测出基本类型(除null)
instanceof:优点能检测出引用类型,缺点:不能检测出基本类型,且不能跨iframe
constructor:优点基本能检测所有的类型(除了null和undefined),缺点:constructor易被修改,也不能跨iframe
Object.prototype.toString.call:检测出所有的类型,缺点:IE6下,undefined和null均为Object
call、apply、bind三者的异同?
apply和call一样,修改指向的同时调用函数,唯一的区别是,传参方式不同,aplly需要提供一个数组。
bind修改this指向时不会调用函数,而是生成一个新的函数,新的函数和原函数代码一样,但是里面的this是绑定过的。
应用场景:1. call经常用作继承
2. apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值
3. bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
BFC是什么?
BFC(会计格式上下文):一个创建了新的BFC的盒子是独立布局的,盒子内元素的布局不会影响盒子外面的元素,在同一个BFC中的两个相邻的盒子在垂直方向发生margin重叠的问题
BFC是值浏览器中创建了一个独立的渲染区域,该区域内所有元素的布局不会影响到区域外元素的布局,这个渲染区域只对块级元素起作用
vue中computed和watch的区别是什么?
computed计算属性就是为了简化template里面模板字符串的计算复杂度,防止模板太过冗余。它具有缓存特性
computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理
watch主要用于监控vue实例的变化,它监控的变量当然必须在data里面声明才可以,他可以监控一个变量,也可以是一个对象,一般用于监控路由,input输入框的值特殊处理等等,它比较适合的场景是一个数据影响多个数据,它不具有缓存性
watch:检测的是属性值,只要属性值发生变化,其都会触发执行回调来执行一系列操作
computed:检测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算
除此之外,有点很重要的区别是:计算属性不能执行异步任务,计算属性必须同步执行,也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性。watch也可以检测computed属性
谈谈你平时都用了哪些方法进行性能优化?
1. 减少http请求次数
2. 打包压缩上线代码
3. 使用懒加载
4. 使用精灵图
5. 动态渲染组件
6. CDN加载包
什么是递归,递归有哪些优点或缺点?
递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己,这个函数就是递归函数
优点:结构清晰、可读性强
缺点:效率低,调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的内容是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。
this的指向有哪些?
1. 普通函数中的this指向window
2. 定时器中的this指向window
3. 箭头函数没有this,它的this指向取决于外部环境
4. 事件中的this指向事件的调用者
5. 构造函数中this和原型对象中的this,都是指向构造函数new出来的实例对象
6. 类class中的this指向由constructor构造器new出来的实例对象
7. 自调用函数中的this指向window
组件中的data为什么要定义成一个函数而不是一个对象?
每个组件都是Vue的实例,组件共享data属性,当data的值是同一个引用类型的值时,改变其中一个会影响其它
v-for循环为什么一定要绑定key?
需要使用key来给循环中每个节点做一个唯一标识,要保证一个循环中key的值各不相同, 以避免vue中的重用机制造成可能的渲染异常. 从底层来看, key属性主要为了Diff算法就可以正确的识别此节点。并高效的更新虚拟DOM。
什么叫优雅降级和渐进增强?
都是解决网站对于老旧版本浏览器的兼容问题。
优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效。
渐进增强:从被所有浏览器支持的基本功能开始,逐步的添加那些只有新式浏览器才支持的功能,向页面增加无害于基础浏览器的额外样式和功能。当浏览器支持时,它们会自动的呈现出来并发挥作用。