vuex购物车

Hi,这个购物车是通过 koa后台读取json数据,前台通过vue,vuex写的前台,小伙伴们主要还是思路要清楚哦,下面先来看看这个小型案例的魔法吧!!!!!

  • home.js
    • 主要写的首页渲染,,以及添加购物车的功能点
<template>
    <div class="home">
        <header>首页</header>
        <section>
              <div class="cont">
                    <dl v-for="(item,index) in data" :key="index">
                        <dt><img :src="item.img" alt=""></dt>
                        <dd>
                            <p class="tit"><span>{{item.title}}</span><button @click="add(item)">来一份</button></p>
                            <p>{{item.intro}}</p>
                            <p>{{item.price}}</p>
                        </dd>
                    </dl>
           </div>
        </section>
      <Footer></Footer>
    </div>
</template>
<script>
import Footer from "../components/footer"
import axios from 'axios'
import {mapState,mapMutations} from 'vuex'
export default {
    props:{

    },
    components:{
        Footer,
    },
    data(){
        return {
            data:[]
        }
    },
    computed:{
        ...mapState(['adddata']),
        
    },
    methods:{
        ...mapMutations(['changedata']),
        add(adddata){  //添加进入购物车
            this.$router.push("/shopcar")
            this.$store.commit('changedata',adddata)
        }
    },
    created(){
        axios.get('/api').then(res => {
            this.data=res.data.message
        })       
    }}
</script>
<style scoped lang="">
  
    .home{
        height: 100%;
        width: 100%;
        display: flex;
        flex-direction: column;
    }
    header{
        height: 44px;
        width: 100%;
        background: salmon;
        line-height: 44px;
        text-align: center;
    }
    section{
        flex:1;
        overflow-y:auto;
    }
 
    .cont dl{
        width: 100%;
        display: flex;
        padding: 8px;
    }
    dl dt{
        width: 110px;
        height: 110px;
        background: skyblue;
        flex-shrink: 0;
    }
    dl dt img{
        height:100%;
        width:100%;
    }
    dl dd{
        flex: 1;
        padding-left: 10px;
        line-height: 2.2;
    }
    dl dd .tit{
        display: flex;
        justify-content: space-between;
        padding-right: 25px;
    }
    dl dd .tit button{
        border: none;
        background: none;
        outline: none;
        color: rgb(6, 196, 202);
        font-size:16px;
    }
</style>
  • shopcar.js
  • 主要的功能是添加订单,以及其他的传参
<template>
    <div class="shopcar">
        <header>购物车</header>
       <section>
            <!--购物车  -->
           <div class="content">
                <div class="title" v-for="(item,index) in adddata" :key="index">
                    <div class="names">
                        <span>{{item.title}}</span>
                        <span>{{item.price}}</span>
                    </div>
                   <div class="btn">
                        <button @click="add(item.num-1,item.id)">-</button>
                        <span>{{item.num}}</span>
                        <button @click="add(item.num+1,item.id)">+</button>
                   </div>
              </div>
                <div class="allPrice">
                    <span>总价:{{allPrice}}</span>
                    <span>总数:{{allNum}}</span> 
                </div>
           </div>
             <!-- 订单 -->
            <div class="order">
                 <p>联系方式</p>
                 <div class="froms">
                        <p>姓名:<input type="text"  placeholder="请输入姓名" name id v-model="name"></p>
                        <p>电话:<input type="text"  placeholder="请输入电话" name id v-model="tel"></p>
                        <p>地址:<input type="text"  placeholder="请输入地址" name id v-model="address"></p>

                 </div>
                 <div class="bottom">
                      <button @click="clearAll">清除购物车</button>
                      <button @click="goOrder(allPrice)">下单</button>
                 </div>
            </div>
       </section>
      <Footer></Footer>
    </div>
</template>
<script>
import Footer from "../components/footer"
import {mapActions,mapState,mapMutations} from "vuex"
export default {
    props:{

    },
    components:{
       Footer
    },
    data(){
        return {
            name:"",
            tel:null,
            address:""
      
        }
    },
    computed:{
        ...mapState(["adddata","allPrice","allNum"]) 
         
    },
    methods:{
        ...mapMutations(["addOrderList","clearAll"]),
        add(num,id){ //加减
            if(num<=1){
                num=1;
            }
            this.$store.commit("addnum",{num,id})
        },
         //清空购物车
        clearAll(){

        },
        goOrder(allPrice){  //跳转到订单页面
        //获取本地时间
         let time=new Date().toLocaleString() 
          let res=this.adddata.filter(item=>item.num)
         let orderArr=[];
         let obj={}
          res.map(item=>{
              obj={
                title:item.title,
                 num:item.num
              }
              orderArr.push(obj)
              console.log(orderArr,"111")
          })

          //获取订单信息
           let orderObj={
                time:time,
                orderArr:orderArr,
                con: [{ con: this.name }, { con: this.tel }, { con: this.address }],
                allPrice,
                tit:"货到付款"
          }
          //添加订单
          this.addOrderList(orderObj)  //传参
          this.$router.push("/order")
       
        },
    },
    created(){
        

    },
    mounted(){

    }
}
</script>
<style scoped lang="">
   .shopcar{
        height: 100%;
        width: 100%;
        display: flex;
         flex-direction: column; 
   }
   header{
         height: 44px;
        width: 100%;
        background: salmon;
        line-height: 44px;
        text-align: center;
   }
   section{
       flex:1;
       overflow-y: auto;
   }
   section .title{
       display: flex;
       width:100%;
       height:80px;
       padding:0px 10px;
       box-sizing:border-box;
       align-items: center;
       border-bottom:1px solid #ccc;
   }
   .title .names{
       width:240px;;
       height:80px;
       line-height:80px;
   }
   .title .names span:nth-child(2){
       margin-left:20px;
   }
 
  .btn{
      flex:1;
      height:80px;
     line-height: 80px;
     
  }
  .btn button{
      height: 24px;
      width:24px; 
      margin:0px 6px;
  }
  .allPrice{
      height: 40px;
      width:100%;
      line-height: 40px;
      background:silver;
      justify-content:space-around;
      display: flex;
  }
  .order{
      width:100%;
      height:150px;
     
  }
  .order>p{
      height: 40px;
      text-indent: 12px;
      line-height: 40px;
      font-weight: bold;
      color:deepskyblue;

  }
  .froms{
     height: 120px;
     width:100%;
  }
  .froms p{
      width:100%;
      height:35px;
      margin-left:10px;
  }
  .froms p input{
      width:75%;
      height:30px;
      margin-left:5%;
      text-indent: 10px;
      border:1px solid #ccc;

  }
  .bottom{
      height:50px;
      width:100%;
      display: flex;
      justify-content: space-around;
  }
  .bottom button{
      height:40px;
      width:110px;
      background: skyblue;
      color:#fff;
      border:0;
      font-size:16px;
  }
</style>
  • order.js
  • 对订单页面的渲染
<template>
    <div>
          <header>订单</header>
        <section>
           <div class="content">
                <div class="title" v-for="(item,index) in orderList" :key="index">
                <p>订餐时间:{{item.time}}</p>
                    <h4 style="color:#f7883a">订餐内容<p v-for="(ite,ind) in item.orderArr" :key="ind"><span>{{ite.title}}</span><span>{{ite.num}}</span></p></h4>
                    <h4>订餐信息<p v-for="(val,k) in item.con" :key="k"><span>{{val.con}}</span><span>{{val.con}}</span><span>{{val.con}}</span></p></h4>
                <p style="color:red">合计金额{{item.allPrice}}</p> 
                <p>支付状态:{{item.tit}}</p>
          </div>
           </div>
        </section>
        <Footer></Footer>
      
    </div>
</template>
<script>
import Footer from "../components/footer"
import {mapActions,mapState,mapMutations} from "vuex"
export default {
    props:{
    },
    components:{
      Footer

    },
    data(){
        return {

        }
    },
    computed:{
        ...mapState(["orderList"])
    },
}
</script>
<style scoped lang="">
 div{
        height: 100%;
        width: 100%;
        display: flex;
        flex-direction: column;
   }
   header{
         height: 44px;
        width: 100%;
        background: salmon;
        line-height: 44px;
        text-align: center;
   }
   section{
       flex:1;
       overflow-y: auto;
   }
   .title{
        padding:15px 0px;
        width:100%;
        padding:0px 10px;
        box-sizing: border-box;
        border:1px solid #ccc;
        margin-top:2px;
   }
   .title p{
       line-height: 1.9;
   }
</style>
  • mine.js
    <div>
       <header>我的</header>
       <section></section>
       <Footer></Footer>
    </div>
</template>
<script>
import Footer from "../components/footer"
export default {
    props:{

    },
    components:{
        Footer

    },
    data(){
        return {

        }
    },
    computed:{

    },
    methods:{

    },
    created(){

    },
    mounted(){

    }
}
</script>
<style scoped lang="">
 div{
        height: 100%;
        width: 100%;
        display: flex;
        flex-direction: column;
   }
   header{
         height: 44px;
        width: 100%;
        background: salmon;
        line-height: 44px;
        text-align: center;
   }
   section{
       flex:1;
       overflow-y: auto;
   }
</style>
store下面有三个文件
  • index.js
  • store下面的index.js需要在main.js引入进去注册实例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import state from './car/state'
import mutations from './car/mutations.js'
export default new Vuex.Store({
    mutations,
    state,   
})
  • state.js
const state ={
    adddata:[],
    allPrice:0,
    allNum:0,
   orderList:[] 
}
export default state;
  • mutation.js
const mutations = {
	changedata(state, value) {
		//点击添加购物车
		console.log(state.adddata, value);
		if (state.adddata.length == 0) {
			state.adddata.push(value);
		} else {
			let ind = state.adddata.findIndex(item => {
				return item.id == value.id;
			});
			if (ind == -1) {
				state.adddata.num = 1;
				state.adddata.push(value);
			} else {
				state.adddata[ind].num++;
			}
        }
          let sum = 0;
		state.adddata.map(item => {
			return sum += item.price * item.num;
        });
        state.allPrice=sum
         
        //总数
        let nums=0;
        state.adddata.map((item,index)=>{
            return nums+=item.num*1
        })
        state.allNum=nums
	},
	addnum(state, obj) {
		//点击加减
		let ind = state.adddata.findIndex(item => {
			return item.id == obj.id;
		});
        state.adddata[ind].num = obj.num;
       
        //总价
        let sum = 0;
		state.adddata.map(item => {
			return sum += item.price * item.num;
        });
        state.allPrice=sum
       
        let nums=0;
        state.adddata.map((item,index)=>{
            return nums+=item.num*1
        })
        state.allNum=nums		
	},
	clearAll(state, obj1) {
		state.adddata.splice(0);
		state.allPrice = 0;
	},
	
	addOrderList(state,objs){
     state.orderList.push(objs)
     	console.log(state.orderList,"qqqq")	
	}
};

export default mutations;

  • router index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/home'
import Mine from '../views/mine'
import Order from "../views/order"
import Shopcar from "../views/shopcar"
Vue.use(Router)
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },{
      path: '/mine',
      name: 'Mine',
      component: Mine
    },{
      path: '/order',
      name: 'Order',
      component: Order
    },{
      path: '/shopcar',
      name: 'Shopcar',
      component: Shopcar
    }
  ]
})

  • footer.js 封装的footer.js
  <footer>
            <router-link to="/">首页</router-link>
            <router-link to="/shopcar">购物车</router-link>
            <router-link to="/order">订单</router-link>
            <router-link to="/mine">我的</router-link>
        </footer>
  • data.json
[
	{
		"id": 0,
		"img":"/static/img/1 (1).jpg",
		"title": "北京老杂酱面",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 24,
		"num": 1
	},
	{
		"id": 1,
		"img":"/static/img/1 (3).jpg",
		"title": "油泼面",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 13,
		"num": 1
	},
	{
		"id": 2,
		"img":"/static/img/2.jpg",
		"title": "酸辣土豆丝",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 12,
		"num": 1
	},
	{
		"id": 3,
		"img":"/static/img/3.jpg",
		"title": "家乡味糖醋排骨",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 20,
		"num": 1
	},
	{
		"id": 4,
		"title": "魏家凉皮",
			"img":"/static/img/1 (2) - 副本.jpg",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 34,
		"num": 1
	},
	{
		"id": 5,
			"img":"/static/img/5.jpg",
		"title": "家乡味的酸汤肥牛",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 21,
		"num": 1
	},
	{
		"id": 6,
		"title": "北京烤鸭",
			"img":"/static/img/4.jpg",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 19,
		"num": 1
	},
	{
		"id": 7,
		"title": "家乡凉拌黄瓜",
			"img":"/static/img/3.jpg",
		"intro": "苏格兰打卤面,大杯可乐",
		"price": 43,
		"num": 1
	}
]

server index.js
  • koa 后台读取数据,返回数据
let koa = require("koa");

let app = new koa();

let fs=require('fs');

let data=require('../src/mock/data.json')

let bodyParser=require('koa-bodyparser')
console.log(data)
console.log(bodyParser)
app.use(bodyParser())
app.use(async function(ctx){
    // await next();
    ctx.body={
        message:JSON.parse(fs.readFileSync('../src/mock/data.json'))
    }
})

app.listen(9090)
发布了103 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/M106588L/article/details/100698523
今日推荐