Vue电商网站项目开发总结

您所在的位置:网站首页 vue适合开发网站吗 Vue电商网站项目开发总结

Vue电商网站项目开发总结

2023-09-18 04:38| 来源: 网络整理| 查看: 265

实现的功能:

基于vue.js的知识点(webpack,Vuex,Vue-router)开发电商网站项目,实现的功能包括:商品列表按照价格、销量排序;商品列表按照品牌、价格过滤;动态的购物车,使用优惠码等。

main.js:

    路由配置(router),使用History路由模式

    状态管理(Vuex,store),设置了state、getters、mutations、actions

router.js

   路由的页面配置放在router.js文件内单独维护,设置了list(默认页面)、product/:id、cart的路由列表。

style.css

全局使用的CSS样式,在main.js中导入(import './style.css'),每个vue文件scoped的样式一同提取输出到main.css文件。

plugins:[ //重命名提取后的css文件 new ExtractTextPlugin({ filename:'[name].css', allChunks:true }), //vue-loader在15.*后的版本需要伴生VueLoaderPlugin的,否则启动报错 new VueLoaderPlugin() ]

项目根目录下views目录下放置每个路由页面的.vue文件;components目录存放公共组件(product.vue定义了每个产品框的内容);images目录存放项目用到的照片。

1.模块拆分:

    商品列表(list)用于展示相关的所有商品,具有筛选和排序两种过滤方法;筛选条件可以叠加,可以按照价格、销量等在筛选的基础上进行排序,最终筛选出符合要求的商品。

    排序为单选,初始按“默认”进行排序,价格可分为升序和降序两种排序,销量按照降序;品牌和颜色为单选,单次点击选中,再次点击取消选中;

    初次打开商品列表页请求一次远程数据(用setTimeout模拟异步,真实场景通过Ajax获取),获取到全部的商品数据,然后筛选和排序在本地完成。

    商品列表主要有两个模块,路由组件(views/list.vue),负责数据的请求、过滤相关的逻辑;商品简介组件(components/produce.vue,每个商品卡片),鼠标划过时,显示“加入购物车”的按钮;两个模块的样式都直接写在各自vue文件的中。

 

2.商品简介组件:

    每个商品的选项包括标题、价格、颜色等,为方便父子间传递,在product.vue中设置一个property:info来接收一个对象格式的数据,父级可直接将获取到的数据传递过来,省去拆分的工作。info数据结构如下:

product.js { id: 2, name: 'BeatsX 入耳式耳机', brand: 'Beats', image: '../images/2.jpeg', sales: 11000, cost: 1188, color: '白色' }

    颜色比较特殊,直接返回的中文无法对应到具体的色值,在product.vue的data选项中定义map,用于映射颜色和色值。

最终会渲染成一个标签,链接到:to定义的url(商品详情页),id作为参数通过vue-router传递。

components/product.vue

    鼠标悬浮在卡片上时会显示“加入购物车”按钮的实现是绑定@click事件,使用prevent修饰符来阻止冒泡,否则在点击按钮的同时,也会点击到标签进入详情页。

components/product.vue 加入购物车

    “加入购物车”按钮先设置了handleCart方法,通过Vuex出发mutation保存到购物车,参数为商品的id。

components/product.vue handleCart () { this.$store.commit('addCart', this.info.id); }

3.列表按照价格、销量排序(views/list.vue)

    数据部分,列表相关的数据都通过Vuex来维护,获取商品列表的数据是异步获取的,写在Vuex的actions里。(真实场景中数据应当是通过ajax从服务端获取,实例是用setTimeout来模拟异步,并用本地数据来mock);数据位置是/product.js

    main.js中导入数据,并在Vuex中声明数据列表相关的state、mutations、actions

    通过action的getProductList方法获取数据(product_data对应于product.js中的数据),由mutation的setProduction方法将数据设置到productList

main.js const store = new Vuex.Store({ state: { productList: [], cartList: [] }, mutations: { // 添加商品列表 setProductList (state, data) { state.productList = data; } } actions: { // 请求商品列表 getProductList (context) { // 真实环境通过 ajax 获取,这里用异步模拟 setTimeout(() => { context.commit('setProductList', product_data); }, 500); } } }

    数据准备好之后,再关注视图部分,在根实例app.vue中挂载路由并设置导航条:

    数据cartList是购物车中添加的商品;路由视图挂载了所有的路由组件

app.vue 电商网站示例 购物车 {{ cartList.length }} export default { computed: { cartList () { return this.$store.state.cartList; } } }

    商品列表list.vue在初始化时调用Vuex的action触发请求数据操作,并设置计算属性从Vuex中读取数据productList

list.vue import Product from '../components/product.vue'; export default { components: { Product }, computed: { list () { // 从Vuex获取商品列表数据 return this.$store.state.productList; } mounted () { // 初始化时,通过Vuex的action请求数据 this.$store.dispatch('getProductList'); } }

    实现按照价格、销量排序,不能直接使用数据list,也不能直接重置list(过滤不是一次性的,不能破坏原数据,否则无法复原),所以用计算属性来动态返回过滤后的数据。

    计算属性 filteredAndOrderedList将list进一步过滤,返回筛选、排序后的数据,排序依据于data:order;排序直接使用javas数组的sort方法对前后两个值比较大小;把循环的数据由list改为 filteredAndOrderedList 后,显示的就是过滤后的数据,之后在视图中通过操作改变order。

list.vue filteredAndOrderedList () { // 复制原始数据 let list = [...this.list]; // 按品牌过滤 if (this.filterBrand !== '') { list = list.filter(item => item.brand === this.filterBrand); } // 按颜色过滤 if (this.filterColor !== '') { list = list.filter(item => item.color === this.filterColor); } // 排序 if (this.order !== '') { if (this.order === 'sales') { list = list.sort((a, b) => b.sales - a.sales); } else if (this.order === 'cost-desc') { list = list.sort((a, b) => b.cost - a.cost); } else if (this.order === 'cost-asc') { list = list.sort((a, b) => a.cost - b.cost); } } return list; }

    需要在list.vue的模板里加入排序按钮,并绑定相关事件。“默认”和“销量”只能单词点击,“价格”按钮可以点击切换为升序和降序两种状态;通过判断order的状态,给3个按钮绑定class(.on)来高亮显示当前排序的按钮。

list.vue 排序: 默认 销量 ↓ 价格 ↑ ↓

4.列表按照品牌、颜色筛选

    首先准备数据,品牌和颜色的数据可以作为getters从Vuex的productList里遍历获取。使用map方法把productList(product.js中数据)里的brand或color数据过滤出来,然后用getFilterArray方法对数组去重;getters里的brands和colors依赖数据productList,与计算属性原理类似,只要维护好productList,brands和colors就可以自动更新。

main.js //数组去重 function getFilterArray (array) { const res = []; const json = {}; for (let i = 0; i < array.length; i++){ const _self = array[i]; if(!json[_self]){ res.push(_self); json[_self] = 1; } } return res; } // 数据过滤 const store = new Vuex.Store({ state: { productList: [], }, getters: { brands: state => { const brands = state.productList.map(item => item.brand); return getFilterArray(brands); }, colors: state => { const colors = state.productList.map(item => item.color); return getFilterArray(colors); } } }

    然后在list.vue中把Vuex里的品牌和颜色数据引入,完成列表的过滤;

list.vue export default { components: { Product }, computed: { list () { // 从Vuex获取商品列表数据 return this.$store.state.productList; }, brands () { return this.$store.getters.brands; }, colors () { return this.$store.getters.colors; } } }

    品牌和颜色都是单选(单次点击选中,再次点击取消选中),可以协同过滤。

5.商品详情页

    views目录下新建product.vue文件作为“商品详情页”;商品详情的路由接收一个参数id,以id作为接口的索引,查询出所有相关的数据;为了使业务更好的解耦,从商品列表页跳转至详情页时,只传递商品的id,不需要其他数据,其他相信的数据重新获取;通过$route可以获取当前路由的参数,并在页面初始化是请求该商品的数据,示例使用setTimeout来模拟异步,真实场景下应该通过Ajax来请求数据。示例从数据源(product.js)里通过数组的find()方法拿到指定id的数据,完成数据mock。

views/product.vue // 导入本地数据做匹配用,真实场景不需要 import product_data from '../product.js'; export default { data () { return { // 获取当前路由中的参数 id: parseInt(this.$route.params.id), product: null } }, methods: { getProduct () { // 真实环境通过 ajax 获取,这里用异步模拟 setTimeout(() => { this.product = product_data.find(item => item.id === this.id); }, 500); }, // 加入购物车 handleAddToCart () { this.$store.commit('addCart', this.id); } }, mounted () { this.getProduct(); } }

    将数据写入模板,示例将10张产品的图片依次展示作为商品的内容。

6.购物车

    购物车中需要完成结算,每件商品至少选择一件,可以删除,每件商品有价格小计;可以使用优惠码,使用后在总价的基础上减少500元;总价会根据购买商品的数量动态计算;右上角的 购物车入口也会显示当前购物车商品的数量。

    商品加入购物车是通过Vuex来完成的,在main.js中,先定义Vuex中的state和mutations;数组cartList中保存购物车记录,数据格式为数组,包含商品id和购买数量两个数据(遵循解耦,其他信息通过id间接获取)。

main.js const store = new Vuex.Store({ state: { productList: [], cartList: [] }, mutations: { addCart (state, id) { // 先判断购物车是否已有,如果有,数量+1 const isAdded = state.cartList.find(item => item.id === id); if (isAdded) { isAdded.count ++; } else { state.cartList.push({ id: id, count: 1 }) } } } }

    购物车数据准备完毕,显示数据并动态修改数据;在app.vue中定义购物车入口和已添加商品数量(即list页面右上角购物车入口和显示数量);

    views目录新建cart.vue文件,在router.js中添加购物车路由;在cart.vue中,准备动态数据:Vuex中的购物车数据cartList,product.js中所有商品的数据,将product.js中的数组转换为字典productDictList,方便快速选取,商品总数countAll,总费用costAll。这些数据都使用计算属性实现,productDictList是对象,key是商品id,value是商品信息,数据是product.js中每项的内容,通过id可以快速便捷的获取对应商品的信息。

cart.vue computed: { cartList () { return this.$store.state.cartList; }, productDictList () { const dict = {}; this.productList.forEach(item => { dict[item.id] = item; }); return dict; }, countAll () { let count = 0; this.cartList.forEach(item => { count += item.count; }); return count; }, costAll () { let cost = 0; this.cartList.forEach(item => { cost += this.productDictList[item.id].cost * item.count; }); return cost; }

    下单前对每个商品的数量进行加减,或者删除商品,先将购物车cartList循环渲染,并完成表格样式。

    handleCount方法用于修改购物车商品数量,最小为1;handleDelete方法用于删除商品;两者都根据接收的参数(循环cartList中的索引),并从数据cartList获取具体商品信息;两个方法通过$store.commit提交给Vuex的mutations来操作数据。

    使用优惠码:优惠码的功能使用两个数据:promotionCode和promotion,前者用于双向绑定输入框数据,后者是优惠金额。优惠价默认是0,可以不再判断是否使用了优惠码。

cart.vue handleCheckCode () { if (this.promotionCode === '') { window.alert('请输入优惠码'); return; } if (this.promotionCode !== 'Vue.js') { window.alert('优惠码验证失败'); } else { this.promotion = 500; } }

    下单的操作通过Vuex的action完成,下单成功后,清空购物车数据;因为下单要通知服务端,所以需要在action中操作:

cart.vue // 通知Vuex完成下单 handleOrder () { this.$store.dispatch('buy').then(() => { window.alert('购买成功'); }) } main.js mutations: { // 清空购物车 emptyCart (state) { state.cartList = []; } }, actions: { // 购买 buy (context) { // 真实环境应通过 ajax 提交购买请求后再清空购物列表 return new Promise(resolve=> { setTimeout(() => { context.commit('emptyCart'); resolve(); }, 500) }); } }

在action中,使用setTimeout模拟异步,并通过返回一个Promise对象来通知cart.vue的handleOrder购物完成。

项目代码Github地址:https://github.com/guocaiyao/VUE/tree/master/VuePractice/shopping



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3