# 框架相关算法 ## 1. 虚拟DOM Diff 算法 > **场景**:React/Vue 核心渲染机制、理解为何需要 key 属性、性能优化方向。 > **解决**:直接操作真实 DOM 性能开销大,通过对比新旧虚拟树最小化 DOM 操作。 ### 简化版 Diff 实现 ```js function diff(oldVNode, newVNode) { const patches = []; // 节点不存在 if (!newVNode) { patches.push({ type: 'REMOVE' }); return patches; } // 类型不同,替换节点 if (typeof oldVNode !== typeof newVNode || (typeof oldVNode === 'string' && oldVNode !== newVNode) || oldVNode.tag !== newVNode.tag) { patches.push({ type: 'REPLACE', node: newVNode }); return patches; } // 比较属性 if (newVNode.props) { const propsPatches = diffProps(oldVNode.props || {}, newVNode.props); if (Object.keys(propsPatches).length) { patches.push({ type: 'PROPS', props: propsPatches }); } } // 比较子节点 diffChildren(oldVNode.children || [], newVNode.children || [], patches); return patches; } function diffProps(oldProps, newProps) { const patches = {}; // 新增或修改的属性 for (const key in newProps) { if (newProps[key] !== oldProps[key]) { patches[key] = newProps[key]; } } // 删除的属性 for (const key in oldProps) { if (!(key in newProps)) { patches[key] = undefined; } } return patches; } function diffChildren(oldChildren, newChildren, patches) { const len = Math.max(oldChildren.length, newChildren.length); for (let i = 0; i < len; i++) { const childPatches = diff(oldChildren[i], newChildren[i]); if (childPatches.length) { patches.push({ type: 'CHILDREN', index: i, patches: childPatches }); } } } ``` --- ## 2. Vue 响应式原理 > **场景**:Vue 项目开发、理解数据驱动视图更新、排查响应式失效问题。 > **解决**:手动操作 DOM 繁琐易错,自动追踪数据变化并更新视图。 ### Vue 2 (Object.defineProperty) ```js function observe(obj) { if (typeof obj !== 'object' || obj === null) return; Object.keys(obj).forEach(key => { let value = obj[key]; const dep = new Set(); observe(value); // 递归处理嵌套对象 Object.defineProperty(obj, key, { get() { if (currentEffect) dep.add(currentEffect); return value; }, set(newVal) { if (newVal === value) return; value = newVal; observe(newVal); dep.forEach(fn => fn()); } }); }); } let currentEffect = null; function watchEffect(fn) { currentEffect = fn; fn(); currentEffect = null; } ``` ### Vue 3 (Proxy) ```js function reactive(obj) { return new Proxy(obj, { get(target, key, receiver) { track(target, key); const result = Reflect.get(target, key, receiver); return typeof result === 'object' ? reactive(result) : result; }, set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); trigger(target, key); return result; } }); } const targetMap = new WeakMap(); let activeEffect = null; function track(target, key) { if (!activeEffect) return; let depsMap = targetMap.get(target); if (!depsMap) targetMap.set(target, (depsMap = new Map())); let dep = depsMap.get(key); if (!dep) depsMap.set(key, (dep = new Set())); dep.add(activeEffect); } function trigger(target, key) { const depsMap = targetMap.get(target); if (!depsMap) return; depsMap.get(key)?.forEach(effect => effect()); } function effect(fn) { activeEffect = fn; fn(); activeEffect = null; } ``` --- ## 3. React useState 简单模拟 > **场景**:React 函数组件状态管理、理解 Hooks 为何不能在条件语句中调用。 > **解决**:函数组件无状态,通过闭包和数组模拟类组件的状态能力。 ```js let state = []; let stateIndex = 0; function useState(initialValue) { const currentIndex = stateIndex; state[currentIndex] = state[currentIndex] ?? initialValue; const setState = (newValue) => { state[currentIndex] = typeof newValue === 'function' ? newValue(state[currentIndex]) : newValue; render(); // 触发重新渲染 }; stateIndex++; return [state[currentIndex], setState]; } function render() { stateIndex = 0; // 重置索引 // 调用组件函数... } ``` --- ## 4. useEffect 简单模拟 > **场景**:React 副作用处理(数据请求、事件订阅、定时器)、理解依赖数组作用。 > **解决**:函数组件中处理生命周期和副作用,替代类组件的 componentDidMount 等。 ```js let effectIndex = 0; let effects = []; function useEffect(callback, deps) { const currentIndex = effectIndex; const prevDeps = effects[currentIndex]?.deps; const hasChanged = !prevDeps || deps.some((dep, i) => !Object.is(dep, prevDeps[i])); if (hasChanged) { // 执行清理函数 effects[currentIndex]?.cleanup?.(); // 延迟执行 effect Promise.resolve().then(() => { const cleanup = callback(); effects[currentIndex] = { deps, cleanup }; }); } effectIndex++; } ``` --- ## 5. 简易 Redux > **场景**:跨组件状态管理、理解单向数据流架构、实现时间旅行调试。 > **解决**:多组件共享状态混乱,集中管理应用状态并可预测地变更。 ```js function createStore(reducer) { let state; const listeners = []; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); }; const subscribe = (listener) => { listeners.push(listener); return () => { const index = listeners.indexOf(listener); listeners.splice(index, 1); }; }; dispatch({ type: '@@INIT' }); // 初始化 state return { getState, dispatch, subscribe }; } // 使用示例 const reducer = (state = { count: 0 }, action) => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }; ```