Vue+vuex+vue-router+sass+webpack+mint-ui 全家桶 開發商城(購物車)

先上截圖,項目跑起來就是這個樣子,是不是符合你的購物車?哈哈哈哈哈哈哈,我就知道




購物車實現的功能:添加購物車、選擇某商家下所有商品、選擇指定商品、更新指定商品數量(加減)、刪除指定商品、全選商品、清空購物車,等功能;

準備工作:

使用Vue全家桶(vue2.0+vue-router+vuex+webpack+sass+mint-ui),由於都是靜態數據,就沒有使用axios;

注:通常使用npm安裝會出現以下報錯,安裝失敗。(網路問題)

可以通過淘寶的npm鏡像安裝node-sass,解決以上問題。

$ npm install -g cnpm --registry=https://registry.npm.taobao.org  (安裝淘寶鏡像)

安裝 vue-cli: 

cnpm install -g vue-cli  //全局安裝vue-cli;
vue init webpack User //User爲項目名稱
cd User //進入User項目
cnpm install //安裝依賴
npm run dev //運行項目
此時項目 基本運行起來,在瀏覽器輸入:http://localhost:8080

安裝vue-router,vuex,sass,mint-ui

cnpm install vue-router --save //安裝路由
cnpm install vuex -S //暗轉vuex
cnpm install node-sass --save-dev //安裝node-sass環境
cnpm install sass-loader --save-dev //安裝sass-loader

cnpm install mint-ui --save //安裝mint-ui



到這裏基本安裝完成,然後在User->src文件夾中創建 store,router,view文件夾,在store,router,view文件裏創建如下目錄

                     

下面來修改main.js 文件: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 VueRouter from 'vue-router'
import axios from 'axios'

import App from './App'
import routes from './router'//導入註冊路由表
import store from './store'//導入vuex

import MintUI from 'mint-ui'
import 'mint-ui/lib/style.css'

import '@/assets/css/reset.css'

Vue.config.productionTip = false

Vue.use(MintUI)
Vue.use(VueRouter)

Vue.prototype.$ajax = axios

const router = new VueRouter({
  routes
})

router.beforeEach(({meta, path}, from, next) => {
  var { auth = true } = meta
  var isLogin = Boolean(store.state.user.phone) //true用戶已登錄, false用戶未登錄
  console.log('isLogin:'+isLogin+',,,auth:'+auth+',,,path:'+path)

  if (!auth && !isLogin && path !== '/login') {
    return next({ path: '/login' })
  }
  next()
})


/* eslint-disable no-new */
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

  現在編寫路由註冊表 :router->index.js
import Vue from 'vue'
// import Router from 'vue-router'
// import index from '@/components/index'

import main from '@/views/main'

import mainpage from '@/views/barItem/mainpage'
import productList from '@/views/barItem/productList'
import shopping from '@/views/barItem/shopping'
import usercenter from '@/views/barItem/usercenter'

import details from '@/views/details/details'

import seller from '@/views/seller/seller'

import classy from '@/views/classy/classy'

import login from '@/views/login/login'

// Vue.use(Router)

export default [
  {
    path: '/',
    name: 'main',
    component: main,
    children:[
      {
        path:'/',
        name:'精選',
        component:mainpage
      },
      {
        path:'/productList',
        name:'逛逛',
        component:productList
      },
      {
        path:'/shopping',
        name:'購物車',
        meta: { auth: false },
        component:shopping
      },
      {
        path:'/usercenter',
        name:'我的',
        component:usercenter
      },
    ]
  },
  {
    path:'/details',
    name:'產品詳情',
    component:details
  },
  {
    path:'/classy',
    name:'分類',
    component:classy
  },
  {
    path:'/seller',
    name:'賣家主頁',
    component:seller
  },
  {
    path:'/login',
    name:'登錄',
    component:login
  },
  {
    path: '*', //其他頁面,強制跳轉到登錄頁面
    redirect: '/login'
  }
]

現在編寫重中之重的就是,store狀態管理了

在store->modeles文件下,有兩個js文件,解釋下:user.js是保存登錄狀態,cart.js是保存購物車狀態;(一波強加解釋.......);

store->index.js(這裏不做太多解釋了):

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


import user from './modules/user'//導入user
import cart from './modules/cart'//導入購物車

Vue.use(Vuex)//使用vuex

export default new Vuex.Store({
  modules: {
    user,
    cart
  },
  strict: process.env.NODE_ENV !== 'production', //在非生產環境下,使用嚴格模式
})

store->modeles->user.js:

import Vue from 'vue'

export const USER_SIGNIN = 'USER_SIGNIN' //登錄成功
export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登錄

export default {
  state: JSON.parse(sessionStorage.getItem('user')) || {},
  mutations: {
    [USER_SIGNIN](state, user) {
      sessionStorage.setItem('user', JSON.stringify(user))
      Object.assign(state, user)//Object.assign() 方法用於將所有可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
    },
    [USER_SIGNOUT](state) {
      sessionStorage.removeItem('user')
      Object.keys(state).forEach(k => Vue.delete(state, k))//Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用 for...in 循環遍歷該對象時返回的順序一致 (兩者的主要區別是 一個 for-in 循環還會枚舉其原型鏈上的屬性)。
    }
  },
  actions: {
    [USER_SIGNIN]({commit}, user) {
      commit(USER_SIGNIN, user)
    },
    [USER_SIGNOUT]({commit}) {
      commit(USER_SIGNOUT)
    }
  }
}

store->modeles->cart.js

//初始化數據
const state = {
  detailsData:{},//臨時保存詳情頁信息
  addCart:[]//添加到購物車的商品(已選商品)
}


//getter 拋出去的數據
const getters ={
  //獲取詳情頁信息
  getDetails:state => {
    return state.detailsData
  },
  //購物車的列表
  cartDataList:state =>{
    console.log(state.addCart)
    return state.addCart;
  },
  //計算總價
  totalPrice:(state,getters) => {
    let total = 0;
    getters.cartDataList.map(//遍歷所有商家
      item => {
        item.goodsList.map((n) => {//遍歷該商家下所有商品
          if(n.checked === true){//篩選選中的商品

            //---------這裏可以添加運費,減免運費的等條件-------------

            total += n.goodsInfo.price * n.number;//計算所有選中商品價格*數量,相加
          }
        });
      }
    );
    return total;
  },
  //計算選中商品總數量
  totalNum:(state,getters) => {
    let total = 0;
    getters.cartDataList.map(
      item => {
        item.goodsList.map((n) => {//遍歷該商家下所有商品
          if(n.checked === true){//篩選選中的商品
            total += n.number//計算所有選中商品數量,相加
          }
        });
      }
    );
    return total;
  },
  //提交按鈕是否被激活
  isActive:(state,getters) => {
    let active = true;
    getters.cartDataList.map(item => {
      active = item.goodsList.find(n => n.checked === true );
    })
    return active;
  }
}


//action 異步的操作
const actions = {
  //設置詳情頁信息
  setDetails({commit},item){
    commit('setDetails',{item})
  },
  //添加購物車
  addToCart({commit},item){
    commit('addToCart',{item})
  },
  //修改全選狀態
  setSelectAll({commit},val){
    commit('setSelectAll',val)
  },
  //選擇商家下所有商品
  checkedShop({commit},id){
    commit('checkedShop',id)
  },
  //選擇某一件商品
  checkedGodds({commit},item){
    commit('checkedGodds',item)
  },
  //更新某一件商品數量
  updateGoods({commit},item){
    commit('updateGoods',{item})
  },
  //刪除某一件商品
  delGodds({commit},item){
    commit('delGodds',{item})
  },
  //清空購物車
  clearAllCart({commit}){
    commit('clearAllCart')
  }
}


//mutations 同步的操作
const mutations = {
  //設置詳情頁信息
  setDetails(state,item){
    state.detailsData = item;
  },
  //添加購物車方法
  addToCart(state,{item}){//當接受的參數爲對象時用{},字符串時不用{}

    let recordAdmin = state.addCart.find(n => n.adminId === item.adminId);//遍歷購物車是否存在該商家

    if(!recordAdmin){//購物車不存在該商家

      state.addCart.push({//在數組首部插入,確保新加入購物車的商品在購物車列表最上部顯示
        adminId:item.adminId,//商家ID
        adminName:item.adminName,//商家名稱
        adminAvatar:item.avatar,//商家頭像
        shopChecked:true,//店鋪全選
        goodsList:[
          {
            id:item.id,//商品
            checked:true,//商品是否被選中
            goodsInfo:item,//商品詳情
            number:1//添加數量
          }
        ]
      })

    }else{//購物車已存在該商家

      let recordProduct = recordAdmin.goodsList.find(n => n.id === item.id);//遍歷是否存在該商品

      if(!recordProduct){//購物車不存在該商品
        recordAdmin.goodsList.push(
          {
            id:item.id,//商品
            checked:true,//商品是否被選中
            goodsInfo:item,//商品詳情
            number:1//添加數量
          }
        )
      }else{//購物車存在該商品
        recordProduct.checked = true;//商品是否被選中
        recordProduct.number++
      }

      console.log(recordAdmin)
    }

    console.info(state.addCart)
  },
  //修改全選狀態
  setSelectAll(state,val){
    state.addCart.map(item => {//遍歷所有商家
      item.shopChecked = val;//修改該商家選中狀態
      item.goodsList.map(n => {//遍歷該商家下所有商品
        n.checked = val;//修改該商品選中狀態
      })
    })
  },
  //選擇商家
  checkedShop(state,id){
    let shopItem = state.addCart.find(n => n.adminId === id);//獲取(adminID===item.shopId)商家
    shopItem.goodsList.map((n) => {//遍歷該商家下所有商品
      if(!shopItem.shopChecked){//商家下商品全選
        n.checked != true ? n.checked = !n.checked : '';//已選中的商品不執行
      }else{
        n.checked = false;
      }
    });
    shopItem.shopChecked = !shopItem.shopChecked;//修改商家選中狀態
  },
  //選擇商品
  checkedGodds(state,item){
    let shopItem = state.addCart.find(n => n.adminId === item.shopId);//獲取(adminID===item.shopId)商家
    let goodsItem = shopItem.goodsList.find(n => n.id === item.goodsId);//該商家下(id===item.goodsId)的商品

    goodsItem.checked = !goodsItem.checked;//修改商品選中狀態

    let shopChecked = shopItem.goodsList.find(n => n.checked === false);//查看該商家下是否有沒有選中的商品

    if(!shopChecked){//沒有未選中的商品
      shopItem.shopChecked = true;//將該商家選中狀態
    }else{
      shopItem.shopChecked = false;
    }

  },
  //更新商品數量
  updateGoods(state,item){
    let shopItem = state.addCart.find(n => n.adminId === item.shopId);//獲取(adminID===item.shopId)商家
    let goodsItem = shopItem.goodsList.find(n => n.id === item.goodsId);//該商家下(id===item.goodsId)的商品

    goodsItem.number = goodsItem.number+item.value < 1 ?1 : goodsItem.number+item.value;//修改該商品數量
  },
  //刪除購物車指定商品
  delGodds(state,item){
    let shopItemIndex = state.addCart.findIndex(n => n.adminId === item.shopId);//獲取(adminID===item.shopId)商家index
    let goodsItemIndex = state.addCart[shopItemIndex].goodsList.findIndex(n => n.id === item.goodsId);//該商家下(id===item.goodsId)的商品index

    state.addCart[shopItemIndex].goodsList.splice(goodsItemIndex,1);//刪除該商家該商品

    if(!state.addCart[shopItemIndex].goodsList.length){//商品爲空,刪除該商家
        state.addCart.splice(shopItemIndex,1);
    }
  },
  //清空購物車
  clearAllCart(state){
    state.addCart = []
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

到這裏基本的都完成了,剩下的就是組件調用 vuex裏的方法了(只上乾貨,下面我會附上源碼):

登錄功能:

import {mapActions} from 'vuex'
import {USER_SIGNIN} from '@/store/modules/user'

export default {
  data(){
    return{
      form:{
        phone:'',
        password:''
      }
    }
  },
  methods:{
    ...mapActions([USER_SIGNIN]),
    submit() {
      this.btn = true
      if(!this.form.phone || !this.form.password) return
      this.USER_SIGNIN(this.form)
      this.$router.replace({ path: '/' })
    }
  }
}

退出登錄:

import {mapActions} from 'vuex'
import {USER_SIGNOUT} from '@/store/modules/user'

export default {
  name: 'hello',
  data () {
    return {
    }
  },
  methods: {
    ...mapActions([USER_SIGNOUT]),
    sigout:function(){
      console.log('退出登錄')
      this.USER_SIGNOUT()
      this.$router.replace({ path: '/usercenter/login' })
    }
  }
}

購物車頁面:

import {mapGetters,mapMutations} from 'vuex'
export default {
  data(){
    return{

    }
  },
  computed:{
    ...mapGetters(['cartDataList','totalPrice','totalNum','isActive']),//cartDataList:購物車列表;totalPrice:購物車總價;totalNum:確定購買數量;isActive:按鈕是否被激活
    //全選按鈕
    selectAll: {
      //獲取是否全選
      get: function () {
        return this.cartDataList.filter(function (items) { //動態判斷全選按鈕是否選中(根據 選中的商店數量==items數組長度)
          return items.shopChecked === true;
        }).length == this.cartDataList.length;
      },
      //修改全選按鈕狀態
      set: function (val) {
        this.setSelectAll(val);//調用methods中setSelectAll方法,修改vuex中所有商家和商品選中狀態
      }
    }
  },
  methods:{
    ...mapMutations(['setSelectAll','checkedShop','checkedGodds','updateGoods','delGodds','clearAllCart']),

    //選擇商家
    selectedShop(adminId){
      this.checkedShop(adminId)
    },
    //選擇商品
    selectedGoods(shopId,goodsId){
      let item = {
        shopId:shopId,//商家id
        goodsId:goodsId//商品id
      }
      this.checkedGodds(item)
    },
    //更新指定商品數量,加減
    update(n,shopId,goodsId){
      let item = {
        value:n,//改變數值
        shopId:shopId,//商家id
        goodsId:goodsId//商品id
      };
      console.log(item)
      this.updateGoods(item);
    },
    //刪除指定商品
    delBtn(shopId,goodsId){
      this.$messageBox.confirm('確定執行此操作?').then(action => {
        let item = {
          shopId:shopId,//商家id
          goodsId:goodsId//商品id
        }
        console.info(item)
        this.delGodds(item)
      });
    },
    //清空購物車
    clearCart(){
      this.clearAllCart();
    },
    //結算按鈕
    submitBtn(isActive){
      console.log(isActive)
    }
  }
}

想看源碼的小朋友,看這裏:https://github.com/jianjiayi/User 點擊打開鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章