Vue面试总结+复盘

95 阅读3分钟

Vue2和Vue3的区别

主要有:

  1. 组合式API和选择式API
  2. TypeScript的支持
  3. this指针的优化
  4. 生命周期函数将BeforeCreate和created更改为setup
  5. diff算法的优化->从组件更新到节点更新
  6. 响应式原理从Object.defineProperty到Proxy+Reflect
  7. 响应式API的添加,增加了ref/reactive等响应式API
  8. Vue3支持TreeShaking

Vue3的diff和Vue2的diff

Vue2的diff就是简单的组件属性对比然后以树的形式对children进行遍历对比。

Vue3的diff的区别主要是,Vue2是全部组件内部参数遍历,Vue3的话对于组件中的响应式数据打上标记,组件检查更新时,只需要检查标记变量是否diff,对于组件中的静态变量不需要运算,将整个diff过程从组件更新节点更新

Vue3的watch和watchEffect

watch: 会有oldVal和newVal,需要显式得展示需要监视的响应式数据。

watchEffect: 在回调函数中使用响应式数据会自动监视其变化。

<script>
export default{
    data(){
        return {
            count:0,
        }
    }
    watch:{
        count(newVal,oldVal){
            console.log("发生变化")
        }
    }
}
</script>

<script>
import {ref} from 'vue'
export default{
    setup(){
        const count  = ref(0)
        watcheffect(()=>{
            //在回调函数中使用count会自动监视其变化
        })
        return {count}
    }
}
</script>

组件通信

全局:

  1. 事件总线eventBus
  2. 外部存储空间Vuex/LocalStorage等等

父子:

  1. v-bind + props
  2. attrs
  3. 依赖注入 provide和inject--->被CompositionAPI的ref和reactive替代
  4. parent和children
  5. ref和this.$refs

子父:

  1. 插槽
  2. emit

V-model

本质上是v-bind和v-on语法糖

v-bind是单向绑定 v-on是事件监听

<input v-model="message">
<input v-bind:value= "message" @input = "updateMessage">

<script>
export default{
    data(){
        return {
            message:""
        }
    }
    updateMessage(e){
        this.message = e.taget.value
    }
}
</script>

当然可以使用js实现响应式

<body>
    <div>
        <input id="input" placeholder="">
        <p id="message">Message:</p>
    </div>
    <script>
        let ipt = document.getElementById("input");
        let msg = documnet.getElementById("message")
        let date = {
            message:""
        }
        
        ipt.addEventListener("input",function(e){
            data.message = e.target.value
            msg.innerText = "Message:"+data.message
        })
    </script>
</body>

生命周期

  1. beforeCreate

变量创建为赋值

  1. created

数据赋值完毕

——————————以上在Vue3中为setup——————————

  1. beforeMount

虚拟DOM构建

  1. Mounted

真实DOM挂载

  1. beforeUpdate

数据更新完毕

  1. Updated

更新数据成功挂载

  1. beforeDestory和Destoryed

DOM摧毁,一般不调用

特殊:beforeRouteEnter和beforeRouteLeave来处理路由缓存(刚发现activated和deactivated竟然Vue1.0就被停用了吗古早八股害人不浅)

路由跳转组件生命周期调用

父子组件:

父组件beforeCreate->->一直到父组件beforeMount

子组件beforeCreate->->一直到子组件Mounted

父组件Mounted

子组件beforeDestory->destoryed

父组件beforeDestory->destoryed

新旧组件:

新组件beforeCreate->->一直到新组件beforeMount

旧组件beforeDestory->destoryed

新组建Mounted

Vue是什么

MVVM模型中的VM

一款前端界面的开发框架,能够实现组件化开发,具有Vuex(Pinia)作为数据仓库,VueRouter作为路由导航工具,然后具有一系列的指令语法指令比如V-bind等等。

Vue中的设计模式

  1. 单例模式

全局事件总线

  1. 代理模式

Vue的响应式原理

  1. 发布订阅和观察者

到处都是,比如事件总线

  1. 装饰器模式

自定义指令

  1. 工厂模式

组件封装、复用,比如hooks内的函数,全局组件

  1. 迭代器模式

async和await语法糖

watch、method和computed

watch:

  1. oldVal和newVal
  2. 响应式监听
  3. 异步操作

computed:

  1. 具有缓存
  2. 自动响应式触发
  3. 响应式数据不变会直接调用缓存的值

method:

  1. 无缓存
  2. 无响应式,单纯的方法

Vue的key的作用

  1. 作为唯一的标识符
  2. 帮助Vue在diff算法中追踪节点

ref、reactive和computed

ref:

  1. 常用于对于基础数据结构实现响应式
  2. .value调用值

reactive:

  1. 常用于对于引用数据结构实现响应式
  2. 不需要.value,内部一定是响应式数据

computed:

  1. 计算属性
  2. 响应式数据变动触发
  3. .value调用

服务端渲染SSR

服务器端生成HTML网页,然后客户端只需要将相关文件渲染成真实DOM就行

优点:

  1. SEO友好
  2. 加载快,因为不需要等待js代码执行,数据是填充好的

Vue的路由跳转模式

hash模式:

  1. 网站地址+#+hash值
  2. window.location.hash记录hash值进行跳转
  3. seo相对来说不友好
  4. 可以自由使用浏览器的前进后退按钮

history模式:

  1. 创建路由时声明history模式
  2. 无#,seo友好
  3. 无法自由使用浏览器的前进后退,因为地址默认是有#的,history类似于重定向到一个地址,所以需要服务端去进行一个重定向配置
  4. 通过window.history的pushState()和popState()方法等实现

动态组件

<component>实现自定义动态渲染

<template>
  <div>
    <button @click="showComponent('ComponentA')">显示组件 A</button>
    <button @click="showComponent('ComponentB')">显示组件 B</button>
    <!--动态组件-->
    <component :is="currentComponent"></component>
  </div>
</template>

<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
  data() {
    return {
      currentComponent: null,
    };
  },
  methods: {
    showComponent(componentName) {
      if (componentName === 'ComponentA') {
        this.currentComponent = ComponentA;
      } else if (componentName === 'ComponentB') {
        this.currentComponent = ComponentB;
      }
    },
  },
};
</script>

另外还可以通过路由配置实现动态路由跳转

const routes = [{
    path: '/user/:id', // 动态路由占位符 ":id" 
    component: UserProfile, 
}];

Vite和Webpack的区别

  1. Vite使用的ejs的方法;Webpack使用的cjs的方法
  2. Vite依托于ejs能够实现按需加载;Webpack需要额外的配置
  3. Vite支持快速的HMR;Webpack的HMR相对较慢
  4. Vite配置文件十分轻量;Webpack生态链成熟,但是意味着配置复杂

Vuex中的mutation和action的区别

mutation:

  • 处理同步代码
  • commit触发

action:

  • 处理异步代码
  • dispatch触发

为什么使用commit和action主要是因为Vuex是一个单向数据流,把复杂的异步代码单独隔离开来可以更好地管理数据的状态,实现业务逻辑分离,提高代码的可维护性和一致性。

常见Header

  • Content-type:application/javascript text/css application/json image/jepg image/png等等
  • Etag
  • Last-Modified
  • Cache-control

场景题

Vue的数据更新但是页面没有响应式更新怎么办?

  1. nextTick去实现DOM更新后再更新数据。因为DOM更新是异步的,数据如果DOM更新异步的时候更改,就会先被Vue收集,然后在DOM更新之后统一使用nextTick进行更新。
  2. 另外一种可能性就是data定义了一个值假设是obj,obj具有两个属性,后续又通过赋值的方式给obj定义一个新属性,这个新属性的响应值是不会同步更新到页面上,需要使用this.$set添加属性进行更新,才会实现真正的更新。

this.$set

  • object 绑定对象
  • key 属性名
  • value 绑定初始值

Vue错误捕获

没有什么是一个trycatch无法解决(误)

通用方法trycatch

如果是promise的话使用catch异常穿透,try catch无法捕获promise的错误,会使得整个程序崩溃

其他错误捕获方式比如window.onerror这种全局错误信息捕获,vue的话也有专门的钩子函数去进行异常捕获。

Vue的渲染流程

  1. 初始化,构建Vue的实例,初始化数据、监听器、事件函数等等。
  2. 将模板代码编译成JavaScript渲染函数,负责将模板代码以及相关数据等映射成虚拟DOM。
  3. 构建虚拟DOM
  4. 将虚拟DOM渲染成真实DOM。
  5. 响应式监听,通过响应原理监听相关数据。
  6. 组件批量更新,因为DOM更新是异步的,所以会出现数据更新但是DOM没有更新的情况。
  7. 销毁阶段。

Vue编译会阻塞吗?

不会阻塞主线程,Vue即使是组件引入也是在微任务等方式进行引入。

super的作用

调用父类的构造函数

如果一定要create内部操作DOM?

可以使用nextTick不然还是在mounted内操作DOM比较好

Vue的template编译流程

  1. 把模板编译程render函数
  2. 根据节点调用生成虚拟DOM
  3. 通过DIFF算法把虚拟DOM映射到真实DOM上
  4. 响应式监听数据
  5. 组件批量式更新,重复DIFF的步骤