1. 目录结构
2. mock 数据
mock数据只能通过ajax请求获取,从而达到模拟后台接口的作用
定义数据 data.json
[
{
"id": 1,
"name": "TCL彩电",
"price": 1000,
"num": 1
},
{
"id": 2,
"name": "机顶盒",
"price": 1000,
"num": 1
},
{
"id": 3,
"name": "海尔冰箱",
"price": 1000,
"num": 1
},
{
"id": 4,
"name": "小米手机",
"price": 1000,
"num": 1
},
{
"id": 5,
"name": "PPTV电视",
"price": 1000,
"num": 2
}
]
提供数据接口 mockServer.js
/*
使用mockjs提供mock数据接口
*/
import Mock from 'mockjs'
import data from './data.json'
// 返回goods的接口
Mock.mock('/', {
data:data});
// export default ??? 不需要向外暴露任何数据, 只需要保存能执行即可
main.js 导入
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import store from './store' // 导入vuex
import './mock/mockServer' // 导入mock接口
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store, // 实例化
components: {
App },
template: '<App/>'
})
3. vuex 状态管理
action.js
/*
通过mutation间接更新state的多个方法
*/
import {
LIST, DELETE_GOOD, ADD_GOOD_COUNT, SUB_GOOD_COUNT, UPDATE_GOOD_COUNT} from './mutation_types'
import axios from 'axios'
export default {
// 异步请求mock数据接口获取list数据
async reqList({
commit}){
const result = await axios.get('/');
const list = result.data.data;
commit(LIST, {
list})
},
// 删除商品
deleteGood({
commit}, id){
commit(DELETE_GOOD, {
id})
},
// 添加商品
addGood({
commit}, id){
commit(ADD_GOOD_COUNT, {
id})
},
// 减少商品
subGood({
commit}, id){
commit(SUB_GOOD_COUNT, {
id})
},
// 更新商品
updateGood({
commit}, {
id, value}){
commit(UPDATE_GOOD_COUNT, {
id, value})
}
}
getters.js
/*
包含多个基于state的getter计算属性的对象
*/
export default {
// 计算商品总数
total(state){
let sumPrice = 0;
state.list.forEach((item)=>{
sumPrice += item.price * item.num
});
return sumPrice
}
}
index.js
/*
vuex最核心的管理对象store
*/
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutation'
import actions from './action'
import getters from './getters'
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
mutatioan.js
/*
直接更新state的多个方法
*/
import {
LIST, DELETE_GOOD, ADD_GOOD_COUNT, SUB_GOOD_COUNT, UPDATE_GOOD_COUNT} from './mutation_types'
export default {
[LIST](state, {
list}){
state.list = list
},
[DELETE_GOOD](state, {
id}){
// 通过id获取索引
const index = state.list.findIndex(item=>{
return item.id === id;
});
state.list.splice(index,1)
},
[ADD_GOOD_COUNT](state, {
id}){
// 通过id获取索引
const index = state.list.findIndex(item=>{
return item.id === id;
});
state.list[index].num ++
},
[SUB_GOOD_COUNT](state, {
id}){
// 通过id获取索引
const index = state.list.findIndex(item=>{
return item.id === id;
});
state.list[index].num --
},
[UPDATE_GOOD_COUNT](state, {
id, value}){
// 通过id获取索引
const index = state.list.findIndex(item=>{
return item.id === id;
});
state.list[index].num = value;
},
}
mutation_type.js
/*
所有常量
*/
export const LIST = 'list'; // 数据列表
export const DELETE_GOOD = 'delete_good'; // 删除商品
export const ADD_GOOD_COUNT = 'add_good_count'; // 添加商品数量
export const SUB_GOOD_COUNT = 'sub_good_count'; // 减少商品数量
export const UPDATE_GOOD_COUNT = 'update_good_count'; // 修改商品数量
state.js
/*
所有管理的状态对象
*/
export default {
list: []
}
main.js 导入,见上
4. 组件使用
app.vue
<template>
<div id="app">
<div class="container">
<div class="cart">
<Header></Header>
<!-- $event 接受子组件传过来的参数 -->
<List :list="list" @del="del($event)" @changeNum="changeNum($event)"></List>
<Footer :list="list"></Footer>
</div>
</div>
</div>
</template>
<script>
import Header from "./components/Header";
import List from "./components/List";
import Footer from "./components/Footer";
import {
mapState} from 'vuex'
export default {
components:{
Header, List, Footer
},
computed:{
...mapState(['list'])
},
// 页面刷新请求数据
mounted(){
this.$store.dispatch('reqList')
}
}
</script>
<style type="text/css">
.container {
}
.container .cart {
width: 300px;
margin: auto;
}
.container .title {
background-color: lightblue;
height: 40px;
line-height: 40px;
text-align: center;
/*color: #fff;*/
}
.container .total {
background-color: #FFCE46;
height: 50px;
line-height: 50px;
text-align: center;
}
.container .total button {
margin: 0 10px;
background-color: #DC4C40;
height: 35px;
width: 80px;
border: 0;
}
.container .total span {
color: red;
font-weight: bold;
}
.container .item {
height: 55px;
line-height: 55px;
position: relative;
border-top: 1px solid #ADD8E6;
}
.container .item img {
width: 45px;
height: 45px;
margin: 5px;
}
.container .item .name {
position: absolute;
width: 90px;
top: 0;
left: 55px;
font-size: 16px;
}
.container .item .change {
width: 100px;
position: absolute;
top: 0;
right: 50px;
}
.container .item .change a {
font-size: 20px;
width: 30px;
text-decoration: none;
background-color: lightgray;
vertical-align: middle;
}
.container .item .change .num {
width: 40px;
height: 25px;
}
.container .item .del {
position: absolute;
top: 0;
right: 0px;
width: 40px;
text-align: center;
font-size: 40px;
cursor: pointer;
color: red;
}
.container .item .del:hover {
background-color: orange;
}
</style>
头部
<template>
<div class="title">我的商品</div>
</template>
<script>
export default {
name: "Header"
}
</script>
<style scoped>
</style>
列表
<template>
<div>
<div class="item" v-for="item in list">
<img src="../img/a.jpg">
<div class="name"> {
{
item.name }} </div>
<div class="change"><a href="" @click.prevent="sub(item.id)">-</a>
<input type="text" class="num" :value="item.num" @blur="updateCount(item.id, $event)">
<a href="" @click.prevent="add(item.id)">+</a></div>
<div class="del" @click="del(item.id)">×</div>
</div>
</div>
</template>
<script>
import {
mapState} from 'vuex'
export default {
name: "List",
computed:{
...mapState(['list'])
},
methods:{
del(id){
this.$store.dispatch('deleteGood', id)
},
add(id){
this.$store.dispatch('addGood', id);
},
sub(id){
this.$store.dispatch('subGood', id)
},
updateCount(id, event){
this.$store.dispatch('updateGood',{
id:id, value: event.target.value})
}
}
}
</script>
<style scoped>
</style>
尾部
<template>
<div class="total"><span>总价:{
{
total }}</span>
</div>
</template>
<script>
import {
mapGetters} from 'vuex'
export default {
name: "Footer",
props:['list'],
computed:{
...mapGetters(['total'])
}
}
</script>
<style scoped>
</style>