Back-end data emulation

Create vue.config.js in the root directory, write the interface and data, install CNPM I axios-s, and restart the server

module.exports = {
    devServer: {
        before(app, serve) {
            app.get('/api/products', (req, res) => {
                res.json({
                    results: products
                })
            })
        }
    }
}

const products = [
    { id: 1.title: 'iphone11'.price: 800.inventory: 10 },
    { id: 2.title: 'iphone11 pro'.price: 1200.inventory: 15 },
    { id: 3.title: 'iphone11 pro max'.price: 1400.inventory: 7}]Copy the code

Get data & Render data list

Vuex product module products.js introduces AXIos and asynchronously sends requests for data

import Axiso from 'axios'

export default {
    namespaced: true.state: {
        products: []},mutations: {
        getAllProducts(state, results) {
            state.products = results; //3. Assign the obtained data to products in the current state}},actions: {
        async getAllProducts({ commit }) { //2. Send an asynchronous request for data submission
            try {
                const res = await Axiso.get('/api/products'); // Request data from the interface
                const results = res.data.results; // Assign the extracted data to the new attribute
                commit('getAllProducts', results) //commit calls mutation and passes the data obtained
            } catch (error) {
                console.log(error); }}}}Copy the code

Obtained data:

Data: {... },status: 200.statusText: "OK".headers: {... },config: {... },... }Copy the code

Products.vue component:

<template>
	<div>
		<h2>goods</h2>
		<ul><! -- 5. Render product list -->
			<li v-for="product in products" :key="product.id">
				<h3>{{product.title}} - {{product.price}}</h3>
			</li>
		</ul>
	</div>
</template>

<script>
import { mapState } from "vuex";
export default {
	computed: {
		...mapState("products"["products"]) //4. The auxiliary function gets the status of the products module in store
	},
	created() {
		this.$store.dispatch("products/getAllProducts");//1. After the component is created, call the Action of the product component in the store to get the server data}};</script>
Copy the code

Fliter decorates the data

Register global filters in main.js:

Vue.filter('currency', (value) => {
  return '$' + value;
})
Copy the code

Intra-component references:

<ul>
    <li v-for="product in products" :key="product.id">
        <h3>{{product.title}} - {{product.price | currency}}</h3>
    </li>
</ul>
Copy the code

Registering global components

Register global components in main.js:

import CartList from '@/components/CartList.vue' // Import components

Vue.component(CartList.name, CartList) // Register the global component
Copy the code
export default {
	name: "CartList" // Component name used when registering global components
};
Copy the code

Add data to the shopping cart module

Get the method in the VUEX shopping cart module in the product component and add the event button to trigger and pass the value

<template>
	<div>
		<h2>product</h2>
		<ul>
			<li v-for="product in products" :key="product.id">
				<h3>{{product.title}} - {{product.price | currency}} - {{product.inventory}}</h3>
                <! Add the click event to trigger the action and pass the value of the currently clicked data object to the store(this will include any not referenced in the list rendering) -->
				<button @click="addProductToCart(product)">Add to shopping cart</button>
			</li>
		</ul>
	</div>
</template>

<script>
import { mapState, mapActions } from "vuex";
export default {
	computed: {
		...mapState("products"["products"])
	},
	created() {
		this.$store.dispatch("products/getAllProducts");
	},
	methods: {
        //1. Get the methods in the vuex shopping cart module. mapActions("cartList"["addProductToCart"])}};</script>
Copy the code

The shopping cart module receives trigger events and incoming data, makes judgments and stores and modifies the shopping cart data

export default {
    namespaced: true.state: {
        cartList: [] //3. Declare the cart status
    },
    getters: {
        evenOrOdd2(state) {
            return state.count % 2= = =0 ? 'even number' : 'odd'}},mutations: {
        //7. Add the product name to the cart
        pushProductToCart(state, { id, quantity }) {
            state.cartList.push({
                id,
                quantity
            })
        },
        //7. Product quantity plus one
        addProductQuantity(state, { id }) {
            // Obtain the cartList corresponding ID data according to the id of the data passed in
            const product = state.cartList.find(item= > item.id === id);
            // Add one to this numberproduct.quantity++; }},actions: {
        addProductToCart({ commit, state }, product) { //4. Call the add cart method to pass in state and receive product
            if (product.inventory > 0) { // Check whether the inventory is greater than 0 from the inventory of product
                // get the data in the cartList, determine whether the corresponding id of the item is the same as the data passed in and assign a variable
                const cartItem = state.cartList.find(item= > item.id === product.id);
                console.log(cartItem);

                if(! cartItem) {CartItem = faulse; //6.cartList = null; cartItem = faulse
                    // Cart has no data to add data to cartList
                    commit('pushProductToCart', { id: product.id, quantity: 1})}else {
                    // Pass the product ID to the product add method
                    commit('addProductQuantity', { id: product.id })
                }
            }

        }
    }
}
Copy the code

Render shopping cart list

Getter methods in the Vuex shopping cart module generate data

state: {
	cartList: []},getters: {
    // Get the cart data from the product module and compare it with the cart data from the current cart module by the third parameter in the getter
    getCartList(state, getters, rootState) {
        // Traverse the cartList data into an ordered list via map and deconstruct the ID and quantity,
        // Returns a new array generated by map. Map does not detect empty arrays
        return state.cartList.map(({ id, quantity }) = > {
            /* The first products is the module name, the second is the status name, get an array of all product data of the product module, judge by the function in the find method,map each traverse of cartList compares all product data one by one, obtain the same ID object to assign value to product */
            const product = rootState.products.products.find(item= > item.id === id);
            return { // Each product ID of the cartList corresponds to the product object,
                // Get the number of title and price and cartlist. id of the product data, which is returned to map to store in a new array
                title: product.title, //title is the title of the product
                price: product.price, //price is the title of product
                quantity // Quantity is the number of corresponding ids in the current shopping cart module}}}})Copy the code

The shopping cart component gets the shopping cart data generated by the getter

<template>
	<div>
		<h2>The shopping cart</h2>
		<ul><! Render the getter data as a list -->
			<li v-for="(item,index) in getCartList" :key="index">
				<h3>{{item. The title}} - {{item. The price | currency}} ({{item. Quantity}}</h3>
			</li>
		</ul>
	</div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
	name: "CartList".computed: {
        // Get the cart data generated by the getter method of the Vuex shopping cart module. mapGetters("cartList"["getCartList"])}};</script>
Copy the code

Gross price calculation

Vuex shopping cart module:

getters: {
    getCartList(state, getters, rootState) {
        return state.cartList.map(({ id, quantity }) = > {
            const product = rootState.products.products.find(item= > item.id === id);
            return {
                title: product.title,
                price: product.price,
                quantity
            }
        })
    },
    //1. Add the cart total price method and pass the second parameter getters to get another getter
    cartTotalPrice(state, getters) { 
        //2. Get the array returned by getCartList above, use reduce() to calculate and pass in the array product generated by getCartList
        return getters.getCartList.reduce((total, product) = > {
            //3. Total acts as an accumulator and accumulates the total price of a single product by multiplying the price and quantity of product starting from 0. Reduce () returns the total price of all products
            return total + product.price * product.quantity
        }, 0); }},Copy the code

The reduce() method takes a function as an accumulator, and each value in the array (from left to right) starts to shrink and eventually adds up to a single value, because the shopping cart is empty when it doesn’t have any data, and the reduce() method gives an error when the object is empty, passes in the default value, and evaluates from zero

<template>
	<div>
		<h2>The shopping cart</h2>
		<ul>
			<li v-for="(item,index) in getCartList" :key="index">
				<h3>{{item. The title}} - {{item. The price | currency}} ({{item. Quantity}}</h3>
			</li>
		</ul>
        <! -- 5. Reference methods and add global filters -->
		<h3>Total price: {{cartTotalPrice | currency}}</h3>
	</div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
	name: "CartList".computed: {
        //4. Add the method of vuex shopping cart module total price calculation into the auxiliary function. mapGetters("cartList"["getCartList"."cartTotalPrice"])}};</script>
Copy the code

Inventory reduction

Under the Add product to cart method in the shopping cart module, submit a call to the method in the product module

actions: {
    addProductToCart({ commit, state }, product) {
        if (product.inventory > 0) {
            const cartItem = state.cartList.find(item= > item.id === product.id);
            if(! cartItem) { commit('pushProductToCart', { id: product.id, quantity: 1})}else {
                commit('addProductQuantity', { id: product.id })
            }
            // Every time you click add to cart, the method in the Products module is triggered and the id of the current product is passed
            // If you want to submit methods in one module in another, you need a third argument {root:true} to return to the root
            commit('products/decrementProductsInventory', { id: product.id }, { root: true})}}}Copy the code

Mutations of the product module:

mutations: {
    // Method passes in product data and deconstructs the id of the passed product
    decrementProductsInventory(state, { id }) {
        // Compare the data in the module with the incoming id to obtain the corresponding product data
        const product = state.products.find(item= > item.id === id);
        // The inventory of each triggered product is reduced by oneproduct.inventory--; }}Copy the code

The button cannot be clicked when the inventory is 0

Determine whether the inventory of the current product is 0 by binding the Button’s Disabled event. If 0 is faulse, set it to true and let disabled take effect

<button :disabled=! "" product.inventory" @click="addProductToCart(product)">Add to shopping cart</button>
Copy the code