前端:Vue学习 - 购物车项目

前端:Vue学习 - 购物车项目

    • [1. json-server,生成后端接口](#1. json-server,生成后端接口)
    • [2. 购物车项目 - 实现效果](#2. 购物车项目 - 实现效果)
    • [3. 参考代码 - Vuex](#3. 参考代码 - Vuex)

1. json-server,生成后端接口

全局安装json-server,json-server官网为:json-server

js 复制代码
npm install json-server -g
// 全局安装

安装之后启动可能存在json-server与node版本不兼容导致的问题,为此,建议指定一个json-sever版本。

需要准备一个json文件,然后在json文件中写入json数据,利用json-server,就可以实现增删改查功能。

json 复制代码
{
    "books":[
        {"id":1,"bookName":"三国演义","price":23},            
        {"id":2,"bookName":"西游记","price":43},
        {"id":3,"bookName":"水浒传","price":33}
    ]
}

在这个json文件的目录下执行下述命令,


2. 购物车项目 - 实现效果

就是更改对应书本的购买数量,下面显示共计多少本书,以及需要多少钱实时更新。界面上构建了两个组件,分别为单个书本组件和下面总计组件。状态控制使用vuex.store来进行管理。

3. 参考代码 - Vuex

使用模块化对这个界面需要用到store进行封装,命名为books.js,代码如下:

js 复制代码
import axios from 'axios'

const state = {
    books2:[]
};
const mutations = {
    updateBooks(state,newBooks){
        state.books2 = newBooks;
    },
    updateCount(state,obj){
        const book = state.books2.find(item => item.id == obj.id);
        book.count = obj.newCount;
    }
};
const actions = {
    async getBooks(context){
        const res = await axios.get('http://localhost:3000/books');
        context.commit('updateBooks',res.data);
    },
    async updateBooks(context,obj){
        await axios.patch(`http://localhost:3000/books/${obj.id}`,{
            count:obj.newCount
        })
        // 后台修改数据
        context.commit('updateCount',{
            id:obj.id,
            newCount:obj.newCount
        });
        // 前端页面显示
    }
};
const getters = {
    totalCount(state) {
        return state.books2.reduce((sum, item) => sum + item.count,0);
    },
    totalPrice(state) {
        return state.books2.reduce((sum, item) => sum + item.count * item.price,0);
    }
};


export default {
    namespaced:true,
    state,
    mutations,
    actions,
    getters
}

在store目录下index.js文件引入这个模块即可。

js 复制代码
import books from './modules/books'

export default new Vuex.Store({
	...,
	modules:{
		books
	}
})

App.vue代码如下:

html 复制代码
<template>
  <div id="app">
    <ul>
      <li v-for="item in books2" :key="item.id" class="sp">
        <Cart :item="item"></Cart>
      </li>
    </ul>
    <TotalPrice class="total-price-position"></TotalPrice>
  </div>
</template>

<script>
import {mapState} from 'vuex'
import Cart from './components/Cart.vue';
import TotalPrice from './components/TotalPrice.vue';

export default {
  name: 'App',
  components: {
    Cart,TotalPrice
  },
  async created(){
    this.$store.dispatch('books/getBooks');
  },
  computed:{
    ...mapState('books',['books2'])
  }
}
</script>

<style lang="less" scoped>
  #app{
    position: relative;
    width: 100%;
    height: 700px;
    .total-price-position{
      position: absolute;
      bottom: 0;
      left: 0;
    }
  }
  .sp{
    height: 100px;
    margin-top: 5px;
    border-bottom: 1px solid yellow;
  }
</style>

当个书本组件代码如下:Cart.vue

html 复制代码
<template>
    <div class="sp-item">
        <!-- <img :src="require('@/static/'+item.bookName+'.png')" alt=""> -->
        <img src="@/static/水浒传.png" alt="">
        <p class="sp-name">{{item.bookName}}</p>
        <p class="sp-price">¥{{item.price}}</p>
        <div class="sp-btn">
            <button class="sp-l-btn" @click="btnClick(-1)">-</button>
            <p class="sp-count">{{item.count}}</p>
            <button class="sp-r-btn" @click="btnClick(1)">+</button>
        </div>
    </div>
</template>

<script>

export default {
    name:'Cart',
    props:{
        item:Object
    },
    methods:{
        btnClick(step){
            const newCount = this.item.count + step;
            const id = this.item.id;

            if(newCount < 1)
                return
            this.$store.dispatch('books/updateBooks',{
                id,
                newCount
            })
        }
    }
}
</script>

<style lang="less" scoped>
    .sp-item{
        width: 100%;
        height: 100%;
        position: relative;
        >*{
            position: absolute;
        }
        img{
            width: 100px;
            top: 50%;
            left: 0;
            transform: translateY(-50%);
        }
        .sp-name{
            top: 6px;
            left: 104px;
            font-size: 18px;
        }
        .sp-price{
            bottom: 4px;
            left: 104px;
            color: red;
            font-weight: 600;
        }
        .sp-btn{
            bottom: 4px;
            right: 2px;
            >*{
                display: inline-block;
                width: 20px;
                height: 20px;
                line-height: 20px;
                text-align: center;
            }
        }
    }

</style>

总计组件代码如下:TotalPrice.vue

html 复制代码
<template>
    <div class="total-price-div">
        <span class="z-span"></span>
        共<span>{{totalCount}}</span>本,总共<span class="total-price">{{totalPrice}}</span>元
        <button>结算</button>
    </div>
</template>

<script>
import {mapGetters} from 'vuex';

export default {
    name:"TotalPrice",
    computed:{
        ...mapGetters('books',['totalCount','totalPrice'])
    }
}
</script>

<style scoped lang="less">
    .total-price-div{
        height: 60px;
        width: 100%;
        line-height: 60px;
        padding: 2px;
        background-color: #e1dcdc;
    }
    .total-price{
        color: red;
    }
    .z-span{
        width: 146px;
        display: inline-block;
    }
    button{
        color: white;
        background-color: green;
        border-radius: 6px;
        width: 60px;
        height: 40px;
        line-height: 40px;
    }
</style>

项目中需要用到axios、less、vuex。

相关推荐
车厘小团子1 天前
🎨 前端多主题最佳实践:用 Less Map + generate-css 打造自动化主题系统
前端·架构·less
小徐_23338 天前
uni-app 还在手写请求?alova 帮你全搞定!
前端·uni-app·axios
小徐_233310 天前
uni-app 网络请求终极选型:uni.request、axios、uni-network、alova 谁才是你的真命请求库?
前端·uni-app·axios
一枚前端小能手11 天前
💎 Less/Sass写出优雅代码的4个高级技巧
css·less
胡西风_foxww14 天前
如何在nuxt项目中使用axios进行网络请求?
axios·网络请求·nuxt·异步·nuxt.config.js
盛夏绽放15 天前
原生CSS vs LESS:样式表语言的进化之旅
css·tensorflow·less
一个很帅的帅哥17 天前
JavaScriptAJAX异步请求:XHR、Fetch与Axios对比
javascript·axios·xmlhttprequest·fetch
qczg_wxg17 天前
王学岗Axios的data加密报错的问题
axios
胡西风_foxww19 天前
Vue2 项目实现 Gzip 压缩全攻略:从配置到部署避坑指南
nginx·部署·vue2·配置·gzip·压缩·攻略
用户849137175471619 天前
vue-element-plus-admin 第5期|Axios实战:HTTP 请求与数据处理
前端框架·axios·前端工程化