vue项目之购物车

简单的完成一个购物车项目,满足基本功能

安装创建好项目以后需要引入安装elementui和vuex

项目目录如下:(home.vue为主页面)

 

 

### ~home.vue

<template>
  <div>

    <!-- <div>我是默认显示页面</div> -->
    <!-- 绑定自定义事件,事件函数里面执行操作 -->
    <Nav v-if="see" :NavActiveIndex="activeIndex" @fromNavVal='fromNavValfn'></Nav>
    <div v-else>折叠以后{{activeIndex2}}</div>
    <router-view />
  </div>
</template>
<script>
  import Nav from './Nav.vue'
  export default {
    name: 'home',
    components: {
      //nav是home的子组件
      Nav
    },
    data() {
      return {
        activeIndex: '/buycar',
        activeIndex2: '1',
        see: true,
      };
    },
    methods: {
      fromNavValfn(val) {
        //此时的val为子组件中$emit中发射过来的参数
        // console.log(val)
        this.activeIndex2 = val;
        this.see = !this.see;
      }

    }
  }
</script>
<style>

</style>

 

###~About.vue

<template>
  <div>
   This is an about page
  </div>
</template>

<script>
</script>

<style>
</style>

 

###~Nav.vue

<template>
    <div>
    <!-- {{NavActiveIndex}} -->
      <!-- 父子组件之间通讯用props和emit,无关系组件之间需要用eventbus和vuex -->
      <!-- 要传入默认绑定激活的路由 default-active 此处在父组件home中 activeIndex: '/about' 默认绑定根路由下的about-->
      <el-menu
        :default-active="NavActiveIndex"
        class="el-menu-demo"
        mode="horizontal"
        @select="handleSelect"
        background-color="#545c64"
        text-color="#fff"
        router
        active-text-color="#ffd04b">
        <el-menu-item index="/buycar">购物车{{buycarCount}}</el-menu-item>
        <el-submenu index="2">
          <template slot="title">我的工作台</template>
          <el-menu-item index="/about">about</el-menu-item>
          <el-menu-item index="/test">test</el-menu-item>
          <el-menu-item index="/test2">test2</el-menu-item>
        </el-submenu>
        <el-menu-item index="3"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
      </el-menu>
      <button @click="click">折叠导航栏</button>
    </div>
</template>

<script>
  import bus from '@/assets/bus.js'
  export default {
      name: 'nav',
      props:{
        NavActiveIndex:String
      },
      data() {
        return {
          activeIndex: '1',
          activeIndex2: 'nav的123',
          buycarCount : 0,
        };
      },
      created(){
        //非父子组件之间接受方法
        //$on监听事件
        //数量改变的时候触发这个事件
        bus.$on('buycarCountChange',(num) => {
            this.buycarCount = num ;
        })
      },
      methods: {
        handleSelect(key, keyPath) {
          console.log(key, keyPath);
        },
        click(){
          //第一个参数为父组件绑定的自定义事件名字,第二个为携带的参数
            this.$emit('fromNavVal',this.activeIndex2)
        }
      }
  }
</script>

<style>
</style>

 

###~router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import home from '../views/Home.vue'
import test from '../views/test.vue'
// import about from '../views/About.vue'

Vue.use(Router)

export default new Router({
  mode:'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: home,
      children:[
        {
          path:'buycar',
          name:'buycar',
          component: () => import('@/components/buycar.vue')
        },
        {
          path: 'about',
          name: 'about',
          component: () => import ('../views/About.vue')
        },
        {
          path: 'test2',
          name: 'test',
          component: () => import ('../views/test2.vue')
        },
      ]
    },
    {
      path:'/test',
      component:test,
    }

  ]
})

 

###~assets /bus.js

import Vue from 'vue';
const EventBus = new Vue();

// console.log(1)
export default EventBus;


//事件注册中心
//所有的事件共同使用的
//所有的组件都可以向这个中心注册或者接受事件

 

###~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 router from './router'
// import store from './store'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  // store,
  components: { App },
  template: '<App/>'
})

 

###~store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// export default new Vuex.store({
//     state:{
//       buycarCount: 10
//     },
//     mutations:{
//         changebuyCarCount(state,num){
//           state.buycarCount = num ;
//         }
//     },
//     actions:{
// 
//     }
// 
// 
// })
// 

 

###~buycar.vue

<template>
  <div>
    <div v-if='list.length>0'>
      <div>
        <el-col :span="6">商品信息</el-col>
        <el-col :span="3">尺码/颜色</el-col>
        <el-col :span="3">吊牌价</el-col>
        <el-col :span="3">数量</el-col>
        <el-col :span="3">折扣</el-col>
        <el-col :span="3">总金额</el-col>
        <el-col :span="3">删除</el-col>
      </div>
      <div>
        <ul>
          <li v-for="item in list">
            <el-col :span="6">
              <el-checkbox v-model="selectArrCloth" :label="item.id" @change="item.checked = ! item.checked">{{item.name}}</el-checkbox>
              <img src="../assets/logo.png" style="width: 20px; height: 20px;">
            </el-col>
            <el-col :span="3">{{item.size}} {{item.color}}</el-col>
            <el-col :span="3">{{item.price}}</el-col>
            <el-col :span="3">
              <span @click="pre(item)">-</span>
              {{item.count}}
              <span @click="add(item)">+</span>
            </el-col>
            <el-col :span="3">{{item.active}}</el-col>
            <el-col :span="3">{{item.price * item.count * item.active}}</el-col>
            <el-col :span="3">
              <img src="../assets/logo.png" @click="del(item)" style="width: 30px; height: 30px;">
            </el-col>
          </li>
        </ul>
      </div>

    </div>
    <div v-else>购物车没有商品,快去逛逛</div>
    <div>
      <div class="cls">
      <!-- {{selectArrCloth}} -->
        <el-checkbox v-model="allCheck" @change="getAllChecked">全选</el-checkbox>
      </div>
      <div class="cls">合计 {{totalPrice}} 元</div>
      <div class="cls">已选商品 {{totalCount}} 件</div>
    </div>
  </div>

</template>

<script>
  import bus from '@/assets/bus.js'
  export default {
    data() {
      return {
        selectArrCloth: [],
        totalCount: 0,
        totalPrice: 0,
        allCheck: false,
        list: []
      }
    },
    created() {
      this.getList()
    },
    methods: {
      getAllChecked(val) {
        let selectArrCloth = [];
        if (val) {
          this.list.forEach(item => {
            //根据状态来添加价格,所以需要点击全选的时候循环给数组中数据给true反之给false
            item.checked = true;
            selectArrCloth.push(item.id)
          })
          this.selectArrCloth = selectArrCloth;
        } else {
          this.list.forEach(item => {
            item.checked = false;
          })
          this.selectArrCloth = [];
        }
        this.getTotalCount();
      },
      getTotalCount: function() {
        let totalCount = 0;
        let totalPrice = 0;
        //循环添加属性
        this.list.forEach(item => {
          if (item.checked) {
            totalPrice = totalPrice + (parseFloat(item.price).toFixed(2) * parseFloat(item.active) * item.count)
            totalCount = totalCount + parseInt(item.count)
          }
        })
        this.totalCount = totalCount;
        this.totalPrice = totalPrice;
      },
      getList() {
        //ajax
        let arr = [{
            name: '款式1',
            count: '2',
            size: 'L',
            color: '红色',
            price: '120',
            active: '0.5',
            id: '1'
          },
          {
            name: '款式2',
            count: '2',
            size: 'L',
            color: '红色',
            price: '103',
            active: '0.5',
            id: '2'
          },
          {
            name: '款式3',
            count: '2',
            size: 'L',
            color: '红色',
            price: '150',
            active: '0.5',
            id: '3'
          },
          {
            name: '款式4',
            count: '2',
            size: 'L',
            color: '红色',
            price: '160',
            active: '0.5',
            id: '4'
          },
        ]
        //循环给数组中元素增加一个默认checked为false的属性
        arr.forEach(item => {
          item.checked = false;
        })
        this.list = arr;
      },
      pre: function(item) {
        if (item.count == 0) return;
        item.count--;
        this.getTotalCount();
      },
      add: function(item) {
        item.count++;
        this.getTotalCount();
      },
      del: function(item) {
        //当点击这个图片的下标与数组中下标一致清除这个数据返回新数组
        let index = this.list.findIndex(cloth => {
          return cloth.id == item.id
        })
        // console.log(index)
        this.list.splice(index, 1)
        this.getTotalCount();
      },
    },
    watch: {
      //当id状态数组发生改变的时候会执行这个方法
      selectArrCloth: function() {
        this.getTotalCount();
        if (this.selectArrCloth.length == this.list.length) {
          this.allCheck = true;
        } else {
          this.allCheck = false;
        }
      },
      //监听list
      //此时list为一个对象
      list:{
        //当值为函数的时候不会进行深度遍历
        //需要让其数组进行深度遍历用handler方法
        //当deep为true的时候就会深度监听
        handler:function(){
          let count = 0;
          this.list.forEach(item => {
            count += parseInt(item.count)
          })
          bus.$emit('buycarCountChange', count)
        },
        deep: true
      }
    }
  }
</script>
<!-- 加上scoped为本组件生效 -->
<style scoped>
  .cls {
    display: inline-block;
    margin-top: 50px;
    margin-left: 400px;
    color: red;
  }
</style>

 

 

以上为购物车demo

posted @ 2019-11-16 15:08  阿蒙不萌  阅读(651)  评论(0编辑  收藏  举报