webDevInterviewQuestions/algorithm/05-framework-algorithms.md
2026-01-19 09:34:13 +08:00

246 lines
5.1 KiB
Markdown

# 框架相关算法
## 1. 虚拟DOM Diff 算法
### 简化版 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 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 简单模拟
```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 简单模拟
```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;
}
};
```