美文网首页
购物车案例

购物车案例

作者: 家乡的蝈蝈 | 来源:发表于2024-03-24 12:17 被阅读0次

需求说明:

  1. 渲染功能
  2. 删除功能
  3. 修改个数
  4. 全选反选
  5. 统计选中的 总价 和 总数量
  6. 持久化到本地

实现思路:

1.基本渲染: v-for遍历、:class动态绑定样式

2.删除功能 : v-on 绑定事件,获取当前行的id

3.修改个数 : v-on绑定事件,获取当前行的id,进行筛选出对应的项然后增加或减少

4.全选反选

  1. 必须所有的小选框都选中,全选按钮才选中 → every
  2. 如果全选按钮选中,则所有小选框都选中
  3. 如果全选取消,则所有小选框都取消选中
    声明计算属性,判断数组中的每一个checked属性的值,看是否需要全部选

5.统计 选中的 总价 和 总数量 :通过计算属性来计算选中的总价和总数量

6.持久化到本地: 在数据变化时都要更新下本地存储 watch
1. 渲染功能

<script>
  const app = new Vue({
    el: '#app',
    data: {
      // 水果列表
      fruitList: [
        {
          id: 1,
          icon: './img/火龙果.png',
          isChecked: true,
          num: 2,
          price: 6,
        },
        {
          id: 2,
          icon: './img/荔枝.png',
          isChecked: false,
          num: 7,
          price: 20,
        },
      ],
    },
  })
</script>
<!-- 身体 -->
<div class="tbody">
  <div :class="{tr:true, active: item.isChecked }" v-for="(item, index) in fruitList" :key="item.id">
    <div class="td"><input type="checkbox" v-model="item.isChecked" /></div>
    <div class="td"><img :src="item.icon" alt="" /></div>
    <div class="td">{{ item.price }}</div>
    <div class="td">
      <div class="my-input-number">
        <button class="decrease"> - </button>
        <span class="my-input__inner">{{ item.num }}</span>
        <button class="increase"> + </button>
      </div>
    </div>
    <div class="td">{{ item.num * item.price }}</div>
    <div class="td"><button>删除</button></div>
  </div>
</div>

2. 删除功能和修改个数

// 设置checked disabled selected都为true、false
<div class="my-input-number">
  <button :disabled="item.num <= 1" class="decrease" @click="sub(item.id)"> - </button>
  <button class="increase" @click="add(item.id)"> + </button>
</div>
<div class="td"><button @click="del(item.id)">删除</button></div>
</div>
methods: {
  del(id) {
    this.fruitList = this.fruitList.filter(item => item.id !== id)
  },
  add(id) {
    // 1. 根据 id 找到数组中的对应项 → find
    const fruit = this.fruitList.find(item => item.id === id)
    // 2. 操作 num 数量
    fruit.num++
  },
  sub(id) {
    // 1. 根据 id 找到数组中的对应项 → find
    const fruit = this.fruitList.find(item => item.id === id)
    // 2. 操作 num 数量
    fruit.num--
  }
}

5. 统计选中的总价 和 总数量

<div class="right-box">
  <!-- 所有商品总价 -->
  <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">{{ totalPrice }}</span></span>
  <!-- 结算按钮 -->
  <button class="pay">结算( {{ totalCount }} )</button>
</div>
// 统计选中的总数 reduce
totalCount () {
  let result = this. fruitList. filter(item => item. isChecked)
  return result.reduce((sum, item) => {
    return sum + item.num * item.price
  }, 0)
},
// 总计选中的总价 num * price
totalPrice () {
  let result = this. fruitList. filter(item => item.isChecked) // item.isChecked === true
  return result.reduce((sum, item) => sum += item.num, 0) // 箭头函数简写,省略了{}和return
}

4. 全选反选

  <!-- 全选 -->
<label class="check-all">
  <input type="checkbox" v-model="isAll" />
  全选
</label>
computed: {
  // 默认计算属性:只能获取不能设置,要设置需要写完整写法
  // isAll () {
  //   // 必须所有的小选框都选中,全选按钮才选中 → every
  //   return this.fruitList.every(item => item.isChecked)
  // }

  // 完整写法 = get + set
  isAll: {
    get() {
      return this.fruitList.every(item => item.isChecked)
    },
    set(value) {
      // 基于拿到的布尔值,要让所有的小选框 同步状态
      this.fruitList.forEach(item => item.isChecked = value)
    }
  }
},

6. 持久化到本地

const app = new Vue({
  el: '#app',
  data: {
    // 水果列表
    fruitList: JSON.parse(localStorage.getItem('list')) || defaultArr,
  },
  watch: {
    fruitList: {
      deep: true,
      handler (newValue) {
        // 需要将变化后的 newValue 存入本地 (转JSON)
        localStorage.setItem('list', JSON.stringify(newValue))
      }
    }
  }
})

相关文章

网友评论

      本文标题:购物车案例

      本文链接:https://www.haomeiwen.com/subject/nmkltjtx.html