喔唷网 - 网络从业者技术信息综合门户!

当前位置: 主页 > 教程技术 > 编程语言 > javascript

JavaScript 项目实战 从菜鸟到全栈的蜕变之旅

时间 : 2025-04-23 12:24来源 : 喔唷网作者 : 喔唷网点击 :
欢迎来到编程的实战训练营!这一章我们将把前面学到的所有知识融会贯通,打造四个真实项目。就像从烹饪学校毕业前需要完成几道大菜一样,这些项目将成为你的"毕业作品集"。 13.1 待办事项应用

欢迎来到编程的实战训练营!这一章我们将把前面学到的所有知识融会贯通,打造四个真实项目。就像从烹饪学校毕业前需要完成几道大菜一样,这些项目将成为你的"毕业作品集"。

13.1 待办事项应用 - 你的第一个"全栈"应用

项目目标:一个可以CRUD(增删改查)任务的待办清单

// 数据结构设计
let todos = [
  { id: 1, text: "学习JavaScript", completed: false },
  { id: 2, text: "买菜", completed: true }
];

// 核心功能实现
class TodoApp {
  constructor() {
    this.todos = JSON.parse(localStorage.getItem('todos')) || [];
    this.render();
  }

  addTodo(text) {
    this.todos.push({
      id: Date.now(),
      text,
      completed: false
    });
    this._save();
  }

  toggleTodo(id) {
    const todo = this.todos.find(t => t.id === id);
    if (todo) todo.completed = !todo.completed;
    this._save();
  }

  deleteTodo(id) {
    this.todos = this.todos.filter(t => t.id !== id);
    this._save();
  }

  _save() {
    localStorage.setItem('todos', JSON.stringify(this.todos));
    this.render();
  }

  render() {
    const list = document.getElementById('todo-list');
    list.innerHTML = this.todos.map(todo => `
      <li class="${todo.completed ? 'completed' : ''}">
        <input type="checkbox" ${todo.completed ? 'checked' : ''} 
               onchange="app.toggleTodo(${todo.id})">
        <span>${todo.text}</span>
        <button onclick="app.deleteTodo(${todo.id})">删除</button>
      </li>
    `).join('');
  }
}

const app = new TodoApp();

// 添加新任务
document.getElementById('add-btn').addEventListener('click', () => {
  const input = document.getElementById('todo-input');
  if (input.value.trim()) {
    app.addTodo(input.value.trim());
    input.value = '';
  }
});

技术要点

  • 使用Class组织代码
  • localStorage持久化数据
  • 事件委托优化性能
  • 模板字符串生成HTML

13.2 天气预报应用 - 对接真实API

项目目标:通过API获取并显示天气数据

// 使用Fetch API获取数据
async function getWeather(city) {
  try {
    const response = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=YOUR_API_KEY&units=metric&lang=zh_cn`
    );
    const data = await response.json();
    
    if (data.cod === 200) {
      displayWeather(data);
    } else {
      throw new Error(data.message);
    }
  } catch (error) {
    showError(error.message);
  }
}

function displayWeather(data) {
  const weatherDiv = document.getElementById('weather');
  const { name, main, weather, wind } = data;
  
  weatherDiv.innerHTML = `
    <h2>${name}天气</h2>
    <div class="weather-main">
      <img src="http://openweathermap.org/img/wn/${weather[0].icon}@2x.png">
      <span>${weather[0].description}</span>
    </div>
    <ul>
      <li>温度: ${main.temp}°C</li>
      <li>体感: ${main.feels_like}°C</li>
      <li>湿度: ${main.humidity}%</li>
      <li>风速: ${wind.speed}m/s</li>
    </ul>
  `;
}

// 获取用户位置
navigator.geolocation?.getCurrentPosition(async pos => {
  const { latitude, longitude } = pos.coords;
  const response = await fetch(
    `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=YOUR_API_KEY&units=metric`
  );
  const data = await response.json();
  displayWeather(data);
});

// 搜索城市
document.getElementById('search-btn').addEventListener('click', () => {
  const city = document.getElementById('city-input').value.trim();
  if (city) getWeather(city);
});

技术要点

  • 异步API调用
  • Fetch API使用
  • 地理位置API
  • 错误处理

13.3 简易电商页面 - 前端+模拟后端

项目架构

project/
├── index.html
├── style.css
├── script.js
└── db.json (模拟数据库)
// 模拟后端API
class MockAPI {
  static async getProducts() {
    const response = await fetch('db.json');
    return await response.json();
  }

  static async addToCart(productId) {
    // 模拟网络延迟
    return new Promise(resolve => {
      setTimeout(() => {
        const cart = JSON.parse(localStorage.getItem('cart')) || [];
        cart.push(productId);
        localStorage.setItem('cart', JSON.stringify(cart));
        resolve();
      }, 500);
    });
  }
}

// 前端逻辑
class ECommerceApp {
  async init() {
    this.products = await MockAPI.getProducts();
    this.renderProducts();
    this.updateCartCount();
  }

  renderProducts() {
    const container = document.getElementById('products');
    container.innerHTML = this.products.map(product => `
      <div class="product">
        <img src="${product.image}">
        <h3>${product.name}</h3>
        <p>¥${product.price.toFixed(2)}</p>
        <button onclick="app.addToCart(${product.id})">加入购物车</button>
      </div>
    `).join('');
  }

  async addToCart(productId) {
    await MockAPI.addToCart(productId);
    this.updateCartCount();
    showToast('已添加到购物车');
  }

  updateCartCount() {
    const cart = JSON.parse(localStorage.getItem('cart')) || [];
    document.getElementById('cart-count').textContent = cart.length;
  }
}

const app = new ECommerceApp();
app.init();

// 模拟Toast通知
function showToast(message) {
  const toast = document.createElement('div');
  toast.className = 'toast';
  toast.textContent = message;
  document.body.appendChild(toast);
  
  setTimeout(() => {
    toast.classList.add('show');
    setTimeout(() => toast.remove(), 2000);
  }, 100);
}

技术要点

  • 前后端分离架构
  • 模拟API接口
  • Promise处理异步
  • 本地存储管理状态

13.4 数据可视化图表 - 使用Chart.js

项目目标:将数据转化为直观图表

<!-- 引入Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<canvas id="myChart" width="400" height="200"></canvas>
// 获取数据
async function fetchData() {
  const response = await fetch('sales-data.json');
  return await response.json();
}

// 创建图表
async function renderChart() {
  const data = await fetchData();
  const ctx = document.getElementById('myChart').getContext('2d');
  
  new Chart(ctx, {
    type: 'bar',
    data: {
      labels: data.map(item => item.month),
      datasets: [{
        label: '销售额 (万元)',
        data: data.map(item => item.amount),
        backgroundColor: [
          'rgba(255, 99, 132, 0.7)',
          'rgba(54, 162, 235, 0.7)',
          'rgba(255, 206, 86, 0.7)',
          'rgba(75, 192, 192, 0.7)',
          'rgba(153, 102, 255, 0.7)'
        ],
        borderWidth: 1
      }]
    },
    options: {
      responsive: true,
      scales: {
        y: {
          beginAtZero: true
        }
      },
      plugins: {
        title: {
          display: true,
          text: '2023年季度销售额'
        }
      }
    }
  });
}

// 添加交互功能
document.getElementById('chart-type').addEventListener('change', (e) => {
  const type = e.target.value;
  Chart.getChart('myChart').config.type = type;
  Chart.getChart('myChart').update();
});

renderChart();

技术要点

  • 第三方库集成
  • 数据映射与转换
  • 图表配置与自定义
  • 动态更新图表

本章总结

  1. 待办事项:掌握状态管理与本地存储
  2. 天气预报:实战API调用与数据处理
  3. 电商页面:模拟前后端交互
  4. 数据可视化:学习图表库集成

升级挑战

  1. 为待办事项添加分类标签功能
  2. 在天气应用中增加5天预报
  3. 为电商页面实现商品搜索和筛选
  4. 在图表中添加多数据集对比

开发者日志:

## Day 1
- 完成了TodoApp的基本CRUD功能
- 遇到问题:删除按钮有时不响应
- 解决方案:改用事件委托

## Day 2 
- 成功接入OpenWeatherMap API
- 发现免费API有调用限制
- 优化:添加加载状态和错误提示

## Day 3
- 实现购物车本地存储
- 挑战:模拟网络延迟
- 解决:使用setTimeout包装Promise

## Day 4
- 集成Chart.js成功
- 学习到图表配置非常灵活
- 下一步:尝试动态切换图表类型

恭喜完成实战训练!这些项目将成为你简历中的亮点。记住,真正的学习发生在调试和优化过程中。接下来我们要探索性能优化的奥秘,让你的应用飞起来!

栏目列表

关联类容

热点推荐

栏目推荐

猜你喜欢