vue+vuex实现响应式布局加购物车简单案例

哈喽,我又来了,vue想必大家都用的挺多的,所以,今天就用vue和vuex来写一个案例,那么,闲话不多说,我们就开始吧!
在写之前,想必大家对购物车这一电商案例会有很多的经历吧,那今天就写个购物车案例吧!为了增加点难度,我会加入响应式布局,代码如下:

//home
<template>
  <div class="home">
    <div class="home_header">
      <div>admin</div>
      <div>logout</div>
      <div @click="addCartClick">
        <img src="../assets/gouwuche.png" alt/>
      </div>
    </div>
    <div class="home_price_con">
      <div class="home_price">
        <div>
          sort by:
          <span>Default</span>
        </div>
        <div @click="defalut">
          price
          <span
            v-for="(item,index) in option"
            :key="index"
          >{{value===0?item.title1:item.title}}</span>
        </div>
      </div>
    </div>
    <div class="home_price_con_active">
      <div class="home_price_active">
        <div @click="defalut">
          <span>Default</span>
          price
          <span
            v-for="(item,index) in option"
            :key="index"
          >{{value===0?item.title1:item.title}}</span>
        </div>
        <div>sort by:</div>
      </div>
    </div>
    <div class="home_content_con">
      <div class="home_content">
        <div class="home_left">
          <h3>PRICE</h3>
          <div
            v-for="(item,index) in filter"
            :key="index"
            :class="selectIndex===index?'home_left_item_active':'home_left_item' "
            @click="onClick(index,item)"
          >{{item.title}}</div>
        </div>
        <div class="home_right">
          <el-row
            :gutter="15"
          >
            <el-col
              :xs="24"
              :sm="8"
              :md="8"
              :lg="6"
              :xl="6"
              v-for="(element,index) in items"
              :key="index"
            >
              <div class="item_conetent">
                <div class="item_content_image">
                  <img :src="element.productImage" alt />
                </div>
                <div class="item_content_name_price">
                  <div>{{element.productName}}</div>
                  <div class="item_content_price">{{element.salePrice}}</div>
                </div>
                <div class="home_list_item_button">
                  <button @click="addCart(element)">加入购物车</button>
                </div>
              </div>
            </el-col>
          </el-row>
        </div>
      </div>
    </div>
    <div class="home_loading" v-show="isShow">
      <img src="../assets/loading2.gif" alt="" />
    </div>
    <div v-show="show" class="home_loadings">
      <img src="../assets/640.webp" alt="" />
      <button @click="onClicked">点击取消</button>
    </div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  name: "Home",
  components: {},
  data() {
    return {
      filter: [],
      list: [],
      items: [],
      selectIndex: 0,
      option: [{ title1: "↑" }, { title: "↓" }],
      value: 0,
      isShow:false,
      temps:false,
      show:false,
    };
  },
  methods: {
    onClick(index, item) {
      // console.log(item);
      this.selectIndex = index;
      var temp = [];
      if (item.title == "ALL") {
        temp = this.list;
      } else {
        this.list.forEach(ele => {
          if (ele.salePrice <= item.high && ele.salePrice > item.low) {
            temp.push(ele);
          }
        });
      }
      this.items = temp;
    },
    defalut() {
      if (this.value === 1) {
        this.value = 0;
        this.list.sort((a, b) => {
          return a.salePrice - b.salePrice;
        });
      } else if (this.value === 0) {
        // window.console.log(111)
        this.value = 1;
        this.list.sort((a, b) => {
          return b.salePrice - a.salePrice;
        });
      }
    },
    onClicked(){
      this.show =false
    },
    addCart(element) {
      // window.console.log(element)
      this.$store.dispatch("getCartItem",element)
    },
    addCartClick(){
      this.$router.push("/cart")
    }
  },
  mounted() {
    axios.get("http://localhost:8080/data.json").then(res => {
      window.console.log(res.data.result);
      this.filter = res.data.result.filter;
      this.list = res.data.result.list;
      this.items = res.data.result.list;
    });
    window.addEventListener("scroll",()=>{
      var scrolltop = document.documentElement.scrollTop;
      var scrollhight = document.documentElement.scrollHeight;
      var cliHight = document.documentElement.clientHeight;

      var offSet =scrollhight-cliHight-scrolltop
      window.console.log(offSet)
      if (offSet <= 1) {
        if (this.temps) {
         this.isShow = true
          window.setTimeout(()=>{
             axios
            .get("http://localhost:8080/data3.json")
            .then(res => {
              this.list = [...this.list, ...res.data.result.list];
              this.items = [...this.list];
              this.temps = null
              this.isShow = false
               window.console.log("***",this.list);
            })
            .catch(error => {
              window.console.log(error);
            });
          },3000)
        } else if(this.temps === false){
          this.isShow = true
          window.setTimeout(()=>{
             axios
            .get("http://localhost:8080/data2.json")
            .then(res => {
              this.list = [...this.list, ...res.data.result.list];
              this.items = [...this.list];
              this.temps = true
              this.isShow = false
               window.console.log("+++",this.list);
            })
            .catch(error => {
              window.console.log(error);
            });
          },3000)
         
        }else{
             this.isShow = true
          window.setTimeout(()=>{
            this.isShow = false
            this.show = true
          },3000)
        }
      }
    })
  }
};
</script>
<style>
.home {
  width: 100%;
  background: gainsboro;
}
.home_header {
  width: 100%;
  height: 64px;
  background: #fff;
  display: inline-flex;
  justify-content: flex-end;
  align-items: center;
}
.home_header div {
  margin-right: 20px;
}
.home_header img {
  width: 25px;
}
.home_price_con {
  display: block;
  width: 80%;
  margin: 15px auto;
}
.home_price {
  width: 100%;
  height: 64px;
  background: #fff;
  display: inline-flex;
  justify-content: flex-end;
  align-items: center;
}
.home_price div {
  margin-right: 20px;
}
.home_content_con {
  width: 80%;
  margin: 0 auto;
}
.home_content {
  width: 100%;
  display: inline-flex;
  background: gainsboro;
  /* justify-content: space-between; */
}
.home_left {
  width: 20%;
  height: 1000px;
  /* background: green; */
  margin-top: 10px;
}
.home_left_item {
  width: 100%;
  height: 50px;
  line-height: 50px;
}
.home_left_item_active {
  width: 100%;
  height: 50px;
  border-left: 2px solid red;
  color: red;
  line-height: 50px;
}
.home_right {
  width: 79%;
  margin-left: 10px;
}
.item_conetent {
  height: 400px;
  background: #fff;
  margin: 10px 0px;
  /* text-align: center; */
}
.item_conetent:hover {
  transform: scale(1.02);
  box-shadow: 5px 5px 20px 5px rgb(255, 60, 0);
}
.item_content_image {
  width: 100%;
  /* height: 150px; */
  display: inline-flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 20px;
}
.item_content_image img {
  width: 85%;
}
.item_content_price {
  margin: 10px 0px;
  color: red;
}
.home_list_item_button {
  width: 80%;
  height:60px;
  margin: 30px auto;
  /* line-height: 10px; */
}
.home_list_item_button button {
  width: 90%;
  height: 40px;
  border: 1px solid red;
  color: red;
  text-align: center;
}
.home_price_con_active {
  display: none;
  width: 80%;
  margin: 15px auto;
}
.home_price_active {
  width: 100%;
  height: 64px;
  background: #fff;
  display: inline-flex;
  justify-content: space-between;
  align-items: center;
}
.home_loading{
  width: 100%;
  display: inline-flex;
  justify-content: center;
  /* align-items: center; */
  position: fixed;
  bottom: 0px;
  left: 0px;
}
.home_loading img{
  width: 120px;
}
.home_loadings{
  width: 100%;
  display: inline-flex;
  justify-content: center;
  position: fixed;
  top: 0px;
  left: 0px;
}
.home_loadings img{
  width: 600%;
}
@media screen and (max-width: 768px) {
  .item_conetent {
    width: 100%;
    height: 100px;
    display: inline-flex;
    justify-content: flex-start;
    align-items: center;
  }
  .item_content_image {
    width: 20%;
  }
  .item_content_image img {
    width: 50%;
  }
  .item_content_name_price {
    width: 60%;
  }
  .home_list_item_button {
    width: 20%;
    display: inline-flex;
    justify-content: flex-end;
  }
  .home_left {
    display: none;
  }
  .home_right {
    width: 100%;
  }
  .home_price_con {
    /* width: 100%; */
    display: none;
  }
  .home_content_con {
    width: 100%;
  }
  .home_price_con_active {
    width: 100%;
    display: block;
  }
}
</style>

//cart页面
<template>
  <div class="cart">
     <div>
       <div v-for="(item,index) in cartItem"
       :key="index"
       class="cart_item">
        <div>
          <input type="checkbox" 
          :checked="item.checked" 
          @click="onCheckedClick(item)"/>
        </div>
        <div>
          <img :src="item.productImage" alt="" />
        </div>
        <div>{{item.productName}}</div>
        <div>{{item.salePrice}}</div>
        <!-- <van-stepper v-model="item.count" /> -->
        <div class="cart_count">
          <button @click="minusItem(item)">-</button>
          <div class="cart_item_count">{{item.count}}</div>
          <button @click="addItem(item)">+</button>
        </div>
        <div class="cart_item_iamge" @click="deleteItem(item)">
          <img src="../assets/delete.png" alt="" />
        </div>
       </div>
     </div>
     <div class="cart_sub_bar">
       全选 <input type="checkbox" 
       :checked="allChecked" 
       :disabled="cartItem.length ===0?true:false"
       @click="allSelected"/>
       <span>{{`总价:${totalPrice}`}}</span>
       <span>{{`总量${totalCount}`}}</span>
     </div>
  </div>
</template>

<script>
export default {
  computed:{
    cartItem:function(){
      return this.$store.state.cartItem
    },
    allChecked:function(){
      return this.$store.state.allChecked
    },
    totalCount:function(){
      return this.$store.state.totalCount
    },
    totalPrice:function(){
      return this.$store.state.totalPrice
    }
  },
  methods:{
    onCheckedClick(item){
      this.$store.dispatch("getItemChecked",{_id:item._id,checked:event.target.checked})
    },
     allSelected(){
      this.$store.dispatch("getItemAllChecked",event.target.checked)
    },
    addItem(item){
      this.$store.dispatch("getaddItem",item)
    },
    minusItem(item){
      // if(item.count >1){
      //    item.count--
      // }
      this.$store.dispatch("getminusItem",item)
    },
    deleteItem(item){
      this.$store.dispatch("getdeleteItem",item)
    }
  }
}
</script>

<style>
.cart_item{
  width: 100%;
  display: inline-flex;
  justify-content: space-around;
  align-items: center
}
.cart_item img{
   width: 100px;
}
.cart_sub_bar{
  width: 100%;
  height: 64px;
  position: fixed;
  bottom: 0px;
  left: 30px;
}
.cart_count{
  display: inline-flex;
}
.cart_item_count{
  width: 30px;
  height: 30px;
  background: #fff;
  text-align: center;
  line-height: 30px;
}
.cart_item_iamge img{
  width: 25px;
}
</style>

// vuex页面 index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    cartItem: JSON.parse(localStorage.getItem("cartItems")) || [],
    allChecked:JSON.parse(localStorage.getItem("allcheckeds")) ||  false,
    totalCount: 0,
    totalPrice: 0,
    empty:[]
  },
  mutations: {
    //获取数据,并去重
    getCartItem(state, items) {
      var fang = false;
      state.cartItem.forEach((ele) => {
        if (ele._id === items._id) {
          ele.count++;
          fang = true
        }
      });
      if (!fang) {
        items.count = 1;
        items.checked = false
        state.allChecked = false
        state.cartItem.push(items)
      }
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
      localStorage.setItem("allcheckeds", JSON.stringify(state.allChecked))
    },
    // 单选
    getItemChecked(state, items) {
      window.console.log("+++", items)
      state.cartItem.forEach((ele) => {
        if (ele._id === items._id) {
          ele.checked = items.checked
        }
      });
      state.allChecked = state.cartItem.every((ele) => {
        return ele.checked === true
      })
      state.totalCount = 0;
      state.totalPrice = 0;
      state.cartItem.forEach((ele) => {
        if (ele.checked) {
          state.totalCount += ele.count;
          state.totalPrice += (ele.count * ele.salePrice)
        }
      })
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
      localStorage.setItem("allcheckeds", JSON.stringify(state.allChecked))
    },
    // 全选
    getItemAllChecked(state, boolean) {
      state.allChecked = boolean
      state.cartItem.forEach((ele) => {
        ele.checked = boolean
      });
      state.totalCount = 0;
      state.totalPrice = 0;
      state.cartItem.forEach((element) => {
        if (element.checked) {
          state.totalCount += element.count;
          state.totalPrice += (element.count * element.salePrice);
        }
      })
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
      localStorage.setItem("allcheckeds", JSON.stringify(state.allChecked))
    },
    // 加
    getaddItem(state, item) {
      item.count++
      state.totalCount = 0;
      state.totalPrice = 0;
      state.cartItem.forEach((element) => {
        if (element.checked) {
          state.totalCount += element.count;
          state.totalPrice += (element.count * element.salePrice);
        }
      })
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
    },
    //减
    getminusItem(state, item) {
      if (item.count > 1) {
        item.count--
      }
      state.totalCount = 0;
        state.totalPrice = 0;
        state.cartItem.forEach((element) => {
          if (element.checked) {
            state.totalCount += element.count;
            state.totalPrice += (element.count * element.salePrice);
          }
        })
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
    },
    //删除
    getdeleteItem(state, item) {
      state.cartItem.forEach((ele,index) => {
        if (ele._id===item._id) {
          state.cartItem.splice(index,1)
        }
      })
      state.totalPrice = 0;
      state.totalCount = 0;
      state.cartItem.forEach((element) => {
        if (element.checked) {
          state.totalCount += element.count;
          state.totalPrice += (element.count * element.salePrice);
        }
      })
      if(state.cartItem.length ===0){
        state.allChecked = false
        localStorage.setItem("allcheckeds", JSON.stringify(state.allChecked))
      }
      // state.cartItem.splice(index , 1)
      window.console.log(state)
      localStorage.setItem("cartItems", JSON.stringify(state.cartItem))
    }
  },
  actions: {
    getCartItem(context, items) {
      context.commit("getCartItem", items)
    },
    getItemChecked(context, item) {
      context.commit("getItemChecked", item)
    },
    getItemAllChecked(context, boolean) {
      context.commit("getItemAllChecked", boolean)
    },
    getdeleteItem(context, item) {
      context.commit("getdeleteItem", item)
    },
    getaddItem(context, item) {
      context.commit("getaddItem", item)
    },
    getminusItem(context, item) {
      context.commit("getminusItem", item)
    }
  },
  modules: {
  }
})


你可能感兴趣的:(前端)