vuex mysql_vuex + koa + mysql实现购物车功能(一)
雙十一剛過去的你是不是又要開始準備雙十二了呢?🤔談到購物就離不開購物車,那購物車功能如何實現呢?就小米商城購物車,我們來談一談
效果圖如下(基本是我們見過的購物車的效果):
動手前思考
1.數據庫需要建兩個表:?所有商品表(cart),?購物車商品表(cartselected)
2.cart表: id(主鍵,自增),img,title,price,recommend
cartselected表:id(與cart表id關聯),img,title,price,recommend,num,checked(是否選中狀態,只有0和1兩個值)
3.axios請求在actions中進行,請求回來的數據放入state中,相關計算在getters中進行
4.axios需要多次用到,可以進行封裝
5.商品欄展示cart表數據,購物車欄展示cartselected表數據
準備工具
vscode
navicat
mysql
數據庫表結構如下:
接下來讓我們一個一個功能分別實現吧!😀
實現功能
1.搭建后臺服務、連接mysql
// 配置數據庫連接
const config = {
database: {
DATEBASE: 'xiaomi',
USERNAME: 'root',
PASSWORD: '******',
PORT: '3306',
HOST: 'localhost'
}
}
// 創建連接池
var pool = mysql.createPool({
host: config.database.HOST,
user: config.database.USERNAME,
password: config.database.PASSWORD,
database: config.database.DATEBASE,
port: config.database.PORT
})
// 統一連接數據庫的方法
let allServies = {
query: function (sql, values) {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sql, values, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release() // 釋放連接池
})
}
})
})
}
}
復制代碼
連接成功后可以用postman,或者直接瀏覽器測試一下(這里就不測試啦)
2.細講每一個功能實現(按照sql語句 -> 后端接口 -> vuex -> 具體component方式)
隨機查詢
場景:當購物車為空時,頁面顯示20件商品,當購物車有商品時,則顯示10件商品
let findallgoods = function (num) { // 隨機查詢num數量的商品信息
let _sql = `select * from cart order by rand() limit ${num} ;`
return allServies.query(_sql)
}
復制代碼
后端路由:
router.post('/allcart', async (ctx, next) => {
let _num = ctx.request.body.num
await userService.findallgoods(_num).then((res) => {
ctx.body = {
data: res
}
})
})
復制代碼
前端訪問
data () {
return {
allcart: [] // 返問后拿到的數據
}
},
methods: {
requestGoods (nums) { // 請求接口返回數據
axios({
url: 'http://localhost:3000/users/allcart',
method: 'post',
data: {
num: nums
}
}).then(res => {
this.allcart = res.data.data
}).catch(err => {
console.log(err)
})
}
},
watch: { // 監聽cart長度從而判斷請求幾條數據(10條還是20條)
cart (newval, old) {
if (newval.length == 0 && old.length != 0) {
this.requestGoods(20)
} else {
this.requestGoods(10)
}
}
},
復制代碼
加入購物車及移出購物車
// 從購物車中查找某一件商品
let findcart = function (id) {
let _sql = `select * from cartselected where id="${id}";`
return allServies.query(_sql)
}
// 查找購物車所有商品
let findallcart = function () {
let _sql = `select * from cartselected;`
return allServies.query(_sql)
}
// 插入購物車(id, title, price, recommend, img, num, checked)
let insertgoods = function (value) {
let _sql = `insert into cartselected set id=?,title=?,price=?,recommend=?,img=?,num=?,checked=?`
return allServies.query(_sql, value)
}
// 根據id刪除購物車某一件商品
let deletegoods = function (value) {
let _sql = `delete from cartselected where id=?`
return allServies.query(_sql, value)
}
復制代碼// 購物車所有商品
router.post('/allcarts', async (ctx, next) => {
await userService.findallcart().then((res) => {
ctx.body = {
data: res
}
})
})
// 加入購物車
router.post('/insertcart', async (ctx, next) => {
let _id = ctx.request.body.id
let _title = ctx.request.body.title
let _price = ctx.request.body.price
let _recommend = ctx.request.body.recommend
let _img = ctx.request.body.img
let _num = ctx.request.body.num
let _checked = ctx.request.body.checked
if (!_id) {
return
} else {
let cart = {
id: _id,
title: _title,
price: _price,
recommend: _recommend,
img: _img,
num: _num,
checked: _checked
}
await userService.findcart(cart.id).then(async (res) => {
if (res.length) {
try {
throw Error('購物車中已存在')
} catch (error) {
console.log(error)
}
ctx.body = {
code: '800003',
data: 'err',
mess: '購物車已存在該商品'
}
} else {
await userService.insertgoods([cart.id, cart.title, cart.price, cart.recommend, cart.img, cart.num, cart.checked]).then(async (res) => {
let r = ''
if (res.affectedRows !== 0) {
await userService.findcartgoods(cart.id).then((res1) => {
ctx.body = {
code: '800000',
data: res1,
mess: '增加購物車成功'
}
})
} else {
r = 'error'
ctx.body = {
code: '800004',
data: r,
mess: '增加購物車失敗'
}
}
})
}
})
}
})
// 刪除購物車某一件商品
router.post('/deletegood', async (ctx, next) => {
let _id = ctx.request.body.id
await userService.deletegoods(_id).then(res => {
ctx.body = {
code: '800000',
data: res,
mess: '刪除成功'
}
}).catch(err => {
ctx.body = {
code: '800002',
data: err
}
})
})
復制代碼
vuex 的actions:
getcart ({commit}, status) { // 獲取購物車表的數據
axios({
url: 'http://localhost:3000/users/allcarts',
method: 'post',
data: {}
}).then(res => {
commit('setcart', res.data.data) // commit方法給mutations,給state的cart賦值
}).catch(err => {
console.log(err)
})
},
addcart ({dispatch}, {id, title, price, recommend, img, num, checked}) { // 加入購物車
axios({
url: 'http://localhost:3000/users/insertcart',
method: 'post',
data: {
id: id,
title: title,
price: price,
recommend: recommend,
img: img,
num: num,
checked: checked
}
}).then(res => {
if (res.data.code === '800000') {
dispatch('getcart'); // 再次請求購物車數據
} else {
console.log('增加購物車失敗')
}
}).catch(err => {
console.log(err)
})
},
deletecart ({dispatch}, id) { // 刪除購物車某件商品
axios({
url: 'http://localhost:3000/users/deletegood',
method: 'post',
data: {
id: id
}
}).then (res => {
dispatch('getcart')
})
}
復制代碼
component:
addcart (id, title, price, recommend, img, num, checked) { // 點擊加入購物車
this.$store.dispatch('addcart', {id, title, price, recommend, img, num, checked})
},
deletecart (id) { // 刪除購物車的商品
this.$store.dispatch('deletecart', id)
}
復制代碼
增加減少數量
// 購物車數量增加
let _sql = `update cartselected set num=num+1 where id="${id}"`
// 購物車數量減少
let _sql = `update cartselected set num=num-1 where id="${id}" and num >= 2`
// num > 2是因為數量不能減少到0復制代碼
后端接口
// 增加購物車某個商品數量
router.post('/addcartnum', async (ctx, next) => {})
// 減少購物車某個商品數量
router.post('/reducecartnum', async (ctx, next) => {})
復制代碼
vuex:
addcartnum ({dispatch}, params) {}) // 增加數量
reducecartnum ({dispatch}, params) {}) // 減少數量
復制代碼
component:
add (id) { // 增加商品數量
this.$store.dispatch('addcartnum', id)
},
reduce (id) { // 減少商品數量
this.$store.dispatch('reducecartnum', id)
}
復制代碼
全選與單選
// 設置全不選
let allfalse = function () {
let _sql = `update cartselected set checked=0`
return allServies.query(_sql)
}
// 設置全選
let alltrue = function () {
let _sql = `update cartselected set checked=1`
return allServies.query(_sql)
}
// 根據id切換該商品選中還是不選中
let singleselect = function (id) {
let _sql = `update cartselected set checked=(case when checked=0 then 1 else checked=0 end) where id="${id}"`
return allServies.query(_sql)
}
復制代碼
后端接口:
// 設置全選
router.post('/alltrue', async (ctx, next) => {})
// 設置全不選
router.post('/allfalse', async (ctx, next) => {})
// 根據id切換該商品選中還是不選中
router.post('/singleselect', async (ctx, next) => {})
復制代碼
vuex:
allfalse ({dispatch}, status) {})
alltrue ({dispatch}, status) {})
singleselect ({dispatch}, status) {})
復制代碼
component
data () {
return {
allcheked: false //是否全選
}
},
methods: {
allselect () { // 全選
if (this.allcheked) {
this.$store.dispatch('allfalse')
} else {
this.$store.dispatch('alltrue')
}
},
singleselected (id) { // 單選
this.$store.dispatch('singleselect', id)
}
},
computed: {
...mapGetters([
'cart'
])
},
watch: {
cart: {
handler(newValue, oldValue) {
for (let i = 0; i < newValue.length; i++) {
console.log(newValue[i].checked)
if (newValue[i].checked == 0) {
this.allcheked = false
return
}
this.allcheked = true
}
},
deep: true
}
}
復制代碼
相關計算
getters
const getters = {
cart: state => state.cart,
littletotalPrice (state) { // 小計
let money = []
if (state.cart.length != 0) {
state.cart.forEach((item) => {
console.log(item)
let price = item.price.substring(0, item.price.indexOf('元'))
money.push(price * item.num)
})
return money
} else {
return []
}
},
totalPrice (state) { // 總計
let selected = state.cart.filter(function(elem) {
return elem.checked == 1
})
let totalprice = 0
for (let i = 0; i < selected.length; i++) {
let price1 = selected[i].price.substring(0, selected[i].price.indexOf('元'))
let price2 = price1 * selected[i].num
totalprice += price2
}
return totalprice
},
selectednum (state) { // 選中的數量
let selected = state.cart.filter(function(elem) {
return elem.checked == 1
})
return selected.length
},
totalnum (state) { // 商品數
let sum = 0
for (let i = 0; i < state.cart.length; i++) {
sum = sum + state.cart[i].num
}
return sum
}
}
復制代碼
這樣購物車功能及基本實現了(心里不免哀嘆一聲:好像都是在搬磚😪,有沒有更簡單的方法呢?)
總結
每一個方法都要請求一次甚至更多次后端接口,對后端造成巨大壓力,由于對數據的操作大部分靠sql語句驅動,對于sql語句不熟練的同學就不太友好了,因此需要更好的方法來解決。
后續
下次我們將改善我們購物車功能的實現,接口值訪問一次,功能全在vuex中實現
總結
以上是生活随笔為你收集整理的vuex mysql_vuex + koa + mysql实现购物车功能(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wincc 报警记录 mysql_win
- 下一篇: shell读取excel_[PHP 开源