Vvue 的优点:
- 轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有即时Kb
- 简单易学:国人开发,中文文档,不存在语言障碍,易于理解和学习
- 双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单
- 组件化:保留了 react 的优点,实现了 html 的封装和重用,在构建单页应用方面有着独特的优势
- 视图:数据,结构分离,使数据的更改更为简单,不需要进行逻辑代码的更改,只需要操作数据就能完成相关操作
- 虚拟DOM:dom 是非常耗费性能的,不再使用原生 的dom 操作节点,极大解放dom 操作,但具体操作的还是 dom 不过是换了另外一种方式
- 运行速度更快:相对于 react 而言,同样是操作虚拟dom,就性能而言,vue 存在很大的优势
说说你对 SPA 单页面的理解,他的优缺点分别是什么
- SPA 仅在 Web 页面初始化时加载相应的 HTML,JS和CSS
- 一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或者跳转
- 而页面的变化是利用路由机制实现 HTML内容的变换,避免页面的重新加载
优点:
- 用户体验度好,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
- 减少了不必要的跳转和重复渲染,这样相对减轻了服务器的压力
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理
缺点:
- 初次加载耗时多
- 不能使用浏览器的前进后退功能,由于单页应用是在一个页面中显示所有的内容,所以,无法前进后退
- 不利于搜索引擎检索:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上有着其天然的弱势
SPA 首屏加载速度慢是怎么解决
首屏时间:指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个页面不一定要全部渲染完成,但需要展示当前视窗需要的内容。
首屏加载慢点原因:
- 网络延时问题
- 资源文件体积是否过大
- 资源是否重复发送请求去加载了
- 加载脚本的时候,渲染内容堵塞了
常见的几种SPA 首屏优化方式
- 减少入口文件体积
- 静态资源本地缓存
- UI框架按需加载
- 图片资源的压缩
- 组件重复打包
- 开启Gzip打包
- 使用SSR
有一个博客写的关于SPA讲解的挺详细的,感兴趣的可以看一下:详解SPA
Vue 初始化过程中(new Vue(options)) 都做了什么
- 处理组建配置项: 初始化根组件时进行了选项合并操作,将全局配置合并到根组件的局部配置上;初始化每个子组件时做了一些性能优化,将组件配置对象上的一些深层次属性放到 vm.$options 选项中,以提高代码的执行效率
- 初始化组件实例的关系属性,比如 parent,children,root,refs等
- 处理自定义事件
- 调用before Create钩子函数
- 初始化组件的 inject 配置项,得到 ref[key]=val形式的配置对象,然后对该配置对象进行响应式处理,并代理每个 key 到 vm 示例上
- 数据响应式,处理 props,methods,data,computed,watch等选项
- 解析组件配置项上的 provide 对象,将其挂载到 vm_provided 属性上
- 调用 created 钩子函数
- 如果发现配置上 有 el 选项,则自动调用 $mount 方法,也就是说有了 el. 选项,就不需要再手动调用 $mount方法,反正,没提供 el 选项则必须调用 $mount
- 接下来进入挂载阶段
-
对 MVVM 的理解
MVVM 由 Model,View,ViewModel 三部分构成:Model层代表数据模型,也可以Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转换成UI展现出来;View Model 是一个同步 View 和 Model的对象
在MVVM 架构下,View 和Model 之间并没有直接的联系,而是通过ViewModel 进行交互,Model 和 ViewModel之间的交互是双向的,因此 View 数据的变化会同步到 Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过数据双向绑定把 View和Model层连接起来,而View 和model之间的同步工作完全是自动的,无需认为干涉,因此开发者只需要关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM来统一管理
Vue 数据双向绑定原理
实现MVVM数据双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来给各个属性添加setter,getter并劫持监听,在数据变动时发布消息给订阅者,触发相应的监听回调。
就必须实现一下几点:
- 实现一个数据监听器 Observer ,能够对数据对象的所有属性进行监听,如有变动可以拿到最新值并通知订阅者
- 实现一个指令解析器 Compile ,对每个元素节点的指令进行扫描和解析,根据指令模版替换数据,以及绑定相应的更新函数
- 实现一个watcher,作为连接 Observer和Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令的相应回调函数,从而更新视图
-
Vue 的响应式原理
什么事响应式,也就是说,数据发生改变的时候,视图会重新渲染,匹配更新为最新的值
Object.defineProperty 为对象中的每一个属性,设置 get. 和set. 方法,每个声明的属性,都会有一个专属的依赖收集器 subs ,当页面使用到某个属性时,会触发 Object.defineProperty-get 函数,页面的watcher 就会被放到属性的依赖收集器 subs中,在数据变化时,通知更新:当数据改变的时候,会触发Object.defineProperty-set 函数,数据会遍历自己的依赖收集器 subs,逐个通知watcher,视图开始更新;
Vue 3.x 响应式数据原理:
Vue3.x 改用Proxy 替代object.defineProperty .因为proxy可以直接监听对象和数组的变化,并且由多达13种拦截方法,并且作为新标准将受到浏览器厂商重点持续的性能优化;proxy只会代理对象的第一层,vue3 是怎么处理的呢
判断当前Reflect.get 的返回值是否是 Object,如果是 则再通过 reactive方法做代理,这样就实现了深度观测。监测数组的时候可能触发多次 get/set,那么如何防止触发多次?我们可以判断key 是否为当前代理对象 target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger
Vue 3.0为什么要用proxy API 替代 defineProperty API
- definePropety API 的局限性最大原因是它只能针对单例属性做监听,Vue2.x 中的响应式实现正式基于objectProperty中的descriptor,对data中的属性做了遍历+递归,为每个属性设置了 getter/setter。这也就是为什么vue 只能对data 中定义过的属性做出响应的原因
- Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作,这就完全可以代理所有的属性,将会带来很大的性能提升和更优的代码;Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界对访问进行过滤和改写
- 响应式是惰性的。在Vue2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历这个对象,执行Object.defineProperty,把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。在Vue3.0中,使用Proxy API 并不能监听到对象内部深层次的属性变化,因此它的处理方式是在getter中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗
Proxy 与Object.defineProxy 优劣对比
- Proxy 可以直接监听对象而非属性
- Proxy可以监听数组的变化
- Proxy有多大13种拦截方法:不限于apply,ownKeys,deleteProperty,has 等等,是Object.defineProperty不具备的
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
- Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利
- ObjectProperty 的优势:兼容性好,支持IE9,而Proxy 的存在浏览器兼容性问题,而且无法用polyfill 磨平,因此Vue 的作者才声明需要等到下一个大版本(3.0)才能用 Proxy 重新
Vue 中组件的data为什么是一个函数,而 new Vue 实例里,data可以直接是一个对象
我们知道,每一个.vue文件就是一个Vue组件,Vue组件其实就是一个Vue 实例。Js中的实例是通过构造函数来创建的,每个构造函数可以new 出很多个石榴,那么每个实例都会继续原型上的方法或者属性。Vue 的data 数据其实是Vue 原型上的属性,数据存在于内存中。Vue 为了保证每个实例上的data 数据的独立性,规定了必须使用函数,而不是对象。因为使用对象的话,每个实例(组件)上使用的data数据是相互影响的,这当然就不是我们想要的了。对象是对于内存地址的引用,直接定义个对象的话组件之间都会使用这个对象,这样会造成组件之间数据相互影响。使用函数之后,使用的是data()函数,data()函数中的this 指向的是当前实例本身,就不会相互影响了。而new Vue 的实例,是不会被复用的,因此就不存在引用对象的问题。
Vue 中 data的属性可以和methods 中方法同名么,为什么
Vue 中的data属性可以和methods中的方法进行同名的,但是methods中的方法会被data的属性覆盖,调试台也会出现报错信息,但是不影响执行。这样子的原因是:源码定义的initState函数内部执行的顺序是:props>methods>data>computed>watch
Vue 中 created 与 mounted 区别
在 created 阶段,实例已经被初始化了,但是还没有挂载在 el 上,所以我们无法获取到对应的节点,但是此时我们可以获取到 vue 中data 与methods 中的数据;
在 mounted 阶段, vue 的template 成功挂载在 el 上,此时一个完整的页面已经能够显示在浏览器中,所以在这个阶段,可以调用节点了;
Vue 中 computed 与 methods 的区别
computed 和 methods 相同点:如果作为模版的数据显示,二者能实现响应的功能,唯一不同的是methods 定义的方法需要执行
computed 和 methods 不同点:
- competed 会基于响应数据缓存,而 methods 不会进行缓存
- diff 之前先看 data 里面的数据是否发生变化,如果没有变化computed 的方法不会执行,但methods 里面的方法会执行
- computed 是属性调用,而methods 是函数调用
虚拟 DOM 中key 的作用
- 简单的说:key 是虚拟 DOM 对象的唯一标识,在更新显示时key起着极其重要的作用。
- 复杂的说:当状态中的数据发生了变化时,react 会根据 新数据 生成 新的虚拟DOM,随后 React 进行 新虚拟DOM 与 旧虚拟 DOM 的diff 比较.
- 比较规则如下: 旧虚拟DOM中找到了与新虚拟DOM相同的key,若虚拟DOM中的内容没有变,直接使用之前的真实DOM;若虚拟DOM中内容发生了改变,则生产新的真实DOM,随后替换掉页面中之前的真实DOM。旧虚拟DOM中没有找到与新虚拟DOM相同的key,则根据数据创建新的真实DOM,然后渲染到页面上。
用 index 作为 key 可能会引发到问题
- 若对数据进行:逆序添加/逆序删除等破坏顺序的操作,会产生没有必要的真实DOM更新,界面虽然没有问题,但是数据过多的话,会效率过低;
- 如果结构中还包含输入类的DOM,会产生错误DOM更新,界面有问题
- 如果不存在对数据的逆序操作,仅限于渲染表用于展示,使用 index 作为key 也是没有问题的
Vue 中 watch 用法详解
- 在Vue 中,使用 watch 来监听数据的变化,在监听的数据后面可以写成对象形式,包含 handler 方法,immediate 和 deep
- immediate 表示在 watch 中首次绑定的时候,是否执行 handler,值为true表示 在 watch 中声明的时候,就立即执行handler 方法,值为 false,则和一般使用 watch一样,在数据发生变化的时候才能执行handler。
- 当需要监听一个对象的改变时,普通的 watch 方法无法监听到 对象内部属性的改变,只有data 中的数据才能监听到变化,此时就需要deep 属性,对对象进行深度监听,值为true
-
Vue 中 对mixins 的理解和使用
mixins 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混合对象可以包含任意组件选项,当组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项,而mixins 引入组件之后,则是将组件内部的内容如 data 等方法,methods 等属性 与父组件相应内容进行合并。相当于引入后,父组件的各种属性方法都被扩充了。
有一个博客写的蛮好的,可以参考一下:mixins
Vue 中的插槽 :Vue 中的神兵利器,插槽 slot !
为什么 Vue 采用异步渲染
- Vue 是组件级别更新,当前组件里的数据变了,它就会去更新这个组件。当数据更改一次组件就要重新渲染一次,性能不高,为了防止数据一更新就更新组件,所以做了个异步渲染。(核心的方法就是 nextTick)
- 源码实现原理:当数据变化后会调用 notify 方法,将 watcher 遍历,调用update 方法通知 watcher 进行更新,这个时候 watcher 并会不会立即去执行,在 update 中会调用 queueWatcher 方法将watcher 放到一个队列里,在 queueWatcher 会根据 watcher 的进行去重,多个属性依赖一个 watcher,如果队列中没有该 watcher,将会将该watcher添加到队列中,然后通过nextTick 异步执行flushSchedulerQueue 方法刷新 watcher队列。 flushSchedulerQueue 中开始会触发一个 before到方法,其实就是beforeUpdate,然后 watcher.run()才开始真正执行watcher,执行完页面就渲染完成了,更新完成后就会调用 updated 钩子
Vue 的异步更新机制是如何实现的
- Vue 的异步更新机制的核心是利用了浏览器的异步任务队列来实现的,首选微任务队列,宏任务队列次之
- 当响应式数据更新后,会调用 dep.notify 方法,通知 dep 中收集的 watcher 去执行update 方法,watcher.upadte 将 watcher 自己放入一个watcher 队列 (全局queue 数组)。然后通过nextTick 方法 将一个刷新 watcher 队列的方法(flushSchedulerQueue) 放入一个全局的 callbacks 数组中。如果此时浏览器的异步任务队列中没有一个叫 flushCallbacks 的函数,则执行 timeFunc 函数,将 flushCallbacks 函数放入异步任务队列。如果异步任务队列中已经存在 flushCallbacks 函数,等待其执行完以后再放入下一个 flushCallbacks 函数。flushCallbacks 函数负责执行 callbacks 数组中的所有 flushSchedulerQueue 函数。flushSchedulerQueue 函数负责刷新 watcher 队列,即执行 queue 数组中每一个 watcher 的 run 方法,从而进入更新阶段,比如执行组件更新函数或者执行 用户 watch 的回调函数。
$nextTick 的理解
- $nextTick 的用法:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获得更新后的DOM。
- 实现的原理,为什么:Vue 实现响应式并不是数据发生变化之后DOM立即变化,而是按一定的策略进行DOM的更新。Vue 在更新DOM 时是异步执行,只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于不必要的计算和DOM操作是非常重要的。然而,在下一个的事件循环 ‘tick'中,Vue刷新队列并执行实际(以去重的)工作。所以为了在数据变化之后等待 Vue 完成更新DOM,可以在数据变化之后立即使用Vue.nextTick(callback),这样回调函数将会在DOM更新完成后被调用。
- 使用场景:在你更新完数据后,需要及时操作渲染好的DOM时。
Vue 的自定义指令
- Vue 除了核心功能默认内置的指令,Vue 也允许注册自定义指令
- 自定义指令用来操作 :DOM的,尽管 Vue 推崇数据驱动视图的理念,但并非所有情况都适合数据驱动,自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM 操作,并且是可复用的。
- 添加自定义指令的两种方式:全局指令和局部指令
- 全局指令:通过 Vue.directive() 函数注册一个全局的指令
- 局部指令:通过组件的 directives 属性,对该组件添加一个局部的指令。
- 有几个写的比较好的博客,感兴趣的可以看看详解:自定义指令
- 使用的场景:比如 v-image:登陆的默认头像
为什么避免 v-if 和v-for 一起使用
- vue 2.x 版本中,当 v-if 与v-for 一起使用时,v-for 具有比v-if 更高的优先级
- vue 3.x 版本中,当v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级
- 官方明确指出:避免v-if 和v-for 一起使用,永远不要在一个元素上同时使用这两个指令
- 解决这种方案:可以先对数据在计算数据中进行过滤,然后再进行遍历渲染;操作和实现起来都没什么问题,页面也会正常显示,但是会带来不必要的性能消耗。
v-show 和v-if 的共同点和不同点
- 相同点:v-show 和v-if 都可以控制元素的显示和隐藏。
- 不同点:实现本质方法不同,v-show 本质通过设置css 中的 display 设置none 控制隐藏;v-if 是动态的向DOM 树内添加或者删除DOM元素;v-show 都会编译,初始值为false,只是将 display 设为 none,但它也编译了;v-if 初始值为 false,就不会编译了;
- v-show 只编译一次,后面其实就是控制 css,而v-if 不停的销毁和创建,如果要频繁切换某节点时,故v-show 性能更好一点
- 实际开发中使用场景:按钮权限控制 v-if ;选择框筛选条件控制按钮的显示和隐藏:v-show;
Vue 为什么在 HTML 中监听事件
- 你可能注意到这种事件监听到方式违背了关注点分离(separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的ViewModel上,它不会导致任何维护上的困难。
- 实际上,使用v-on 或者@ 有几个好处:
- 扫一眼 HTML 模版便能轻松定位 在 JavaScript 代码里对应的方法,因为你无需在 JavaScript 里手动绑定事件,你的 ViewMode 代码可以是非常存粹的逻辑,和DOM完全解藕,更便于测试。当一个ViewModel 被销毁时,所有的事件处理器都会被自动删除,你无须担心如何清理他们
Vue.set 改变数组和对象中的属性
- 在一个组件实例中,只有在 data 里面初始化的数据才是响应式的,Vue 不能监测到对象属性的添加或者删除,没有在 data 里声明的属性不是响应式的,所以数据改变了但是不会在页面渲染;
- 解决办法:使用 Vue.set(object,key,value) 方法将响应属性添加到嵌套的对象上。
- Vue.set(object,key,value)别名vm.$set
- vm.$set(obj,key,value)做了什么:由于 Vue 无法探测到对象新增属性或者通过索引为数组新增一个元素,所以才有了 vm.set,它是 Vue.set 的别名;vm.set 用于向响应式对象添加一个 新的 property,确保这个新的 property 同样是响应式的,并触发视图更新。
- 为对象添加一个响应式的数据:调用的是 defineReactive 方法为对象提那件响应式数据,然后执行 dep.notify 进行依赖通知,更新视图。
- 为数组添加一个新的响应式数据:通过splice 方法实现
说说对 Vue 生命周期的理解
- Vue 生命周期:通俗的讲就 Vue 实例从创建到销毁的过程,八大钩子函数
- beforecreate(初始化界面前) created(初始化界面后)
- beforemount(渲染界面前) mounted(渲染界面后)
- beforeupdate (更新数据前) updated(更新数据后)
- beforedestory(卸载组件前) destoryed(卸载组件后)
- 值得说一下的是,当被问到这个问题,你可以进行八大钩子函数都做了什么进行一个开展解说
第一次页面加载会触发哪几个钩子:beforeCreate,created,beforemount,mounted
Vue 组件通信有哪些方法
- 父传子:props 。父组件通过props向下传递数据给子组件。子组件的数据共三种形式:props,data,computed
- 父传子/孙:provide 和inject。父组件定义provide方法return 需要分享给子孙组件的属性,子孙组件使用 inject 选项来接收指定的我们想要添加在这个实例上的属性;
- 子传父:$emit。子组件通过$emit() 事件形式给父组件发送消息,父组件通过 v-on 绑定事件来接收数据;
- 父子,兄弟,跨级:eventBus。这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来(emit)触发事件和(on)监听事件,巧妙清亮地实现了任何组件间的通信
- 通信插件:PubSub.js
- Vuex:vuex 是 vue 的状态管理器,存储的数据是响应式的。只需要把共享的值放到 vuex 中,其他需要的组件可以直接获取使用即可;
router 和route 的区别
- router 作为 VueRouter 的实例,相当于一个全局的路由器对象,里面包含很多属性和子对象,例如 history 对象。经常用的跳转链接就可以用 this.$router.push ,和 router-link 跳转是一样的。
- route 相当于当前正在跳转的路由对象,可以从里面获取 name,path,params,query等
Vue-router 有几种钩子函数
- 全局路由:全局路由导航钩子主要有两种钩子:前置守卫(beforeEach),后置钩子(afterEach)
- 路由独享的钩子:单个路由独享的导航钩子,它是在配置路由上直接进行定义的
- 组件内的导航钩子:组件内的导航钩子主要有三种:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave。他们是直接在路由组件内部直接进行定义的。
- 路由详解可以看一下
vue-router 路由跳转方式
- 声明式(标签跳转)
- 编程式(js跳转)
vue-router 路由传参
- ruoter-link 进行页面按钮式路由跳转传参:router中路由配置传参;父组件 home 点击传参;子组件 homeDetails 接受传参
-
有个比较好的博客可以参考一下 。
- this.$router.push 进行编程式路由跳转传参:router 中路由配置传参;父组件 home 点击传参;子组件 homeDetails 接受传参。 其中路由配置传参通过params,有两种方式:路由配置;name传参或者query方式的路由配置;
有个比较好的博客可以参考一下。
对keep-alive 的了解
- 首先,是 Vue 的内置组件。能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
- 其次,它实现的原因,当包裹动态组件时,会缓存不活动的组件实例,而不是销毁她们。
Vuex 是什么,它的作用是什么,怎么使用
- Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便实现组件数据之间的共享。
- Vuex 集中管理共享的数据,易于开发和后期维护
- Vuex 能够实现组件之间的数据共享,提高开发效率
- Vuex 存储在Vuex 中的数据是响应式的,能够实时保持页面和数据的同步
- Vuex 重要核心属性包括:state,mutations,action,getters,modules
- state :vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据,需要通过mutations.
- mutations: 定义的方法动态修改 Vuex 的 store 中的状态或者数据
- action :可以理解为通过将 mutations 里面处理数据的方法变成异步处理数据的方法,简单的说就是异步操作数据。View 层通过 store.dispath 来分发 action。
- getters: 类似 vue 的计算属性,主要用来过滤一些数据
- modules:项目特别复杂的时候,可以让每一个模块拥有自己的 state,mutation,action,getters 使结构非常清晰,方便管理;有一个比较好的博客可以看一下
- 使用场景:如果应用足够简单,最好不要使用 vuex,一个简单的store 模式即可;需要构建一个中大型单页应用时,使用vuex 能够更好的在组件外部管理状态。
Vuex 和单纯的全局对象有什么区别
- Vuex 的状态存储是响应式的。当 vue 组件从store 中读取状态的时候,若 store 中的状态发生了变化,那么相应的组件也会相应地得到高效更新。不能直接改变 store 中的状态,改变 store 中的状态的唯一途径就是显式地提交(commit) mutation,这样使得我们可以方便地追踪到每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
为什么 Vuex 的mutation 中不能做异步操作
- 因为mutation 执行完后都会对应到一个新的状态变更,这样 devtools 就可以大哥快照存下来,然后就可以实现 time-travel 了。如果mutation 支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。
axios 是什么,其特点和常用语法是什么
- axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
- 前端最流行的 ajax 请求库。
- react/vue 官方都推荐使用 axios 发 ajax 请求
- 特点:
- 基于 promise 的异步 ajax 请求库,支持 promise 所有的 API
- 浏览器端/ node 端都可以使用,浏览器中创建 XMLHttpRequest
- 支持请求 /响应拦截器
- 支持请求取消
- 可以转换请求数据和响应数据,并对响应回来的内容自动转换成JSON 类型的数据
- 批量发送多个请求
- 安全性更高,客户端 支持防御 XSRF,就是让你的每一个请求都带一个 cookie 中拿到 key,根据浏览器同源策略,假冒的网站是拿不到 你cookie 中的key 的,这样,后台就轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略
- 常用语法:
- axios(config):通用/最本质的发任意类型请求的方式
- axios(url[,config]):可以指定 url 发get 请求
- axios.request(url[,config]):等同于 axios(config)
- axios.get(url[,config]) 发送get 请求
- axios.delete(url[,config]) 发delete 请求
- axios.post(url[,data,config]) 发post 请求
- axios.put(url[,data,config]) 发put 请求
- axios.defaults.XXX 请求的默认全局配置
- axios.interceptors.request.use() ;添加请求拦截器
- axios.interceptors.response.use(); 添加响应拦截器
- axios.create([config]);创建一个新的 axios (它没有下面的功能)
- axios.Cancel();用于创建取消请求的错误对象
- axios.CancelToken();用于创建取消请求的token 对象
- axios.isCancel();是否是一个取消请求的错误
- axios.all(promises) 用于批量执行多个异步请求
- axios.spread() :用来指定接收所有成功数据的回调函数的方法
对SSR 有了解么,它主要解决什么问题
- Server-Side Rendering 我们称其为 SSR,意思是指服务端渲染;指由服务侧完成页面的HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。
- 优点:便于SEO,搜索引擎优先爬取页面 HTML 结构,使用SSR 时,服务端已经生成了和业务相关联的HTML ,有利于 SEO;首屏渲染渲染,用户无需等待页面所有 js. 加载完成就可以看到页面视图(压力来到了服务器,素以需要权衡哪些用服务端渲染,哪些交给客户端)
- 缺点:复杂度,这个那个项目的复杂度,性能将会受到影响;服务器负载变大,相对于前后端分离服务器只需要提供静态资源来说,服务器负载更大,所以要慎重使用。
Vue. 要做到权限管理该怎么办做,控制到按钮级别的权限是怎么做的
- 有一个比较好的博客
- 实际项目中:公司有一套权限管理系统,接入,配置权限,代码中引入,按钮权限通过 自定义指令 配合 v-if 一起使用
Vue 项目前端开发环境请求服务器端接口跨越问题
- 对于 vue-cli 2.x 版本在config 文件夹配置服务器代理
- 对于 vue-cli 3.x 版本前端配置服务器代理在 vue.config.js 中设置服务器代理:比如target 对应的属性值为:你准备向后端服务器发送请求的主机+端口;含义为:相当于把前端发送请求的主机+端口自动替换成挂载的主机和端口,这样前后端的主机端口,就不会存在跨域问题了;
- ws:表示 webScoket 协议
- changeOrigin:true;表示是否会改变原域名,这个一定选择为 true;这样子就不会出现跨域问题了。
做过哪些 VUE 的性能优化:
- 编码阶段:尽量减少 data中的数据,data 中的数据都会增加 getter和setter,会收集对应的watcher;v-if 和v-for 不连用;防抖,节流;使用路由懒加载,异步组件;第三发模块按需导入;图片懒加载;长列表滚动到可视区域动态加载;key 保证唯一;SPA 页面采用 keep-alive 缓存组件;如果需要使用 v-for 给每项元素绑定事件时使用事件代理
- SEO优化:服务端渲染 SSR;预渲染;
- 打包优化:压缩代码;Tree Shaking/ScopeHoisting;使用cdn 加载第三发模版;多线程打包 happypack;splitChunks 抽离公共文件;sourceMap 优化
- vue 3.x 有了解过么,能说说与 vue 2.x的区别吗
有一个不错的博客
Vue 3.0 所采用的composition API 和 Vue 2.x 使用的 options API 有什么区别
- options API :包含一个描述组件选项(data,methods,props 等)的对象 options;API 开发复杂组件,同一个功能逻辑的代码被拆分到不同选项;使用mixin 重用公共代码,也有问题:比如命名冲突,数据来源不清晰
- compositon API:vue 3新增的一组 api,它是基于函数的 api,可以更灵活的组织组件的逻辑;解决options API 在大型项目中,options API 不好拆分和重用的问题。
elment-ui 中遇到的问题:
- el-cascader 多选在 IE 中样式不正常