实现的最终页面如下:
页面父组件
<template>
<div class="home">
<topVue />
<centerVue />
<bottomVue />
</div>
</template>
<script>
import axios from "axios";
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
import bottomVue from "./bottom.vue";
import centerVue from "./center.vue";
import topVue from "./top.vue";
export default {
name: "HomeView",
components: {
topVue,
centerVue,
bottomVue,
},
methods: {},
computed: {},
};
</script>
三个子页面:
top.vue
<template>
<div class="top">
<div style="20px;!important">
<input
type="checkbox"
:checked="this.$store.state.goods.allSelect"
@change="toggleAll"
/>全选
</div>
<div style="100px;margin-left:-80px">商品</div>
<div style="50px">单价</div>
<div style="50px">数量</div>
<div style="50px">小计</div>
<div>操作</div>
</div>
</template>
<script>
import { mapMutations } from "vuex";
export default {
mounted() {},
methods: {
...mapMutations({
toggleAll: "goods/toggleAll",
}),
},
};
</script>
<style>
.top {
display: flex;
justify-content: space-between;
align-items: center;
background: #f3f3f3;
border: 1px solid #e9e9e9;
}
</style>
center.vue
<template>
<div>
<div class="center" v-for="(item, index) in list" :key="index">
<div
style="
display: flex;
justify-content: space-between;
align-items: center;
"
>
<input
type="checkbox"
@change="selectOne(index)"
:checked="item.flag"
/>
<span class="imgBox">
<img :src="item.img" alt="123" />
</span>
<span>{{ item.name }}</span>
</div>
<div>¥{{ item.price }}</div>
<div class="count">
<button @click="reduce(index)">-</button>
<input
style="width: 50px; text-align: center"
type="text"
:value="item.num"
/>
<button @click="add(index)">+</button>
</div>
<div>{{ changePrice(item.num, item.price) }}</div>
<span class="deleteBtn" @click="deleteGood(item.id)">删除</span>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
export default {
created() {
this.$store.dispatch("goods/getList");
},
methods: {
// selectOne(index){
// this.$store.commit()
// }
changePrice(n, p) {
return "¥" + (n * (p * 10)) / 10;
},
...mapMutations({
add: "goods/add",
reduce: "goods/reduce",
selectOne: "goods/selectOne",
}),
...mapActions({
deleteGood: "goods/deleteGood",
}),
},
computed: {
...mapState({
list: (state) => state.goods.list,
}),
},
};
</script>
<style>
.center {
height: 150px;
display: flex;
align-items: center;
justify-content: space-between;
background: #fff4e8;
margin-bottom: 10px;
}
.count {
display: flex;
align-items: center;
}
.imgBox {
display: block;
width: 150px;
height: 100px;
margin-left: 100px;
}
.imgBox > img {
width: 100%;
height: 100%;
}
.deleteBtn {
cursor: pointer;
}
</style>
bottom.vue
<template>
<div class="bottom">
<div style="margin-left: 100px">
已选择<span style="color: red">{{ goodsCount.goodsCountNum }}</span
>件商品
</div>
<div>
总价:<span>{{ goodsCount.goodsPrice | toPrice }}</span>
</div>
<button style="color: red">去结算</button>
</div>
</template>
<script>
import { mapGetters, mapState } from "vuex";
export default {
computed: {
...mapGetters({
goodsCount: "goods/goodsCount",
}),
},
filters: {
toPrice(v) {
return "¥" + v;
},
},
};
</script>
<style>
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
store中index.js
import Vue from 'vue'
import Vuex from 'vuex'
import goods from './goodStore'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
goods
},
})
商品模块goodStore中index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";
Vue.use(Vuex)
export default {
state: {
list: [],
allSelect: true,
},
getters: {
goodsCount(state) {
let goodsCountNum = 0
let goodsPrice = 0
state.list.filter((item) => {
if (item.flag) {
goodsCountNum += item.num
goodsPrice += (item.num * (item.price * 10)) / 10
}
})
console.log(goodsCountNum, goodsPrice, '99999909')
return { goodsCountNum, goodsPrice }
}
},
mutations: {
getMList(state, list) {
state.list = list
},
add(state, i) {
state.list[i].num++
},
reduce(state, i) {
let num = state.list[i].num
if (num <= 1) {
state.list[i].num == 1
} else {
state.list[i].num--
}
},
toggleAll(state) {
state.allSelect = !state.allSelect
state.list.map((item) => {
item.flag = state.allSelect
})
},
selectOne(state, index) {
state.list[index].flag = !state.list[index].flag
for (var i = 0; i < state.list.length; i++) {
if (!state.list[i].flag) {
state.allSelect = false
break
} else {
state.allSelect = true
}
}
}
},
actions: {
getList(context) {
axios({
method: "get",
url: "http://localhost:3000/posts",
}).then((res) => {
let data = res.data;
data.map((item) => {
item.flag = true
})
context.commit('getMList', data)
});
},
deleteGood({ dispatch }, i) {
axios({
method: 'delete',
url: 'http://localhost:3000/posts/' + i
}).then((res) => {
console.log(res)
dispatch('getList')
})
}
},
namespaced: true,
modules: {
}
}
json-server 模拟的数据 data.json
{
"posts": [
{
"id": 1,
"name": "iPhone14",
"price": "5986.5",
"img": "img/1.jpg",
"num": 1
},
{
"id": 2,
"name": "三星",
"price": "6895",
"img": "img/2.jpg",
"num": 1
},
{
"id": 3,
"name": "华为",
"price": "6895",
"img": "img/3.jpg",
"num": 1
},
{
"id": 4,
"name": "小米",
"price": "3896",
"img": "img/4.jpg",
"num": 1
}
]
}