在前端开发领域,待办事项列表(Todo List)是一个经典且常见的项目类型,它不仅能帮助开发者巩固基础技能,也是展示不同前端技术实现方式的绝佳载体。
本文将对比使用原生 JavaScript 和 React 框架实现待办事项列表项目的差异,从项目结构、技术栈、功能实现细节等多个维度展开分析,探讨两种实现方式的优缺点。
一、项目概述
todoListNative 项目(原生 JavaScript项目)
todoListNative 项目采用原生 HTML、CSS 和 JavaScript 构建,是最基础的前端开发模式。在项目结构上,HTML 文件负责页面的结构搭建,定义页面中待办事项的展示框架;CSS 文件用于样式设计,赋予待办事项列表美观的视觉效果;而核心功能则由 JavaScript 文件script.js来实现。这种方式没有复杂的构建工具和框架依赖,开发者直接操作 DOM 元素,直观地控制页面内容的展示与交互,非常适合初学者理解前端开发的基本原理。
todoListComponents 项目(React 框架项目)
todoListComponents 项目基于 React 框架,并借助 Vite 构建工具进行开发。React 作为流行的前端 JavaScript 库,采用组件化的开发模式,将整个待办事项列表拆分为多个独立的组件,每个组件负责特定的功能和 UI 展示。App.jsx作为项目的核心组件文件,管理着整个应用的状态和数据流。Vite 则提供了快速的开发服务器和高效的构建能力,能够显著提升开发效率。这种技术栈组合适合开发中大型的前端应用,便于代码的维护和扩展。
二、实现细节对比
1. 任务添加功能
在原生 JavaScript 的script.js中,实现任务添加功能时,需要通过document.getElementById等方法获取页面中的输入框和列表元素,然后创建新的 DOM 节点,将用户输入的任务内容添加到列表中。例如,当用户点击添加按钮时,通过监听按钮的click事件,获取输入框的值,再使用createElement和appendChild方法将新任务添加到页面上。这种方式直接操作 DOM,每一次添加任务都需要手动更新页面结构。具体代码如下:
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="taskInput">
<button id="addButton">添加任务</button>
<ul id="taskList"></ul>
<script src="script.js"></script>
</body>
</html>
// script.js
const addButton = document.getElementById('addButton');
const taskInput = document.getElementById('taskInput');
const taskList = document.getElementById('taskList');
addButton.addEventListener('click', function () {
const taskText = taskInput.value;
if (taskText.trim()!== '') {
const li = document.createElement('li');
li.textContent = taskText;
taskList.appendChild(li);
taskInput.value = '';
}
});
而在 React 的App.jsx中,任务添加功能借助状态管理来实现。定义一个状态变量存储待办事项列表,当用户输入任务并点击添加按钮时,通过setState(在 React hooks 中使用useState的更新函数)更新状态,React 会自动根据状态的变化重新渲染相关组件,无需开发者手动操作 DOM。这种声明式的编程方式,使得代码逻辑更加清晰,开发效率更高。具体代码如下:
// App.jsx
import React, { useState } from'react';
function App() {
const [tasks, setTasks] = useState([]);
const [newTask, setNewTask] = useState('');
const handleAddTask = () => {
if (newTask.trim()!== '') {
setTasks([...tasks, newTask]);
setNewTask('');
}
};
return (
<div>
<input
type="text"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
/>
<button onClick={handleAddTask}>添加任务</button>
<ul>
{tasks.map((task, index) => (
<li key={index}>{task}</li>
))}
</ul>
</div>
);
}
export default App;
2. 任务删除功能
原生 JavaScript 实现任务删除,通常是为每个任务项添加删除按钮,并为按钮绑定click事件。在事件处理函数中,通过parentNode.removeChild等方法直接从 DOM 树中移除对应的任务节点。但这种方式需要开发者精确管理 DOM 元素的关系,当页面结构复杂时,容易出现错误。具体代码如下:
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" id="taskInput">
<button id="addButton">添加任务</button>
<ul id="taskList"></ul>
<script src="script.js"></script>
</body>
</html>
// script.js
const addButton = document.getElementById('addButton');
const taskInput = document.getElementById('taskInput');
const taskList = document.getElementById('taskList');
addButton.addEventListener('click', function () {
const taskText = taskInput.value;
if (taskText.trim()!== '') {
const li = document.createElement('li');
li.textContent = taskText;
const deleteButton = document.createElement('button');
deleteButton.textContent = '删除';
deleteButton.addEventListener('click', function () {
li.parentNode.removeChild(li);
});
li.appendChild(deleteButton);
taskList.appendChild(li);
taskInput.value = '';
}
});
React 中,删除任务同样是通过更新状态来触发重新渲染。当点击删除按钮时,修改存储待办事项的状态数组,移除对应的任务元素,React 会根据新的状态自动更新页面,将被删除的任务从 UI 中移除。由于 React 采用虚拟 DOM 技术,它会高效地计算出实际需要更新的 DOM 部分,减少不必要的 DOM 操作,提升性能。具体代码如下:
// App.jsx
import React, { useState } from'react';
function App() {
const [tasks, setTasks] = useState([]);
const [newTask, setNewTask] = useState('');
const handleAddTask = () => {
if (newTask.trim()!== '') {
setTasks([...tasks, newTask]);
setNewTask('');
}
};
const handleDeleteTask = (index) => {
const newTasks = [...tasks];
newTasks.splice(index, 1);
setTasks(newTasks);
};
return (
<div>
<input
type="text"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
/>
<button onClick={handleAddTask}>添加任务</button>
<ul>
{tasks.map((task, index) => (
<li key={index}>
{task}
<button onClick={() => handleDeleteTask(index)}>删除</button>
</li>
))}
</ul>
</div>
);
}
export default App;
3. 标记任务完成功能
使用原生 JavaScript 标记任务完成,一般是通过为任务项添加点击事件,在事件处理函数中修改任务项的 CSS 样式,比如添加删除线、改变颜色等,以此表示任务已完成。这种实现方式耦合度较高,样式修改和逻辑处理混杂在一起。
React 实现该功能时,同样是基于状态的改变。定义一个布尔类型的状态来表示任务是否完成,当任务被点击时,更新该状态。然后在组件的渲染逻辑中,根据状态值来决定任务项的样式,例如通过三元表达式动态添加 CSS 类名,实现样式的切换。这种方式将数据和视图进行了更好的分离,代码更易于维护。
三、优缺点分析
1. 原生 JavaScript 的优缺点
原生 JavaScript 实现待办事项列表的优点在于入门门槛低,没有框架和工具的学习成本,非常适合初学者理解 HTML、CSS 和 JavaScript 的基本原理和交互逻辑,能够帮助开发者掌握 DOM 操作、事件监听等核心前端技能。但它的缺点也很明显,随着项目规模的扩大,代码会变得冗长且难以维护,因为所有的逻辑和 DOM 操作都混杂在一起,并且没有有效的状态管理机制,对于复杂交互和数据更新的处理效率较低。
2. React 的优缺点
React 的优势在于其组件化开发模式,使得代码具有良好的封装性和复用性,便于团队协作开发和项目的长期维护。通过虚拟 DOM 和高效的 Diff 算法,React 能够快速准确地更新页面,提升应用的性能。同时,React 拥有丰富的生态系统,大量的第三方库和工具可以帮助开发者快速实现各种功能。然而,使用 React 需要学习其特有的语法和概念,如 JSX 语法、状态管理、生命周期函数(或 hooks)等,对于初学者来说有一定的学习曲线。此外,引入 React 框架和构建工具会增加项目的初始加载时间和打包体积。
四、总结与建议
原生 JavaScript 和 React 实现待办事项列表各有千秋。原生 JavaScript 适合前端入门学习、小型且逻辑简单的项目开发,或是对性能要求不高且不需要频繁更新的静态页面。它能让开发者深入理解前端底层原理,打好坚实的基础。
而 React 则更适合开发中大型、交互复杂、需要频繁更新数据和状态管理的前端应用。在企业级项目开发、团队协作场景下,React 的组件化和高效的状态管理机制能够极大地提升开发效率和代码的可维护性。
在实际项目选择中,开发者应根据项目的规模、复杂度、性能要求以及团队成员的技术水平等因素综合考虑,合理选择合适的技术方案,从而高效地完成前端开发任务。