JavaScript:从数组动态生成带复选框的任务列表并实现每日更新
在现代Web应用中,任务管理是一项常见需求。本文将介绍如何使用JavaScript从一个数组动态生成一个带有复选框的任务列表,并实现每日自动更新的功能。
实现思路
我们的实现将分为以下几个步骤:
创建一个包含任务的初始数组
编写一个函数来动态生成HTML任务列表
为每个任务添加复选框和事件监听器
实现每日自动更新任务状态的功能
添加手动刷新功能以便测试
基础HTML结构
首先,我们需要一个基本的HTML结构来容纳我们的任务列表:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态任务列表</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.task-list {
list-style-type: none;
padding: 0;
}
.task-item {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
}
.task-item:hover {
background-color: #f9f9f9;
}
.task-checkbox {
margin-right: 10px;
}
.completed {
text-decoration: line-through;
color: #888;
}
.controls {
margin: 20px 0;
}
button {
padding: 8px 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<h1>我的任务列表</h1>
<div class="controls">
<button id="refreshBtn">刷新任务</button>
<span id="lastUpdated"></span>
</div>
<ul id="taskList" class="task-list"></ul>
<script src="app.js"></script>
</body>
</html>JavaScript核心逻辑
接下来,我们编写JavaScript代码来实现动态生成任务列表和每日更新功能:
// app.js
// 初始任务数组
let tasks = [
{ id: 1, title: '完成项目报告', completed: false, lastUpdated: new Date().toISOString() },
{ id: 2, title: '学习JavaScript高级特性', completed: true, lastUpdated: new Date().toISOString() },
{ id: 3, title: '准备下周会议材料', completed: false, lastUpdated: new Date().toISOString() },
{ id: 4, title: '回复客户邮件', completed: false, lastUpdated: new Date().toISOString() }
];
// DOM元素
const taskList = document.getElementById('taskList');
const refreshBtn = document.getElementById('refreshBtn');
const lastUpdatedSpan = document.getElementById('lastUpdated');
// 初始化应用
function initApp() {
renderTasks();
setupEventListeners();
scheduleDailyUpdate();
updateLastUpdatedDisplay();
}
// 渲染任务列表
function renderTasks() {
taskList.innerHTML = '';
tasks.forEach(task => {
const taskItem = document.createElement('li');
taskItem.className = 'task-item';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'task-checkbox';
checkbox.checked = task.completed;
checkbox.dataset.id = task.id;
const taskTitle = document.createElement('span');
taskTitle.textContent = task.title;
if (task.completed) {
taskTitle.classList.add('completed');
}
taskItem.appendChild(checkbox);
taskItem.appendChild(taskTitle);
taskList.appendChild(taskItem);
});
}
// 设置事件监听器
function setupEventListeners() {
// 复选框点击事件
taskList.addEventListener('change', function(e) {
if (e.target.classList.contains('task-checkbox')) {
const taskId = parseInt(e.target.dataset.id);
toggleTaskStatus(taskId, e.target.checked);
}
});
// 刷新按钮点击事件
refreshBtn.addEventListener('click', function() {
checkAndResetTasks();
updateLastUpdatedDisplay();
});
}
// 切换任务状态
function toggleTaskStatus(taskId, isCompleted) {
const taskIndex = tasks.findIndex(task => task.id === taskId);
if (taskIndex !== -1) {
tasks[taskIndex].completed = isCompleted;
tasks[taskIndex].lastUpdated = new Date().toISOString();
// 更新UI
const taskTitle = taskList.querySelector(`input[data-id="${taskId}"]`).nextElementSibling;
if (isCompleted) {
taskTitle.classList.add('completed');
} else {
taskTitle.classList.remove('completed');
}
}
}
// 检查并重置任务(每日更新)
function checkAndResetTasks() {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
let hasChanges = false;
tasks.forEach(task => {
const lastUpdated = new Date(task.lastUpdated);
const lastUpdatedDate = new Date(lastUpdated.getFullYear(), lastUpdated.getMonth(), lastUpdated.getDate());
// 如果最后更新日期不是今天,则重置任务状态
if (lastUpdatedDate.getTime() !== today.getTime()) {
task.completed = false;
task.lastUpdated = now.toISOString();
hasChanges = true;
}
});
if (hasChanges) {
renderTasks();
}
}
// 安排每日更新
function scheduleDailyUpdate() {
const now = new Date();
const night = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0); // 第二天凌晨
const msToMidnight = night.getTime() - now.getTime();
setTimeout(() => {
checkAndResetTasks();
updateLastUpdatedDisplay();
// 设置每天重复
setInterval(checkAndResetTasks, 24 * 60 * 60 * 1000);
}, msToMidnight);
}
// 更新最后更新时间显示
function updateLastUpdatedDisplay() {
const now = new Date();
lastUpdatedSpan.textContent = `最后更新: ${now.toLocaleString()}`;
}
// 启动应用
initApp();代码解析
数据结构设计
我们使用一个对象数组来存储任务信息,每个任务包含以下属性:
id: 任务的唯一标识符title: 任务标题completed: 任务完成状态lastUpdated: 任务最后更新时间
动态生成任务列表
renderTasks() 函数负责根据任务数组动态生成HTML列表。它遍历任务数组,为每个任务创建一个列表项,包含一个复选框和任务标题。
事件处理
我们使用事件委托来处理复选框的点击事件,这样可以避免为每个复选框单独绑定事件监听器。当用户点击复选框时,toggleTaskStatus() 函数会更新对应任务的状态。
每日更新机制
scheduleDailyUpdate() 函数计算当前时间到第二天凌晨的毫秒数,然后设置一个定时器。当到达第二天凌晨时,它会调用 checkAndResetTasks() 函数来检查并重置所有任务的完成状态。
checkAndResetTasks() 函数会比较每个任务的最后更新日期和当前日期,如果发现不匹配,就将该任务标记为未完成,并更新最后更新时间。
扩展功能
这个基础实现可以进一步扩展,以下是一些可能的改进方向:
添加本地存储支持,使任务列表在页面刷新后仍然保留
实现任务的添加、编辑和删除功能
添加任务分类和优先级
实现更复杂的更新策略,如每周或每月重置
添加用户通知功能,提醒用户每日任务已重置
总结
本文介绍了如何使用JavaScript动态生成带复选框的任务列表,并实现每日自动更新功能。通过合理使用数组操作、DOM操作和定时器,我们可以创建一个简单但实用的任务管理系统。这个示例展示了前端开发中常见的数据绑定、事件处理和定时任务等技术。