news 2026/4/20 1:23:53

手把手教你用Vue2和原生JS复刻蓝桥杯真题:购物车与分页列表实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用Vue2和原生JS复刻蓝桥杯真题:购物车与分页列表实战

Vue2与原生JS实战:从蓝桥杯真题到工程化项目开发

1. 项目背景与核心价值

在当今前端开发领域,Vue.js因其简洁的API和响应式数据绑定机制,已成为构建用户界面的首选框架之一。而原生JavaScript作为前端开发的基石,其重要性同样不可忽视。本文将围绕蓝桥杯Web真题中的两个经典场景——购物车功能与分页列表,展示如何将竞赛题目转化为具有工程化价值的实战项目。

为什么选择这两个场景?

  • 购物车功能涵盖了Vue2的核心特性:数据绑定、组件通信、状态管理
  • 分页列表则考验原生JS的DOM操作、事件处理和异步数据加载能力
  • 两者结合可形成完整的前端技能闭环

2. 购物车功能深度实现

2.1 Vue2项目初始化与工程配置

首先创建Vue2项目并配置必要依赖:

vue create shopping-cart cd shopping-cart npm install vuex axios --save

项目目录结构建议:

/src /components CartItem.vue ProductList.vue /store index.js App.vue main.js

2.2 状态管理设计

使用Vuex管理购物车状态,store配置示例:

// store/index.js export default new Vuex.Store({ state: { cartItems: [], products: [] }, mutations: { ADD_TO_CART(state, product) { const existingItem = state.cartItems.find(item => item.id === product.id) if (existingItem) { existingItem.quantity++ } else { state.cartItems.push({ ...product, quantity: 1 }) } }, REMOVE_FROM_CART(state, itemId) { const index = state.cartItems.findIndex(item => item.id === itemId) if (index !== -1) { if (state.cartItems[index].quantity > 1) { state.cartItems[index].quantity-- } else { state.cartItems.splice(index, 1) } } } }, actions: { async fetchProducts({ commit }) { const response = await axios.get('/api/products') commit('SET_PRODUCTS', response.data) } } })

2.3 购物车核心功能实现

商品列表组件关键代码:

<template> <div class="product-list"> <div v-for="product in products" :key="product.id" class="product-card"> <h3>{{ product.name }}</h3> <p>价格: ¥{{ product.price }}</p> <button @click="addToCart(product)">加入购物车</button> </div> </div> </template> <script> export default { computed: { products() { return this.$store.state.products } }, methods: { addToCart(product) { this.$store.commit('ADD_TO_CART', product) } } } </script>

购物车组件交互逻辑:

<template> <div class="cart"> <div v-for="item in cartItems" :key="item.id" class="cart-item"> <span>{{ item.name }} × {{ item.quantity }}</span> <button @click="decreaseQuantity(item.id)">-</button> <button @click="increaseQuantity(item.id)">+</button> </div> <p>总价: ¥{{ totalPrice }}</p> </div> </template> <script> export default { computed: { cartItems() { return this.$store.state.cartItems }, totalPrice() { return this.cartItems.reduce( (total, item) => total + item.price * item.quantity, 0 ) } }, methods: { decreaseQuantity(id) { this.$store.commit('REMOVE_FROM_CART', id) }, increaseQuantity(id) { this.$store.commit('ADD_TO_CART', this.cartItems.find(item => item.id === id)) } } } </script>

3. 原生JS分页列表实现

3.1 基础HTML结构与样式

<div class="pagination-container"> <div id="course-list" class="course-list"></div> <div class="pagination-controls"> <button id="prev-btn">上一页</button> <span id="page-indicator">第1页</span> <button id="next-btn">下一页</button> </div> </div>

3.2 数据加载与分页逻辑

class Pagination { constructor(containerId, pageSize = 5) { this.container = document.getElementById(containerId) this.pageSize = pageSize this.currentPage = 1 this.data = [] this.init() } async init() { await this.loadData() this.render() this.setupEventListeners() } async loadData() { try { const response = await fetch('/api/courses') this.data = await response.json() this.totalPages = Math.ceil(this.data.length / this.pageSize) } catch (error) { console.error('数据加载失败:', error) } } render() { const startIndex = (this.currentPage - 1) * this.pageSize const endIndex = startIndex + this.pageSize const pageData = this.data.slice(startIndex, endIndex) this.container.innerHTML = pageData.map(item => ` <div class="course-item"> <h3>${item.title}</h3> <p>${item.description}</p> <span>价格: ¥${item.price.toFixed(2)}</span> </div> `).join('') document.getElementById('page-indicator').textContent = `第${this.currentPage}页/共${this.totalPages}页` document.getElementById('prev-btn').disabled = this.currentPage === 1 document.getElementById('next-btn').disabled = this.currentPage === this.totalPages } setupEventListeners() { document.getElementById('prev-btn').addEventListener('click', () => { if (this.currentPage > 1) { this.currentPage-- this.render() } }) document.getElementById('next-btn').addEventListener('click', () => { if (this.currentPage < this.totalPages) { this.currentPage++ this.render() } }) } } // 初始化分页实例 new Pagination('course-list')

3.3 性能优化技巧

  1. 数据缓存:首次加载后缓存数据,避免重复请求
  2. 虚拟滚动:对于大数据量,实现虚拟滚动提升性能
  3. 节流处理:对分页按钮点击事件进行节流控制
// 节流函数实现 function throttle(func, limit = 300) { let lastFunc let lastRan return function() { const context = this const args = arguments if (!lastRan) { func.apply(context, args) lastRan = Date.now() } else { clearTimeout(lastFunc) lastFunc = setTimeout(function() { if ((Date.now() - lastRan) >= limit) { func.apply(context, args) lastRan = Date.now() } }, limit - (Date.now() - lastRan)) } } }

4. 工程化进阶实践

4.1 API模拟与联调

使用JSON Server快速搭建模拟API:

npm install -g json-server echo '{ "products": [ {"id": 1, "name": "Vue实战课程", "price": 299}, {"id": 2, "name": "JS高级编程", "price": 199} ], "courses": [ {"id": 1, "title": "前端基础", "description": "HTML/CSS/JS入门", "price": 99}, {"id": 2, "title": "Vue组件开发", "description": "深入理解Vue组件", "price": 129} ] }' > db.json json-server --watch db.json

4.2 错误处理与边界情况

增强分页组件的健壮性:

class Pagination { // ...其他代码... render() { if (!this.data || this.data.length === 0) { this.container.innerHTML = '<div class="empty-message">暂无数据</div>' return } // ...原有渲染逻辑... } async loadData() { try { const response = await fetch('/api/courses') if (!response.ok) throw new Error('网络响应不正常') this.data = await response.json() this.totalPages = Math.max(1, Math.ceil(this.data.length / this.pageSize)) this.currentPage = Math.min(this.currentPage, this.totalPages) } catch (error) { console.error('数据加载失败:', error) this.container.innerHTML = ` <div class="error-message"> 数据加载失败: ${error.message} <button onclick="location.reload()">重试</button> </div> ` } } }

4.3 响应式设计适配

购物车样式优化方案:

/* 移动端优先设计 */ .cart-item { display: flex; justify-content: space-between; align-items: center; padding: 12px; border-bottom: 1px solid #eee; } @media (min-width: 768px) { .cart-item { padding: 16px; } } /* 分页控件响应式 */ .pagination-controls { display: flex; justify-content: center; gap: 8px; margin-top: 20px; } @media (min-width: 576px) { .pagination-controls { gap: 16px; } }

5. 项目优化与扩展方向

5.1 性能监控指标

关键性能指标及优化建议:

指标优化目标实现方法
首次内容渲染(FCP)<1s代码分割、懒加载
交互时间(TTI)<2s减少主线程工作
总阻塞时间(TBT)<300ms优化长任务
页面大小<500KB资源压缩

5.2 可扩展架构设计

推荐的项目结构扩展:

/src /features /cart Cart.vue cart.store.js /products ProductList.vue products.store.js /shared /components Pagination.vue /utils api.js helpers.js

5.3 测试策略

为购物车功能添加单元测试:

// cart.store.spec.js import cartStore from './cart.store' describe('购物车Store', () => { beforeEach(() => { cartStore.state.cartItems = [] }) test('添加商品到购物车', () => { const product = { id: 1, name: '测试商品', price: 100 } cartStore.mutations.ADD_TO_CART(cartStore.state, product) expect(cartStore.state.cartItems).toHaveLength(1) expect(cartStore.state.cartItems[0].quantity).toBe(1) }) test('重复添加同一商品应增加数量', () => { const product = { id: 1, name: '测试商品', price: 100 } cartStore.mutations.ADD_TO_CART(cartStore.state, product) cartStore.mutations.ADD_TO_CART(cartStore.state, product) expect(cartStore.state.cartItems).toHaveLength(1) expect(cartStore.state.cartItems[0].quantity).toBe(2) }) })

6. 从竞赛到实战的思维转变

在将蓝桥杯真题转化为实际项目时,需要特别注意以下几点差异:

  1. 代码组织:竞赛代码通常集中在一个文件,而工程化项目需要模块化拆分
  2. 错误处理:实际项目必须考虑各种边界情况和错误处理
  3. 性能考量:真实用户环境下的性能优化至关重要
  4. 团队协作:代码可读性和可维护性成为重要指标
  5. 持续集成:需要建立自动化构建和测试流程

实际开发中,建议使用ESLint+Prettier保证代码风格一致,配置Husky在提交前自动运行测试,这些工程化实践能显著提升项目质量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 1:08:35

用 AR 眼镜重构生活记忆:我做了一个「空间记忆管家」智能体

用 AR 眼镜重构生活记忆&#xff1a;我做了一个「空间记忆管家」智能体 很多瞬间其实并不盛大&#xff0c;却会在未来某个时刻突然变得珍贵。比如家里一次普通的生日聚会&#xff0c;朋友坐在沙发上聊天时的笑声&#xff0c;傍晚海边一段安静的散步&#xff0c;或者旅行途中抬头…

作者头像 李华
网站建设 2026/4/20 1:07:53

如何在Python中正确使用MongoDB事务

MongoDB事务仅支持副本集或分片集群&#xff0c;单节点不支持&#xff1b;需显式传入session参数&#xff0c;超时60秒不可配置&#xff1b;writeConcern和readConcern需合理设置以保障一致性。事务只在副本集或分片集群上可用单节点 MongoDB 实例不支持事务&#xff0c;调用 s…

作者头像 李华
网站建设 2026/4/20 1:06:56

FastAPI零基础入门(纯知识点版)(附完整代码)

一、环境搭建1. 创建虚拟环境python -m venv venv2. 激活虚拟环境# Windows venv\Scripts\activate # Mac/Linux source venv/bin/activate3. 安装包pip install fastapi uvicorn二、第一个程序4. 创建main.pyfrom fastapi import FastAPIapp FastAPI()app.get("/")…

作者头像 李华