computed和watch的区别
功能上:computed 是计算属性,watch是监听一个值的变化
是否缓存:computed中的函数所依赖的属性没有发生变化则从缓存中拿,而watch在每次监听值发生变化时都会返回
是否ruturn,computed必须return watch 不是必须
coputed第一次加载就开始监听 ,而watch 默认不监听 需要加属性immediate 为true
使用场景:computed 购物车 一个数据(总额)受多个数据影响 总结 watch 搜索 一个数据影响多个数据
get 和post请求区别
1.本质上的却别:约定和规范上的的区别
在规范中gei请求是用来获取资源的,也就是查询操作的,而post请求是用来传输实体对象的,因此会用post进行怎删改操作
约定来说 get和post的参数传递也是不同的,get请求是将参数拼加到url上进行参数传递的;而post是将参数写入到请求正文中传递的
2、非本质区别:
缓存不同:get平球一般会被缓存,比如常见的css、js、html请求等都会被缓存,而post默认不进行缓存的
参数长度限制不同:
get请求参数是通过url 传递的 只有2k,当然浏览器厂商不同版本不同这个限制大小可能也不同,但相同的是他们都会对url进行限制;而post请求参数是放在正文中 所以没有大小限制。
回退和刷新不同
get请求可以直接进行回退和刷新,不会对用户和程序产生任何影响;而post请求如果是直接回滚和刷新会把数据再次提交
历史记录不同
GET 请求的参数会保存在历史记录中,而 POST 请求的参数不会保留到历史记录中。
书签不同
GET 请求的地址可被收藏为书签,而 POST 请求的地址不能被收藏为书签。
vue中的data为什么是个函数?(重要)
vue中的data必须声明是一个初始化的函数,因为组件可能被用来创建多个实例。如果data仍然是一个纯粹的对象,所有实例将共享一个数据对象,通过提供data是个函数,每次创建一个新的实例后,我们能够调用data函数,从而返回一个全新的数据对象
是为了再冲虚房间实例的时候避免共享同一数据造成数据污染, 互不影响。
写函数的原因是为了保证这个对象是独立的
Vue 中的 data 必须是个函数,因为当 data 是函数时,组件实例化的时候这个函数将会被调用,返回一个对象,计算机会给这个对象分配一个内存地址,实例化几次就分配几个内存地址,他们的地址都不一样,所以每个组件中的数据不会相互干扰,改变其中一个组件的状态,其它组件不变。
简单来说,就是为了保证组件的独立性和可复用性,如果 data 是个函数的话,每复用一次组件就会返回新的 data,类似于给每个组件实例创建一个私有的数据空间,保护各自的数据互不影响
防抖和节流(闭包写的)
防抖:触发事件后,在n秒内,事件只执行一次,如果在n秒内又触发了事件,则会重新计算函数的执行时间。
比如点击按钮,2秒后调用函数,结果在1.5秒的时候又点了,则会重新计算2秒后在调用函数。
节流:连续发生的事件在n秒内,只执行为一次
应用场景:滚动条
写一个防抖函数
function de(fn,times){
var time =null
return function(){
if(time !=null){
清除计时器
clear()
}
setInterval (()=>{
调用方法
fn()
},times)
}
}
什么是闭包
能够访问函数读取函数内部的变量
存在的意义:
可以延长变量的生命周期 可以创建私有的环境
好处:可以读取其他函数的内部的变量
将变量始终保持再内存中
可以封装对象的私有属性和方法
坏处:消耗内存、使用不当造成内存泄露
什么是原型链?(必背)
实例对象会先查找自身有没有所需成员,如果没有就会通过proto向构造函数的prototype中查找
如果还是没有,又会通过构造函数的prototype的proto去找到object的prototype,还是没有找到
就会通过object的prototype的proto找到null 像这样用proto一层层往上查找的方式,称为原型链
JS作用域和变量提升?(必背)
作用域:变量起作用的范围 变量访问会层层往上级作用域访问直到window,称为作用域链
变量提升:JS编译阶段会将文件中所有var,function声明的变量提升到当前作用域最顶端
什么是递归?(必背)
函数内部自己调用自己, 这个函数就是递归函数 作用和循环效果一样,但很容易发生“栈溢出”错误,必须加退出条件return
改变this 指向的方式(必背)
call()方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向 应用场景: 经常做继承.
apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。应用场景: 经常跟数组有关系
bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数 应用场景:不调用函数,但是还想改变this指向
如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind
JavaScript 有几种类型(必背)
基本数据类型:undefined、null、boolean、number、string、symbol(es6的新数据类型)
引用数据类型:object、array、function(统称为object)
什么是宏任务和微任务?
宏任务包括:settimeout setinterval ajax
微任务:promise async/await
微任务比哄任务的执行时间要早
promise的then要比 settimeout(0s)时早
什么是promise?
什么是async.await
await async2(), 这里的代码相当于new Promise(()=>{async2()}),而将 await 后面的全部代码放到.then()中去;//所以输出『async2』,把async2()后面的代码放到微任务中
async/await底层是基于Promise封装的,所以await前面的代码相当于new Promise,是同步进行的,await后面的代码相当于.then回调,才是异步进行的。
区别:async是来定义函数的,定义异步函数,打印匿名函数可以得到一个promise对象,言外之意可以通过这个,函数名称.thenzhege 方法。
await后面跟的是任意表达式,一般使用promise的表达式
await内部实现,又返回值,成功返回promise,resove(),出错返回promise.reject()返回只用catch捕获(需要自己定义)
优点:async和await 属于es7语法。编写方便,提高程序效率,避免了回调地狱
补充:promise和async和await的区别
promise es6语法,promise中包含catch,async需要自己定义catch
promise 提供的方法会多一些,all、race等方法,aync中是没有的。
什么是事件循环
同步和异步 :js是单线程执行语言,在同一时间只能做一件事,这就导致后面的任务需要等到前面的任务执行完才能执行,如果前面的任务耗时就会造成后面的任务一直等。为了解决这个问题 js就出现了同步任务和异步任务
同步任务:在主线程上排队的任务只有前一个执行完才能进下一个,形成一个执行线
异步任务:不进入主线程,而是进入任务队列,当主线程中的任务执行完毕,就能从任务队列中取出任务放进主线程中来执行,由于主线程不断的获取任务执行任务 所以这种机制就被叫做事件循环。
我们都知道 Js 是单线程的,但是一些高耗时操作带来了进程阻塞的问题。为了解决这个问题,Js 有两种任务的执行模式:同步模式(Synchronous)和异步模式(Asynchronous)
在异步模式下,创建异步任务主要分为宏任务与微任务两种。ES6 规范中,宏任务(Macrotask) 称为 Task, 微任务(Microtask) 称为 Jobs。
cookie、localStorage、sessionStorage的区别
共同点:都是保存再浏览器端,同源的
不同点:cookie数据始终在同源的htt请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。cookie数据还有路径的概念 ;localstorage、sessionstorage 存在本地
储存大小有限制
cookie 不能超过4k,sessionStorage和localStorage可以达到5M
sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;
cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
作用域不同
sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在
cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在
去重的方法
for循环
set方法
filter方法三个参数
arr.filter((item, index, self) => {
console.log(item, index, self)
return self.indexOf(item) === index
})
4.indexof方法 用push
map和forEach的区别
forEach方法,是最基本的方法,遍历和循环。默认有3个参数:分别是遍历的每一个元素item,遍历的索引index,遍历的数组array;哪怕return也是没有返回值 undefind,改变原来的数组
map方法,和foreach一致,不同的是会返回一个新的数组,所以callback需要有return返回值,如果没有会返回undefined
数组方法汇总
map 循环遍历数组、不会改变原来的数组,返回一个新的数组
forEach 循环遍历数组,改变原来的数组
push/pop 在数组的末尾添加/删除元素 改变原数组
unshift/ shift 在数组的头部添加/删除元素,改变原数组
join 把数组转化为字符串
some 有一项返回为true,则整体为true
every 有一项返回为true,则整体为false
filter 数组过滤
slice(start, end) 数组截取,包括开头,不包括截取,返回一个新的数组
splice(坐标index, number几位, 添加新的value) 删除数组元素,改变原数组
indexof/lastindexof: 查找数组项,返回对应的下标
concat:数组的拼接,不影响原数组,浅拷贝
sort:数组排序 改变原数组
reverse: 数组反转,改变原数组
vue 路由守卫/导航守卫
既然是守卫,首先是对咱们后台页面访问的一层保护,如果我没有进行登录过,后台的操作页面是不允许用户访问的 我们是用到vue路由中的一个钩子函数beforeEach,那么这个函数中有三个参数,分别是 to from next to 是去哪里 from从哪来 next 放行
主要逻辑是判断我们有没有登录,那么我们可以通过登录后获取到的token来判断,如果有token就直接next 如果没有我们再判断用户访问的是不是登录页面 还是得话放行 不是就跳回到登录页
token失效 前端如何处理?token失效后端接口会返回token失效 这时我们再请求获取token接口
vue权限路由/动态路由/鉴权
既然说到权限 那么肯定是根据不同账户得到不同的权限来做路由配置和菜单的渲染
第一点当我们登录之后会获取到当前账户的身份(权限),那么我们的路由配置实际上就是一个数组
我们要做的事情就是把获取到的身份与这个数组做对比,通过相关的计算筛选出最终匹配当前身份的路由配置
然后将计算出来的路由数组通过router.addRouters动态挂载
还要注意的一点就是需要将我们筛选出来的路由配置渲染到我们的前端页面上去一一相对应
vue拦截器:请求拦截 响应拦截
请求拦截:因为http是无状态的 无法保存我们的状态,那么我们就需要一个标识
当我们登录之后,后续的所有请求操作都需要携带我们这个token,所以我们统一把它添加到请求头当中,避免了
无意义请求
响应拦截:当设置了响应拦截后所有的响应都会经过它,所以方便我们统一处理响应数据做相关的操作
请求怎么带token?(放入了哪里?每次请求前做了什么操作) (重要)
获取本地存储中的 token,并放在请求拦截器中,这样所有的请求都可以直接通过请求拦截器将token传给服务器
axios的封装
为了方便使用我们进行了封装
首先我们封装一个get或者post的这些方法,然后通过返回一个promise对象进行使用
在promise中通过.then和.catch拿到axios请求结果
然后通过工具层将不同的业务版块需要调用的接口进行模块化再暴露出去
在我们的但页面中引入相对于的接口模块,然后调用,因为我们底层封装的是一个promise对象
所以我们可以通过ES7中的 async await直接拿到响应数据
vue中的key
key的唯一性可以给每一个节点有一个唯一标识,当添加或删除节点时,通过对比数据前后的变化,只用操作某个变化的节点,不需要重新渲染所有的数据,提高了性能
.$nextTick用过吗,有什么作用?
视图更新之后,基于新的视图进行操作
一般created的时候dom没有渲染,如果要操作dom,最好放在this.$nextTick(()=>{})回调函数 中完成
vue常用指令有哪些?
v-for /v-bind(😃 /v-if/ v-show/ v-else-if /v-else/ v-model / v-on(@) / v-text / v-html / v-once /
v-prev / v-cloak
v-if 和 v-show的区别是什么? 什么时候使用v-if更好? 什么时候用v-show更好?
v-show 可以操作display属性.主要用于频繁操作
v-if 销毁和创建元素,主要是用于大量数据渲染到页面时使用符合条件就将数据渲染,频繁使用会消耗性能
vue-router路由的传参方式(重要)
第一种:使用router的name属性也就是params来传递参数
传值页面:this.$router.push({name:'路由配置中赌赢的name名',params:参数}) 取值页面:this.$route.params.id
第二种:query
this.$router.push({
path:'/路由哦',
query:{}
}) 取值this.$route.query.id
v-on可以监听多个方法么? 要注意什么?(必背)
可以,
1.当没有参数传递时,方法名称后面可以不加小括号
2.当需要传递参数时,且只有一个参数需要传递,而没有进行传递,会默认输出浏览器的event对象
3.当需要传递多个参数时,想要获取浏览器的event对象,需要在前面加$符号
vue中ref的作用是什么?(必背)
作用一(基本用法):本页面获取dom元素
作用二:获取子组件中的data
作用三:调用子组件中的方法
作用四:子组件调用父组件方法
数组常用方法有哪些?
pop/ push/ shift/ unshift/ reverse/ sort/ splice
findIndexOf/ indexOf / forEach / map / join / concat / filter /slice
new操作具体干了什么?
在堆空间中创建一个对象
this指向这个对象
执行构造函数的语句
返回这个对象
请以自己理解讲解js堆和栈,以及深拷贝怎么解决?(重点)
浅拷贝:浅拷贝是指对内存地址的复制,让目标对象指针和源对象指向同一片内存空间
深拷贝是指拷贝对象的具体内容,二内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象页互相不影响
基本类型:string,number undefinde booler
解决浅拷贝方法1:stringify parse 2.[].concant(arr) 3.arr.splice() 4.Array.form(arr)
vue v-mode的原理
v-model通过view层更新data的原理:可以理解为在input框里面通过v-bind动态绑定一个value,然后在input框里面通过@input方法去动态获取input输入的值,然后重新给变量赋值就可以。
vue2响应式原理之Object.defineProperty()方法
get()和set()方法 只要一访问就会触发get,设置就会触发set
var obj = {}
var com; //设置变量周转
Object.defineProperty(obj , 'name' , {
get(){
console.log('访问obj.name属性触发')
return com
},
set(newValue) {
console.log('修改obj.name属性触发' , newValue)
com = newValue
}
})
obj.name //访问属性
console.log(obj.name) //乔丹
obj.name = "科比" //修改属性科比
console.log(obj.name) //最后控制台打印 科比
跨域引起的原因,以及开发时的解决方案?
跨域: 非同源策略的就叫跨域
同源策略就是相同的http,相同的地址,相同的端口
解决方法: 1 nginx反向代理
vue的3种组件通信方式?
父子通信
通过给子组件身上绑定自定义属性,然后再子组件里使用props属性来接收即可
在子组件中 props: { 自定义的属性名: { type: , default} }
子组件给父组件传递数据
1通过父组件给 子组件绑定一个自定义事件实现 @bindName= bindName 子组件通过$emit方法,把数据传给父组件
2.通过父组件给子组件绑定一个自定义事件实现:使用ref实现
全局事件总线:可以实现任意组件间的数据传递
将全局事件bus,挂载到Vue的原型上,这样所有的组件都可以使用
兄弟之间的传值
兄弟组件A通过$emit触发时间同时传递数据给兄弟B
兄弟B通过$on绑定 一个事件名,同时接手数据