面试备战录

72 阅读5分钟

1、Vue 如何处理组件性能优化?(如 watchEffect、memo、Suspense)

答:Vue组件性能优化手段包括依赖精确追踪(watchEffect)跳过不必要渲染(v-memo, v-once)组件缓存(keep-alive)异步占位(Suspense) 以及传统的 虚拟列表、懒加载等。核心思路是减少无关渲染,优化首屏与大数据场景

  • Vue组件性能瓶颈常见于:重复渲染(父组件更新导致子组件无关渲染)、大数据列表渲染过多、异步数据加载阻塞页面、复杂计算/副作用频繁触发
  • watchEffect与依赖追踪
    • 用于收集依赖的副作用逻辑,只有相关依赖变化时才重新执行。
    • 避免冗余的计算或副作用调用。
  • v-memo (Vue 3.2+)
    • 用于跳过组件或节点的渲染,当绑定的依赖不变时,直接复用之前的渲染结果。
<div v-memo="[id]">
  <span>{{ id }}</span>
  <span>{{ name }}</span>
</div>
<!-- 只有`id`变化才会重新渲染,`name`变化时会被忽略。-->
<!-- 类似`React`的`memo`,适合大列表、局部渲染优化。 -->
  • <Suspense>异步组件加载优化
    • Vue内置的 异步组件占位机制,在异步数据/组件加载时展示fallback,避免白屏。
<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <LoadingSpinner />
  </template>
</Suspense>
  • 其它优化手段
    • v-once:一次性渲染,永不更新
    • keep-alive:缓存动态组件,避免重复创建/销毁
    • 计算属性缓存:复杂计算逻辑放入computed,避免重复执行
    • 事件绑定优化:使用事件委托,避免在大列表中每个元素单独绑定事件
    • 异步组件 & 懒加载:路由级别拆分,减少首屏压力

2、vuex 和 pinia 有何不同?pinia 是如何实现状态持久化的?

  • VuexVue2时代的官方状态管理库,采用mutations + actions,语法偏重。
  • PiniaVue3官方推荐的状态管理库,API更简洁,支持组合式写法,无mutations,更贴近原生Vue响应式。
  • 持久化:Pinia自身不带持久化,需要通过 插件机制(如pinia-plugin-persistedstate)将store自动存储到localStorage / sessionStorage,并在初始化时恢复。
  • Vuex特点
    • 单一状态树(Single Source of Truth
    • 强制mutations同步修改state(方便devtools追踪)
    • actions处理异步逻辑,最后提交到mutations
    • 结构清晰但模板代码多
  • Pinia特点
    • 直接使用函数defineStore定义store
    • 不再强制区分mutations / actions,直接写方法修改state
    • 支持TypeScript完整类型推导
    • Vue组合式API更自然结合

3、解释一下 z-index 的作用及层叠上下文的形成规则

答:z-index用来控制元素在z轴上的显示顺序,但只在同一个层叠上下文中比较。层叠上下文可以由根元素、设置了定位且z-indexauto的元素、或一些特殊属性(如opacity < 1、transform、filter)创建。不同层叠上下文之间互相独立,内部元素不会跨上下文去比较z-index,这就是为什么有时z-index设置很大也无法“置顶”的原因。

z-index的作用

  • 作用:在同一个层叠上下文(stacking context)中,决定元素在**z 轴方向(前后顺序)**的绘制顺序。
  • 前提:只有定位元素(position 不是 static)或某些特殊属性的元素,才会创建层叠上下文,z-index才有实际意义。

层叠上下文(Stacking Context):层叠上下文是浏览器绘制时的一个分组/局部坐标系,内部元素的层叠顺序受控于这个上下文,而不会与外部元素直接比较。

形成层叠上下文触发条件

  • 根元素 (<html>) 天然是一个层叠上下文。
  • 定位元素 +z-indexautoposition: relative | absolute | fixed | sticky; z-index: 0 | 正数 | 负数;
  • 特定CSS属性(即使没有z-index):opacity < 1transformperspectivefilterwill-changemix-blend-modeisolation: isolatecontain: paintclip-path

层叠顺序规则:在同一层叠上下文中,元素的绘制顺序遵循以下规则(从低到高,后面的会覆盖前面的):

  • 背景与边框(block background/border)
  • z-index的子元素
  • 普通文档流中的block/inline元素(z-index: auto的内容)
  • 浮动元素
  • 正常的inline/inline-block(z-index: auto)
  • z-index ≥ 0的定位子元素(按z-index数值排序)

不同stacking context的元素不会打乱内部顺序,而是整个上下文作为一个单元,参与外层的比较。

常见坑

  • z-index无效
    • 父元素未形成层叠上下文时,子元素的z-index可能表现异常。
    • 解决:给父元素设置position + z-index或其他会创建上下文的属性。
  • z-index冲突解释错误
    • 很多人以为z-index: 9999就能绝对置顶,但其实要看它所在的stacking context
  • 层叠上下文隔离
    • 内层元素无法“逃脱”父层叠上下文,即使z-index设置再大,也盖不住外层兄弟。

4、CSS 选择器优先级规则是怎样的?

答:CSS选择器优先级规则是:行内样式最高,其次是ID选择器,然后是类/属性/伪类,最后是元素/伪元素。同级比较数量,从高到低逐层比。!important可以提升声明优先级,但不会改变选择器本身的权重。

行内 > ID > 类/属性/伪类 > 元素/伪元素。同级比较数量,层级逐级比较。!important能碾压一切(除非对方也有)。

特殊规则

  • 通配符 *关系选择器 > + ~否定伪类 :not():不会增加优先级。(比如div :not(.a),优先级只算.a
  • !important:会将当前声明提升到最高优先级,但不会改变选择器权重。如果两个规则都有!important,就再比较选择器优先级。
  • 继承的样式:优先级最低,只有在没有更具体的规则时才生效。