2022年vue面试题总结

vue 中 data 为什么是一个函数

vue组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,
如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;
而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。

vue 组件的通信

①ref通信
②$children
③$parent
④props和$emit
    ==>async修饰符
    ==>this.$emit("update:变量",需要传递的值)
⑤eventBus事件总线
    ==>vue.prototype.$EventBus = new Vue()
    ==>import Vue from 'vue'---export const EventBus = new Vue()
⑥provide/inject
⑦vuex通信
⑧attrs/listeners 适用于 隔代组件通信
    ==>inheritAttrs:false
    ==> 
⑨vue2.6新加的v-slot实现作用域插槽通信:在父组件中使用子组件的数据
    ==>0000000000
    ==>

vuex 的原理

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
State: 驱动应用的数据源
Actions: 专门用来与后端backend API打交道
Mutations: Vuex中专门用于更新state
Modules:分模块管理vuex
Getters: 当于组件中的计算属性computed,与state相关,发生变化

1、可以用mapState、mapGetters在computed进行简写。
2、可以用mapMutations、mapActions在methods进行简写。
3、this.$store.dispatch触发actions上的方法进行调用后端数据。
4、this.$store.commit触发mutations上的方法修改state上的变量。

vue 生命周期

vue的生命周期:Vue 实例从创建到销毁的过程;开始创建-->初始化数据-->编译模块-->挂载dom渲染页面-->更新dom渲染页面—>卸载。
生命周期钩子函数:组件不同阶段会触发相应的钩子函数
初始化阶段、模板编译阶段、挂载阶段、卸载阶段
beforecreat
    ==>初始化事件、与data属性进行绑定
    该实例内的所有东西都还没有创建$el,data都是undefined。
creacted
    ==>判断是否有el,如果有就继续往下编译,如果没有直到在该实例上调用vm.$mount(el)[也就是动态引入了el]。
    render函数>template选项>outer Html-------渲染的一个优先级
beforeMount
    ==>此时是给vue实例对象添加$el成员,并且替换掉挂载的DOM元素。
mounted
beforeUpdate
    ==>当vue发现data中的数据发生变化,会触发对对应组件的重新渲染,
    当数据改变后调用beforeupdata,当渲染完成后调用updated钩子函数。
updated
beforeDestroy
    ==>官方解释:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
    移除事件监听器(EventBus.$off, window.addEventListener("scroll", 方法名))、关闭定时器、销毁所有的子实例
destroyed
activated
    ==>keep-alive(组件激活时触发)
deactivated
    ==>keep-alive(组件销毁时触发)
ErrorCaptured

beforeCreate    组件实例被创建之初,组件的属性生效之前
created 组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用
mounted el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子
beforeUpdate    组件数据更新之前调用,发生在虚拟 DOM 打补丁之前
update  组件数据更新之后
activited   keep-alive 专属,组件被激活时调用
deactivated keep-alive 专属,组件被销毁时调用
beforeDestory   组件销毁前调用
destoryed   组件销毁后调用

v-if 与 v-for 的优先级

当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级;所以不一般不能用于同一个标签上
每一次判断都需要遍历整个数组,将会十分影响性能
所以在实际开发中,我们会先判断再循环

v-if 和 v-show 的区别

①v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏
②v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
如果是频繁的切换用v-show,否则用v-if

vue 中 key 的作用

1、key的作用主要是为了高效的更新虚拟DOM
2、不能使用index作为v-for中的key;你删除一个数组长度为3的第二项,vue会认为你删除的是第三项,因为index也是连续的
3、当页面的数据发生变化时,Diff算法只会比较同一层级的节点
4、有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误

虚拟 dom

virtual DOM:是将真实的DOM的数据抽取出来,以对象的形式模拟树形结构
template模板(编译)==>渲染函数(执行)==>虚拟dom==>patch(patching算法)==>真实dom(视图)
虚拟DOM的最终目标是将虚拟节点渲染到视图上

diff 算法

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁
虚拟DOM最核心的部分,它可以将vnode渲染成真实的DOM
1、用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
2、当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
3、把所记录的差异应用到所构建的真正的DOM树上,视图就更新了

conputed 和 watch 的区别

conputed
1. 支持缓存,只有依赖数据发生改变,才会重新进行计算
2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3.computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
5.如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
watch
1. 不支持缓存,数据改变,直接会触发相应的操作;
2.watch支持异步;
3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
4. 当一个属性发生变化时,需要执行对应的操作;一对多;
5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
immediate:组件加载立即触发回调函数执行,
deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动

vue 的自定义指令

{{}}插值语法
v-html插入html片段,可以防止xss攻击,类似innerHTML
v-once只渲染一次
v-text插入文本,不解析html,类似innerText
v-model 在表单元素上实现:双向数据绑定
    ==>v-bind绑定一个value属性;v-on指令给当前元素绑定input事件。
v-on
v-bind
v-show
v-if
v-else-if
v-else
v-for

$nextTick

==>在js中属于微任务
==>$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM,
==>Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,
而此时进行DOM操作无异于徒劳

v-on 可以监听多个方法


keep-alive

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
实现keep-alive的方式
1、  
2、include等于组件名:
  
  


路由跳转传参 params 和 query 的区别

1、接收参数的方式不同
    ==>this.$route.params/this.$route.query
2、query的方法传参url路径会显示传递的参数
3、params刷新页面会丢失参数
4、params是用name属性,query是用path属性来编写传参地址

route

$router:$router对象是全局路由的实例,是router构造方法的实例
$route:$route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等
this.$router.push()
this.$router.replace()
this.$router.go(n)
this.$router.back()

Vue-router 跳转和 location.href 有什么区别

①vue-router使用pushState进行路由更新,静态跳转,页面不会重新加载;location.href会触发浏览器,页面重新加载一次
②vue-router使用diff算法,实现按需加载,减少dom操作
③vue-router是路由跳转或同一个页面跳转;location.href是不同页面间跳转;
④vue-router是异步加载this.$nextTick(()=>{获取url});location.href是同步加载

Vue-router 导航守卫有哪些

beforeRouteEnter(to, from,) {
    console.log("to", to)
    console.log("from", from)
    console.log("next", next)
    next(vm => {
    // 通过 `vm` 访问组件实例
    })
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
},
//全局的前置路由
router.beforeEach

vue-router 中常用的 hash 和 history 路由模式实现原理

//hash 路由
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 '#search':
以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)
// history 路由
history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录
pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染)
history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

vuex 和 localStorage 的区别

1、vuex的数据刷新页面会丢失,而localStorage的数据是永久存储的,除非手动清除。
2、vuex存储在内存,localstorage(本地存储)则以文件的方式存储在本地,永久保存;
sessionstorage( 会话存储 ) ,临时保存。localStorage和sessionStorage只能存储字符串类型,
对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理
3、应用场景:vuex用于组件之间的传值,localstorage,sessionstorage则主要用于不同页面之间的传值。
4、vuex的数据是响应式的
5、localstorage无法存储function.

vue 中的动态路由

像后台管理系统的左边菜单的导航栏,要做角色权限的一个控制;路由由后端返回
简单的角色权限:管理员权限和普通用户
复杂的路由权限:OA系统,门店用户,个人用户,区域用户

vue 的插槽 v-slot

父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。
在vue2.6版本以上使用v-slot代替了slot 和 scope-slot ,vue3.0中也弃用了。
v-slot 只能添加到template 或自定义组件上
可以在子组件上写插槽的默认内容:11111111111
1、默认的插槽
    ==>任何没有被包裹在带有 v-slot 的 组件标签 中的内容都会被视为默认插槽的内容。
            没有名字的 隐含有一个 “default” 名称
2、具名插槽
    ==>
    ==>
3、作用域插槽
    ==>0000000000
    ==>
4、动态插槽名
    ==>
1、父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
2、标签里面的内容会作为后备内容且有默认的名字default
3、(特殊:独占默认插槽的缩写语法)---只要出现多个插槽,请始终为所有的插槽使用完整的基于