首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >北京百思可瑞教育:用 TypeScript 实现一个简化版 React

北京百思可瑞教育:用 TypeScript 实现一个简化版 React

原创
作者头像
用户1162104
发布2025-08-19 10:40:34
发布2025-08-19 10:40:34
1300
举报

以下是用 TypeScript 实现简化版 React 的核心代码,包含虚拟 DOM、状态管理和协调更新机制:

代码语言:typescript
复制
// 类型定义
type VNode = {
  type: string | Function;
  props: Record<string, any>;
  children: VNode[];
  dom?: HTMLElement;
};

type Component = {
  render: () => VNode;
  __state?: any;
  __hooks?: any[];
};

// 虚拟 DOM 创建函数
function createElement(
  type: string | Function,
  props: Record<string, any>,
  ...children: (VNode | string)[]
): VNode {
  return {
    type,
    props,
    children: children.map(child => 
      typeof child === 'object' ? child : createTextElement(child)
    )
  };
}

function createTextElement(text: string): VNode {
  return {
    type: 'TEXT',
    props: { nodeValue: text },
    children: []
  };
}

// 渲染器
let rootInstance: Component | null = null;

function render(vnode: VNode, container: HTMLElement) {
  const prevInstance = rootInstance;
  const nextInstance = reconcile(container, prevInstance, vnode);
  rootInstance = nextInstance;
}

// 协调器
function reconcile(
  parent: HTMLElement,
  instance: Component | null,
  vnode: VNode
): Component {
  if (instance == null) {
    // 创建新实例
    const newInstance = instantiate(vnode);
    parent.appendChild(newInstance.dom!);
    return newInstance;
  } else if (vnode == null) {
    // 删除实例
    parent.removeChild(instance.dom!);
    return null!;
  } else if (instance.vnode.type !== vnode.type) {
    // 替换实例
    const newInstance = instantiate(vnode);
    parent.replaceChild(newInstance.dom!, instance.dom!);
    return newInstance;
  } else {
    // 更新实例
    instance.update(vnode);
    return instance;
  }
}

// 实例化组件
function instantiate(vnode: VNode): Component {
  const { type, props } = vnode;
  
  if (typeof type === 'function') {
    // 函数组件
    const component: Component = { __state: {}, __hooks: [] };
    const child = type(props);
    const instance = Object.assign(component, child);
    instance.dom = createDom(child);
    return instance;
  }

  // 原生 DOM 元素
  const dom = document.createElement(type as string);
  updateDom(dom, {}, props);
  
  return {
    type,
    props,
    dom,
    update(vnode: VNode) {
      updateDom(this.dom!, this.props, vnode.props);
      this.props = vnode.props;
    }
  };
}

// DOM 更新函数
function updateDom(
  dom: HTMLElement,
  prevProps: Record<string, any>,
  nextProps: Record<string, any>
) {
  // 移除旧属性
  Object.keys(prevProps)
    .filter(isEvent)
    .forEach(name => dom.removeEventListener(name.toLowerCase(), prevProps[name]));

  // 设置新属性
  Object.keys(nextProps)
    .filter(isProperty)
    .forEach(name => dom[name] = nextProps[name]);

  // 绑定事件
  Object.keys(nextProps)
    .filter(isEvent)
    .forEach(name => dom.addEventListener(name.toLowerCase(), nextProps[name]));
}

// 辅助函数
function isEvent(key: string): boolean {
  return key.startsWith('on');
}

function isProperty(key: string): boolean {
  return key !== 'children' && !isEvent(key);
}

// 状态管理
let hookIndex = 0;

function useState<T>(initialState: T): [T, (newState: T) => void] {
  const instance = rootInstance!;
  const hooks = instance.__hooks || (instance.__hooks = []);
  const currentIndex = hookIndex++;
  
  hooks[currentIndex] = hooks[currentIndex] || initialState;
  
  const setState = (newState: T) => {
    hooks[currentIndex] = newState;
    // 触发重新渲染
    render(instance.vnode, instance.dom!.parentNode!);
  };
  
  return [hooks[currentIndex], setState];
}

// 使用示例
function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

// 渲染到 DOM
const root = document.getElementById('root')!;
render(<Counter />, root);

关键实现要点:

  1. 虚拟 DOM 结构
    • 使用树形结构表示 UI
    • 包含类型、属性和子节点信息
    • 支持函数组件和原生 DOM 元素
  2. 协调机制
    • Diff 算法比较新旧节点
    • 智能复用 DOM 节点
    • 处理节点替换、更新和删除
  3. 状态管理
    • 实现 useState Hook
    • 闭包保存组件状态
    • 状态更新触发重新渲染
  4. 渲染流程
    • 首次渲染创建 DOM 节点
    • 后续更新进行差异对比
    • 最小化 DOM 操作
  5. 事件处理
    • 自动绑定事件监听器
    • 事件名自动转换为小写
    • 清理旧事件监听器

这个实现展示了 React 的核心思想:

  • 声明式 UI 编程
  • 虚拟 DOM 协调
  • 组件化架构
  • 状态驱动更新

可以通过以下方式扩展功能:

  1. 添加生命周期方法
  2. 实现 useEffect Hook
  3. 增加 key 属性支持
  4. 优化 diff 算法
  5. 添加错误边界处理

注意:这是简化实现,实际 React 的完整实现包含更多优化和边界情况处理。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档