前端Vue面试八股常考题(一)

发布于:2025-07-01 ⋅ 阅读:(22) ⋅ 点赞:(0)

1、什么是 Vue 指令?Vue 有哪些常用的指令?

Vue 指令是带有 v- 前缀的特殊属性,其职责是当表达式的值改变时,将变化高效应用到 DOM 上。

常用指令分类及说明:

  1. 属性绑定指令

    • v-bind:动态绑定属性或组件 prop,简写为

      <img :src="imageSrc">
      <button :[key]="value">动态属性名</button>
      
    • v-model:在表单元素上创建双向数据绑定

      <input v-model="message">
      <!-- 等价于 -->
      <input :value="message" @input="message = $event.target.value">
      
  2. 事件绑定指令

    • v-on:绑定事件监听器,简写为@

      <button @click="doThis">点击事件</button>
      <button @[event]="doThis">动态事件名</button>
      
  3. 条件渲染指令

    • v-if/v-else/v-else-if:根据条件动态创建或销毁 DOM 元素

      <div v-if="type === 'A'">A</div>
      <div v-else-if="type === 'B'">B</div>
      <div v-else>Not A/B</div>
      
    • v-show:通过切换display 属性控制元素显示 / 隐藏,不销毁 DOM

      <div v-show="isVisible">Hello</div>
      
  4. 列表渲染指令

    • v-for:基于数组或对象渲染列表,需使用 key 优化性能

      <div v-for="item in items" :key="item.id">
        {{ item.text }}
      </div>
      
  5. 内容渲染指令

    • v-text:更新元素文本内容
    • v-html:更新元素 innerHTML(注意 XSS 风险)
  6. 特殊功能指令

    • v-slot:具名插槽或接收 prop 的插槽,简写为 #
    • v-pre:跳过元素及其子元素的编译过程
    • v-cloak:隐藏未编译模板直到实例准备完毕(需配合 CSS [v-cloak] { display: none; }
    • v-once:只渲染一次,后续更新跳过

扩展:自定义指令

Vue 允许注册自定义指令,钩子函数与组件生命周期类似:

// 全局注册
app.directive('focus', {
  mounted(el) { el.focus() }
})

// 局部注册
export default {
  directives: {
    focus: {
      mounted(el) { el.focus() }
    }
  }
}

2、Vue 计算属性 computed 的函数名和 data 中的属性可以同名吗?为什么?

不可以同名,原因如下:

  1. 命名冲突本质:data 和 computed 最终都会作为 Vue 实例属性存在,若同名会导致实例属性被覆盖。
  2. 优先级顺序:data 优先级高于 computed,若同名,模板中会优先使用 data 数据,导致 computed 失效。
  3. 警告机制:Vue 初始化时会检测重复定义并抛出警告,避免不可预知的错误。

扩展:Vue 实例属性优先级

  • props > methods > data > computed > watch
    后挂载的属性会覆盖先挂载的同名属性(如 methods 方法会覆盖 data 同名属性)。

3、Vue 中 data 的属性可以与 methods 中的方法同名吗?为什么?

不可以同名,因为:

  1. 实例属性共享命名空间:data、methods、computed 等会被合并到组件实例对象,同名会导致冲突。
  2. 方法覆盖属性:methods 优先级高于 data,同名时方法会覆盖 data 属性,导致数据无法访问。

示例:冲突场景

<script>
export default {
  data() { return { count: 10 } },
  methods: {
    count() { return this.count * 2 } // 错误!会覆盖 data.count
  }
}
</script>

4、Vue 的 v-cloak 和 v-pre 指令有什么作用?

1. v-cloak 指令

  • 作用:隐藏未编译的模板内容,避免 “模板闪烁”(用户看到 {{ message }} 原始标签)。
  • 使用方式:需配合 CSS 规则 [v-cloak] { display: none; },Vue 实例挂载后自动移除该属性。
  • 应用场景:
    • 无构建工具的开发环境(如直接在 HTML 中使用 Vue)。
    • 大型应用加载时或网络较慢时提升用户体验。

2. v-pre 指令

  • 作用:跳过元素及其子元素的编译过程,直接显示原始内容。
  • 应用场景:
    • 展示 Vue 模板语法(如文档示例)。
    • 优化性能:对静态内容跳过编译。
    • 保留 HTML 注释(默认编译会移除注释)。

示例:

<!-- v-cloak 示例 -->
<div v-cloak>{{ message }}</div>

<!-- v-pre 示例 -->
<span v-pre>{{ 这段内容不会被编译 }}</span>

5、Vue 的 v-show 和 v-if 有什么区别?使用场景分别是什么?

对比项 v-if v-show
渲染机制 条件为 false 时移除 DOM 元素 始终渲染,通过 display 控制显示
初始开销 惰性渲染(条件为 true 时才渲染) 初始必渲染,开销更高
切换开销 销毁 / 重建 DOM,开销大 仅修改 CSS,开销小
分支支持 支持 v-else/v-else-if 不支持分支
模板元素 可在 上使用 不可在 上使用

使用场景:

  • v-if 适用场景
    • 条件不频繁切换(如用户权限控制)。
    • 多条件分支(配合 v-else-if/v-else)。
    • 需要完全销毁组件实例(如表单重置)。
  • v-show 适用场景
    • 频繁切换显示状态(如标签页、对话框)。
    • 需要结合 CSS 过渡动画(因元素始终存在于 DOM 中)。

示例:

<!-- v-if 示例:用户权限控制 -->
<admin-panel v-if="user.isAdmin"></admin-panel>

<!-- v-show 示例:频繁切换的对话框 -->
<div v-show="isDialogVisible" class="dialog">对话框内容</div>

扩展:与生命周期的关系

  • v-if 为 false 时,组件不渲染,条件切换时触发完整生命周期。
  • v-show 始终渲染组件,仅控制显示,生命周期仅触发一次。

6、在 Vue 组件中写 name 选项有什么作用?

Vue 组件的 name 选项用于显式声明组件名称,主要作用如下:

1. 调试与开发体验

  • Vue DevTools 识别:设置 name 后,组件在 DevTools 中显示更直观,便于调试复杂应用。
  • 错误堆栈信息:在报错时,name 能明确显示问题发生的组件位置。

2. 递归组件引用

组件需通过 name 选项实现自引用:

<!-- 递归组件示例 -->
<script>
export default {
  name: 'TreeNode',
  props: {
    children: Array
  },
  template: `
    <ul>
      <li v-for="child in children" :key="child.id">
        {{ child.name }}
        <TreeNode v-if="child.children" :children="child.children" />
      </li>
    </ul>
  `
}
</script>

3. 动态组件与 keep-alive

  • 动态组件切换:通过 name 缓存组件状态(如 keep-alive)。
  • 异步组件加载name 可作为异步组件的标识。

4. 不同 API 中的定义方式

  • 选项式 API:直接在组件选项中定义 name

  • 组合式 API:通过defineOptions 宏定义(Vue 3.3+):

    <script setup>
    defineOptions({
      name: 'MyComponent'
    })
    </script>
    

7、Vue 2 和 Vue 3 支持哪个版本以上的 IE 浏览器?

版本 浏览器支持 原因
Vue 2 IE9+(含 IE9) 使用 Object.defineProperty 实现响应式,IE8 及以下不支持该 API。
Vue 3 不支持任何版本 IE(包括 IE11) 基于 ES6+ 语法和 Proxy 实现响应式,IE 无法兼容;官方推荐使用现代浏览器(Chrome、Firefox、Edge 等)。

8、为什么不建议在 Vue 中同时使用 v-if 和 v-for?

1. 优先级问题导致的行为差异

版本 优先级顺序 潜在问题
Vue 2 v-for > v-if 先循环再条件判断,即使条件为 false 仍会遍历整个数组,性能浪费。
Vue 3 v-if > v-for 先条件判断再循环,但可能导致 v-if 无法访问 v-for 作用域内的变量(如 item),引发编译错误。

2. 正确替代方案

  • 场景 1:过滤列表项
    使用计算属性或方法预先过滤数据:

    <script>
    export default {
      computed: {
        activeUsers() {
          return this.users.filter(user => user.isActive)
        }
      }
    }
    </script>
    <template>
      <li v-for="user in activeUsers" :key="user.id">
        {{ user.name }}
      </li>
    </template>
    
  • 场景 2:条件性渲染整个列表
    使用 <template> 分离逻辑:

    <template v-if="shouldRenderList">
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </template>
    

9、在 Vue 渲染模板时,如何保留模板中的 HTML 注释?

方法 适用版本 示例代码 特点
comments 选项 Vue 2 new Vue({ comments: true }) 全局配置,保留所有注释,可能增加打包体积。
v-pre 指令 Vue 2/3 <div v-pre><!-- 注释 --></div> 跳过元素编译,保留内部所有内容(包括注释),但会导致该元素及其子元素无法使用 Vue 指令。
特殊注释语法 Vue 3 <!--[COMMENTS] 这是会被保留的注释 --> 仅保留符合该格式的注释,其他注释仍会被移除,更精准控制。

10、为什么 Vue 中的 data 属性是一个函数而不是一个对象?

1. 核心原因:避免组件实例间数据共享

  • 对象是引用类型:若 data 为对象,所有组件实例将共享同一数据对象,导致数据污染。
  • 函数返回新对象:每个实例调用 data() 都会返回独立的数据副本,保证数据隔离。

2. 根实例 vs 组件实例的区别

场景 允许 data 为对象 原因
根实例 根实例仅创建一次,不存在复用问题,数据不会被共享。
组件实例 组件可能被多次复用,若 data 为对象,所有实例将共享同一数据。

3. Vue 2 与 Vue 3 的实现差异

版本 响应式原理 数据独立性实现方式
Vue 2 Object.defineProperty 通过 data() 返回对象后,对每个属性进行劫持,创建独立的 getter/setter。
Vue 3 Proxy 通过 data() 返回对象后,用 Proxy 代理整个对象,实现响应式,每个实例的 Proxy 独立。

11、Vue 的 template 标签有什么用?

<template> 标签在 Vue 中作为占位符或逻辑容器使用,其行为在 Vue 2 和 Vue 3 中有所不同:

1. 核心用途

  • 条件渲染

    :包裹多个元素,避免添加额外 DOM 节点:

    <template v-if="condition">
      <h1>标题</h1>
      <p>内容</p>
    </template>
    
  • 列表渲染:与 v-for 结合,不生成额外 DOM:

    <template v-for="item in list" :key="item.id">
      <div>{{ item.name }}</div>
      <span>{{ item.value }}</span>
    </template>
    
  • 插槽定义:定义具名插槽或默认插槽:

    <template #header>
      <h1>头部内容</h1>
    </template>
    

2. Vue 2 vs Vue 3 的差异

版本 行为 示例
Vue 2 始终作为占位符,编译后被移除,不影响最终 DOM。 <template v-if="true"><div>内容</div></template> → 渲染为 <div>内容</div>
Vue 3 若未使用指令(如 v-ifv-for),会渲染为原生 <template> 标签;否则编译后移除。 <template>原始内容</template> → 渲染为 <template>原始内容</template>(浏览器中不可见)。

12、Vue 中 MVVM、MVC 和 MVP 模式的区别是什么?

模式 核心结构 数据流方向 Vue 中的应用场景
MVVM Model ←→ ViewModel ←→ View 双向数据绑定 Vue 框架的核心模式,通过 datatemplate 实现数据与视图的自动同步,ViewModel 由 Vue 实例内部实现。
MVC Model ← Controller → View 单向数据流(用户操作 → Controller → Model → View) Vue Router 中路由守卫可视为 Controller,处理导航逻辑并更新视图;大型应用中可能拆分出独立的 Model 层(如 API 服务)。
MVP Model ← Presenter → View 单向数据流(Presenter 作为中介) Vue 组件中的 propsemit 机制类似 MVP,父组件通过 props 传递数据给子组件,子组件通过 emit 通知父组件更新,形成单向数据流。

扩展:Vue 中的 MVVM 实现

  • 响应式系统:Vue 2 使用 Object.defineProperty,Vue 3 使用 Proxy 实现数据劫持。
  • 模板编译:将 template 编译为渲染函数,生成虚拟 DOM。
  • 双向绑定:通过 v-model 实现表单元素与数据的双向绑定,本质是 :value + @input 的语法糖。

网站公告

今日签到

点亮在社区的每一天
去签到