某知名it培训班前端三阶段vue相关面试题

1. Vue 的核心是什么?

Vue 的核心主要包含两点:

  • **数据驱动(Data-Driven)**:视图由数据状态决定,数据变更自动更新 DOM,无需手动操作 DOM;
  • **组件化(Component-Based)**:将页面拆分为独立、可复用的组件,降低耦合度,提升开发效率;
  • 补充:核心还包括响应式系统、虚拟 DOM 等底层支撑能力。
2. 请简述你对 Vue 的理解

Vue 是一套​渐进式 JavaScript 框架​,核心定位是"渐进式"------可以按需使用核心功能(如响应式、组件),也可结合路由(Vue Router)、状态管理(Vuex/Pinia)等生态扩展复杂应用;

  • 设计理念:轻量、易用、高效,兼顾开发体验和运行性能;
  • 核心特性:响应式数据绑定、组件化、指令系统、虚拟 DOM、生命周期等;
  • 应用场景:从简单的表单页面到复杂的单页应用(SPA)均可覆盖,是前端主流框架之一。
3. 请简述 Vue 的单向数据流

Vue 的单向数据流核心规则:​数据只能从父组件流向子组件,子组件不能直接修改父组件传递的 props​;

  • 具体表现:
    • 父组件通过 props 向子组件传值,子组件只读 props,不能直接修改;
    • 若子组件需修改数据,需通过触发父组件的自定义事件,由父组件修改源数据,再反向更新子组件 props;
  • 目的:保证数据流向可追溯,避免多个组件随意修改数据导致状态混乱,符合"单向绑定"的设计思想。
4. Vue 常用的修饰符有哪些

Vue 的修饰符按用途可分为三类,核心常用如下:

类型 常用修饰符 作用举例
事件修饰符 .stop、.prevent、.once .stop 阻止事件冒泡,.prevent 阻止默认行为,.once 只触发一次
按键修饰符 .enter、.esc、.tab 监听特定按键触发事件(如 @keyup.enter)
表单修饰符 .trim、.number、.lazy .trim 去除输入首尾空格,.number 转为数字,.lazy 失去焦点后更新数据
鼠标修饰符 .left、.right、.middle 监听鼠标特定按键(左键/右键/中键)
5. v-text 与 {{}}的区别

两者均用于渲染文本,核心区别:

  • **{{}}(插值表达式)**:
    • 可嵌入 HTML 标签内(如 <div>姓名:{``{name}}</div>);
    • 存在"闪烁问题"(页面加载时可能先显示 {``{name}} 再渲染值,可通过 v-cloak 解决);
    • 支持简单表达式(如 {``{age + 1}});
  • v-text
    • 是指令,需直接绑定在标签上(如 <div v-text="name"></div>);
    • 无闪烁问题,覆盖标签内所有内容(包括子节点);
    • 不支持复杂表达式,仅接收变量/简单值;
  • 补充:两者均会转义 HTML(若需渲染 HTML 用 v-html)。
6. v-on 可以绑定多个方法吗?

可以,有两种实现方式:

  • 方式 1:绑定一个方法数组(Vue 2.4+ 支持)

    Plain 复制代码
    <button @click="[handleClick1, handleClick2]()">点击触发多个方法</button>
  • 方式 2:绑定一个统一方法,内部调用多个子方法

    Plain 复制代码
    <button @click="handleAll">点击触发多个方法</button>
    <script>
    export default {
      methods: {
        handleAll() {
          this.handleClick1();
          this.handleClick2();
        },
        handleClick1() { /* 逻辑1 */ },
        handleClick2() { /* 逻辑2 */ }
      }
    }
    </script>
  • 注意:数组方式中方法需加 () 执行,否则仅定义不触发。

7. Vue 循环的 key 作用

key 是 Vue 列表渲染的核心属性,作用:

  • 唯一标识节点:Vue 根据 key 判断节点是否为同一节点,避免复用错误(如输入框值错乱);
  • 提升更新效率:当列表数据变化时,Vue 通过 key 精准定位需要更新的节点,而非重新渲染整个列表;
  • 注意:
    • key 需用唯一值(如 id),避免用 index(index 会随数据顺序变化,失去标识意义);
    • 无 key 时 Vue 会采用"就地更新"策略,可能导致 DOM 复用异常。
8. 什么是计算属性?

计算属性(computed)是 Vue 用于处理派生数据的特性,基于依赖数据动态计算值:

  • 核心特性:

    • 缓存性:依赖数据不变时,多次访问计算属性只会执行一次计算,提升性能;
    • 响应式:依赖数据变化时,计算属性自动重新计算并更新视图;
    • 支持 get/set(默认 get,set 可手动修改依赖数据);
  • 示例:

    Plain 复制代码
    <script>
    export default {
      data() {
        return { a: 1, b: 2 };
      },
      computed: {
        sum() { // 只读计算属性
          return this.a + this.b;
        },
        fullName: { // 可读写计算属性
          get() { return this.firstName + ' ' + this.lastName; },
          set(val) { const [first, last] = val.split(' '); this.firstName = first; this.lastName = last; }
        }
      }
    }
    </script>
9. Vue 单页面(SPA)的优缺点
优点 缺点
1. 无页面刷新,体验接近原生 App 1. 首屏加载慢(需加载整包 JS/CSS)
2. 组件化复用性高 2. SEO 不友好(页面内容动态渲染)
3. 前后端分离,开发效率高 3. 路由切换需手动处理缓存/滚动
4. 数据管理更集中 4. 打包体积大,需按需加载优化
10. Vuex 是什么?怎么使用?在哪些场景下使用?
  • 定义 :Vuex 是 Vue 官方的集中式状态管理库,用于管理多组件共享的状态(如用户信息、全局配置);
  • 使用步骤
    • 安装:npm install vuex --save

    • 创建 store:

      JavaScript 复制代码
      import Vue from 'vue';
      import Vuex from 'vuex';
      Vue.use(Vuex);
      export default new Vuex.Store({
        state: { count: 0 }, // 状态
        mutations: { increment(state) { state.count++ } }, // 同步修改状态
        actions: { asyncIncrement({ commit }) { setTimeout(() => commit('increment'), 1000) } }, // 异步操作
        getters: { doubleCount(state) { return state.count * 2 } }, // 派生状态
        modules: { /* 模块拆分 */ }
      });
    • 挂载到 Vue 实例:new Vue({ store, ... })

    • 组件中使用:

      1. 读取 state:this.$store.state.countmapState 辅助函数;
      2. 修改 state:this.$store.commit('increment')(同步)/ this.$store.dispatch('asyncIncrement')(异步);
  • 使用场景
    • 多组件共享同一状态(如购物车、用户登录状态);
    • 组件层级深,props/emit 传值繁琐;
    • 需要追踪状态变更(Vuex 可记录状态修改日志)。
11. Vuex 与 Pinia 的区别

Pinia 是 Vue 3 推荐的状态管理库,替代 Vuex 4,核心区别:

维度 Vuex Pinia
核心结构 分 state/mutations/actions/getters/modules 仅 state/actions/getters(无 mutations/modules)
模块化 需通过 modules 嵌套,命名空间复杂 每个 store 独立,天然模块化,无需命名空间
TypeScript 支持差,需手动类型声明 原生支持 TS,类型推断更友好
代码简洁度 冗余(如 mutations 必须同步) 简洁(actions 可同步/异步,无需 commit)
Vue 版本支持 Vue 2/3(Vuex 3 对应 Vue 2,Vuex 4 对应 Vue 3) 主要支持 Vue 3(也可兼容 Vue 2)
调试 依赖 Vue Devtools,需配置 原生集成 Vue Devtools,调试更友好
12. Vue 路由的跳转方式

Vue Router 的跳转分两类:声明式(模板)和编程式(JS):

  • **声明式()**:

    Plain 复制代码
    <!-- 基础跳转 -->
    <router-link to="/home">首页</router-link>
    <!-- 带参数 -->
    <router-link :to="{ path: '/user', query: { id: 1 } }">用户页</router-link>
    <router-link :to="{ name: 'User', params: { id: 1 } }">用户页</router-link>
  • **编程式($router.push/replace/go)**:

    JavaScript 复制代码
    // 基础跳转
    this.$router.push('/home');
    // 带query参数(路径拼接,如/user?id=1)
    this.$router.push({ path: '/user', query: { id: 1 } });
    // 带params参数(需路由配置name,如/user/1)
    this.$router.push({ name: 'User', params: { id: 1 } });
    // 替换当前历史记录(不新增历史)
    this.$router.replace('/home');
    // 前进/后退
    this.$router.go(-1); // 后退一页
13. 跨域的解决方式

跨域是浏览器同源策略限制(协议、域名、端口任一不同即跨域),前端常用解决方案:

  1. **Vue CLI 代理(开发环境)**:

    JavaScript 复制代码
    // vue.config.js
    module.exports = {
      devServer: {
        proxy: {
          '/api': {
            target: 'http://localhost:3000', // 后端接口地址
            changeOrigin: true, // 开启跨域
            pathRewrite: { '^/api': '' } // 重写路径
          }
        }
      }
    }
  2. **后端 CORS(跨域资源共享)**:后端设置响应头 Access-Control-Allow-Origin: *(或指定域名);

  3. JSONP :仅支持 GET 请求,通过动态创建 <script> 标签请求;

  4. Nginx 反向代理:生产环境通过 Nginx 转发请求,统一域名;

  5. WebSocket:基于 TCP 协议,无跨域限制。

14. Vue 生命周期请简述

Vue 生命周期是组件从创建到销毁的全过程,分 8 个核心阶段(Vue 2):

  1. 创建阶段:beforeCreate(实例初始化,数据/方法未挂载)→ created(数据/方法挂载完成,DOM 未生成);
  2. 挂载阶段:beforeMount(编译模板,即将挂载 DOM)→ mounted(DOM 挂载完成,可操作 DOM);
  3. 更新阶段:beforeUpdate(数据更新,DOM 未重新渲染)→ updated(DOM 重新渲染完成);
  4. 销毁阶段:beforeDestroy(实例即将销毁,数据/方法仍可用)→ destroyed(实例销毁,所有监听/绑定解除);
  • Vue 3 补充:组合式 API 中用 onMounted/onUpdated 等钩子替代选项式,新增 setup(替代 beforeCreate/created)。
15. Vue 生命周期的作用

生命周期钩子允许开发者在组件不同阶段插入自定义逻辑,核心作用:

  1. 初始化逻辑:created 中请求数据、初始化变量;
  2. DOM 操作:mounted 中操作 DOM(如初始化第三方插件);
  3. 数据更新处理:updated 中处理 DOM 更新后的逻辑;
  4. 资源清理:beforeDestroy 中清除定时器、取消事件监听,避免内存泄漏;
  5. 性能优化:按需执行逻辑,避免无效代码(如仅在挂载后请求数据)。
16. DOM 渲染在哪个生命周期阶段内完成
  • 核心结论:mounted 阶段完成 DOM 渲染;
  • 细节:
    • beforeMount:模板已编译,但未挂载到 DOM($el 为虚拟 DOM);
    • mounted:真实 DOM 挂载完成,$el 指向真实 DOM 节点,可安全操作 DOM;
    • 若组件包含子组件,mounted 仅表示当前组件 DOM 挂载完成,子组件可能仍在挂载中。
17. Vue 路由的实现

Vue Router 的核心实现依赖​前端路由原理​,分两步:

  1. 路由匹配
    1. 定义路由规则(routes 数组),每个规则包含 path、component 等;
    2. Vue Router 监听 URL 变化,匹配对应路由规则;
  2. 视图渲染
    1. 通过 <router-view> 组件作为路由出口,匹配到的组件渲染到该位置;
    2. 底层依赖 Vue 的组件系统,通过动态组件切换实现视图更新;
  • 补充:路由模式(hash/history)决定 URL 的表现形式,底层分别基于 hashchange 事件和 History API。
18. 简述 Vue 路由模式 hash 和 history
维度 hash 模式(默认) history 模式
URL 表现 带#(如 http://xxx/#/home) 无#(如 http://xxx/home)
底层原理 基于 hashchange 事件,#后的内容不会发送到服务器 基于 HTML5 History API(pushState/replaceState)
服务器配置 无需配置,刷新页面不会 404 需配置后端,刷新页面需重定向到 index.html(否则 404)
兼容性 兼容所有浏览器(包括 IE) 仅支持 HTML5 浏览器
SEO 部分搜索引擎不识别#后内容 更友好,SEO 效果更好
19. Vue 路由传参方式,params 与 query 方式和区别
  • 传参方式:分 query 和 params 两种核心方式,均支持声明式/编程式;
  • 核心区别
维度 query 参数 params 参数
URL 表现 拼接在路径后(?key=value) 嵌入路径中(/user/1)
路由配置 无需特殊配置 需在路由 path 中定义(如/user/:id)
刷新页面 参数不会丢失 若路由未定义参数,刷新后丢失
取值方式 this.$route.query.key this.$route.params.key
可选性 可传可不传 路由定义的参数必须传(否则跳转失败)
  • 示例:

    JavaScript 复制代码
    // query传参
    this.$router.push({ path: '/user', query: { id: 1 } }); // URL: /user?id=1
    // params传参(需路由name)
    this.$router.push({ name: 'User', params: { id: 1 } }); // URL: /user/1
20. Vue 数据绑定的几种方式

Vue 数据绑定分三类,核心是响应式绑定:

  1. 单向绑定
    1. 插值表达式 {``{}}:渲染文本;
    2. v-bind(简写 :):绑定属性(如 :src="imgUrl":class="className");
  2. 双向绑定
    1. v-model:主要用于表单元素(如 <input v-model="value">),本质是 v-bind+v-on 的语法糖;
  3. 一次性绑定
    1. v-once:绑定后数据变化不再更新视图(如 <div v-once>{``{name}}</div>)。
21. Vue 注册一个全局组件

全局组件注册后,所有 Vue 实例/组件均可直接使用,步骤:

JavaScript 复制代码
// 1. 定义组件
const MyComponent = {
  template: `<div>{{msg}}</div>`,
  data() {
    return { msg: '全局组件' };
  }
};
// 2. 注册全局组件(Vue 2)
import Vue from 'vue';
Vue.component('MyComponent', MyComponent);

// Vue 3(createApp方式)
import { createApp } from 'vue';
const app = createApp({});
app.component('MyComponent', MyComponent);
app.mount('#app');
  • 注意:全局组件需在 Vue 实例创建前注册,否则无法使用。
22. Vue 的路由钩子/路由守卫有哪些

Vue Router 的路由守卫分三类,用于控制路由跳转权限:

  1. 全局守卫 (所有路由生效):

    1. router.beforeEach:路由跳转前触发(常用作登录验证);
    2. router.afterEach:路由跳转后触发(无权限控制);
    3. router.beforeResolve:所有组件内守卫和异步路由解析完成后触发;
  2. 路由独享守卫 (单个路由生效):

    JavaScript 复制代码
    const routes = [
      {
        path: '/user',
        component: User,
        beforeEnter: (to, from, next) => { // 仅/user路由生效
          if (/* 验证 */) next();
          else next('/login');
        }
      }
    ];
  3. 组件内守卫 (组件内生效):

    1. beforeRouteEnter:进入组件前触发(无法访问 this,需通过 next 回调);
    2. beforeRouteUpdate:组件复用(如动态路由)时触发;
    3. beforeRouteLeave:离开组件前触发(如提示未保存)。
23. Vue 中如何进行动态路由设置?有哪些方式?怎么获取传递过来的参数?
  • 动态路由定义 :在路由 path 中用 :参数名 定义,匹配任意值;

  • 定义方式

    JavaScript 复制代码
    // 1. 基础动态路由
    const routes = [
      { path: '/user/:id', name: 'User', component: User }
    ];
    // 2. 可选参数(加?)
    { path: '/user/:id?', component: User }
    // 3. 通配符(匹配所有)
    { path: '*', component: NotFound }
  • 获取参数

    • 组件内通过 this.$route.params 获取(如 this.$route.params.id);

    • 组合式 API 中用 useRoute

      JavaScript 复制代码
      import { useRoute } from 'vue-router';
      const route = useRoute();
      console.log(route.params.id);
24. Element UI 中常用组件有哪些?请简述并说下他们的属性有哪些

Element UI 是 Vue 2 主流 UI 库,核心常用组件及属性:

组件 用途 核心属性
Button 按钮 type(primary/success)、size(small/medium)、disabled、icon
Input 输入框 v-model、placeholder、disabled、clearable、type(text/password)
Table 表格 data(数据源)、columns(列配置)、pagination(分页)、border、height
Form 表单 model(表单数据)、rules(校验规则)、label-width、inline
Dialog 弹窗 visible(显示/隐藏)、title、width、modal(遮罩)、close-on-click-modal
Select 下拉选择 v-model、options(选项)、multiple(多选)、disabled
Pagination 分页 total(总条数)、page-size(每页条数)、current-page(当前页)、layout(布局)
25. Vue CLI 中如何自定义指令

自定义指令用于扩展 DOM 操作,分全局/局部指令:

  • 全局自定义指令 (main.js):

    JavaScript 复制代码
    // Vue 2
    import Vue from 'vue';
    // 注册v-focus指令(自动聚焦输入框)
    Vue.directive('focus', {
      inserted(el) { // 指令绑定到元素并插入DOM时触发
        el.focus();
      }
    });
    
    // Vue 3
    import { createApp } from 'vue';
    const app = createApp({});
    app.directive('focus', {
      mounted(el) { el.focus(); }
    });
  • 局部自定义指令 (组件内):

    Plain 复制代码
    <script>
    export default {
      directives: {
        focus: {
          inserted(el) { el.focus(); }
        }
      }
    }
    </script>
  • 指令钩子:bind(绑定)、inserted(插入 DOM)、update(更新)等(Vue 3 调整为 created/mounted/updated)。

26. Vue 中指令有哪些

Vue 指令分内置指令 和​自定义指令​,核心内置指令:

类别 指令 用途
数据绑定 v-text、v-html、v-bind 渲染文本/HTML、绑定属性
事件绑定 v-on 绑定事件(简写 @)
双向绑定 v-model 表单数据双向绑定
条件渲染 v-if、v-else、v-show 条件显示/隐藏 DOM
列表渲染 v-for 循环渲染列表
其他 v-once、v-cloak、v-pre 一次性绑定、解决闪烁、跳过编译
27. Vue 如何定义一个过滤器

过滤器用于格式化数据(Vue 3 已移除,推荐用计算属性/方法替代),Vue 2 定义方式:

  • 全局过滤器 (main.js):

    JavaScript 复制代码
    import Vue from 'vue';
    // 注册全局过滤器(格式化时间)
    Vue.filter('formatTime', (value) => {
      return new Date(value).toLocaleString();
    });
  • 局部过滤器 (组件内):

    Plain 复制代码
    <script>
    export default {
      filters: {
        formatTime(value) {
          return new Date(value).toLocaleString();
        }
      }
    }
    </script>
  • 使用:{``{ time | formatTime }}v-bind:title="time | formatTime"

28. 对 Vue 中 keep-alive 的理解

keep-alive 是 Vue 的内置组件,用于​缓存组件实例​,避免重复创建/销毁:

  • 核心特性:
    • 包裹动态组件时,缓存不活动的组件,而非销毁;
    • 触发组件的 activated(激活)/deactivated(失活)钩子;
  • 常用属性:
    • include:仅缓存指定组件(如 include="User,Home");
    • exclude:排除指定组件;
    • max:最大缓存数量(超出则销毁最久未使用的组件);
  • 应用场景:路由切换时缓存表单数据、列表滚动位置等(如 <keep-alive><router-view></router-view></keep-alive>)。
29. 如何让组件中的 CSS 在当前组件生效

通过样式隔离实现,核心方式:

  1. scoped 属性​(推荐):

    Plain 复制代码
    <style scoped>
    .box { color: red; } // 仅当前组件生效
    </style>
    1. 原理:Vue 为组件 DOM 添加唯一属性(如 data-v-xxx),CSS 自动添加属性选择器,实现隔离;
  2. CSS Modules​:

    Plain 复制代码
    <style module>
    .box { color: red; }
    </style>
    <template>
      <div :class="$style.box">内容</div>
    </template>
    1. 原理:类名被编译为唯一哈希值,避免冲突;
  3. 深度选择器​(如需修改子组件样式):

    Plain 复制代码
    <style scoped>
    ::v-deep .child-box { color: blue; } // Vue 2
    :deep(.child-box) { color: blue; } // Vue 3
    </style>
30. Vue 生命周期一共有几个阶段
  • Vue 2 :分 4 个大阶段,8 个核心钩子:
    • 创建阶段(2 个):beforeCreate、created;
    • 挂载阶段(2 个):beforeMount、mounted;
    • 更新阶段(2 个):beforeUpdate、updated;
    • 销毁阶段(2 个):beforeDestroy、destroyed;
    • 补充:还有 activated/deactivated(keep-alive 组件)、errorCaptured(错误捕获)等钩子;
  • Vue 3:组合式 API 中钩子更细分,核心阶段一致,钩子名调整为 onXxx(如 onMounted),新增 setup(替代 beforeCreate/created)。
31. MVVM 和 MVC 的区别

两者均为软件架构模式,核心区别:

维度 MVC(Model-View-Controller) MVVM(Model-View-ViewModel)
核心角色 Model(数据)、View(视图)、Controller(控制器,连接 M/V) Model(数据)、View(视图)、ViewModel(桥梁,双向绑定)
数据流向 单向(Model→Controller→View) 双向(View←→ViewModel←→Model)
耦合度 View 和 Model 需通过 Controller 通信,耦合较高 View 和 Model 完全解耦,由 ViewModel 中转
核心特性 手动更新视图(需 Controller 操作 DOM) 自动更新视图(数据驱动,ViewModel 实现响应式)
应用框架 jQuery、Backbone.js Vue、React(类 MVVM)、Angular
32. Vue 组件中的 data 为什么是函数

核心原因:​保证组件实例的独立性​,避免多个组件实例共享同一数据对象;

  • 原理:

    • 若 data 是对象,所有组件实例会引用同一个对象,修改一个实例的 data 会影响其他实例;
    • 若 data 是函数,每次创建组件实例时,函数返回一个新的对象,各实例数据独立;
  • 示例:

    Plain 复制代码
    <script>
    export default {
      // 正确:函数返回新对象
      data() {
        return { count: 0 };
      },
      // 错误:所有实例共享count
      // data: { count: 0 }
    }
    </script>
  • 补充:根实例(new Vue({}))的 data 可以是对象(仅一个实例,无共享问题)。

33. Vue 双向绑定原理

Vue 2 基于​Object.defineProperty ​,Vue 3 基于​Proxy​,核心流程:

  • Vue 2
    • 数据劫持:通过 Object.defineProperty 监听 data 中所有属性的 get/set;
    • 依赖收集:模板编译时,访问属性触发 get,收集依赖(Watcher);
    • 派发更新:修改属性触发 set,通知 Watcher 更新视图;
    • 缺陷:无法监听数组下标/长度变化、对象新增属性;
  • Vue 3
    • 数据代理:通过 Proxy 代理整个 data 对象,支持监听数组/对象所有变化;
    • 依赖收集/派发更新逻辑与 Vue 2 类似,但效率更高;
  • 核心公式:MVVM = 数据劫持 + 发布-订阅模式
34. Vue 组件中的传值方式

组件传值分 7 种核心场景,覆盖父子/兄弟/跨级:

场景 传值方式 示例
父 → 子 props 子组件定义 props,父组件 :prop="value"
子 → 父 自定义事件($emit) 子组件 this.$emit('event', data),父组件 @event="handle"
兄弟组件 事件总线/Vuex/Pinia 事件总线:Vue.prototype.$bus = new Vue()$bus.$emit/$on
跨级组件 provide/inject 父组件 provide 提供数据,子组件 inject 注入
任意组件 Vuex/Pinia 全局状态管理,直接读取/修改共享数据
路由传参 query/params 跳转路由时携带参数
本地存储 localStorage/sessionStorage 持久化传值(非响应式)
35. Bootstrap 的原理

Bootstrap 是前端 UI 框架,核心原理:

  1. 栅格系统 :基于 Flex/Grid 布局,将页面分为 12 列,通过 col-xs-*/col-md-* 等类实现响应式布局;
  2. 响应式设计:通过媒体查询(@media)适配不同屏幕尺寸(移动端/平板/PC);
  3. 预定义样式:提供按钮、表单、导航等组件的 CSS 样式,直接复用;
  4. jQuery 插件:内置轮播、弹窗、下拉菜单等交互插件(Bootstrap 5 移除 jQuery,改用原生 JS);
  5. 变量/混合器(Sass 版本):支持自定义主题,通过变量覆盖默认样式。
36. Vue 兄弟组件传值

兄弟组件无直接传值通道,常用 3 种方式:

  1. **事件总线(Vue 2)**:

    JavaScript 复制代码
    // 1. 全局注册总线
    import Vue from 'vue';
    Vue.prototype.$bus = new Vue();
    // 2. 组件A发送事件
    this.$bus.$emit('sendData', data);
    // 3. 组件B接收事件(mounted中)
    this.$bus.$on('sendData', (data) => { /* 处理数据 */ });
    // 4. 销毁时解绑(避免内存泄漏)
    beforeDestroy() {
      this.$bus.$off('sendData');
    }
  2. Vuex/Pinia:将共享数据存入全局状态,兄弟组件直接读取/修改;

  3. 父组件中转:组件 A→ 父组件($emit)→ 组件 B(props)。

37. 如果一个组件需要在多个项目中使用怎么办

核心方案:​组件封装并发布为 npm 包​,步骤:

  1. 组件封装
    1. 抽离组件的通用逻辑,参数通过 props 暴露,事件通过$emit 触发;
    2. 避免硬编码,支持自定义样式/配置;
  2. 打包发布
    1. 用 Vue CLI/lib 模式打包:vue-cli-service build --target lib --name my-component src/index.js
    2. 配置 package.json(main 指向打包后的文件,指定版本、依赖等);
    3. 发布到 npm(npm publish);
  3. 其他方案
    1. 搭建私有 npm 仓库(如 Verdaccio),存放内部组件;
    2. 通过 Git submodule 引入组件源码(适合频繁修改的场景);
    3. 使用 Monorepo 管理多项目共享组件(如 pnpm workspace)。
38. 简述槽口(Slot)

Slot(插槽)是 Vue 组件的内容分发机制,允许父组件向子组件插入自定义内容:

  • 核心类型

    • 默认插槽 :子组件 <slot></slot>,父组件直接写内容;

    • 具名插槽 :子组件 <slot name="header"></slot>,父组件 <template v-slot:header>内容</template>(简写 #header);

    • 作用域插槽 :子组件向父组件传递数据,父组件自定义渲染逻辑:

      Plain 复制代码
      <!-- 子组件 -->
      <slot :user="user"></slot>
      <!-- 父组件 -->
      <template v-slot:default="slotProps">
        {{ slotProps.user.name }}
      </template>
  • 作用:提升组件灵活性,实现组件内容的自定义渲染。

39. 简述 watch

watch 是 Vue 的​侦听器​,用于监听数据变化并执行自定义逻辑:

  • 核心特性:

    • 监听单个/多个数据(如 data、props、计算属性);
    • 支持深度监听(deep: true)、立即执行(immediate: true);
    • 可监听对象属性(如 'user.name');
  • 示例:

    Plain 复制代码
    <script>
    export default {
      data() {
        return { user: { name: '张三' }, count: 0 };
      },
      watch: {
        // 监听基本类型
        count(newVal, oldVal) {
          console.log('count变化:', newVal, oldVal);
        },
        // 监听对象(深度监听)
        user: {
          handler(newVal) {
            console.log('user变化:', newVal);
          },
          deep: true,
          immediate: true // 初始化时执行一次
        },
        // 监听对象单个属性
        'user.name'(newVal) {
          console.log('姓名变化:', newVal);
        }
      }
    }
    </script>
40. 简述 Vant UI

Vant UI 是有赞开源的​移动端 Vue UI 组件库​,核心特点:

  1. 适配场景:专注移动端(H5/小程序),适配各种屏幕尺寸;

  2. 版本支持:Vant 2 支持 Vue 2,Vant 3/4 支持 Vue 3;

  3. 核心组件:Button、Cell、List、PullRefresh、Swipe、Dialog、Toast 等;

  4. 特性

    1. 轻量:按需引入,减少打包体积;
    2. 易用:API 简洁,文档完善;
    3. 兼容:支持小程序(微信/支付宝)、H5、App(通过 uni-app);
  5. 使用方式

    Bash 复制代码
    npm i vant
    # 按需引入(需配置babel-plugin-import)
    import { Button } from 'vant';
    Vue.use(Button);
41. 计算属性与 watch 的区别
维度 计算属性(computed) 侦听器(watch)
核心用途 派生数据(如 a+b) 监听数据变化执行副作用(如请求、修改 DOM)
缓存性 有缓存,依赖不变则不重新计算 无缓存,数据变化即触发
返回值 必须有返回值 无需返回值
语法 声明式(类似变量) 命令式(函数)
适用场景 简单的同步数据计算 异步操作、复杂的逻辑处理
深度监听 自动深度监听对象属性 需手动设置 deep: true
  • 示例对比:

    JavaScript 复制代码
    // 计算属性:适合简单计算
    computed: { fullName() { return this.first + ' ' + this.last; } }
    // watch:适合异步逻辑
    watch: { firstName(newVal) { this.$axios.get('/api', { params: { name: newVal } }); } }
42. MVVM 框架是什么?它和其他框架的区别是什么?哪些场景适合?
  • MVVM 定义:MVVM(Model-View-ViewModel)是前端架构模式,核心是 ViewModel 作为 View 和 Model 的桥梁,实现数据与视图的双向绑定;
  • 与其他框架的区别
    • 与 jQuery(无架构):MVVM 数据驱动,无需手动操作 DOM;jQuery 需手动选择 DOM、修改内容;
    • 与 React(类 MVVM):React 核心是单向数据流(State→View),需手动 setState 更新;Vue(MVVM)原生支持双向绑定;
    • 与 Angular(全量 MVVM):Vue 更轻量、易用,Angular 功能全但学习成本高;
  • 适用场景
    • 中大型单页应用(SPA):数据交互频繁,需高效管理状态;
    • 表单类应用:双向绑定简化表单处理;
    • 移动端/H5 应用:轻量、高性能,适配移动端;
    • 不适用场景:简单静态页面(如纯展示页),用 jQuery/原生 JS 更高效。
43. Vue 首屏加载慢的原因,怎么解决的,白屏时间怎么检测,怎么解决白屏问题
(1)首屏加载慢的原因
  1. 打包体积大:未按需引入组件/库、未压缩代码、包含无用依赖;
  2. 网络问题:请求资源过大、网络延迟高;
  3. 渲染阻塞:JS 执行时间长,阻塞 DOM 渲染;
  4. 服务器响应慢:接口请求耗时久。
(2)解决方法
  1. 优化打包体积
    1. 按需引入(如 Element UI/Vant);
    2. 路由懒加载:const Home = () => import('./Home.vue')
    3. 压缩代码(Vue CLI 默认开启)、移除 console;
    4. CDN 引入第三方库(如 Vue、Vue Router),减少打包体积;
  2. 网络优化
    1. 开启 Gzip 压缩(Nginx 配置);
    2. 使用 HTTP/2、静态资源 CDN;
    3. 预加载/预取(<link rel="preload">);
  3. 渲染优化
    1. 首屏骨架屏(Skeleton);
    2. 异步组件、懒加载图片;
    3. 服务端渲染(SSR)/静态站点生成(SSG)。
(3)白屏时间检测
  1. 浏览器 Performance 面板

    1. 记录首屏时间(First Contentful Paint, FCP)、最大内容绘制(LCP);
    2. 查看 JS 执行、资源加载耗时;
  2. 代码埋点

    JavaScript 复制代码
    // 监听DOM加载完成
    document.addEventListener('DOMContentLoaded', () => {
      console.log('DOM加载完成时间:', Date.now() - performance.timing.navigationStart);
    });
    // 监听首屏绘制
    new PerformanceObserver((entryList) => {
      const entry = entryList.getEntries()[0];
      console.log('首屏时间:', entry.startTime);
    }).observe({ type: 'paint', buffered: true });
(4)解决白屏问题
  1. 骨架屏:首屏加载时显示占位骨架,替代空白;
  2. 预加载关键资源:优先加载首屏所需 CSS/JS;
  3. 服务端渲染(SSR):服务端生成首屏 HTML,直接返回;
  4. 减小首屏 JS 体积:路由懒加载、按需引入,只加载首屏必要代码。
44. Vue 双向数据绑定中,怎么实现一侧数据改变之后通知另一侧

核心是​发布-订阅模式​,分两步:

  1. 数据劫持/代理
    1. Vue 2 用 Object.defineProperty 监听数据的 setter,Vue 3 用 Proxy 监听对象变化;
  2. 依赖收集与派发更新
    1. 当视图渲染访问数据时(getter),收集依赖(Watcher,关联视图);
    2. 当数据修改时(setter),触发派发更新,通知所有相关 Watcher 执行更新逻辑,重新渲染视图;
    3. 反向(视图 → 数据):v-model 监听输入事件(input/change),修改对应数据,完成双向绑定。
45. Vuex 流程

Vuex 的核心数据流向是​单向循环​:

  1. 组件通过 dispatch 触发Action(可执行异步操作);
  2. Action 通过 commit 提交Mutation
  3. Mutation 修改State(唯一能修改 State 的方式);
  4. State 变化触发Getter(可选,派生数据);
  5. 组件监听 State/Getter 变化,更新视图;
  • 简化流程:组件 → Action → Mutation → State → 组件(同步操作可直接 commit Mutation)。
46. Vuex 怎么请求异步数据

Vuex 中异步数据请求需在 Action 中执行,步骤:

JavaScript 复制代码
// 1. 定义Action
const store = new Vuex.Store({
  state: { userList: [] },
  mutations: {
    SET_USER_LIST(state, data) {
      state.userList = data;
    }
  },
  actions: {
    // 异步请求数据
    async fetchUserList({ commit }) {
      try {
        const res = await this.$axios.get('/api/user/list');
        commit('SET_USER_LIST', res.data); // 提交Mutation修改State
      } catch (err) {
        console.error('请求失败:', err);
      }
    }
  }
});
// 2. 组件中触发Action
this.$store.dispatch('fetchUserList');
  • 注意:Mutation 只能执行同步操作,异步操作必须放在 Action 中。
47. Vuex 中 Action 如何提交给 Mutation

Action 通过 commit 方法提交 Mutation,有两种方式:

  1. 解构 context 对象 (推荐):

    JavaScript 复制代码
    actions: {
      increment({ commit }) { // 解构commit
        commit('INCREMENT'); // 提交Mutation
      }
    }
  2. 完整 context 对象

    JavaScript 复制代码
    actions: {
      increment(context) {
        context.commit('INCREMENT'); // context包含commit/dispatch/state等
      }
    }
  • 带参数提交:commit('INCREMENT', payload)(payload 为任意类型数据)。
48. route 与 router 的区别
维度 $route $router
核心含义 当前路由信息对象 路由实例(导航控制器)
包含内容 path、params、query、name 等 push、replace、go 等导航方法
用途 读取当前路由参数/信息 触发路由跳转
示例 this.$route.params.id this.$router.push('/home')
49. Vuex 有哪几种状态和属性

Vuex 的核心属性(5 个):

  1. state:存储全局状态(唯一数据源);
  2. mutations:同步修改 state 的方法(唯一入口);
  3. actions:异步操作,提交 mutation 修改 state;
  4. getters:派生状态(类似计算属性,基于 state 计算);
  5. modules:模块化拆分 state,解决单一状态树体积过大问题。
50. Vuex 的 state 特性是?
  1. 唯一性:整个应用只有一个 state(单一状态树);
  2. 响应式:state 中的数据是响应式的,修改后视图自动更新;
  3. 只读性:不能直接修改 state,必须通过 mutation;
  4. 可模块化:通过 modules 拆分 state,每个 module 有独立的 state/mutations 等;
  5. 组件访问 :通过 this.$store.statemapState 辅助函数访问。
51. Vuex 的 getter 特性是?
  1. 缓存性:依赖的 state 不变时,多次访问 getter 不会重新计算;
  2. 派生状态:基于 state 计算新值(如过滤列表、计算总数);
  3. 只读性:不能直接修改 getter,需修改依赖的 state;
  4. 可传参 :通过返回函数实现传参(如 getters.getUserById(state) => (id) => state.users.find(u => u.id === id));
  5. 组件访问 :通过 this.$store.gettersmapGetters 辅助函数访问。
52. Vuex 的 mutation 特性是?
  1. 同步性:必须是同步函数(异步操作会导致状态变更无法追踪);
  2. 唯一修改入口:只能通过 mutation 修改 state;
  3. 参数:第一个参数是 state,第二个是 payload(可选,传递数据);
  4. 可追踪:Vue Devtools 可记录 mutation 的调用记录,便于调试;
  5. 调用方式 :通过 store.commit('mutationName', payload),不能直接调用。
53. Vuex 的 action 特性是?
  1. 异步性:支持异步操作(如请求数据、定时器);
  2. 不直接修改 state:需提交 mutation 修改 state;
  3. 参数:第一个参数是 context 对象(包含 commit/dispatch/state/getters);
  4. 支持 Promise:action 可返回 Promise,便于链式调用;
  5. 调用方式 :通过 store.dispatch('actionName', payload),组件中可通过 async/await 等待执行完成。
54. Vuex 的优势
  1. 集中式管理:多组件共享状态统一存储,避免状态分散;
  2. 可追踪性:所有状态修改通过 mutation,便于调试和日志记录;
  3. 单向数据流:状态变更流程清晰,降低维护成本;
  4. 模块化:支持 modules 拆分状态,适配大型应用;
  5. 生态集成:与 Vue Devtools 深度集成,可视化调试;
  6. 复用性:公共逻辑(如数据请求)可封装在 action 中,多组件复用。
55. 简述 Vue 路由懒加载

路由懒加载(按需加载)是代码分割的一种方式,核心是将路由组件拆分为独立的 JS 包,只有访问该路由时才加载对应的包:

  • 实现方式

    JavaScript 复制代码
    // 基础懒加载
    const Home = () => import('./views/Home.vue');
    // 带分包命名(webpackChunkName),便于打包后识别
    const User = () => import(/* webpackChunkName: "user" */ './views/User.vue');
    const routes = [
      { path: '/home', component: Home },
      { path: '/user', component: User }
    ];
  • 优势

    • 减小首屏 JS 包体积,提升首屏加载速度;
    • 按需加载,节省带宽和资源;
  • 原理:基于 ES6 的动态 import 语法,webpack 打包时自动拆分代码块。

56. v-for 和 v-if 的区别
维度 v-for v-if
核心用途 循环渲染列表 条件渲染 DOM
优先级 更高(Vue 2) 更低(Vue 2)
执行时机 每次渲染都循环所有数据 条件为 true 时才渲染 DOM
性能 循环所有数据,性能开销大 仅渲染满足条件的 DOM
结合使用 不推荐直接结合(Vue 2 中 v-for 优先级高,会先循环再判断,性能差) 推荐用 computed 过滤数据后再循环
  • 优化建议:

    JavaScript 复制代码
    // 错误:v-for和v-if同节点
    <div v-for="item in list" v-if="item.visible">{{item.name}}</div>
    // 正确:先过滤数据
    computed: {
      filteredList() {
        return this.list.filter(item => item.visible);
      }
    }
    <div v-for="item in filteredList" :key="item.id">{{item.name}}</div>
  • Vue 3 调整:v-if 优先级高于 v-for,同节点使用会报错,强制开发者先过滤数据。

相关推荐
hxjhnct2 分钟前
Vue 实现多行文本“展开收起”
前端·javascript·vue.js
橙子的AI笔记3 分钟前
2025年全球最受欢迎的JS鉴权框架Better Auth,3分钟带你学会
前端·ai编程
百锦再3 分钟前
Vue大屏开发全流程及技术细节详解
前端·javascript·vue.js·微信小程序·小程序·架构·ecmascript
麻瓜呀5 分钟前
vue2之el-table表格多选改单选
javascript·vue.js·elementui
独自破碎E8 分钟前
你知道Spring Boot配置文件的加载优先级吗?
前端·spring boot·后端
龙仔CLL9 分钟前
vue3使用node-rsa报错buffer is not defined
javascript·vue.js
一树山茶10 分钟前
Vue变化响应
前端
黑土豆12 分钟前
一次真实的流式踩坑:fetchEventSource vs fetch流读取的本质区别
前端·javascript·ai编程
北辰alk13 分钟前
为什么 Vue 渲染列表时,不能随便用数组下标当 key?
vue.js