简单粗暴啊!对比SolidJs和React。。。

点击上方关注 前端技术江湖,一起学习,天天进步

SolidJS 确实在设计上借鉴了 React 的诸多特性,但底层机制却有本质不同。

下面通过代码对比和原理分析来理解:


一、SolidJS 与 React 的相似与差异

1.1 相似之处(表象)
// React 组件
function ReactCounter() {
const [count, setCount] = useState(0)
return<button onClick={() => setCount(c => c+1)}>{count}</button>
}

// SolidJS 组件
function SolidCounter() {
const [count, setCount] = createSignal(0)
return<button onClick={() => setCount(count()+1)}>{count()}</button>
}

• 共同点:函数式组件、JSX 语法、Hooks 风格 API

• 表面差异useState vs createSignal,状态访问需要函数调用 count()

1.2 核心差异

特性

React

SolidJS

响应式机制

虚拟DOM Diff

细粒度订阅更新

渲染策略

整体重渲染(可优化)

精准更新

(编译时分析)

状态更新触发

手动setState触发

信号(Signal)驱动

组件生命周期

明确的生命周期方法

基于createEffect的副作用

编译时参与

基本无

深度编译优化

二、直接操作 DOM 更快

2.1 虚拟DOM 的性能成本
// React 更新流程示例
function updateComponent() {
// 1. 生成新虚拟DOM
const newVdom = renderComponent() 

// 2. Diff 新旧虚拟DOM(时间复杂度O(n^3)优化后O(n))
const patches = diff(oldVdom, newVdom)

// 3. 应用差异到真实DOM
  applyPatches(realDOM, patches)
}

• 性能瓶颈

• 双重计算:先计算虚拟DOM差异,再操作真实DOM

• 过度更新:即使只有 1 个数据变化,也要重新渲染整个组件

• 内存占用:需维护完整虚拟DOM树

2.2 SolidJS 的精准更新
// SolidJS 组件编译后的代码(伪代码)
function CompiledComponent() {
const [count, setCount] = createSignal(0)

// 编译时分析出DOM依赖关系
const button = document.createElement('button')

// 建立细粒度订阅
  createEffect(() => {
    button.textContent = count() // 只绑定这个节点
  })

  button.addEventListener('click', () => setCount(count()+1))
return button
}

• 优化原理

  1. 编译时静态分析:提前确定状态与DOM的依赖关系

  2. 原子级绑定:每个状态变化只更新对应的 DOM 节点

  3. 零虚拟DOM:直接操作真实DOM,无中间计算层

2.3 性能对比数据

以更新 10,000 个列表项为例:

指标

React(虚拟DOM)

SolidJS(直接DOM)

首次渲染

120ms

90ms

更新单个项

15ms

0.5ms
内存占用

85MB

52MB
CPU峰值

95%

68%

(数据来源:JS Framework Benchmark)


三、深度解析更新机制

3.1 React 更新流程(简化的伪代码)
// 假设有一个 TodoList 组件
function TodoList() {
const [todos, setTodos] = useState([...])

return (
    <ul>
      {todos.map(todo => (
        <TodoItem key={todo.id} todo={todo} />
      ))}
    </ul>
  )
}

// 更新时(如删除一个项):
setTodos(newTodos)
// -> 重新渲染整个 TodoList
// -> 每个 TodoItem 都要经历 diff 检查
// -> 即使大部分未变化,仍要执行协调(Reconciliation)
3.2 SolidJS 更新流程
function SolidTodoList() {
const [todos, setTodos] = createStore([...])

return (
    <ul>
      <For each={todos}>
        {(todo) => <TodoItem todo={todo} />}
      </For>
    </ul>
  )
}

// 编译后的优化代码(伪代码):
function CompiledTodoList() {
const [todos, setTodos] = createStore([...])
const ul = document.createElement('ul')

// 建立列表与DOM的精确映射
const listNodes = newMap()

// 每个项独立订阅
  createEffect(() => {
    todos.forEach((todo, i) => {
      if (!listNodes.has(todo.id)) {
        const li = renderTodoItem(todo)
        ul.appendChild(li)
        listNodes.set(todo.id, li)
      }
    })
    
    // 自动处理删除
    Array.from(listNodes.keys()).forEach(id => {
      if (!todos.some(t => t.id === id)) {
        ul.removeChild(listNodes.get(id))
        listNodes.delete(id)
      }
    })
  })

return ul
}

• 关键优化

• 精准更新:只处理实际变化的项

• 无虚拟DOM对比:直接操作真实DOM节点

• 编译时辅助:提前建立状态与DOM的关联


四、什么时候虚拟DOM更快?

虽然 SolidJS 在大多数更新场景占优,但虚拟DOM仍有优势:

  1. 复杂DOM结构批量更新

    // 同时修改100个分散的DOM节点
    // 虚拟DOM的批量更新可能更高效
  2. 极端高频更新(如动画):

    // SolidJS 的细粒度订阅可能触发过多微任务
    // 虚拟DOM的批量处理可能更稳定
  3. **服务端渲染(SSR)**:

    // 虚拟DOM更容易序列化
    // SolidJS 需要额外处理 hydration

The End

欢迎自荐投稿到《前端技术江湖》,如果你觉得这篇内容对你挺有启发,记得点个 「在看」

点个『在看』支持下 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zz_jesse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值