小QA学习前端系列之练习实践vuex-shopping-cart

小QA学习前端系列之练习实践vuex-shopping-cart

代码地址

https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart

直接 npm install 或者yarn ,安装依赖

之后,npm run dev 运行

页面如下

shop

废话不多说,直接看源码。

源码解析

先来看看文件目录

文件

该demo包含了2个module,一个叫cart,另一个叫product.

先看cart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#shop是获取数据的api
import shop from '../../api/shop'
#引入了 mutation-types 使用常量替代 Mutation 事件类型
import * as types from '../mutation-types'
// initial state 初始化了2个状态也可叫数据对象,added:
// shape: [{ id, quantity }]
const state = {
added: [],
checkoutStatus: null
}
// getters getters过滤条件必须是bollean值.根据bolean的条件返回具体数据对象。null在JavaScript中if条件下 均被视为false
const getters = {
checkoutStatus: state => state.checkoutStatus
}
// actions 在actions中提交mutation,并且可以包含任何的异步操作。actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作
const actions = {
checkout ({ commit, state }, products) {
//解构 state.added对象里面的值,并将至存放到savedCartItems对象中
const savedCartItems = [...state.added]
commit(types.CHECKOUT_REQUEST)
shop.buyProducts(
products,
() => commit(types.CHECKOUT_SUCCESS),
() => commit(types.CHECKOUT_FAILURE, { savedCartItems })
)
}
}
// mutations 在Vuex中store数据改变的唯一方法就是mutation
<!--
mutations,里面装着一些改变数据方法的集合,这是Veux设计很重要的一点,就是把处理数据逻辑方法全部放在mutations里面,使得数据和视图分离。 -->
const mutations = {
[types.ADD_TO_CART] (state, { id }) {
state.lastCheckout = null
const record = state.added.find(p => p.id === id)
if (!record) {
state.added.push({
id,
quantity: 1
})
} else {
record.quantity++
}
},
[types.CHECKOUT_REQUEST] (state) {
// clear cart
state.added = []
state.checkoutStatus = null
},
[types.CHECKOUT_SUCCESS] (state) {
state.checkoutStatus = 'successful'
},
[types.CHECKOUT_FAILURE] (state, { savedCartItems }) {
// rollback to the cart saved before sending the request
state.added = savedCartItems
state.checkoutStatus = 'failed'
}
}
export default {
state,
getters,
actions,
mutations
}

在来看看 product

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import shop from '../../api/shop'
import * as types from '../mutation-types'
// initial state
const state = {
all: []
}
// getters JS中数组(不管是不是空的)属于对象类型,对象类型转为boolean类型(内部对应ToBoolean()操作)时都是true。
const getters = {
allProducts: state => state.all
}
// actions
const actions = {
getAllProducts ({ commit }) {
shop.getProducts(products => {
commit(types.RECEIVE_PRODUCTS, { products })
})
}
}
// mutations
const mutations = {
[types.RECEIVE_PRODUCTS] (state, { products }) {
state.all = products
},
[types.ADD_TO_CART] (state, { id }) {
state.all.find(p => p.id === id).inventory--
}
}
export default {
state,
getters,
actions,
mutations
}

看完了 module,再来看看 action

1
2
3
4
5
6
7
8
9
10
//这个是总得action 每个module 都可以有自己的action
import * as types from './mutation-types'
//很简单 判断存货是否大于0 然后提交给mutation具体id
export const addToCart = ({ commit }, product) => {
if (product.inventory > 0) {
commit(types.ADD_TO_CART, {
id: product.id
})
}
}

继续 再来看看总得getter

1
2
3
4
5
6
7
8
9
10
11
//查询 返回对象
export const cartProducts = state => {
return state.cart.added.map(({ id, quantity }) => {
const product = state.products.all.find(p => p.id === id)
return {
title: product.title,
price: product.price,
quantity
}
})
}

再来看定义所有mutation类型文件mutation-types.js

1
2
3
4
5
export const ADD_TO_CART = 'ADD_TO_CART'
export const CHECKOUT_REQUEST = 'CHECKOUT_REQUEST'
export const CHECKOUT_SUCCESS = 'CHECKOUT_SUCCESS'
export const CHECKOUT_FAILURE = 'CHECKOUT_FAILURE'
export const RECEIVE_PRODUCTS = 'RECEIVE_PRODUCTS'

最后index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import cart from './modules/cart'
import products from './modules/products'
import createLogger from '../../../src/plugins/logger'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
actions,
getters,
modules: {
cart,
products
},
strict: debug,
plugins: debug ? [createLogger()] : []
})

至此 所有vuex介绍完毕,然后让我们看这些vuex怎么应用的component中

先来到cart组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<template>
<div class="cart">
<h2>Your Cart</h2>
<p v-show="!products.length"><i>Please add some products to cart.</i></p>
<ul>
<li v-for="p in products">
{{ p.title }} - {{ p.price | currency }} x {{ p.quantity }}
</li>
</ul>
<p>Total: {{ total | currency }}</p>
<p><button :disabled="!products.length" @click="checkout(products)">Checkout</button></p>
<p v-show="checkoutStatus">Checkout {{ checkoutStatus }}.</p>
</div>
</template>
<script>
//通过mapgetters方法解构数据
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters({
products: 'cartProducts',
checkoutStatus: 'checkoutStatus'
}),
total () {
return this.products.reduce((total, p) => {
return total + p.price * p.quantity
}, 0)
}
},
methods: {
//分发action
checkout (products) {
this.$store.dispatch('checkout', products)
}
}
}
</script>

在来看看 product组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<ul>
<li v-for="p in products">
{{ p.title }} - {{ p.price | currency }}
<br>
<button
:disabled="!p.inventory"
@click="addToCart(p)">
Add to cart
</button>
</li>
</ul>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters({
products: 'allProducts'
}),
methods: mapActions([
'addToCart'
]),
created () {
this.$store.dispatch('getAllProducts')
}
}
</script>

最后将这两个component 引入到app.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div id="app">
<h1>Shopping Cart Example</h1>
<hr>
<h2>Products</h2>
<product-list></product-list>
<hr>
<cart></cart>
</div>
</template>
<script>
import ProductList from './ProductList.vue'
import Cart from './Cart.vue'
export default {
components: { ProductList, Cart }
}
</script>

基本上这个demo就介绍完毕

下来我通过vue-cli初始化一个新项目,将上面所有的代码进行练习 谢谢大家欣赏。
代码已经上传
https://github.com/qileilove/vuex-practice