vue相关面试题

182 阅读2分钟

1.keepalive原理

基本作用

  • 正常情况:组件切换时会被销毁(beforeUnmountunmounted),再次进入时重新挂载。
  • 使用 <keep-alive> :组件不会销毁,而是被缓存起来(保留状态、DOM 不卸载),下次再切换回来时会从缓存里取出。

核心原理

(1)抽象组件

<keep-alive> 本身不会渲染任何 DOM,它是一个 抽象组件,只在 vnode 层做处理。

(2)缓存机制

内部维护了一个 缓存 Map,key 是组件的唯一标识(通常是 vnode.type + vnode.key),value 是对应的 组件实例 vnode

const cache = new Map<Key, VNode>();

(3)渲染逻辑

  • render 时,<keep-alive> 会判断子组件是否已经在缓存里:

    • 存在:直接从缓存里拿到之前的 vnode,并复用组件实例。
    • 不存在:创建新组件实例,并放入缓存。

(4)卸载逻辑

  • 被缓存的组件不会真的执行 unmounted,而是执行 deactivated 生命周期钩子。
  • 当缓存组件再次激活时,会执行 activated 生命周期钩子。

生命周期对比

情况普通组件keep-alive 缓存组件
第一次挂载beforeMountmountedbeforeMountmounted
组件切换离开beforeUnmountunmounteddeactivated
组件再次进入beforeMountmountedactivated

缓存控制

<keep-alive> 支持 include / exclude / max 属性来控制缓存:

  • include:只有匹配的组件才会被缓存。
  • exclude:匹配的组件不会被缓存。
  • max:最多缓存多少个,超过会淘汰最久未使用的(LRU 策略)。
<keep-alive include="A,B" exclude="C" max="10">
  <component :is="current"></component>
</keep-alive>

2.react实现keep alive功能

🔹1. 最简单实现:条件渲染 + CSS 隐藏

function App() {
  const [tab, setTab] = useState<"A" | "B">("A");

  return (
    <div>
      <button onClick={() => setTab("A")}>A</button>
      <button onClick={() => setTab("B")}>B</button>

      <div>
        <div style={{ display: tab === "A" ? "block" : "none" }}>
          <ComponentA />
        </div>
        <div style={{ display: tab === "B" ? "block" : "none" }}>
          <ComponentB />
        </div>
      </div>
    </div>
  );
}

🔹2. 封装一个 KeepAlive 组件(带缓存 Map)

import React, { useRef } from "react";

type KeepAliveProps = {
  activeKey: string;
  children: React.ReactNode[];
};

export default function KeepAlive({ activeKey, children }: KeepAliveProps) {
  const cache = useRef(new Map<string, React.ReactNode>());

  // 遍历 children,把它们存入缓存
  React.Children.forEach(children, (child: any) => {
    if (child && child.key) {
      cache.current.set(child.key as string, child);
    }
  });

  return (
    <>
      {Array.from(cache.current.entries()).map(([key, child]) => (
        <div key={key} style={{ display: key === activeKey ? "block" : "none" }}>
          {child}
        </div>
      ))}
    </>
  );
}

🔹3. 高阶封装(withKeepAlive)

function withKeepAlive(WrappedComponent: React.ComponentType) {
  return React.memo((props) => {
    const ref = useRef<JSX.Element>();
    if (!ref.current) {
      ref.current = <WrappedComponent {...props} />;
    }
    return ref.current;
  });
}

使用方法:

const AliveA = withKeepAlive(ComponentA);

2.watch、watchEffect、computed区别

特性watchwatchEffectcomputed
执行时机数据变化时立即执行 + 数据变化时依赖变化时(懒计算)
依赖收集手动指定自动收集自动收集
返回值有(返回计算值)
新旧值
是否缓存✅ 有缓存
适用场景异步/副作用、监听具体数据自动副作用、快速调试计算属性、派生数据