Vue购物车案例

书写步骤和顺序.

  1. 创建一个新的脚手架
  2. 下载axios 和相关需求包
  3. 在全局main.js导入需求包和指定需求
  4. 通过axios请求获取到所需要的相关数据
  5. 申明一个空数组接收相关数据
  6. 循环渲染需求的页面.
  7. 根据具体情况书写具体代码

main.js

import Vue from 'vue'
import App from './App.vue'
import "bootstrap/dist/css/bootstrap.css"

import axios from 'axios'
axios.defaults.baseURL = "https://www.escook.cn"
Vue.prototype.$axios = axios

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

App.vue

<template>
  <div>
      <!-- 1.根据你想要得设置标题和标题得颜色.在对应的组件里添加对应的名字 -->
      <my-header  background="black" title="优衣库"
      ></my-header>
      <div class="main">
     <!-- 2.渲染页面.主体部分.循环 循环的值通过axios发起请求获取 -->
      <my-goods v-for="obj in list" :key="obj.id"
      :obj='obj'
      ></my-goods>
      </div>
      <my-footer
      :obj='list'
      @quanxuan='quanxuan'
      ></my-footer>
  </div>
</template>

<script>
import MyFooter from './components/MyFooter.vue'
import MyGoods from './components/MyGoods.vue'
import MyHeader from './components/MyHeader.vue'
export default {
    data(){
        return{
            list:[]
        }
    },
  components: { MyHeader, MyGoods, MyFooter },
  //2.1在初始化生命周期的时候发起请求.通过设定的this.$axios
  //用await 和 async 修饰...
  async created(){
  const {data} =  await this.$axios({
          method:'get',
          url:'/api/cart',
      })
      console.log(data.list);
      //2.2把获取到对应的值赋值给事先申明好的空白数组中.
      this.list = data.list
  },
  methods:{
      quanxuan(val){
        this.list.forEach(obj =>obj.goods_state = val)
      }
  }

}
</script>

<style lang="less" scoped>
   .main{
       margin: 45px 0;
   }
</style>

header.vue

<template>
  <div class="my-header" :style="{background}">{
   
   {title}}</div>
</template>

<script>
export default {
  //1.1导入父级相应的属性在标题中添加到指定位置.
    props:{
        background:String,
        color:{
            type:String,
            default:'#fff'
        },
        title:{
            type:String,
            required:true
        }
    }

}
</script>

<style lang="less" scoped>
  .my-header {
    height: 45px;
    line-height: 45px;
    text-align: center;
    background-color: #1d7bff;
    color: #fff;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 2;
  }
</style>

goods.vue

<template>
  <div class="my-goods-item">
    <div class="left">
      <div class="custom-control custom-checkbox">
        <!-- 2.4将对应的数据渲染.包括ID -->
        <input type="checkbox" class="custom-control-input" :id="obj.id" v-model="obj.goods_state"
        >
        <label class="custom-control-label" :for="obj.id">
          <img :src="obj.goods_img" alt="">
        </label>
      </div>
    </div>
    <div class="right">
      <div class="top">{
   
   {obj.goods_name}}</div>
      <div class="bottom">
        <span class="price">¥ {
   
   {obj.goods_price}}</span>
        <span>
          <!-- 2.5添加对应指定的组件. -->
            <my-count
            :obj='obj'
            ></my-count>
        </span>
      </div>
    </div>
  </div>
</template>

<script>
import MyCount from './MyCount.vue'
export default {
  components: { MyCount },
  //2.3从父亲那里拿数据.
  props:{
      obj:Object
  }

}
</script>

<style lang="less" scoped>
.my-goods-item {
  display: flex;
  padding: 10px;
  border-bottom: 1px solid #ccc;
  .left {
    img {
      width: 120px;
      height: 120px;
      margin-right: 8px;
      border-radius: 10px;
    }
    .custom-control-label::before,
    .custom-control-label::after {
      top: 50px;
    }
  }
  .right {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    .top{
        font-size: 14px;
        font-weight: 700;
    }
    .bottom {
      display: flex;
      justify-content: space-between;
      padding: 5px 0;
      align-items: center;
      .price {
        color: red;
        font-weight: bold;
      }
    }
  }
}

</style>

footer.vue

<template>
  <!-- 底部 -->
  <div class="my-footer">
    <!-- 全选 -->
    <div class="custom-control custom-checkbox">
      <!-- 3.1判断全选. -->
      <input type="checkbox" class="custom-control-input" id="footerCheck" v-model="isAll">
      <label class="custom-control-label" for="footerCheck">全选</label>
    </div>
    <!-- 合计 -->
    <div>
      <span>合计:</span>
      <!-- 3.1计算总价格 -->
      <span class="price">¥ {
   
   {heji}}</span>
    </div>
    <!-- 按钮 -->
    <!-- 3.2计算总数 -->
    <button type="button" class="footer-btn btn btn-primary">结算 {
   
   { jiesuan }}</button>
  </div>
</template>

<script>
export default {
  //3.拿到父级里的对应属性
   props:{
       obj:Array
   },
   computed:{
     //判断全选.当isAll选择和复选框做出对应的效果
       isAll:{
           set(val){
              this.$emit('quanxuan',val)
           },
           get(){
               return this.obj.every(obj =>obj.goods_state === true)
           },
    },
       jiesuan(){
        return this.obj.reduce((sum,arr)=>{
        if(arr.goods_state === true){
          sum += arr.goods_count
        }
        return sum;
      },0)
       },
       heji(){
        return this.obj.reduce((sum,arr)=>{
        if(arr.goods_state === true){
        sum += arr.goods_count * arr.goods_price
        }
        return sum;
      },0)
       }
   },
}
</script>

<style lang="less" scoped>
.my-footer {
  position: fixed;
  z-index: 2;
  bottom: 0;
  width: 100%;
  height: 50px;
  border-top: 1px solid #ccc;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 10px;
  background: #fff;

  .price {
    color: red;
    font-weight: bold;
    font-size: 15px;
  }
  .footer-btn {
    min-width: 80px;
    height: 30px;
    line-height: 30px;
    border-radius: 25px;
    padding: 0;
  }
}
</style>

count.vue

<template>
  <div class="my-counter">
    <!-- 2.7渲染到当前结构里. -->
    <!-- 2.8数字小于1时禁用 -->
    <button type="button" class="btn btn-light"  @click="obj.goods_count--">-</button>
    <input type="number" class="form-control inp" v-model="obj.goods_count">
    <button type="button" class="btn btn-light" @click="obj.goods_count++">+</button>
  </div>
</template>

<script>
export default {
  //2.6从对应的父亲获取到数据
    props:{
        obj:Object
    },
  //2.9确保数字在更新以后不可以小于等于1.如果小于等于1则默认为1
    updated(){
       if (this.obj.goods_count <=1){
           this.obj.goods_count = 1
       }
    }
}
</script>

<style lang="less" scoped>
.my-counter {
  display: flex;
  .inp {
    width: 45px;
    text-align: center;
    margin: 0 10px;
  }
  .btn, .inp{
    transform: scale(0.9);
  }
}
</style>

Guess you like

Origin blog.csdn.net/wangyangzxc123/article/details/121033641