面试题总结

448 阅读21分钟

h5 语义化标签都有哪些 ?

nav(导航标签) header 文章的头部 footer文章的脚 main(文章的主题内容) i(写文字是斜体) 音频 视频等等

元素盒模型

每一个元素都包含 内容部分 内边距部分 边框 外边距 标准盒子情况下 元素盒子的宽高是不包含 内边距 和边框的 但是如果我们使用了 box-sizing:border-box;样式的情况下 内边距和边框是包含在宽高里面的

用css怎样实现一个三角形

答:css实现一个三角形可以通过边框实现 我们可以将元素宽高设置为0然后通过边框填充整个元素, 这时候我们可以实现四个三角形,只需要将三个方向的边框的颜色设置为透明即可实现一个三角形

让元素垂直水平居中

答: 让元素垂直水平居中的方法有很多,接下我我来介绍几个,第一种我们可以通过给父元素设置宽高, 然后将父元素设置为弹性盒子display: flex;然后通过justify-content:center;设置主轴方向 上居中 然后通过align-items: center;设置元素在主轴的交叉轴方向上也居中就可以了; 第二种方法我们可以通过定位,首先设置父元素相对定位,要居中的元素设置为绝对定位 然后通过 left: 父元素宽度的50% - 子元素宽度的50%;让水平方向居中, 再通过设置top: 父元素高度的50%-子元素 高度的50%居中。

判断数据类型的方法

  1. typeof 他可以判断出某些数据类型 但是无法区分出对象 数组 以及null 因为他们的返回值都是object
  2. instanceof 可以用来区分对象或者数组 返回值是布尔值
  3. constructor 构造函数 但是undefined和null没有构造器 所以无法使用constructor判断出数据类型 但是其他数据类型都可以判断出来
  4. Object.prototype.toString.call() 完美的判断数据类型的方法

如何判断一个数据是不是数组?

  1. instanceof 返回值如果是true证明是数组 否则证明不是数组
  2. constructor arr.proto.constructor.name 返回值如果是array证明是数组
  3. Object.prototype.toString.call() 返回值如果是[object Array]证明是数组
  4. isArray 专门用来判断一个数据是否是数组的 返回值是一个布尔值 true代表是 false代表不是

js的判断语法

  • 常用的判断语法有两种 if 和 switch
  • 平常使用的 try{} catch{} 三元运算 二元运算也可以做判断使用
  • ===(全等) 和 == 是比较运算符 !== 是结果取反
  1. if 判断语句 if else if else
  • if判断()中是条件 条件是真就会执行{}中的逻辑
  • 如果条件为假 就会执行else if{}中的逻辑
  • 如果else if的逻辑也为假 就执行else中的逻辑
  1. switch语句
  // ticket 要判断的数据
  // break 每次条件结束之后必须有break 否则会一直往下执行
  // default 当条件都不满足时才会执行的逻辑 
  switch(ticket) {
      case 1:  //  case 例子 这里是例如 ticket = 1的时候执行的逻辑
        console.log('我中了一等奖,我要去买别墅')
        break;
      case 2: //  case 例子 这里是例如 ticket = 1的时候执行的逻辑
        console.log('我中了二等奖,我要去买车')
      break;
      default:
        console.log('我没有中奖')
      break;
    }

如何往对象里添加属性?

  1. obj.name = ''
  2. obj['name'] = ''
  3. var b = 'tel' obj[b] = 186
  4. 删除对象里面的某一项 delete obj.name
  5. object 对象其实就是一组无序的键值对的组合

js是什么以及概述?

  1. js是一种解释型脚本语言
  2. js的语言是按照从上到下的形式一句一句执行的
  3. js声明变量 变量就是可以变化的量
  4. 变量的名是自定义的
  5. 变量的名 不能以数字开头 声明变量不建议使用中文
  6. 任何一个变量的默认值都是undefined
  7. 查看变量值的方法可以是 alert console
  8. = 是赋值方法 可以改变变量的值

js数据类型

  • 无论是数字还是字符串都属于js的数据类型 js的数据类型还有很多 总体分为两项 基本数据类型的值存储在栈中 引用数据类型的值存储在堆中
  1. 基本数据类型 Number String Boolean undefined null symbol
  2. 引用数据类型 Object Array function

作用域 和 作用域链?

  1. 作用域分全局作用域和局部作用域 全局作用域中声明的属性和方法在任何地方都可以使用 局部作用域中的属性和方法在外部不能获取
  2. 作用域指的是一个变量和函数的作用范围
  3. 函数内部有作用域 也就是函数内部的方法或者变量不能在函数外部获取
  4. 作用域链 因为函数内部还可以继续写函数 函数的作用域不断的形成父子关系,这个关系就叫做作用域链

闭包?

  • 闭包的写法形式就是函数嵌套函数,在函数的内部返回一个函数就是闭包
  1. 闭包的优点
  • 长期保持对闭包变量的引用 使变量不会被销毁
  • 让函数外部能够获取函数内部的数据或者方法
  1. 闭包的缺点
  • 因为变量不会销毁 所以会占用内存 影响运行速度 污染环境
  • 在IE中可能导致内存泄漏 所以不建议滥用闭包

函数

  • 函数的主要作用是封装和复用逻辑

  • function是标记 是一个函数的方法

  • fn是函数的名字 函数的名字是自定义的

  • 函数名加()是函数调用 函数调用会将函数内部的逻辑重新执行一遍

  • console.log(函数名()) 返回值undefined 函数可以有返回值 在没有返回值的情况下 默认是undefined

  • 函数可以通过 return 得到返回值 return后面是什么 函数的返回值就是什么

  • 函数声明的地方可以接受参数 参数用变量的形式表示

  • 参数的名字是自定义的 形参和实参是同一个数据

  • 形参和实参是按照顺序一一对应的

  • 函数调用的时候可以传参 这个参数是实参

  • 实参可以是任意一种类型的数据

vue的路由有几种模式?

  • vue的路由有两种模式 一种是hash模式 另外一种是history模式 默认是hash模式
  • hash模式的表现形式就是在路由地址上 #后面表示路由的地址以及路由参数
  • history模式不需要有#表示路由地址
  • 原理上来讲 hash使用的是锚点
  • history模式使用的是h5新增的pushState 和 replaceState方法

vue的data为什么是一个函数?

如果data是⼀个函数的话,这样每复⽤⼀次组件,就会返回⼀份新的data,类似于给每个组件实例创建⼀个私有的数据空间,让各个组件实例维护各⾃的数据。⽽单纯的写成对象形式,就使得所有组件实例共⽤了⼀份data,就会造成⼀个变了全都会变的结果。 所以说vue组件的data必须是函数。这都是因为js的特性带来的,跟vue本身设计⽆关。

v-if和v-show的区别?

  1. v-if 是vue的一个指令 他是通过删除和新增dom元素来控制内容的显示隐藏
  • v-if的值如果是false的话 会删除对应的dom元素 否则会创建对应的dom元素
  • v-if的安全性会比v-show要高 但是更消耗性能
  1. v-show 也是vue的一个指令 他是通过css样式来控制内容的显示隐藏
  • v-show的值是false的时候 会给元素添加display:none;样式来隐藏内容 否则会删除display:none;样式来显示元素,v-show更适用于频繁切换的逻辑 节省性能

key的作用以及为什么不建议使用index作为key值?

  • key的值必须是惟一的 通常情况下建议使用id
  • 不建议使用index是因为index的值是可以改变的
  • key的作用是给元素添加一个唯一的标识 防止dom重复渲染

vue的computed属性

他是一个计算属性 只有当依赖的数据发生变化的时候才会触发,结果会缓存

v-for?

v-for是一个循环指令 他可以用来循环渲染数组 对象 字符串以及数字等数据 v-for循环数组的时候有两个变量别名 item表示数组项 数组项指的是数组中的每一条数据 他的名字可以自定义 index表示数组的索引值(下标)他的名字也可以自定义 也可以省略不写

v-bind和v-on

:是v-bind的缩写,是vue的一个绑定属性的指令 通过这个执行 属性的值可以写成一个变量也可以是一个表达式 他可以绑定任意属性 包括自定义属性

@是vue的v-on指令的缩写,可以用来绑定所有的事件 包括自定义事件 如果事件的逻辑足够简单我们可以写成一个表达式

this的指向?

this的本质是一个指针 普通函数内部的this指向调用函数的对象 构造函数内部的this指向实例化对象 箭头函数没有自己的this对象 他的this是上层作用域的this

new都做了什么?

  1. 创建了一个空对象
  2. 修改函数内部的this指向 指向实例化对象
  3. 给对象添加属性和方法
  4. 隐式返回该对象

原型和原型链?

  • 声明函数的时候函数会伴生一个对象prototype 这个对象就叫做原型,原型是一个对象,我们可以通过原型.属性名的方法给原型添加属性和方法 原型上的属性和方法可以通过实例化对象直接使用

  • 原型链 使用实例化对象中的方法或者属性的时候会先在自身中找,如果找不到就去自身的原型上找,如果还找不到就去原型的原型上找,直到找到或者报错为止,这个过程就叫原型链

修改this指向的方法 或者call apply bind的区别?

  • js修改this指向的方法有三种 分别是call apply bind call call方法改变this this指向他的第一个参数 他的其他参数是传递给调用call方法的函数的 其他参数以散落的形式传递给函数 apply apply方法和call用法是一样的 第一个参数也是修改函数内部this指向的对象 其他的参数是以数组的形式传递给函数的 call和apply方法会立刻调用函数 bind方法有返回值 返回值是调用bind的函数 不会立即调用函数

v-model?

v-model是vue的一个双向数据绑定的指令 通常用于表单元素 他是v-bind:value和v-on:input事件的语法糖 采用数据劫持 结合发布者订阅者模式 通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调

watch如何监听路由的变化?

watch: {
  $route(to, from) {
    console.log(to, from)
  }
}

computed methods watch 区别?

computed是计算属性 他的值有缓存 只有当依赖的属性发生变化时才会调用 methods里面用来放函数或者方法的 他没有缓存功能, 方法调用一次就执行一次 watch 监听属性,用来监听数据或者路由的变化,监听的数据或者路由发生变化后会自动执行

常用的数组方法有哪些?

常用的数组方法有 push方法 数组的末尾添加元素 可以添加多个 会改变原数组 返回值是新数组的长度 unshift用法和push一样 只是他是向数组的头部添加数据 返回值也是新数组的长度 pop方法 从数组的尾部删除数据 一次只能删除一个 会改变原数组 返回值是删除的元素 shift方法用法和pop一样 知识他是从头部删除一个数据 返回值就是删除的数据 splice方法用来修改数组,他有三个参数 第一个参数是从哪里开始 第二个是删除数据的数量 第三个要修改成的值 他会改变原数组 返回值是删除的数据的集合 concat方法用来合并数组 可以将多个数组数组合并在一起 他的返回值是合并后的新数组 他不会改变原数组 slice他是一个查询方法 他不会改变原数据 他可以用来查询数组或者字符串的片段 返回值就是查询到的片段 他的第一个参数是从哪里开始查 第二个是查到哪里结束 indexOf 用来查询数组或者字符串中是否有某个值 如果有则返回该值的下标,否则返回-1

常用的数组循环方法

forEach 方法接收一个函数作为参数 该函数内部有三个参数 分别是 数组项 索引值以及数组本身 后面的两个参数为可选参数, forEach方法没有返回值 会改变原数组 map方法接收一个函数作为参数 该函数内部有三个参数 分别是 数组项 索引值以及数组本身 后面的两个参数为可选参数 但是map有返回值 返回值是一个新的数组 他不会修改原数组 filter方法接收一个函数作为参数 该函数内部有三个参数 分别是 数组项 索引值以及数组本身 后面的两个参数为可选参数,他是一个数组的过滤方法 可以过滤出满足条件的数据 返回值是满足条件的数据的集合 some方法接收一个函数作为参数 该函数内部有三个参数 分别是 数组项 索引值以及数组本身 后面的两个参数为可选参数,some用来判断数组中是否有满足条件的数据如果有就返回true否则返回false every方法接收一个函数作为参数 该函数内部有三个参数 分别是 数组项 索引值以及数组本身 后面的两个参数为可选参数,every用来判断是数组中的数据是否全部满足条件如果满足就返回true否则返回false sort方法是一个排序方法 他的返回值是排序后的数组

mvvm模式?

vue是一个使用了mvvm模式的轻量级渐进式框架 mvvm中的m指的是model就是数据模型 v指得是view就是视图 vm viewModel 数据改变的时候通知视图更新 视图更新也会通知数据改变

虚拟dom ?

  • 虚拟dom其实本质上就是一个用js描述的对象,虚拟dom可以通过createElement()转化真实的dom

vue的生命周期

vue的生命周期其实就是页面或者组件从创建到销毁的过程 vue的生命周期有 每一个组件或者页面都有这些生命周期 beforeCreate() 虚拟dom创建之前 这个时候组件的实例已经有了 但是选项式api例如data methods里面的方法或者数据还不能使用 created() 虚拟dom创建完成 这个时候选项式api中的方法或者数据就可以使用了 但是这时候dom还没有渲染,所以不能获取到元素 beforeMounte() 准备渲染虚拟dom mounted() 真实的dom渲染完成 这时候就能够获取到真实的dom了 beforeUpdate() 数据改变导致的虚拟dom更新或者打补丁之前触发的生命周期 updated() 数据改变导致的虚拟dom更新或者打补丁之后触发的生命周期 beforeDestory() 组件销毁之前 destoryed() 组件销毁之后 errorCaptured() 捕捉组件错误的生命周期

  • 当我们使用了keep-alive之后会多出两个生命周 activated() 缓存的组件被激活时调用 deActivated() 缓存的组件被销毁时调用

$nextTick

当模版渲染完成或者更新打补丁完成之后立即触发的一个方法 nextTick是在下次DOM更新循环结束之后执⾏延迟回调,在修改数据之后使⽤nextTick 是在下次 DOM 更新循环结束之后执⾏延迟回调,在修改数据之后使⽤ nextTick,则可以在回调中获取更新后的 DOM

props接收的数据类型以及props验证?

  • props在vue中可以用来接收父组件传递给子组件的数据 数据是单向传递的(单向数据流)
  • props接收数据有两种方法 一种是通过数组的形式接收, 另外一个中是通过对象的形式接收 我们建议大家使用对象的形式接收 因为数组的形式没有数据验证

import?

import 导入内容的方法 也叫作依赖注入

px rpx em rem vh vw vmin vmax 百分比的区别?

px值得是像素 固定单位 没有自适应 rpx是小程序的布局单位 能够自适应 1px = 2rpx em 指的是字节单位 当字体大小是20px的时候 1em = 20px rem 我们常用的自适应布局单位 他是根据根节点(html)的字体大小来规定大小 vh 指的是可视高度 1vh 相当读屏幕可视高度的1% vw 指的是可视宽度 1vw 相当于可视宽度的1% vmin 是采用vh和vw中较小的一个作为参考标准 vmax 是采用vh和vw中较大的一个作为参考标准 百分比布局 1% 相当于父元素宽高的1%

本地存储 ?

  1. cookie cookie必须使用在服务器环境 他的存储大小在4k左右 他可以在浏览器和服务器之间穿梭 cookie可以通过expires设置过期时间 也可以通过path设置数据隔离
 document.cookie = "age=16"
 console.log(document.cookie)
  1. localStorage 和 sessionStorage是 h5新增的两种存储数据的方法 他们的存储空间都在5M左右 他们的用法是一样的都是通过 setItem存储数据 通过getItem获取存储的数据 通过 removeItem删除存储的数据 也可以通过clear清空对应的存储数据

他们的区别是localStorage存储的数据不会自动清除 除非用户手动清除或者我们代码中出现removeItem或者clear方法去清楚 sessionStorage是当前对话关闭的时候就是自动清除

同步任务 宏任务和微任务 ?

  • 宏任务和微任务都属于异步操作
  • 宏任务例如有 ajax setTimeout setInterval等异步任务
  • 微任务例如 promise async await
  • 执行顺序 先执行同步任务 再执行微任务 最后执行宏任务

事件循环?

    1. 先执行同步任务
    1. 碰到宏任务就将宏任务方法宏任务队列中
    1. 碰到微任务就将微任务放入微任务队列中
    1. 微任务和宏任务不会影响同步任务的执行
    1. 先执行同步任务 再执行微任务 最后执行宏任务

深复制和浅复制?

深浅拷贝主要是针对引用数据类型来说的 浅拷贝是新数据的指针也指向了老数据,所以新数据改变 老得数据也会跟着改变

深拷贝: 方法常用的有两种一种是使用json,但是json无法深复制数据中的函数 第二种我们常用的深复制方法就是递归 递归就是函数的自我调用 递归深拷贝就是对原有数据层层递归直指将所有数据递归成基本数据类型 然后在重新组合成一个新的数据

 var obj = {
      name: '张三',
      age: 16,
      fun: function() {
        console.log(1)
      },
      info: {
        sex: '男'
      }
    }
      function deepCopy(params) {
      var newVal = {}
      if(params instanceof Object) { // 如果params是一个对象
        for(var key in params) {
          // console.log(key, params[key])
          if(params[key] instanceof Object) {
            newVal[key] = deepCopy(params[key])
          } else {
            newVal[key] = params[key]
          }
          
        }
      }
      return newVal
    }

    var obj2 = deepCopy(obj)
     // console.log(obj2)
    obj2.info.sex = '女'
    console.log(obj2)
    console.log(obj)

自定义指令的钩子函数 ?

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

var let 和 const的区别?

let const是es6新增的两种生命数据的方法 var 声明的变量在代码块外能够获取到,但是存在变量提升 let 声明的数据在代码块外无法获取到,因为let会将当前代码块转化为一个暂时行的死区 不存在变量提升 const 声明的是一个常量 数据在代码块外无法获取到,因为const会将当前代码块转化为一个暂时行的死区 不存在变量提升 const 声明的数据必须赋值 不能重新赋值 但是如果我们声明的是一个引用数据类型 他内部的属性是能够修改的

什么是解构赋值?

解构赋值就是按照一定的模式从数组或者对象中取出数据赋值给其他变量的过程 解构赋值要求等号两边的数据结构保持一致 数组的解构赋值是按照索引值一一对应的 对象的解构赋值是按照key一一对应的 字符串因为也有索引值所以它可以按照数组的形式进行解构赋值

将伪数组转化为数组的方法

Array.from用来将一个类数组对象(伪数组转化为真正的数组的方法)

数组扁平化?

flat es6提出的一种数组扁平化的方法 高纬数组转化为低纬数组的过程就叫做数组扁平化 他的参数是一个数量 数组扁平化的层数 当我们不知道数组有继承的时候 可以选择无限拉平 Infinity

箭头函数和普通函数的区别?

  • 写法上的区别,箭头函数省略了function用=>代替
  • 箭头函数没有自己的this,他的this是上层作用域的this
  • 不可以当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

for...in和for...of的区别?

  • for...in 她可以用来循环数组也可以用来循环对象,循环数组时得到的是index 循环对象时得到的key
  • for...of 不能用来循环对象 循环数组时得到的是数组的值

Set 和 Map数据结构?

  • set数据结构是一个类似数组的数据 但是它不允许有重复的数据 我们可以给他传递一个数组初始化
  • Map数据结构最大的一个特点就是可以使用任何数据作为对象的key 也可以接受一个数组作为参数,但是该数组必须是一个键值对的数组
map.set(a, '张三') // 给map数据设置属性的方法
console.log(map)
console.log(map.has(a)) // 判断map数据中是否有某个属性的方法
console.log(map.get(a)) //获取map中的数据

promise

promise是一种异步编程的解决方法 promise本质上是一个构造函数 他的参数是一个回调函数 promise有三个状态 pending(进行中) fullfilled(已成功) rejected(已失败)

在promise的回调函数中有两个参数 分别时resolve和reject resolve方法一但调用就会将promise立即从进行中的状态转化为已成功的状态

reject方法一担调用就会将promisea立即从进行中的状态转化为已失败的状态

不管promise成功还是失败他都已经执行结束

在promise的原型上有then和catch以及finally方法 then方法用来接受promise执行的结果 then方法有两个回调函数 第一个回调函数接受的是reslove方法传递出来的数据 第二个回调函数用来接受reject方法传递出来的数据 但时平时我们更习惯的去使用catch来获取失败的结果

finally方法是promise执行结束时触发的方法

promise还有一些静态方法包括 all race allSettled any all方法接受多个promise作为参数 只有所有的promise都执行成功时all才会是成功的状态 否则就是失败的状态

allSettled方法可以用来获取接受的所有的promise的结果 不管是成功还是失败都可以接受到

race方法也可以接受多个promise作为参数 哪一个pormise先有结果。race就获取到哪一个的结果

any也是接受多个promise只要其中有一个成功 那么就会将promise的状态转化为成功了

symbol?

symbol是es6提出的一种新的基本数据类型 他用来声明唯一的数据

constructor prototype __proto__三角关系?

函数声明时会生成一个对象叫做 prototype它叫做原型对象 也就是显示原型 prototype是一个对象 对象中有一个方法constructor,该方法指向构造函数本身 在实例化对象中也有一个原型对象 (隐式原型)__proto__指向构造函数的原型prototype

vue的指令?

v-bind 绑定属性的指令 可以绑定任何属性,绑定属性的时候属性的值可以写成变量 v-on 绑定事件的方法 v-html 可以用来解析标签 通常用来渲染富文本 他利用的是原生js的innerHTML方法 v-text 不能解析标签 利用的是原声js的innerText方法 v-model 他是v-bind:value和v-on:input事件的语法糖 他是一个数据双向绑定的指令,通常我们用于表单元素 v-if v-else v-show v-for v-once 只生效一次 v-cloak 防止插值闪烁问题 需要结合样式 [v-cloak]: {display: none;}来使用 v-pre 会跳过mustache标签的编译阶段 v-slot

事件修饰符?

.stop 阻止事件冒泡 .prevent 阻止默认事件 .capture 开启捕获 .self 只对元素本身生效 .once 只生效一次 .nature 触发原声事件 .passive 修饰符尤其能够提升移动端的性能。

组件通信?

  • 父传子
  • 所谓父传子 其实就是让子组件能够使用父组件的数据或者方法
  1. 在父组件中给子组件添加一个自定义属性 子组件通过props接收
  2. this.$parent 获取父组件的实例 从而获取到父组件的数据和方法(在项目中不建议过多使用)
  3. provide inject provide通常用于高阶组件
  • 子传父
  • 子传父其实就是让父组件能够获取和使用子组件数据的过程
  1. 在父组件中给子组件添加一个自定义的事件 在子组件中通过this.$emit触发
  2. this.$children 获取子组件的实例列表
  3. this.$refs 用来获取组件的实例从而获取到组件的数据和方法
  • 非父子组件传值
  • bus 在vue的原型上挂载一个vue的实例 在接受数据的组件中通过 this.bus.bus.on('自定义事件', 回调函数),在要传递数据的组件中通过 this.bus.bus.emit('自定义事件', 要传递的数据)

vue的路由模式?

根据模式的不同 vue的路由可以分为 hash模式 和 history模式两种

vue路由传参方式以及区别?

vue的路由传参 分为query、params以及动态路由传参 query携参 参数会以?key=value&key=value的形式表现在路由地址上 如果我们用name或者path进行页面跳转都可以使用query进行携带参数 query携带的参数可以在页面中通过this.route.query获取到query参数刷新页面不会丢失params参数不会显示在路由地址上params携带的参数可以在页面中通过this.route.query获取到 query参数刷新页面不会丢失 params参数不会显示在路由地址上 params携带的参数可以在页面中通过this.route.params获取 params参数刷新页面会丢失 params和name以及path也可以用来合作跳转页面 但是 params和path合作无法传参 动态路由实在路由地址上设置:自定义属性的形式设置动态地址 动态路由的参数也是通过this.$route.params获取到的

路由守卫?

vue导航守卫分为 全局路由守卫 路由独享守卫 以及 组件内守卫 全局路由守卫 分为 全局前置守卫 (router.beforeEach)全局解析守卫(router.beforeResolve) 全局后置守卫(router.afterEach) 路由独享守卫 beforeEnter() 组件内守卫 分为 路由进入之前(beforeRouterEnter) 路由更新之前(beforeRouteUpdate) 路由离开之前 (beforeRouteLeave) 每一个路由守卫都有的两个参数分别是 to from to表示的是要进入的页面的路由对象 from是要离开的页面的路由对象 router.afterEach没有next参数 因为这个时候页面已经进入了,其他的路由守卫都有next参数 定义路由守卫下一步要到哪里去

mixin 混入

混入分为全局混入和局部混入 全局混入的方法就是 Vue.mixin() 局部混入就是使用选项式api mixins: []

ts

  • ts => typescript 相对于js而言 typescript 更注重type也就是数据的类型
  • typescript是js的超集 微软推出的一门 轻量级的 动态的 编译类型的语言
  • js是一门 轻量级的 动态的 解释类型的语言
  • ts需要编译成js之后才能执行 ts能够兼容js的语法

ts数据类型

  • boolean(布尔值) number(数字) string(字符串) null(null) undefined(undefined) Symbol(Symbol) void(没有类型) any(任意类型)never(从来不会出现的类型)object(对象类型) Enmu(枚举类型和) array(数组类型) turple(元祖类型)

void类型表示没有类型 和any相对 通常用来当函数没有返回值的时候我们给函数定义void类型

any表示任意类型 但是只建议在必要的情况下使用any

never不会出现的了类型

turple TS 中的元祖类型其实就是数组类型的扩展,元祖用于保存定长, 定数据类型的数据

联合类型 可以通过管道符|将变量设置多种类型,赋值时可以根据设置的类型来赋值

枚举类型
enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
// 枚举类型
// 1 未完成 2 已完成 3 已取消
// enum state {
//   '未完成',
//   '已完成' = 2,
//   '已取消'
// }
// console.log(state[1])
// console.log(state[2])
// console.log(state['未完成'])
// console.log(state['已取消'])
  • ts生命变量时一但赋值或者我们添加了类型 那么他的数据类型就不能更改

类型推论

类型推论 会根据值的类型定义变量的类型

interface接口

接口其实就是一种约定

type和interface的区别

interface 接口其实就是一种约定 接口主要用于类型检查,它只是一个结构契约,定义了具有相似的名称和类型的对象结构。除此之外,接口还可以定义方法和事件。

type 不同于 interface 只能定义对象类型,type 声明还可以定义基础类型、联合类型或交叉类型。

区别? interface 只能定义对象类型, 而 type 声明可以声明任何类型,包括基础类型、联合类型或交叉类型。

泛型?

泛型简单来说就是类型变量,在ts中存在类型,如number、string、boolean等。 泛型就是使用一个类型变量来表示一种类型,类型值通常是在使用的时候才会设置。泛型的使用场景非常多,可以在函数、类、interface接口中使用

为什么使用泛型?

TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。 TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活,可以在编译时发现类型错误,从而保证了类型安全。

封装ajax?

var xhr = new XMLHttpRequest() 实例化ajax对象 开启一个ajax请求 请求方式 请求地址 是否异步 xhr.open(options.method, options.url) 发送请求 xhr.send() 监听请求状态的变化 on监听的意思 readyState准备状态 change改变的意思 xhr.onreadystatechange = function() { readyState 有五个状态分别是 0 1 2 3 4 状态变为4的时候表示服务器成功响应了 if(xhr.readyState === 4 && xhr.status === 200) { // 表示请求成功且服务器返回数据 // console.log(JSON.parse(xhr.responseText)) // responseText服务器返回的响应文 resolve(JSON.parse(xhr.responseText)) } }

类型断言?

类型并不会修改数据的类型 他只是欺骗了ts的类型检查机制 下面两种都是类型断言的方法 但是我们推荐使用第一种 (opt as FishConfig).swim() (opt).swim()

// var cat  = {
//   type: '猫',
//   run(){
//     console.log('小猫会四条腿奔跑')
//   }
// }

// var fish = {
//   type: '鱼',
//   fish(){
//     console.log('会游泳')
//   }
// }

// interface CatConfig {
//   type:string,
//   run: () => void
// }
// interface FishConfig {
//   type: string,
//   fish: () => void
// }
// function Animal(opt:CatConfig | FishConfig) {

//   (opt as FishConfig) 类型断言
//   (opt as FishConfig).fish()
// }

// Animal(cat)

ts接口?

interface

interface UserConfig{
  name:string,
  age: number,
  readonly idCard: '1111111111111111', // 定义只读属性
  tel?: number // 定义可选属性
}



// 可选参数必须放在后面
function fn(a:number, b:number, c?:number, d?:number) {

}
fn(1, 2, 3)

类型推论?

会根据值的类型定义变量的类型

vue辅助函数?

...mapState ...mapGetters 写在计算属性里面使用

...mapMutations ...mapAction 写在methods里面使用

载荷?

commit这种传递参数的方法叫做载荷

vuex是什么 ?

专门为vue提供的一种状态管理工具

五个核心用法? state 用来存放公共类型的数据 getters 类似于计算属性 当依赖的state数据发生变化的时候就会触发 有缓存效果

mutations 唯一能够修改state数据的方法 mutation是一个函数 函数名是自定义的 每一个mutation都有一个公共的参数叫做state 执行mutation方法的方法就是在页面中通过this.$store.commit() 他有两个参数第一个是就是我们要提交的mutation函数名 第二个就是要给mutation传递的参数

action dispatch 分发的意思 做异步操作 在组件中通过this.$store.dispatch触发action 然后每个action都有一个参数叫做context(本质上是一个关联vuex上下文的实例) 在action中我们可以通过context.commit()提交mutation 然后通过mutation修改state数据

modules 分发模块 模块化

plugins 记载插件的方法

vuex的固化工具原理是什么?

固化插件使用的也是js的数据存储 localStorage 和 sessionStorage

再使用的时候有两个参数 第一个参数 storage 可以通过该属性设置存储的类型 默认是localStorage 第二个参数 reducer 是一个函数 参数为state 可以使用该方法自定义存储哪些数据

  plugins: [
   persist({
     storage: sessionStorage, //可以通过该属性设置存储的类型 默认是localStorage,
     reducer(state) { // 可以使用该方法自定义存储哪些数据
       return {
          'list': state.list,
          'user': state.user
       }
     }
   })
  ]

vuex中getters的参数?

一共有4个 在不分割模块的情况下 一般只要第一个state

第一个state 当前模块state数据 第二个getters 是包含的所有模块的getters方法 第三个rootState 所有模块中的数据 第四个rootGetters 所有模块的getters方法

vuex中的命名空间?

就是给modules分发的模块文件添加一个 namespaced: true, 属性

vuex中怎么分割模块?

在store文件夹下创建一个js文件 然后在store文件夹下的index.js文件中引入 然后再去modules方法里面注册

每个模块内都有 state getters mutations actions 方法

扩展--------------------------------------

怎么获取模块内的数据?

this.$store.state.模块名

export default {
  state: {},
  getters: {},
  mutations: {},
  actions: {},
}

watchEffect 和 watch 有什么区别?

watch 并不需要传入具体的监听对象。可以自动识别要监听的依赖项 watchEffect 无法获取到原始值,只能获取到变化后的值

vue2中 router-link怎么转换为其他标签?

设置tag属性 如果想要修改成其他标签,比如div标签,只需要在router-link中添加tag="div"即可,并且不会影响其路由的切换

vue3中是 v-slot

怎么实现回到顶部效果?

scrolltop 改为 0

滚动容器设置