电商项目——购物车案例***

1.项目初始化

效果图:

①: vue命令创建项目shopcar-demo

②: 下载bootstrap, less, less-loader@5.0.0
③: main.js – 引入bootstrap样式

import "bootstrap/dist/css/bootstrap.css" //引入第三方包里的某个css文件

④: 创建4个组件文件, 标签和样式(略)
⑤: 把组件相应的引入到对应位置使用

2.头部自定义

需求:组件支持自定义

①: 背景色定义props里变量接收使用(利用了vue组件通信/父传子

②: 文字颜色定义props里变量接收-设默认值
③: 文字内容定义props里变量接收-设必传值
可以对props的变量的值 进行校验!!!
  <div class="my-header" :style="{backgroundColor: background, color}">{{ title }}</div>
export default {
    props: {
        background: String, // 外部插入此变量的值, 必须是字符串类型, 否则报错
        color: {
            type: String, // 约束color值的类型
            default: "#fff" // color变量默认值(外部不给 我color传值, 使用默认值)
        },
        title: {
            type: String,
            required: true // 必须传入此变量的值
        }
    }
}

④: 使用组件传入具体值

在app.vue中:

    <MyHeader background="orange" title="购物车案例"></MyHeader>

3. 数据获取

需求:axios调用接口——获取购物车案例的数据

①: 下载axios, 在main.js引入 import axios from 'axios'

②: 配置基础地址, https://www.escook.cn   
          axios.defaults.baseURL = "http://www.escook.cn"
③: axios挂载到Vue原型上, 作为全局属性  !!     
        Vue.prototype.$axios = axios
④: App.vue的created中使用全局属性axios
  created() {
    // 不必在自己引入axios变量, 而是直接使用全局属性$axios
    this.$axios({
      url: "/api/cart",
    }).then((res) => {
      console.log(res);
      this.list = res.data.list;
    });
  },

⑤: 接口地址为 /api/cart


4.数据渲染 

需求:把数据使用MyGoods组件展示

①: App.vue把数据保存到data定义的变量上

  data() {
    return {
      list: [], // 商品所有数据
    };
  },
②: 使用v-for循环数组使用组件

③: 分别给商品组件传入数据对象

④: 商品组件接收后, 使用对象里字段数据展示
其中涉及2次父向子传值
MyGoods.vue(子):
export default {
    props: {
      gObj: Object
    },
}

App.vue(父):

      <MyGoods v-for="obj in list" :key="obj.id" :gObj="obj"></MyGoods>
MyGoods.vue(子):
每个对象和组件都是独立的,因此用对象里的goods_state关联自己对应商品的复选框
    <div class="left">
      <div class="custom-control custom-checkbox">
        <!-- *重要:
          每个对象和组件都是独立的
          对象里的goods_state关联自己对应商品的复选框
         -->
        <input type="checkbox" class="custom-control-input" id="input"
        v-model="gObj.goods_state"
        >
        <label class="custom-control-label" for="input">
          <img :src="gObj.goods_img" alt="">
        </label>
      </div>
    </div>
    <div class="right">
      <div class="top">{{ gObj.goods_name }}</div>
      <div class="bottom">
        <span class="price">¥ {{ gObj.goods_price }}</span>
        <span>
            <MyCount :obj="gObj"></MyCount>
        </span>
      </div>
    </div>

MyCount.vue(Mygoods.vue的子):

    <input type="number" class="form-control inp" v-model ="obj.goods_count">
export default {
  props: {
    obj: Object // 商品对象
  },
}


5.商品选择

需求:点击复选框完成选中效果;点击商品图片完成复选框选中效果

①: 给v-model关联到小选框上, 数据关联对象的goods_state

②: 注意点图片用label关联的小选框
③: label的for值要和表单标签id一致, 点label才触发小选框
④: id属性分别使用商品的id即可
 <!-- bug:
          循环的所有label的for都是input, id也都是input - 默认只有第一个生效
          解决: 每次对象里的id值(1, 2), 分别给id和for使用即可区分
          -->
        <input type="checkbox" class="custom-control-input" :id="gObj.id"
        v-model="gObj.goods_state"
        >
        <label class="custom-control-label" :for="gObj.id">
          <img :src="gObj.goods_img" alt="">
        </label>

此处bug原因:对象传值赋值传的是引用类型的堆内存地址,多处共同使用这个对象/数组!


6.数量控制 

需求:点击或输入改变商品数量

①: 给MyCount组件传入数据对象关联
②: 输入框v-model关联对象里数量属性
③: 增加或减少修改对象数量属性
④: 控制商品最少1件
 <button type="button" class="btn btn-light" :disabled="obj.goods_count === 1" @click="obj.goods_count > 1 && obj.goods_count--">-</button>
    <input type="number" class="form-control inp" v-model.number="obj.goods_count">
    <button type="button" class="btn btn-light" @click="obj.goods_count++">+</button>
// 目标: 商品数量 - 控制
// 1. 外部传入数据对象
// 2. v-model关联对象的goods_count属性和输入框 (双向绑定)
// 3. 商品按钮 +和-, 商品数量最少1件
// 4. 侦听数量改变, 小于1, 直接强制覆盖1
watch: {
    obj: {
      deep: true,
      handler(){ // 拿到商品数量, 判断小于1, 强制修改成1
        if (this.obj.goods_count < 1) {
          this.obj.goods_count = 1
        }
      }
    }
  }

7.全选

需求:点击全选影响所有小选(计算属性的set方法),点击小选影响全选(计算属性的get方法)

①: v-model用计算属性, 关联全选框

<input
        type="checkbox"
        class="custom-control-input"
        id="footerCheck"
        v-model="isAll"
      />
②: 在set方法里, 获取全选状态
③: 回传到App.vue再同步给所有小选框

页面(视频层)v(true) -> 数据层(变量-) 计算属性(完整写法)

把全选 true/false同步给所有小选框选中状态上(子传父)

MyFooter.vue(子):

computed: {
    isAll: {
      set(val) {
        // val就是关联表单的值(true/false)
        console.log(val);
        this.$emit("changeAll", val);
      },
}

App.vue(父):

    <MyFooter @changeAll="allFn"></MyFooter>
methods: {
    allFn(bool) {
      this.list.forEach((obj) => (obj.goods_state = bool));
      // 把MyFooter内的全选状态true/false同步给所有小选框的关联属性上
    },
  },

④: 在get方法里, 统计小选框给全选复制(父传子)

App.vue(父):

    <MyFooter @changeAll="allFn" :arr="list"></MyFooter>

MyFooter.vue(子):

props: {
    arr: Array,
  },
computed: {
    isAll: {
      set(val) {
        // val就是关联表单的值(true/false)
        console.log(val);
        this.$emit("changeAll", val);
      },
      get() {
        // 查找小选框关联的属性有没有不符合勾选的条件
        // 直接原地false
        return this.arr.every((obj) => obj.goods_state === true);
      },
    },

8.总数量 

需求:统计已选中商品的总数量在右下角按钮显示

reduce累加数组对象数量!!

arr.reduce((sum, obj) => { }, 0);    sum:总数   0:sum从0开始

①: 计算属性allCount变量

    <button type="button" class="footer-btn btn btn-primary">
      结算 ( {{ allCount }} )
    </button>
②: 在统计数组里数据时, 要判断勾选状态才累加数量
③: 把累加好数量返回给allCount变量使用显示
computed: {
    allCount() {
      return this.arr.reduce((sum, obj) => {
        if (obj.goods_state === true) {
          // 选中商品才累加数量
          sum += obj.goods_count;
        }
        return sum;
      }, 0);
    },

④: 输入框的值为空字符串, 需要转换数值类型


9.总价 

需求:统计已选中商品的总价格

①: 计算属性allPrice变量

      <span class="price">¥ {{ allPrice }}</span>
②: 在统计数组里数据时, 要判断勾选状态才累加
③: 把价格和数量先想乘, 再累加
computed: {
    allPrice() {
      return this.arr.reduce((sum, obj) => {
        if (obj.goods_state) {
          sum += obj.goods_count * obj.goods_price;
        }
        return sum;
      }, 0);
    },
  },

④: 累加好数据返回给allPrice变量使用显示

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值