1、v-for和v-if哪个优先级更高
    v-for和v-if同时出现时,打印app.$options.render函数,可以看到_l函数(vue的循环函数)先执行,循环过程中再判断v-if,所以v-for优先级高于v-if
    这样很浪费性能,每次都会先循环再判断是否渲染。解决方案,用一个template包裹写上v-if,里面再使用v-for,先判断是否渲染,这样就可以避免无谓的遍历了。

    2、vue组件中data要函数形式
    为啥组件的data要是函数,根组件可以是对象。
    因为组件可能要创建多次,初始化的时候,都会引用data的指针,修改一个实例,其他组件都会改变。是函数的话,每次都会返回一个新的对象引用,这样就规避了污染。
    根实例只创建一次,不会出现这个问题,而且创建根实例的时候不会检查data类型。

    3、vue中key的作用
    有三胞胎,原来是从小到大排着,后台老大跑到最后面去了,怎么区分呢,给他们带个牌子就能很快认出来了。
    key可以帮助精确判断两个新旧VNode,提高patch过程的效率。

    4、diff算法
    diff不止在vue中使用,在react里面也会用到。vue使用了虚拟dom,数据发生改变后,会产生新的虚拟dom。vue会对比新旧vnode,这个patch过程就需要用到diff算法来精确找到发生变化的地方。
    diff采用了 深度优先、同层比较的策略。两个节点比较,会先根据是否有子节点还是文本节点做不同操作。子节点判断是重点,diff会假设头尾节点相同做四次对比,如果没找到相同节点才会按照普通遍历方式进行对比,查找结束后再处理剩下的节点;借助key可以精确找出相同节点,提高patch效率。

    5、组件化
    vue中,定义组件的方法。全局与局部。
    Vue.component是一个继承于Vue的类。vue组件实例化的时候,局部注册的components和全局注册的components的选项会合并,所以vue组件可以直接用全局components,局部组件只能在注册的地方使用。
    优点:
    (1)独立功能(高内聚、低耦合),可以复用,少写重复代码。
    (2)组件更容易定位,找bug进行维护。
    (3)将页面切割为不同功能的组件,更利于分工合作。
    (4)将经常发生变化的部分切割为一个组件,减少新旧vnode的对比量,降低pacth过程耗时(项目管理预算组件)。
    (5)vue中组件常用技术:prop传参、自定义事件、插槽。父子组件之间是数据单向流。

    6、vue的(设计)理解
    1、渐进式(灵活性)
    应用小的话,只用核心特性就行。大型项目还可以引进vue-router、vue-cli、vuex等库和工具
    2、易用性,简单易上手
    数据式响应、声明式模板(只需要写一些对象属性)
    3、高效性
    vue中的虚拟dom和diff算法使应用具有高效能,在vue3中,引入Proxy使性能进一步提升

    7、mvc、mvp、mvvn
    三者都是框架模式,都是为了降低view层和model层的耦合。
    (1)mvc最早应用在后端,后来前端也借鉴这个模式,比如backbone.js。有点是分层清晰,但是数据流混乱
    (2)mvp是mvc的进化形式,presenter层负责mv之间的通信,用来降低两者耦合度。但是p层可能会很臃肿
    (3)mvvm解决了mv之间的耦合问题,还提开发者做了很多两者之间映射的繁杂代码和dom更新操作,在提高开发效率和可读性的同时,保持了优越的性能表现。

    8、vue组件间通信
    一、父子
    (1)父组件给子组件传数据:props传参、子组件给父组件传值:自定义事件处理函数$emit
    (2)$parent和$children获取父子组件的方法和data
    (3)provide、inject。父组件provide数据后,不管子组件嵌套多深,都可以通过inject获取数据。
    (4)refs,通过refs获取节点属性和方法。
    二、兄弟

    三、跨层
    (1)多组件用到的数据,用vuex,如登录状态、角色选择等。
    (2)事件总线、eventbus:创建一个vue实例,在一个vue组件中引入,调用bus.$emit()触发事件;在另一个vue组件mounted钩子函数调用bus.$on监听并处理事件,通过js函数传参。

    8、vue开发中性能优化
    (1)创建路由时使用懒加载
    引入组件的时候,使用箭头函数返回import方法执行。
    (2)使用keep-alive实现页面缓存
    (3)避免同时使用v-for和v-if,这样会有不必要的遍历执行。
    (4)纯展示列表,把数据直接冻结(Object.freeze),这样就不会进行响应式处理了。
    (5)利用插件,只渲染滚动区域的节点(vue-virtual-scroller)
    (6)定时器销毁,在beforeDestroy钩子中销毁定时器。
    (7)图片懒加载(vue-lazyload库)
    (8)ui框架组件按需引入
    (9)无状态组件使用函数式组件(template标签 加一个functional,这个组件依然可以用props接受数据)
    (10)组件分割,让组件自己负责自己部分的更新,减少patch范围。
    (11)变量本地化,将要重复访问的实例属性保存为一个变量,let base = this.base.这样就会减少访问this上的属性,而是访问一个固定的值。

    9、vue3新特性
    (1)更快:重写了虚拟dom,静态属性提升、基于proxy的响应系统。
    响应式实现方式。es6带来的新语法,proxy,可以直接代理对象对访问和操作进行拦截从而实现响应式,不用像vue2那样循环遍历调用Object.defineProperty一个一个添加属性来实现的。
    (2)更小:通过摇树优化核心库体积
    (3)composition Api
    set up是入口,返回的对象的属性和方法会合并到render函数执行上下文,所以template可以直接使用setup里面的数据。如果要将数据设置为响应式,可以引入vue中的reactive、ref和toRefs函数处理,再将返回值返回。
    setup中不要结构props,解构出来的数据会失去响应式。
    自定义hooks,将vue2中分开的数据方法聚合在一起了,引用的时候更灵活(引用某些数据与方法),还可以再这基础上进行拓展。更贴近模块化编程。

    10、watch和computed比较
    watch监听数据变化,然后触发事件。
    computed用于返回基于某些数据计算得到的结果,比如资金、合计数据、前端分页等。
    watch适用于监听数据,然后进行前后端交互。
    computed有缓存策略,依赖数据发生变化后,才会重新计算。

    11、vue生命周期
    创建前后、挂载前后、更新前后、销毁前后,是自动执行的函数。
    beforeCreate界面还未初始化,也可以进行一些操作,比如vuex在此钩子给每个vue实例混入store
    created 已经可以用到this的属性和方法了
    beforeMount此时模板已经渲染后,还没有挂载。
    mounted,此时模板挂载完成,dom已经生成。echarts可以在此时使用,echarts的初始化必须要用到原生dom。:
    beforeUpdate和updated
    beforeDestroy 此时可以消除定时器,避免内存泄漏
    destroyed 销毁实例上的方法和属性。
    activated 被keep-alive缓存的组件激活时调用 keep-alive可以用于tab切换,缓存组件。
    deactivated 被keep-alive缓存的组件停用时调用。

    12、js中同步任务和异步任务
    同步任务进入主线程执行,异步任务进eventtable 进行回调注册。主线程任务执行完以后,将异步任务放进主线程执行。
    异步任务也有区分:
    (1)宏任务:setTimeout、setInterval、script代码块、ajax请求
    (2)微任务:promise的回调、async/await(promise的excutor是同步任务)
    微任务执行优先级高于宏任务,setTimeout就算等待时间到了,主线程里还有任务执行,就需要等待。就算没有,也不是立马执行,至少是4微秒。

    13、vuex基本实现
    vuex是一个vue插件,vue插件需要提供一个install方法,此方法会得到vue构造函数。此外vuex提供了store类用于生成store实例。
    vuex需要导出包含install和store方法的对象。
    install方法中使用Vue.beforeCreate钩子,使用Vue.mixin为全局混入store:先判断实例有无自己的$options.store,优先使用实例的store,没有的话则给this赋值$store属性。这就是为什么vue每个实例都可以直接用到this.$store的原因。
    store是个class,constructor里面利用了vue实例自身的响应式原理,生成vue实例,将各个状态放进data来保管。

    14、vue-router基本原理
    现在很多vue引用是单页应用,一般不会请求多个页面。vue-router会根据url匹配对应的vue组件进行渲染。
    vue-router提供一个install方法,会把router实例挂载到vue.prototype上,说要vue实例可以访问到$router,还会利用vue.component注册一个全局组件router-view。并且会将传入的routes配置进行映射保存,一遍查找使用。router会给window添加hashchange事件,处理函数会匹出配路由对应的组件,之后调用router-view组件的render函数,渲染匹配到的组件。

    15、nextTick
    用于数据变化,dom更新后,获取dom。
    dom更新,是异步操作。如果数据改变一次就更新一次视图,这样很消耗性能,只需等到所有数据更新完后,在一并更新dom,这样减少无谓的渲染,提升渲染效率。
    nextTick是通过microtask实现的。

    16、递归组件
    递归组件,组件内部可以使用name属性作为标签名,自己调用自己。一般侧边栏菜单会用到,判断该菜单是否有子菜单,有的话就自己调用自己。