jQuery 与 React 对比

详细对比jQuery与React两种前端框架的区别,包括设计理念、使用场景、性能、学习曲线等方面的分析,帮助开发者选择合适的前端技术栈。

设计理念对比

jQuery:直接 DOM 操作

jQuery 的核心思想是直接操作 DOM 元素,通过选择器找到元素,然后对其进行修改。

// jQuery 示例
$("#button").click(function() {
  $("#title").text("Hello React");
  $("#title").css("color", "blue");
});

React:虚拟 DOM + 组件化

React 引入了虚拟 DOM 概念,通过声明式的方式描述 UI,框架自动处理 DOM 更新。

// React 示例
function App() {
  const [title, setTitle] = useState("Hello jQuery");
  
  return (
    <div>
      <button onClick={() => setTitle("Hello React")}>
        点击
      </button>
      <h1 style={{ color: 'blue' }}>{title}</h1>
    </div>
  );
}

核心差异

1. 渲染方式

jQuery:直接操作真实 DOM

$("#list").append("<li>新项目</li>");

React:通过虚拟 DOM diff 算法更新

setItems([...items, "新项目"]);

2. 状态管理

jQuery:状态分散在各个变量中

var count = 0;
$("#button").click(function() {
  count++;
  $("#display").text(count);
});

React:集中式状态管理

const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>
  点击
</button>

3. 事件处理

jQuery:传统事件绑定

$("#form").submit(function(e) {
  e.preventDefault();
  // 处理表单
});

React:合成事件系统

<form onSubmit={handleSubmit}>
  <button type="submit">提交</button>
</form>

4. 组件复用

jQuery:通过函数或插件复用

function createCard(title, content) {
  return `
    <div class="card">
      <h3>${title}</h3>
      <p>${content}</p>
    </div>
  `;
}

React:组件化开发

function Card({ title, content }) {
  return (
    <div className="card">
      <h3>{title}</h3>
      <p>{content}</p>
    </div>
  );
}

性能对比

jQuery

  • 直接操作真实 DOM,频繁更新性能较差
  • 没有优化机制,完全依赖开发者
  • 适合小规模应用

React

  • 虚拟 DOM 减少真实 DOM 操作
  • Diff 算法高效更新
  • Fiber 架构优化渲染性能
  • 适合大规模应用

学习曲线

方面jQueryReact
入门难度⭐ 简单⭐⭐⭐ 较难
概念理解⭐ 简单⭐⭐⭐⭐ 很难
生态学习⭐⭐ 中等⭐⭐⭐⭐ 很难
调试难度⭐⭐ 中等⭐⭐⭐ 较难

适用场景

jQuery 适用场景

  • 简单的静态网站
  • 快速原型开发
  • 传统项目维护
  • 简单的交互效果
  • 不需要复杂状态管理的应用

React 适用场景

  • 大型单页应用
  • 需要高性能的应用
  • 复杂的状态管理
  • 组件化开发需求
  • 团队协作开发

实战对比示例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery 与 React 对比示例</title>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
  .container {
    max-width: 900px;
    margin: 0 auto;
    padding: 20px;
    font-family: Arial, sans-serif;
  }
  .section {
    margin-bottom: 30px;
    padding: 20px;
    background-color: #f8f9fa;
    border-radius: 8px;
  }
  h2 {
    color: #2c3e50;
    margin-top: 0;
  }
  .comparison-box {
    display: flex;
    gap: 20px;
    margin-top: 15px;
  }
  .code-box {
    flex: 1;
    padding: 15px;
    background-color: white;
    border-radius: 5px;
    border: 2px solid #ddd;
  }
  .code-box h3 {
    margin-top: 0;
    color: #3498db;
  }
  .code-box.react h3 {
    color: #61dafb;
  }
  input[type="text"] {
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    margin: 5px 0;
    width: 100%;
    box-sizing: border-box;
  }
  button {
    padding: 10px 20px;
    margin: 5px;
    background-color: #3498db;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
  }
  button:hover {
    background-color: #2980b9;
  }
  .result {
    margin-top: 10px;
    padding: 10px;
    background-color: #e8f5e9;
    border-radius: 5px;
  }
  .feature-list {
    list-style: none;
    padding: 0;
  }
  .feature-list li {
    padding: 8px 0;
    border-bottom: 1px solid #eee;
  }
  .feature-list li:last-child {
    border-bottom: none;
  }
  .tag {
    display: inline-block;
    padding: 3px 8px;
    margin-right: 5px;
    border-radius: 3px;
    font-size: 12px;
    color: white;
  }
  .tag.jquery { background-color: #0769ad; }
  .tag.react { background-color: #61dafb; }
  .todo-item {
    padding: 8px;
    margin: 5px 0;
    background-color: white;
    border-radius: 3px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .todo-item button {
    padding: 5px 10px;
    margin: 0;
    background-color: #e74c3c;
  }
  .todo-item button:hover {
    background-color: #c0392b;
  }
</style>
</head>
<body>

<div class="container">
  <h1>jQuery 与 React 框架对比</h1>

  <div class="section">
    <h2>核心特性对比</h2>
    <div class="comparison-box">
      <div class="code-box">
        <h3>jQuery</h3>
        <ul class="feature-list">
          <li><span class="tag jquery">直接 DOM</span> 手动操作元素</li>
          <li><span class="tag jquery">命令式</span> 告诉浏览器如何做</li>
          <li><span class="tag jquery">简单直观</span> 学习曲线平缓</li>
          <li><span class="tag jquery">灵活自由</span> 无强制规范</li>
          <li><span class="tag jquery">插件生态</span> 丰富的第三方库</li>
        </ul>
      </div>
      <div class="code-box react">
        <h3>React</h3>
        <ul class="feature-list">
          <li><span class="tag react">虚拟 DOM</span> 高效渲染更新</li>
          <li><span class="tag react">声明式</span> 描述想要什么</li>
          <li><span class="tag react">组件化</span> 高度复用</li>
          <li><span class="tag react">单向数据流</span> 数据流向清晰</li>
          <li><span class="tag react">生态完善</span> 工具链成熟</li>
        </ul>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>Todo List 对比</h2>
    <div class="comparison-box">
      <div class="code-box">
        <h3>jQuery 实现</h3>
        <input type="text" id="jqueryInput" placeholder="输入待办事项">
        <button onclick="addJQueryTodo()">添加</button>
        <div id="jqueryTodoList"></div>
      </div>
      <div class="code-box react">
        <h3>React 实现</h3>
        <div id="reactTodoApp"></div>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>计数器对比</h2>
    <div class="comparison-box">
      <div class="code-box">
        <h3>jQuery 实现</h3>
        <button onclick="incrementJQuery()">增加</button>
        <button onclick="decrementJQuery()">减少</button>
        <div class="result" id="jqueryCounter">0</div>
      </div>
      <div class="code-box react">
        <h3>React 实现</h3>
        <div id="reactCounterApp"></div>
      </div>
    </div>
  </div>

  <div class="section">
    <h2>表单处理对比</h2>
    <div class="comparison-box">
      <div class="code-box">
        <h3>jQuery 实现</h3>
        <form id="jqueryForm">
          <input type="text" id="jqueryName" placeholder="姓名">
          <input type="email" id="jqueryEmail" placeholder="邮箱">
          <button type="submit">提交</button>
        </form>
        <div id="jqueryFormResult" class="result"></div>
      </div>
      <div class="code-box react">
        <h3>React 实现</h3>
        <div id="reactFormApp"></div>
      </div>
    </div>
  </div>
</div>

<script>
// jQuery 实现
$(document).ready(function() {
  // Todo List
  var jqueryTodos = [];
  
  window.addJQueryTodo = function() {
    var input = $("#jqueryInput");
    var text = input.val().trim();
    if (text) {
      jqueryTodos.push(text);
      input.val("");
      renderJQueryTodos();
    }
  };

  function renderJQueryTodos() {
    var html = "";
    jqueryTodos.forEach(function(todo, index) {
      html += `
        <div class="todo-item">
          <span>${todo}</span>
          <button onclick="removeJQueryTodo(${index})">删除</button>
        </div>
      `;
    });
    $("#jqueryTodoList").html(html);
  }

  window.removeJQueryTodo = function(index) {
    jqueryTodos.splice(index, 1);
    renderJQueryTodos();
  };

  // 计数器
  var jqueryCount = 0;
  
  window.incrementJQuery = function() {
    jqueryCount++;
    $("#jqueryCounter").text(jqueryCount);
  };

  window.decrementJQuery = function() {
    jqueryCount--;
    $("#jqueryCounter").text(jqueryCount);
  };

  // 表单处理
  $("#jqueryForm").submit(function(e) {
    e.preventDefault();
    var name = $("#jqueryName").val();
    var email = $("#jqueryEmail").val();
    $("#jqueryFormResult").html(`
      <p><strong>姓名:</strong>${name}</p>
      <p><strong>邮箱:</strong>${email}</p>
    `);
  });
});

// React 实现
const { useState } = React;

// Todo App
function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, input]);
      setInput('');
    }
  };

  const removeTodo = (index) => {
    setTodos(todos.filter((_, i) => i !== index));
  };

  return React.createElement('div', null,
    React.createElement('input', {
      type: 'text',
      value: input,
      onChange: (e) => setInput(e.target.value),
      placeholder: '输入待办事项'
    }),
    React.createElement('button', { onClick: addTodo }, '添加'),
    ...todos.map((todo, index) =>
      React.createElement('div', { className: 'todo-item', key: index },
        React.createElement('span', null, todo),
        React.createElement('button', { onClick: () => removeTodo(index) }, '删除')
      )
    )
  );
}

// Counter App
function CounterApp() {
  const [count, setCount] = useState(0);

  return React.createElement('div', null,
    React.createElement('button', { onClick: () => setCount(count + 1) }, '增加'),
    React.createElement('button', { onClick: () => setCount(count - 1) }, '减少'),
    React.createElement('div', { className: 'result' }, count)
  );
}

// Form App
function FormApp() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [submitted, setSubmitted] = useState(false);

  const handleSubmit = (e) => {
    e.preventDefault();
    setSubmitted(true);
  };

  return React.createElement('div', null,
    React.createElement('form', { onSubmit: handleSubmit },
      React.createElement('input', {
        type: 'text',
        value: name,
        onChange: (e) => setName(e.target.value),
        placeholder: '姓名'
      }),
      React.createElement('input', {
        type: 'email',
        value: email,
        onChange: (e) => setEmail(e.target.value),
        placeholder: '邮箱'
      }),
      React.createElement('button', { type: 'submit' }, '提交')
    ),
    submitted && React.createElement('div', { className: 'result' },
      React.createElement('p', null,
        React.createElement('strong', null, '姓名:'),
        name
      ),
      React.createElement('p', null,
        React.createElement('strong', null, '邮箱:'),
        email
      )
    )
  );
}

// 渲染 React 应用
ReactDOM.createRoot(document.getElementById('reactTodoApp')).render(React.createElement(TodoApp));
ReactDOM.createRoot(document.getElementById('reactCounterApp')).render(React.createElement(CounterApp));
ReactDOM.createRoot(document.getElementById('reactFormApp')).render(React.createElement(FormApp));
</script>

</body>
</html>

选择建议

选择 jQuery 的情况

  • 项目规模小,需求简单
  • 需要快速原型验证
  • 团队成员对现代框架不熟悉
  • 维护传统项目
  • 不需要复杂状态管理

选择 React 的情况

  • 构建大型单页应用
  • 需要高性能渲染
  • 复杂的状态管理需求
  • 组件化开发
  • 团队协作开发

总结

jQuery 和 React 代表了前端开发的两个时代。jQuery 以简单直接的方式解决了 DOM 操作问题,适合小规模应用;React 通过虚拟 DOM 和组件化思想,为大规模应用提供了完善的解决方案。选择哪种技术,应该基于项目规模、团队技术能力和长期维护需求来决定。