With AI, You Barely Need a Frontend Framework

vibecoding web Source: dlants.me | Author: dlants | Date: 2026-04-09

核心观点

传统的论点认为像"Vamp"这样的方法太冗长。当人类编写每一行代码时,这种观点是成立的。但当AI代理编写(或修改)代码时,这个观点就不适用了。

对AI来说,重要的是显式性、本地性和可预测性,而不是简洁性。

核心模式

1. Templates - 模板

使用模板字符串将状态渲染为HTML:

class CounterView {
  constructor(container, dispatch, initialState) {
    container.innerHTML = sanitize`
      <div>
        <button data-ref="dec">−</button>
        <span data-ref="count">${initialState.count}</span>
        <button data-ref="inc">+</button>
      </div>
    `;
    // 绑定事件...
  }
}

2. Bindings - 绑定

引入sync函数和绑定来更新DOM:

this.b.bindText("count", (s) => String(s.count));

sync(state: State): void {
  this.b.sync(state);
}

3. Composition - 组合

使用bindChild嵌套子视图:

this.b.bindChild(navRef, NavView, (s) => ({
  loggedIn: s.auth.status === "logged-in",
}), (childMsg) => dispatch({ type: "NAV_MSG", msg: childMsg }));

4. Conditional Children - 条件子元素

使用bindSlot条件挂载/卸载:

this.b.bindSlot(detailRef, (s) => {
  if (!s.selectedId) return undefined;
  return show(DetailView, { id: s.selectedId }, () => {});
});

5. Lists - 列表

使用key来跟踪列表项:

this.b.bindList(listRef, "li", (s) =>
  s.items.map((item) => showKeyed(item.id, ItemView, { item }, () => {}))
);

6. Unique data-refs - 唯一引用

ref()生成唯一的data-ref,防止父子视图冲突:

const countRef = ref("count"); // 返回类似 "count_0"
const incRef = ref("inc");    // 返回类似 "inc_1"

7. Styles - 样式

使用cls()生成唯一类名,mountStyle()注入:

const headerClass = cls("header");
mountStyle(`.${headerClass} { padding: 1rem; }`);
container.innerHTML = `<div class="${headerClass}">...</div>`;

为什么现在可行?

对AI而言:
  • 显式性:没有通过代理或其他魔法产生的远程操作
  • 本地性:模式是显式和重复的,AI可以可靠地模式匹配
  • 可预测性:没有隐藏的机制(fiber调度器、钩子链表、协调启发式)

整个生命周期清晰可见:

class MyView {
  constructor(...) {
    // before mount
    this.content.innerHTML = `...`
    // after mount but before children mount
    this.b.bindSlot(...
  }

  sync(...) {
    // before update
    this.b.sync(...)
    // after update
  }

  destroy(...) {
    this.b.cleanup();
  }
}

附录:React的问题

React Hooks

本质上,React使用链表来跟踪钩子。钩子在链表中的位置是React建立钩子对应关系的唯一方式。因此钩子列表必须是确定性的——钩子必须始终以相同的顺序出现。

React Fiber与并发渲染

React 16引入了fiber概念,本质上将在react树中的渲染任务分解为称为fiber的独立部分。这允许渲染被中断,并分解为更小的片段,防止UI锁定。

问题:由于渲染现在是异步的,并分部分应用,大大复杂化了DOM测量、焦点管理、撕裂和动画计时。

性能

React的VDOM渲染和diff操作以昂贵著称。许多团队采用的解决方案是调优shouldUpdate调用,或引入immer来提供不可变状态,以便框架可以根据对象引用相等性来短路更新。

结论

这个模式被描述在一个300行的markdown文件和一个300行的绑定库/助手TypeScript文件中。你可以复制粘贴库到你的项目中,将markdown文件添加到你的agent的上下文窗口中,然后就可以开始了。

你永远不需要再接触另一个框架了。


← 返回首页