2023前端面试面试笔记(一)

this指向

除了箭头函数,和函数的定义无关,和函数的调用有关。

  • 直接调用,this指向window,严格模式下指向undefined
  • 谁调用指向谁
  • new,this指向实例
  • 箭头函数的this指向上下文

改变this指向的方法

  • fn.call(this指向的,函数需要的实参)
  • fn.apply(this指向的,[函数需要的实参])
  • fn.bind(this指向的),bind不会调用函数,而是根据该函数生成一个新函数,并且新函数的this指向了()的对象

异步

js 是单线程的,也就代表 js 只能一件事情一件事情执行,那如果一件事情执行时间太久,后面要执行的就需要等待,需要等前面的事情执行完成,后面的才会执行。

所以为了解决这个问题,js 委托宿主环境(浏览器)帮忙执行耗时的任务,执行完成后,在通知 js 去执行回调函数,而宿主环境帮我们执行的这些耗时任务也就是异步任务

js 本身是无法发起异步的,是委托给宿主环境发起异步的,但是 es5 之后提出了 Promise 可以进行异步操作

--执行流程如下:

主线程先判断任务类型

  • 如果是同步任务,主线程自己执行
  • 如果是异步任务,交给宿主环境(浏览器)执行

宿主环境进行异步任务的执行,每个异步执行完后,会将回调放进任务队列,先执行完成的先放进任务队列。

等主线程任务全部执行完后,会取任务队列中的任务,根据先进先出原则

在任务队列中取出来的任务,会回到主线程执行,执行完成后,在取下一个,依次重复,这个过程也称为 eventLoop 事件轮训

--而我们所提道的异步任务,也分为宏任务和微任务。

由宿主环境发起的异步被称为宏任务。(setTimeOut、setInterval)

由js自身发起的异步被称为微任务。(promise)

(判断由谁发起的,看是否是ecma的,如果是,则表示是js自身发起的。也就被称为微任务。但是我们用到的微任务基本只有promise————还有一个特殊情况MutationObserver,虽然是由web发起的,但是也是微任务)

promise不是异步的,(.then)才是异步的微任务

await下面的也可以看作是微任务

--执行顺序

  1. 先执行宏任务(将整个script标签的代码段看作是一次宏任务)----同步任务
  2. 宏任务执行完后看微任务队列是否有微任务
  3. 没有微任务执行下一个宏任务
  4. 有微任务将所有微任务执行
  5. 执行完微任务,执行下一个宏任务

解决异步,最常用的就是promise

computed和watch的区别

计算属性computed:

  • 支持缓存,只有依赖数据发生改变,才会重新进行计算
  • 不支持异步,因为有return的存在
  • 定义的时候是方法,使用的是属性

侦听属性watch:

  • 不支持缓存,数据变,直接会触发相应的操作
  • watch支持异步
  • 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
  • watch可以监视:props\data\computed\$route
  • 监视的是一个对象: 开启深度监听 deep:true

动态路由和静态路由

静态路由是管理员手动配置的,不便于拓展网络拓扑结构,一但网络拓扑发生改变,静态路由配置量会很大。动态路由是路由器通过网络协议,动态的学习路由,当网络拓扑发生变化的时候,路由器会根据路由协议自动学习新的路由。

动态路由,因为OSPF,RIP等路由协议都会有周期更新,所以更新量大,占用宽带大。

使用静态路由的好处是网络安全保密性高。动态路由因为路由器之间频繁交替,需要经常使用路由表,而路由表可以分析出拓扑结构和网络地址等,所以安全性低。

动态路由:灵活性高

静态路由:安全,占用宽带小,简单,高效。

路由传参

  • 动态路由传参
  • 路由配置,需要在path上进行参数设置
  • params方法 path: '/xxx/:uid',
  • query方法 path: '/xxx?uid=值',
  • 路由跳转,this.$router.push('地址');
  • 在对应页面中拿到路由参数,this.$route.params.uid / this.$route.query.uid;
  • query方式传参
  • 路由配置不变
  • 路由跳转
  • 用path跳转,this.$router.push(),参数为对象,path:对应路由配置的值,query参数
  • 用name跳转,this.$router.push(),参数为对象,name:对应路由配置的值,query参数
  • 在对应页面中拿到路由参数,this.$route.query.uid;
  • params方式传参,只能通过name跳转
  • 路由配置不变
  • 路由跳转,this.$router.push(),参数为对象,name:对应路由配置的值,params参数
  • 在对应页面中拿到路由参数,this.$route.params.uid;

页面跳转的方法:

1、<router-link to="需要跳转到页面的路径">

2、this.$router.push()跳转到指定的url,并在history中添加记录,点击回退返回到上一个页面

3、this.$router.replace()跳转到指定的url,但是history中不会添加记录,点击回退到上上个页面

4、this.$router.go(n)向前或者后跳转n个页面,n可以是正数也可以是负数

路由守卫

路由守卫分为三种,全局守卫,路由独享守卫以及组件内守卫。

全局守卫
  • 全局前置守卫
    • 写法router.beforeEach()
    • 每一个路由进入前触发
    • 可以用来进行路由权限的控制。
    • 在回调中有三个参数,to,from,next,其中next()必写。
  • 全局后置守卫
    • 写法router.afterEach()
    • 每一个路由进入后触发
    • 用于提示语之类的
路由独享守卫
  • 写法beforeEnter(),写在路由规则配置里面,和path,name同级
  • 单独进入某个路由前触发
  • 在回调中有三个参数,to,from,next,其中next()必写
组件内守卫
  • 写在组件内,和created等生命周期同级
  • 在回调中有三个参数,to,from,next
  • 写法有三个
    • beforeRouteEnter
      • 渲染组件前触发
      • 不能获取组件实例 `this`
    • beforeRouteUpdate
      • 在当前路由改变,但是该组件被复用时调用
      • 一般就是是同一个页面,不同的参数这样,此时组件复用,没有被创建,也就无法重新创建。
      • 可以访问组件实例 `this`
    • beforeRouteLeave:路由离开
      • 路由离开时调用
      • 可以访问组件实例 `this`
      • 比如在编辑过程中,要离开给页面,就会跳出没有保存,是否需要离开的提示。

聊聊vuex

对于vuex的话。

vuex是一个状态管理的库,是用来实现组件之间的数据共享的。

vuex的优点是数据的响应式,可以便于数据的传递,方便维护和管理。

vuex包含了5个属性:

state,用于定义和存储共享的数据。用$store.state或者是辅助函数mapState来进行触发。

mutations,用来修改数据,也是修改数据的唯一来源。(当然,其实state数据是可以直接进行赋值修改的,但是并不建议使用,就像是所有人都可以更改公司数据一样,存在着各种不安全隐患。)用commit或者辅助函数mapmutations来进行触发修改数据。

actions:说道actions,就要提到刚刚说的mutations,mutations的同步的,而actions是异步的。用dispatch或者是辅助函数mapactions来触发。但是actions只能够进行异步处理,不能修改state的数据。所以如果需要修改数据,还是需要调用mutations来处理。

所以我们的同步流程就是直接触发mutations,而异步流程则是先触发actions,再由actions进行异步处理以后再去触发mutations。

getters:基于state进行派生数据

moudles:模块化,将数据模块化后,会有上述的四种属性。模块化后的数据方便维护和管理。每一个模块可以设置命名空间,如果不设置,那么mutations和actions的使用和全局并无差别。如果开启命名空间,则需要通过模块名进行访问。

vuex的缺点就是不能持久化。我们在使用的时候,如果数据是从后台请求回来的,那么可以直接忽略持久化的问题。如果不是请求回来的,那么就需要解决持久化的问题。

解决的方式就是本地存储。除了localStorage, sessionStorage, cookie以外,我们还常用一个自动存储的插件

vuex-persistedstate。

mutations是处理同步的数据的,如果处理异步的话,会导致devtool的记录出现问题,也就无法及时的知道状态是何时更新的,无法追踪状态,给调试带来困难。那我们公司就是不管同步还是异步,都会先进行一个actions的异步处理,再去调用mutations来处理修改数据。

vue.use()的原理

通过全局方法vue.use()使用插件

Vue.use会自动阻止多次注册相同插件

需要在调用new Vue()启动应用之前完成

Vue. use()至少传入一个参数

如果参数是一个Object对象,那么这个对象必须提供一个install函数

如果参数是一个function函数,那么就相当于install函数

Vue. use()的其他参数,都会依次传给install函数

install函数默认的第一个参数是vue,后面的参数来自于Vue.use后续参数

vue.use本质是无法注册全局组件或者给vue原型添加方法的,但是我们在使用路由或者vuex或者element ui,实际还是在install函数内部通过vue.component注册了全局组件或者给Vvue.prototype手动添加方法。

v-if和v-show

v-show和v-if都是可以用来控制元素的隐藏和显示的。true的时候表示显示,false的时候表示隐藏。

v-show的隐藏使用的是css样式display:none的方式,不管是true还是false,它都会渲染对应的dom元素。

优点:不会频繁创建dom

缺点:首次渲染为false也会创建

场景:适用于频繁切换的场景。

v-if的隐藏是直接从dom上移出,不会产生对应的元素。在true的时候,再创建相对应的整个标签。

优点:他是懒渲染,默认首次如果是false,元素不会创建。如果是组件,利用v-if可以重新触发生命周期

缺点:频繁的删除和重建

场景:适用于一进入页面,就确定是显示和隐藏,后期不会改变的场景。

或者组件需要重新触发生命周期的场景

v-if还有一个v-show没有的高级语法,就是和v-else搭配使用的判断条件的用法。

$route和$router

$route:用来获取当前路由信息的,每个路由都会有一个$route对象,是一个局部的对象

可以写作$route.path(当前路径)params,name等

$router:全局路由实例,用来操作路由的

等价于 new VueRouter

包含所有的路由,路由的跳转方式,钩子函数等等。

最常用的就是this.$router.push()进行跳转

v-model

作用:一是数据双向绑定,二是实现组件通信

原理:v-model就是一个语法糖,动态绑定了value和注册了input事件

使用场景:

  • 一是在表单中使用,比如input输入框之类的,需要双向绑定这个数据,就可以绑定一个v-model,绑定的就是input内输入的值
  • 二是在组件上使用,在组件上使用的情况就是:父组件数据要传给子组件,并且子组件需要修改数据(两件事情都需要的情况下才会使用)

缺点:v-model在一个组件上只能使用一次

MVVM 的设计思想的优势

  • mvc的改进版
  • 双向绑定技术,当 数据变化时,视图也会自动变化,视图发生更新,数据也跟着同步
  • 我们减少了 dom 的操作,因为我们只需要关注数据就可以
  • mvvm 的设计思想大大提高了代码的耦合性
  • 数据响应式的原理

keep-alive

keep-alive是一个内置组件,它会缓存不活动的组件实例,而不是将其销毁。不会渲染dom元素

它提供了include和exclude属性。

它包含了activated和deactivated钩子函数

include:指定缓存的组件

exclude:指定不缓存的组件

activate:激活状态

deactivated:失去激活状态

图片懒加载

图片懒加载的原理:优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。

一张图片就是一个<img>标签,浏览器是否发起请求图片是根据<img>的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给<img>的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。

虚拟dom和diff算法

虚拟dom的本质就是一个js对象,用来描述真实dom是什么样子的,这个对象就是我们常说的虚拟dom。

虚拟dom的出现可以进行高效更新,同时可以使用虚拟dom进行跨平台。

我们在初始化渲染的时候,会根据数据和模板生成一个虚拟dom树,当数据发生变化的时候,又会根据新的数据和模板,生成一个新的虚拟dom树。然后将新旧两颗虚拟dom树进行对比。对比的过程使用的就是diff算法。说道diff算法。它的特点是同级比较,深度优先,且采用双指针算法。这里的双指针算法会产生四个指针,新旧虚拟dom树各有两根指针,都是一个指向开始位置,一个指向结束位置。在进行循环的时候,开始位置的指针会在对比完以后向后推,结束位置的指针在对比玩以后会向前推,从而达到高效更新。

diff对比情况分为三种。

一是元素不同,会直接删除重建。

二是元素相同,属性不同,那么元素会进行复用,只会更新属性。

三是v-for循环的情况。这也会分成两种,

一是没有key的时候,如果数据的变化没有影响到顺序,那么性能没有影响。如果数据的变化影响到了顺序,那么性能也会受到影响。因为没有key的时候,我们是根据顺序进行对比的。

二是有key的时候,key是不建议使用索引的,因为索引是会变化的。我们推荐使用唯一值,对比的使用会根据key值进行对比。

路由模式

路由模式分为三种

  1. abstract,支持所有 JavaScript 运行环境,如果发现没有浏览器的 API,路由会自动强制进入这个模式。
  2. hash模式:
    1. 有#/,
    2. 通过window.location.href进行跳转
    3. 通过window.onhashchange进行监听
  1. history模式:(推荐使用)
    1. 没有#/
    2. 通过history.pushState和history.repleaceState进行跳转,
    3. 通过onpopState进行监听,只能监听前进和后退,无法监听history.pushState和history.repleaceState, 源码中将history.pushState和history.repleaceState,进行了统一的包装,通过pushState函数进行包装,不管是history.pushState还是history.repleaceState实际底层最终都会通过pushState这个函数进行跳转,通过pushState进行监听
    4. 刷新会404,需要后端的支持。

环境变量

一个项目在开发的过程中,会经历各种过程才会发布,每个过程的环境不同,就会需要不同的配置参数,所以就可以用环境变量来方便我们管理。

每个不同的环境有一个不同的文件,这些文件都和src同级

一个项目,基准地址(环境)会有3套,分别是开发期间的、测试的、线上的

在package.json中会有相对应的配置,运行不同的命令代表不同的环境,使用的就是不同文件内,环境变量的值。

环境变量是存放基准地址的,不同的环境(比如测试,开发期间,上线等)的基准地址可能会不同。用环境变量来存储。环境变量的值来自于不同的环境文件.env.的文件中

nextTick

作用:数据发生变化后,可以利用nextTick获取最新的视图

原理:数据发生变化会驱动视图,这是一个异步操作。为了性能,等所有数据变化后,进行合并更新视图。因为这个原因,导致数据发生变化后,无法立即获取最新视图。

解决方案就是使用nextTick

nextTick不传回调的时候,则内部是promise对象

nextTick传回调的时候,则内部是setTimeout定时器

token过期问题

token一般的过期时间是2个小时。这里要引入一个其他内容,refresh_token过期时间较长(一周、两周)

在token过期的时候,我们会在用户不知情的情况下,偷偷的发送一个请求,获取新的token。通过refresh__token偷偷进行换取,登录状态就可以继续维持一周到两周。如果refresh__token也过期了,那么就会跳转到登录页,需要重新进行登录。

如何判断token过期

1、前端主动处理

当判断token过期时候,不再发送请求,就可以优化性能。减少网络请求的次数

借助时间戳:

登录成功的时候存下token的时间戳

发送请求前,获取当前的时间戳-存下token的时间戳,等到的值如果超过了token的有效期(两个小时),那么就不发送请求,而是跳转到登录页面,要求重新登录。

2、前端被动处理,由后端主动处理。也就是需要判断请求的时候,返回的状态码,一般401是登录过期,也就是token过期的情况(当然具体是要看后端的返回,这里的401只是一般情况下)

.sync修饰符

修饰符有哪些:

v-on的

  • .stop - 阻止事件冒泡
  • .prevent - 阻止默认行为
  • .once - 程序运行期间, 只触发一次事件处理函数(不可以和其他修饰符连用)
  • .native - 在某个组件的根元素上监听一个原生事件

v-model的

  • .number 以parseFloat转成数字类型
  • .trim 去除首尾空白字符
  • .lazy 在change时触发而非inupt时

作用: 语法糖,也可以实现组件通信, 类似双向绑定(父向子传,子向父改)

原理: .sync解析出一个动态绑定的数据,解析一个自定义事件,@update:属性名,组件内部可以通过this.$emit('update:属性名的')进行触发

.sync: 可以使用多次, 而且.sync可以和v-bind结合直接传递一个对象,将对象的每个属性单独传递进去,单独的绑定v-on事件

:属性名.sync=‘变量’

等价于

:属性名=‘变量’(父向子传值)

@update:属性名=‘变量=$event’(@update表示自定义事件)

首屏优化 

  1. soucemap: 关闭
  2. 路由懒加载
  3. cdn资源
  4. splitChunks: 提取公共资源
  5. 图片压缩
  6. gzip
  7. runtimeChunks
  8. ssr: 服务端渲染
  • 解决首屏加载速度慢的问题,因为首屏服务端直接返回,不需要加载js文件
  • 还可以解决seo,html不再是只有一个id为app的标签,更加有利于seo搜索
  • 实现ssr的方法是使用vue结合nuxt

spa单页面应用

我们vue是使用spa的,spa页面响应速度快,可以减轻服务器压力,但是不利于seo,首屏加载也会比较慢。

这时候就会用到ssr。也就是在vue中使用nuxt框架。虽然可以让爬虫更容易爬到数据,响应速度也更快,但是会增加服务器的压力,并且开发的难度也比较大。

封装创建组件

(1)组件封装思想
  1. 组件的结构:结构考虑复用灵活,一般使用插槽、允许自定义
  2. 组件的样式:考虑支持自定义,一般使用属性传值(通过样式或者类名)
  3. 组件的数据:通过数据传递
  4. 暴露事件:例如弹框组件,点击遮罩弹框关闭,用户使用组件的时候,也需要监听到点击遮罩的行为,用户可以进行自定义的逻辑
(2)如何创建一个全局组件

通过 Vue.component 来创建一个全局组件,第一个参数是组件名字,第二个参数是组件的配置对象,可以通过 template 配置组件的结构,data 定义数据等等

(3)如何创建一个局部组件

在组件内部通过 components 来创建一个局部组件

全局组件和局部组件的区别

局部组件:只能在当前的父组件中使用

全局组件: 在任意地方使用

(4)如何定义局部自定义指令

在组件内部通过 directives 来创建一个局部指令

全局指令和局部指令的区别

局部指令:只能在当前的组件中使用

全局指令: 在任意地方使用

(5)如何定义局部过滤器

在组件内部通过 filters 来创建一个局部过滤器

全局过滤器和局部过滤器的区别

局部过滤器:只能在当前的组件中使用

全局过滤器: 在任意地方使用

link与@import的区别是什么

1、从属关系区别

@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。

2、加载顺序区别

加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。

3、兼容性区别

@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。

4、DOM可控性区别

可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式。

双向数据绑定

数据发生变化,同步视图,视图发生变化,同步数据。

v-model可以完成数据双向绑定。

但原理是v-on绑定事件和v-bind绑定数据,是一个语法糖。

v-bind可以实现数据变同步视图,这是因为数据响应式的原理。

v-on绑定事件可以实现视图变同步数据,这是数据响应式的原理。

是单向数据流? 

在父向子传值的时候,如果改变父组件的值,子组件会跟着同步更新,反之不允许

自定义指令:

当vue 提供的系统指令满足不了我们的需求时,我们就需要自定义指令

全局通过 Vue.directive 进行自定义指令的定义。

局部通过directives进行定义。key为自定义指令的名字,value为对象,对象内有下面三个钩子函数。

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

vue 的两个核心

组件系统、数据驱动

组件插槽

  • 默认插槽:
    • 在组件标签中间可以传递一些子节点
    • 组件内部利用 slot 标签进行接收
  • 具名插槽(可以传多个插槽)
    • 在组件标签中间通过定义 slot 的名字传递子节点
<my-banner>
  <div slot="header">
    头部
  </div>
  <div slot="footer">
    底部
  </div>
</my-banner>
    • 组件内部利用 slot 的 name 进行对应接收
<template id="banner">
  <div>
    <slot name="header"></slot>
    <slot name="footer"></slot>
  </div>
</template>
  • 作用域插槽
    • 在组件内部定义数据,将数据传递给插槽的结构
    • 通过给 slot 动态绑定属性
<template id="my-li">
    <ul>
      <li v-for="item in arr">
        <slot :row="item"></slot>
      </li>
    </ul>
  </template>
    • 插槽内部:通过 slot-scope=“scope”来接收
<my-li>
  <template slot-scope="scope">
    <p>{{scope.row}}</p>
  </template>
</my-li>
<my-li>
  <template slot-scope="scope">
    <a href="04-侦听器.html">{{scope.row}}</a>
  </template>
</my-li>

vue 单页面应用的优缺点

缺点:

  • 不利于 seo
  • 兼容到 ie9
  • 初次加载耗时相对增多

优点

  • 用户体验好,不用重新刷新整个页面
  • 前后端分离
  • mvvm 设计模式
  • 减轻服务期压力,只需要服务器提供数据

v-if和v-for为什么避免同时使用

v2中:

v-for的优先级高于v-if,所以还是会先循环创建虚拟dom,再利用v-if进行移除

解决方式:

  • v-if写到外层
  • 先通过计算属性将数据计算好

v3中: v-if优先级高

mock假数据

现在的项目都是前后端分离的,在前后端同时开发的过程中,后端接口数据没有出来,前端可以使用mock假数据。

优点:

团队可以并行工作。更好的进行前后端分离。

增加测试的真实性,通过随机数据,模拟各种场景。

开发无侵入,不需要修改既有代码,就可以拦截ajax请求,返回模拟的响应数据。

数据类型丰富,支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等。

方便扩展,支持扩展更多数据类型,支持自定义函数和正则。

不涉及跨域问题

mixins

mixins: 将组件中的逻辑功能进行复用,复用部分可以提取到一个js文件中,然后通过mixins这个选项将该文件中暴漏的对象进行混入即可

可以混入哪些: 正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中

优先级:

  • 生命周期:组件和混入的都会调用(混入的先调用)
  • data数据::进行合并,发生冲突以组件为主,mixins中的会被覆盖
  • methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对

axios取消重复请求

  1. 场景:如果在输入框中输入12,然后先发1的请求,再发12的请求,但是如果关键词1的请求响应慢,12请求的数据先回来,那么1请求回来的数据会覆盖12的数据。和我们所需要的结果产生了出入。
  2. 解决方案:使用取消请求的方式。
  3. 原生的ajax可以使用abort()
  4. 取消axios请求,则使用axios内部的cancelToken方法

防抖和节流

防抖和节流都是为了避免函数被多次调用导致页面调用,但它们的本质不一样,防抖是将多次执行变为最后一次执行,节流是将多次执行变为每个一段时间执行一次。

防抖是指触发事件函数后,函数在n秒后只能执行依稀,如果n秒内再次触发,会重新计算时间。也就说说连续触发,只执行最后一次。

场景:

  • 搜索框搜索输入,只需要用户最后一次输入完成,再发送请求。

节流会限制一个函数在n秒内只能执行一次,过了n秒又可以执行一次。

场景:

  • 发送验证码的时候,60秒内只能发送一次。

假值有哪些

假值就是值boolean转出来是false的

  1. 0
  2. Null
  3. NaN
  4. False
  5. undefined
  6. 空字符串

get和post的区别

  • 从标准上来说:

GET 用于获取信息,是无副作用的,是幂等的,且可缓存 ,安全性差

POST 用于修改服务器上的数据,有副作用,非幂等,不可缓存

  • 从请求报文上来说:

GET 和 POST 只是 HTTP 协议中两种请求方式(异曲同工),而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。

在报文格式上,不带参数时,基本一致,带参数时,在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中。

响应拦截器里面都做什么事情

  • 请求拦截器
    在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;
  • 响应拦截器
    同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。

实现实时更新

websocket

比如直播间弹幕啊,股票的实时数据更新,进入页面客服的自动发送信息等等

websocket是一种数据通信协议,常见的是http协议。

http协议的缺陷:通信只能由客户端发起,http基于请求响应实现。

vue 组件中的 data 为什么是一个函数,返回一个对象?

如果不是一个函数返回一个新的对象,组件如果多次使用,实际公用的是同一个数据

但是如果是通过函数 返回一个新的对象,这样的话,每个组件的使用数据是独立的

浅谈事件冒泡和事件捕获

事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

阻止事件冒泡e.stopPropagation()

简单来说,当你鼠标在浏览器上点击了一下。

  1. 浏览器捕获到了click事件。
  2. 然后浏览器根据你点击的事件,从window开始向下,就会触发每个父祖element捕获模式的事件回调。
  3. 直到找到点击所在的最终(最小的element)
  4. 然后浏览器开始继续又向上冒泡其父祖element的click事件,直至window。
  5. 默认的事件都是冒泡模式下触发的。

二维转一维数组,扁平化

1、flat

flat是ES10新增的一个数组处理的方法,非常的好用,它专门用来扁平化数组。

合并返回新数组

参数是层级数,默认为1,层级未知可以用Infinity

2、concat + 扩展符

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

扩展运算符(...)可以将数组转为用逗号分隔的参数序列。

只能二维转一维,多维就不行

3、reduce + concat

reduce() 方法接收一个函数作为累加器,reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(上一次回调的返回值),当前元素值,当前索引,原数组 。

callback:函数中包含四个参数

- previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))

- currentValue (数组中当前被处理的元素)

- index (当前元素在数组中的索引)

- array (调用的数组)

initialValue (作为第一次调用 callback 的第一个参数。)

将初始值设置为了[]空数组,然后将需要扁平化的数组的每一项都用concat重新连接,最终得到一个一维数组。

4、toString + split

先使用 toString 把数组转成字符串,再使用 split 把字符串转回数组:

该方法存在局限性,不适用于一些包含相对特殊子元素的数组,比如包含 null、undefined、对象类型等。

使用map是为了让数组元素变为Number类型。

单点登录

概念: 一个大型公司有很多系统,用的是同一个账号,登录一个系统时,其它系统也可以正常访问

cookie:

某个系统登陆成功,再次去登录其它系统系带token,token如何在多个网站中共享

domain/path

domain: 设置网站域名 设置为主域名(父级域名)/二级域名是可以获取到cookie数据

path: 路径 /

脱离父级域名不可以共享了

认证中心

iframe

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值