JavaScript 的 Web APIs 入门到实战全总结(day7):从数据处理到交互落地的全链路实战(附实战案例代码)

经过前 6 天的基础铺垫,今天我们将聚焦 Web 开发的核心链路:数据处理→DOM 操作→交互实现→数据持久化→表单验证。这是前端开发的 "闭环能力",也是从 "能写代码" 到 "能做项目" 的关键跨越。本文将通过 7 个递进式实战案例,帮你打通全链路技能。

一、JavaScript 数组操作:数据处理的核心能力

数组是处理数据的基础载体,无论是接口返回数据还是本地交互数据,都需要通过数组方法高效处理。

实战案例:待办事项数据管理(增删改查 + 筛选)

javascript 复制代码
// 初始待办数据
let todos = [
  { id: 1, content: '学习数组方法', completed: false },
  { id: 2, content: '练习DOM操作', completed: true },
  { id: 3, content: '实现本地存储', completed: false }
];

// 1. 新增待办(push)
function addTodo(content) {
  if (!content.trim()) return;
  todos.push({
    id: Date.now(), // 时间戳作为唯一ID
    content,
    completed: false
  });
}

// 2. 删除待办(filter)
function deleteTodo(id) {
  todos = todos.filter(todo => todo.id !== id);
}

// 3. 切换完成状态(map)
function toggleTodo(id) {
  todos = todos.map(todo => 
    todo.id === id ? { ...todo, completed: !todo.completed } : todo
  );
}

// 4. 筛选待办(filter)
function filterTodos(status) {
  if (status === 'all') return [...todos];
  if (status === 'active') return todos.filter(todo => !todo.completed);
  if (status === 'completed') return todos.filter(todo => todo.completed);
}

// 测试
addTodo('学习本地存储');
toggleTodo(1);
console.log('筛选未完成:', filterTodos('active'));

核心方法解析

  • push():尾部添加元素(适合新增数据)
  • filter():筛选符合条件的元素(适合删除、筛选场景)
  • map():批量处理元素(适合更新状态)
  • 扩展运算符...:复制对象避免引用污染

二、DOM 基础全解析:页面渲染的核心逻辑

DOM 操作是数据可视化的桥梁,掌握 "数据→DOM" 的映射逻辑是前端开发的基本功。

实战案例:动态渲染待办列表(数据驱动 DOM)

html 复制代码
<div class="todo-app">
  <input type="text" id="todoInput" placeholder="请输入待办事项">
  <button id="addBtn">添加</button>
  <div class="filters">
    <button data-filter="all">全部</button>
    <button data-filter="active">未完成</button>
    <button data-filter="completed">已完成</button>
  </div>
  <ul id="todoList"></ul>
</div>

<script>
// 承接上文的todos数组和方法
let currentFilter = 'all';

// 渲染函数:核心是将数组数据转化为DOM
function renderTodos() {
  const todoList = document.getElementById('todoList');
  const filteredTodos = filterTodos(currentFilter);
  
  // 清空列表(避免重复渲染)
  todoList.innerHTML = '';
  
  // 遍历数据生成DOM
  filteredTodos.forEach(todo => {
    const li = document.createElement('li');
    li.innerHTML = `
      <input type="checkbox" ${todo.completed ? 'checked' : ''} 
             data-id="${todo.id}" class="toggle">
      <span style="text-decoration: ${todo.completed ? 'line-through' : 'none'}">
        ${todo.content}
      </span>
      <button data-id="${todo.id}" class="delete">删除</button>
    `;
    todoList.appendChild(li);
  });
}

// 初始渲染
renderTodos();

// 添加按钮事件(输入→新增→重新渲染)
document.getElementById('addBtn').addEventListener('click', () => {
  const input = document.getElementById('todoInput');
  addTodo(input.value);
  input.value = '';
  renderTodos(); // 关键:数据变化后重新渲染
});
</script>

DOM 操作核心逻辑

  1. 定义render()函数,作为数据→DOM 的映射入口
  2. 每次数据变化(增删改)后调用render(),保证视图与数据一致
  3. 利用data-*属性存储数据 ID,便于后续交互关联

三、事件监听与交互实现:让页面 "活" 起来

交互是前端的灵魂,通过事件监听将用户操作转化为数据变化,再通过渲染函数更新视图。

实战案例:待办列表交互功能完善

javascript 复制代码
// 事件委托:利用父元素监听所有子元素事件(减少绑定次数)
document.getElementById('todoList').addEventListener('click', (e) => {
  const target = e.target;
  const id = Number(target.dataset.id); // 获取data-id并转为数字
  
  // 1. 点击复选框切换状态
  if (target.classList.contains('toggle')) {
    toggleTodo(id);
    renderTodos();
  }
  
  // 2. 点击删除按钮删除待办
  if (target.classList.contains('delete')) {
    deleteTodo(id);
    renderTodos();
  }
});

// 筛选按钮交互
document.querySelector('.filters').addEventListener('click', (e) => {
  if (e.target.tagName === 'BUTTON') {
    currentFilter = e.target.dataset.filter;
    renderTodos(); // 切换筛选条件后重新渲染
  }
});

事件监听技巧

  • 事件委托:将子元素事件绑定到父元素(如ul监听li的点击),支持动态元素
  • dataset:通过data-*属性传递数据(如 ID、筛选条件),避免硬编码
  • 事件处理流程:用户操作→事件触发→数据更新→重新渲染

四、事件流与高效交互:解决复杂场景的交互冲突

事件流(捕获→目标→冒泡)是处理嵌套元素交互的关键,合理利用可避免冲突。

实战案例:弹窗组件的事件流控制

javascript 复制代码
<div id="modal" style="display: none;">
  <div class="modal-mask"></div>
  <div class="modal-content">
    <h3>编辑待办</h3>
    <input type="text" id="editInput">
    <button id="confirmBtn">确认</button>
    <button id="cancelBtn">取消</button>
  </div>
</div>

<script>
// 点击待办文本打开弹窗(新增事件委托逻辑)
document.getElementById('todoList').addEventListener('click', (e) => {
  if (e.target.tagName === 'SPAN') {
    const id = Number(e.target.parentNode.dataset.id);
    const todo = todos.find(t => t.id === id);
    document.getElementById('editInput').value = todo.content;
    document.getElementById('modal').style.display = 'block';
    
    // 确认编辑(利用事件冒泡,点击确认后关闭弹窗)
    document.getElementById('confirmBtn').onclick = () => {
      todo.content = document.getElementById('editInput').value;
      document.getElementById('modal').style.display = 'none';
      renderTodos();
    };
  }
});

// 点击遮罩层关闭弹窗
document.querySelector('.modal-mask').addEventListener('click', () => {
  document.getElementById('modal').style.display = 'none';
});

// 关键:阻止弹窗内容区的事件冒泡(避免点击内部触发遮罩层关闭)
document.querySelector('.modal-content').addEventListener('click', (e) => {
  e.stopPropagation();
});
</script>

事件流应用

  • e.stopPropagation():阻止事件冒泡(如弹窗内容区点击不触发遮罩层事件)
  • 事件冒泡利用:子元素事件可被父元素捕获(如弹窗按钮点击可被外层监听)

五、DOM 进阶与日期对象:增强页面信息展示

结合日期对象可实现动态时间展示,提升页面实用性。

实战案例:显示待办创建时间

javascript 复制代码
// 改造addTodo方法,添加创建时间
function addTodo(content) {
  if (!content.trim()) return;
  todos.push({
    id: Date.now(),
    content,
    completed: false,
    createTime: new Date() // 记录创建时间
  });
}

// 改造renderTodos,显示格式化时间
function renderTodos() {
  // ... 省略部分代码
  filteredTodos.forEach(todo => {
    // 格式化时间:YYYY-MM-DD HH:MM
    const timeStr = `${todo.createTime.getFullYear()}-${
      String(todo.createTime.getMonth() + 1).padStart(2, '0')}-${
      String(todo.createTime.getDate()).padStart(2, '0')} ${
      String(todo.createTime.getHours()).padStart(2, '0')}:${
      String(todo.createTime.getMinutes()).padStart(2, '0')
    }`;
    
    li.innerHTML = `
      <!-- 省略其他内容 -->
      <span class="time">创建于:${timeStr}</span>
    `;
  });
}

日期对象常用方法

  • getFullYear():获取年份
  • getMonth():获取月份(0-11,需 + 1)
  • padStart(2, '0'):补零处理(如 3→"03")

六、本地存储 + BOM 操作:解决数据丢失痛点

页面刷新后数据丢失是常见问题,localStorage可实现数据持久化,结合 BOM 操作优化体验。

实战案例:待办数据持久化存储

javascript 复制代码
// 1. 从localStorage加载数据
function loadTodos() {
  const saved = localStorage.getItem('todos');
  if (saved) {
    // 注意:localStorage存储的是字符串,需解析为对象,且日期需重新实例化
    todos = JSON.parse(saved).map(todo => ({
      ...todo,
      createTime: new Date(todo.createTime)
    }));
  }
}

// 2. 保存数据到localStorage
function saveTodos() {
  localStorage.setItem('todos', JSON.stringify(todos));
}

// 3. 改造所有修改数据的方法,添加保存逻辑
function addTodo(content) {
  // ... 原有逻辑
  saveTodos(); // 新增后保存
}

function deleteTodo(id) {
  // ... 原有逻辑
  saveTodos(); // 删除后保存
}

// 4. 页面加载时自动加载数据
window.addEventListener('load', () => {
  loadTodos();
  renderTodos();
});

// 5. BOM操作:监听页面关闭事件提示
window.addEventListener('beforeunload', (e) => {
  e.preventDefault();
  e.returnValue = '确定要离开吗?未完成的待办会自动保存';
});

本地存储要点

  • localStorage只能存储字符串,需用JSON.stringify()/JSON.parse()转换
  • 日期对象序列化后会变为字符串,需重新实例化new Date()
  • window.onload:页面加载完成后执行初始化操作

七、正则表达式:表单验证实战

表单验证是前端必备能力,正则表达式可高效验证输入合法性。

实战案例:待办输入框验证

html 复制代码
<!-- 改造输入框,添加验证提示 -->
<input type="text" id="todoInput" placeholder="请输入待办事项(至少3个字符,不包含特殊符号)">
<p id="errorMsg" style="color: red; display: none;"></p>

<script>
// 验证待办内容的正则:仅允许中英文、数字、空格和常见标点
const todoReg = /^[\u4e00-\u9fa5a-zA-Z0-9\s,.,。]{3,}$/;

// 改造添加按钮事件,加入验证
document.getElementById('addBtn').addEventListener('click', () => {
  const input = document.getElementById('todoInput');
  const errorMsg = document.getElementById('errorMsg');
  const content = input.value.trim();
  
  if (!todoReg.test(content)) {
    errorMsg.textContent = '请输入至少3个字符,且不包含特殊符号';
    errorMsg.style.display = 'block';
    return;
  }
  
  // 验证通过,隐藏错误提示
  errorMsg.style.display = 'none';
  addTodo(content);
  input.value = '';
  renderTodos();
});

// 输入时实时验证
document.getElementById('todoInput').addEventListener('input', (e) => {
  const errorMsg = document.getElementById('errorMsg');
  if (todoReg.test(e.target.value.trim())) {
    errorMsg.style.display = 'none';
  }
});
</script>

正则表达式解析

  • ^[\u4e00-\u9fa5]:匹配中文字符
  • a-zA-Z0-9:匹配英文和数字
  • \s,.,。:匹配空格和常见标点
  • {3,}:至少 3 个字符
  • test():检测字符串是否符合正则规则

总结:全链路开发思维

今天的实战案例围绕 "待办应用" 展开,串联了 7 大核心技能:

  1. 数组操作 :数据的增删改查(push/filter/map
  2. DOM 操作 :数据驱动视图(render函数的核心作用)
  3. 事件交互:用户操作→数据变化→视图更新的闭环
  4. 事件流stopPropagation()解决嵌套元素冲突
  5. 日期对象:时间格式化与展示
  6. 本地存储localStorage实现数据持久化
  7. 正则表达式:表单输入合法性验证

这些技能是前端开发的 "基础设施",无论是开发 ToDo、电商、管理系统,都离不开这套核心逻辑。建议结合今天的案例,尝试扩展功能(如待办分类、优先级设置),在实践中深化理解。

相关推荐
suzumiyahr2 小时前
用awesome-digital-human-live2d创建属于自己的数字人
前端·人工智能·后端
Predestination王瀞潞2 小时前
Python __name__ 与 __main__
开发语言·python
萧曵 丶2 小时前
Python 字符串、列表、元组、字典、集合常用函数
开发语言·前端·python
申阳2 小时前
Day 10:08. 基于Nuxt开发博客项目-关于我页面开发
前端·后端·程序员
拉不动的猪2 小时前
Webpack 与 Rollup 中 Tree-shaking 的实现原理与效果
前端·webpack·rollup.js
林太白2 小时前
跟着TRAE SOLO学习两大搜索
前端·算法
yunyi2 小时前
使用go的elastic库来实现前后端模糊搜索功能
前端·后端
一枚前端小能手2 小时前
2618. 检查是否是类的对象实例(JavaScript)
前端·javascript
yong99902 小时前
MATLAB实现DLT645协议
开发语言·matlab