Vue3重构购物车 | 掘金技术征文-双节特别篇

1,142 阅读2分钟

效果图

友情提示,vue ui创建项目可以选择vue3版本

效果图

先介绍下本文用到的Vue3新语法

  • 响应式数据:reactive引用类型, ref基本类型
  • 代码基本都写在setup函数里,写完的响应式数据和方法要return
  • computed变成函数式并接收一个回调函数

正文

一. 模拟数据

// goodsData的数据结构
const goodsData = [{
    img: 'https://tse1-mm.cn.bing.net/th/id/OIP.jMZGCh1dDdJH-KwzQs8vYgHaKG?w=206&h=280&c=7&o=5&dpr=1.25&pid=1.7',
    select: false, 是否被选中
    title: '白大褂',
    price: 38,
    desc: '女士 短袖',
    count: 1,
    id: 1
}]
const goodsDatas = reactive(goodsData);
// 渲染的话都是v-for vue3没有变动

二. 按页面结构分为三部分,头部、内容和底部

  • 头部DOM结构
<header>
  <h2>购物车 <span @click="isManage = !isManage">{{isManage ? '完成' : '管理'}}</span></h2>
  <p>共{{goodsDatas.length}}件宝贝</p>
</header>

// js
const isManage = ref(false)
  • isManage表示购物车状态(结算或管理)并显示不同的文字
  • 统计宝贝个数goodsDatas.length很方便

三. 内容

  • DOM结构: 遍历goodsDatas 。单选图片判断select属性用v-show切换,引入图片用require 最后要记得return
<ul id="goods">
  <li v-for="(item, index) of goodsDatas" :key="item.id">
      <img :src="unselect" alt="" v-show="!item.select" class="select" @click="selectItem(index)">
      <img :src="selected" alt="" v-show="item.select" class="select" @click="selectItem(index)">
      <img :src="item.img" alt="" class="poster">
      <aside>
          <h6>{{item.title}}</h6>
          <p>{{item.desc}}</p>
          <h5><b>{{item.price}}</b>
              <div class="change-count">
                  <button class="l" @click="minus(index)">-</button>
                  <input type="text" v-model="item.count" @input="inputCount(item.count, index)">
                  <button class="r" @click="add(index)">+</button>
              </div>
          </h5>
      </aside>
  </li>
</ul>
  • 单选宝贝selectItem(index)。select = !select展示不同的图片。every判断所有宝贝的select状态是否全部选中,如果全部选中isSelectAll为true反之为false
function selectItem(index: number): void {
    const itemSelect: boolean = goodsDatas[index].select
    goodsDatas[index].select = !itemSelect
    const all:boolean = goodsDatas.every(item => {
        return item.select === true
    })
    isSelectAll.value = all ? true : false
}
  • 更改数量item.count. 这里用三个方法minus、add和inputCount,分别是减少、添加和用户输入。
function inputCount(count: number|string, index: number): void {
    if(!count || count == 'Na') {
        goodsDatas[index].count = 1
        return;
    }
    goodsDatas[index].count = parseInt(String(count))
}

function minus(index: number): void {
    const currCount = goodsDatas[index].count
    if(currCount <= 1) return;
    goodsDatas[index].count -= 1
}

function add(index: number): void {
    goodsDatas[index].count += 1
}

四. 底部

  • DOM结构,unselect和selected代表不同状态的图片,合计total用computed计算
<footer>
    <img :src="unselect" alt="" v-show="!isSelectAll" @click="selectAll">
    <img :src="selected" alt="" v-show="isSelectAll" @click="selectAll">
    <span>全选</span>
    <h6><em>合计:</em><i>¥{{total}}</i></h6>
    <button @click="finish">{{isManage ? '移除' : '结算'}}</button>
</footer>
  • selectAll 如果全选则遍历goodsData更改item.select为true,反之为false
function selectAll(): void {
  isSelectAll.value = !isSelectAll.value
  if(isSelectAll.value) {
      goodsDatas.forEach(item => {
          item.select = true
      })
  } else {
      goodsDatas.forEach(item => {
          item.select = false
      })
  }
}
  • 最关键的total. 如果购物车是管理状态直接返回 0,否则map遍历goodsData相加价格currentPrice是单个宝贝的总价
const total = computed(() => {
    if(isManage.value) return 0;
    let n: number = 0
    goodsDatas.map(item => {
        if(item.select) {
            const currentPrice = item.price * item.count
            n = n + currentPrice
        }
    })
    return n
})

至此 我们购物车到此完成了

本文代码地址:git地址

🏆 掘金技术征文|双节特别篇