网站如何做二级域名,免费设计网站,小白如何搭建个人网站,做一个电商平台大概需要多少钱综合案例#xff1a;购物车 数据渲染
构建cart购物车模块 准备后端接口服务环境 请求数据存入vuex cart.js
// 新建购物车模块
import axios from axios
export default {namespaced: true,state () {return {// 购物车数据 [{},{}]list: []}},mutations: {updateList (…综合案例购物车 数据渲染
构建cart购物车模块 准备后端接口服务环境 请求数据存入vuex cart.js
// 新建购物车模块
import axios from axios
export default {namespaced: true,state () {return {// 购物车数据 [{},{}]list: []}},mutations: {updateList (state, newList) {state.list newList}},actions: {// 请求方式get// 请求地址http://localhost:3000/cartasync getList (context) {const res await axios.get(http://localhost:3000/cart)context.commit(updateList, res.data)}},getters: {}
}App.vue
templatediv classapp-container!-- Header 区域 --cart-header/cart-header!-- 商品 Item 项组件 --cart-item v-foritem in list :keyitem.id :itemitem/cart-item!-- Foote 区域 --cart-footer/cart-footer/div
/templatescript
import CartHeader from /components/cart-header.vue
import CartFooter from /components/cart-footer.vue
import CartItem from /components/cart-item.vueimport { mapState } from vuex
export default {name: App,created () {this.$store.dispatch(cart/getList)},computed: {...mapState(cart, [list])},components: {CartHeader,CartFooter,CartItem}
}
/scriptstyle langless scoped
.app-container {padding: 50px 0;font-size: 14px;
}
/stylecart-item.vue
templatediv classgoods-container!-- 左侧图片区域 --div classleftimg :srcitem.thumb classavatar alt/div!-- 右侧商品区域 --div classright!-- 标题 --div classtitle{{ item.name }}/divdiv classinfo!-- 单价 --span classprice{{ item.price }}/spandiv classbtns!-- 按钮区域 --button classbtn btn-light-/buttonspan classcount{{ item.count }}/spanbutton classbtn btn-light/button/div/div/div/div
/template
script
export default {name: CartItem,methods: {},props: {item: {type: Object,require: true}}
}
/scriptstyle langless scoped
.goods-container {display: flex;padding: 10px; .goods-container {border-top: 1px solid #f8f8f8;}.left {.avatar {width: 100px;height: 100px;}margin-right: 10px;}.right {display: flex;flex-direction: column;justify-content: space-between;flex: 1;.title {font-weight: bold;}.info {display: flex;justify-content: space-between;align-items: center;.price {color: red;font-weight: bold;}.btns {.count {display: inline-block;width: 30px;text-align: center;}}}}
}.custom-control-label::before,
.custom-control-label::after {top: 3.6rem;
}
/style修改数量功能的实现 cart.js
// 新建购物车模块
import axios from axios
export default {namespaced: true,state () {return {// 购物车数据 [{},{}]list: []}},mutations: {updateList (state, newList) {state.list newList},// obj: {id:xxx, newCount:xxx}updateCount (state, obj) {// 根据 id 找到对应的对象更新count属性即可const goods state.list.find(item item.id obj.id)goods.count obj.newCount}},actions: {// 请求方式get// 请求地址http://localhost:3000/cartasync getList (context) {const res await axios.get(http://localhost:3000/cart)context.commit(updateList, res.data)},// 请求方式: patch// 请求地址: http://localhost:3000/cart/:id值 表示修改的是哪个对象// 请求参数// {// name:新值【可选】// price:新值【可选】// count:新值【可选】// thumb:新值【可选】// }async updateCountAsync (context, obj) {// 将修改更新同步到后台服务器await axios.patch(http://localhost:3000/cart/${obj.id}, {count: obj.newCount})// 将修改更新同步到 vuexcontext.commit(updateCount, {id: obj.id,newCount: obj.newCount})}},getters: {}
}cart-item.vue
templatediv classgoods-container!-- 左侧图片区域 --div classleftimg :srcitem.thumb classavatar alt/div!-- 右侧商品区域 --div classright!-- 标题 --div classtitle{{ item.name }}/divdiv classinfo!-- 单价 --span classprice{{ item.price }}/spandiv classbtns!-- 按钮区域 --button classbtn btn-light clickbtnClick(-1)-/buttonspan classcount{{ item.count }}/spanbutton classbtn btn-light clickbtnClick(1)/button/div/div/div/div
/template
script
export default {name: CartItem,methods: {btnClick (step) {const newCount this.item.count stepconst id this.item.idif (newCount 1) returnthis.$store.dispatch(cart/updateCountAsync, {id,newCount})}},props: {item: {type: Object,require: true}}
}
/scriptstyle langless scoped
.goods-container {display: flex;padding: 10px; .goods-container {border-top: 1px solid #f8f8f8;}.left {.avatar {width: 100px;height: 100px;}margin-right: 10px;}.right {display: flex;flex-direction: column;justify-content: space-between;flex: 1;.title {font-weight: bold;}.info {display: flex;justify-content: space-between;align-items: center;.price {color: red;font-weight: bold;}.btns {.count {display: inline-block;width: 30px;text-align: center;}}}}
}.custom-control-label::before,
.custom-control-label::after {top: 3.6rem;
}
/style底部 getters 统计 cart.js
// 新建购物车模块
import axios from axios
export default {namespaced: true,state () {return {// 购物车数据 [{},{}]list: []}},mutations: {updateList (state, newList) {state.list newList},// obj: {id:xxx, newCount:xxx}updateCount (state, obj) {// 根据 id 找到对应的对象更新count属性即可const goods state.list.find(item item.id obj.id)goods.count obj.newCount}},actions: {// 请求方式get// 请求地址http://localhost:3000/cartasync getList (context) {const res await axios.get(http://localhost:3000/cart)context.commit(updateList, res.data)},// 请求方式: patch// 请求地址: http://localhost:3000/cart/:id值 表示修改的是哪个对象// 请求参数// {// name:新值【可选】// price:新值【可选】// count:新值【可选】// thumb:新值【可选】// }async updateCountAsync (context, obj) {// 将修改更新同步到后台服务器await axios.patch(http://localhost:3000/cart/${obj.id}, {count: obj.newCount})// 将修改更新同步到 vuexcontext.commit(updateCount, {id: obj.id,newCount: obj.newCount})}},getters: {// 商品总数 sum item.counttotal (state) {return state.list.reduce((sum, item) sum item.count, 0)},// 商品总结个 sum item.count * item.pricetotalPrice (state) {return state.list.reduce((sum, item) sum item.count * item.price, 0)}}
}cart-footer.vue
templatediv classfooter-container!-- 中间的合计 --divspan共 {{ total }} 件商品合计/spanspan classprice{{ totalPrice }}/span/div!-- 右侧结算按钮 --button classbtn btn-success btn-settle结算/button/div
/templatescript
import { mapGetters } from vuex
export default {name: CartFooter,computed: {...mapGetters(cart, [total, totalPrice])}
}/scriptstyle langless scoped
.footer-container {background-color: white;height: 50px;border-top: 1px solid #f8f8f8;display: flex;justify-content: flex-end;align-items: center;padding: 0 10px;position: fixed;bottom: 0;left: 0;width: 100%;z-index: 999;
}.price {color: red;font-size: 13px;font-weight: bold;margin-right: 10px;
}.btn-settle {height: 30px;min-width: 80px;margin-right: 20px;border-radius: 20px;background: #42b983;border: none;color: white;
}
/style