vue学习笔记(购物车小案例)

用一个简单的购物车demo来回顾一下其中需要注意的细节。

先看一下最终效果

功能:

(1)全选按钮和下面的商品项的选中状态同步,当下面的商品全部选中时,全选勾选,反之,则不勾选。

(2)控制购物车商品数量,最低为1

(3)拥有小计和总计功能。其中,总计为勾选的商品所需要的总金额。

首先,先把静态页面写出来。

html 复制代码
<template>
<div>
<h2>购物车</h2>
全选 <input type="checkbox" >
<div v-for="(item,index) in goods" :key="index">
<input type="checkbox" name="" id="" >

--商品名:{{ item.name }}  --价格:{{ item.price }} 
<!-- 后端数据没有item.num,就使用或1的形式给所有商品默认的数量为1,这样就不用一个个在后端数据中加了 -->
--<button type="button" >+</button>{{item.num || 1}}<button  >-</button>
--小计:0
</div>
<div>总计:0</div>
</div>

</template>

上面的代码将静态页面写了出来,目前没有任何功能而。我们一一进行功能的添加。首先,实现简单的数量加减和小计。

思路:

现在存在两种情况,

第一,就是后端返回了商品数量,也就是item.num这个数据后端是直接给你的,然后我们直接进行使用即可。但是,实际的情况是后端返回的数量是这个商品的总库存,作为我们的购物车来说,一般默认的数量是为1的。所以,这里我们使用逻辑运算符的情况考虑了两种情况。

然后就是加一和减一,比较容易的方法就是直接给加和减分别绑定点击事件,分别进行加减,这里需要使用两个方法。这样的方法就不再介绍。不如换一个思路,让两个事件使用同一个事件,这样就少写了一个方法。

就是两者都是加,而减的操作是加-1.这样就可以合并为一个方法。

代码如下

javascript 复制代码
updateNum(actionType,index){
      //初始化num
      this.goods[index].num = this.goods[index].num||1

      //数量操作
      this.goods[index].num+=actionType

    },

解释一下,第一个参数就是传递过来的值,是加1,还是加-1,第二个值就是对应的索引,因为要对对应的商品进行数量加减操作,所以需要对应商品的索引。

首先,在考虑初始化num的时候,也要考虑num不存在的情况,

然后进行对应的数量操作即可。

那么我们的小计也就可以根据商品数量和价格进行计算了,注意:也要考虑数量不存在的情况。

对应的代码为:

html 复制代码
<button type="button" @click="updateNum(1,index)">+</button>{{item.num || 1}}
<button   @click="updateNum(-1,index)">-</button>
--小计:{{(item.num ||1) *item.price}}
</div>

然后就是全选,商品单选,和总计的功能了。

首先进行全选实现,就是让全选的状态和商品单选进行同步。

我们首先定义全选的状态,默认是不选中的。( isAllSelected:false,)

html 复制代码
 data(){
    return{
      isAllSelected:false,
      goods:[{
        name:"商品1",
        price:"100",
        // num:"1",
      },
      {
        name:"商品2",
        price:"200"
      },
      {
        name:"商品3",
        price:"300"
      }]
    }
  },

然后对应的给他添加change事件(注意,这里是change事件,并不是click)

html 复制代码
全选 <input type="checkbox" :checked="isAllSelected" @change="allSelect">

使用动态绑定属性使他与 isAllSelected:的状态同步,然后写allSelect方法

javascript 复制代码
allSelect(){
      this.isAllSelected=!this.isAllSelected
      console.log(this.isAllSelected);

      //同步单选状态
      this.goods.forEach(item=>{
        item.select=this.isAllSelected
      })
    },

这里就是让他的状态和下面的商品列表的选择框进行同步,思路为:就是对下面的商品列表进行遍历,使用forEach方法,并将其状态赋值给每一项商品的选择状态。

然后就是当下面的每一项的商品取消选中时,那个全选的状态要进行改变。

这里用到另一个数组方法every

javascript 复制代码
singleSelect(index){
      //修改当前单选商品状态
      this.goods[index].select=!this.goods[index].select

      //使用every方法循环数组,如果有一个select为false
      //整个结果为false 全部为true 整个结果为true
      //和我们单选联动 全选逻辑一致
      //直接使用返回值 赋给全选状态
      this.isAllSelected=this.goods.every(item=>item.select)
    }

最后就是总计了,这里的总计是将所有选中的商品进行金额的计算。

这里也是用到了两个数组方法,他们分别是filter和every。

html 复制代码
<div>总计:{{ goods.filter(item=>item.select).reduce((total,item)=>total+=item.price*(item.num ||1),0) }}</div>

然后解释一下,这里首先使用filter方法将满足选中状态的商品进行过滤,返回的是一个数组,然后再将返回的数组使用累加方法reduce进行金额的计算。

完整代码附上:

html 复制代码
<!--
 * @Author: RealRoad1083425287@qq.com
 * @Date: 2024-07-06 16:18:52
 * @LastEditors: Mei
 * @LastEditTime: 2024-07-06 17:03:12
 * @FilePath: \Fighting\new_project_0705\my-vue-app\src\components\shopcar.vue
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>
<div>
<h2>购物车</h2>
全选 <input type="checkbox" :checked="isAllSelected" @change="allSelect">
<div v-for="(item,index) in goods" :key="index">
<input type="checkbox" name="" id="" :checked="item.select" @change="singleSelect(index)">

--商品名:{{ item.name }}  --价格:{{ item.price }} 
<!-- 后端数据没有item.num,就使用或1的形式给所有商品默认的数量为1,这样就不用一个个在后端数据中加了 -->
--<button type="button" @click="updateNum(1,index)">+</button>{{item.num || 1}}<button   @click="updateNum(-1,index)">-</button>
--{{(item.num ||1) *item.price}}
</div>
<div>总计:{{ goods.filter(item=>item.select).reduce((total,item)=>total+=item.price*(item.num ||1),0) }}</div>
</div>

</template>

<script>
export default {
  data(){
    return{
      isAllSelected:false,
      goods:[{
        name:"商品1",
        price:"100",
        // num:"1",
      },
      {
        name:"商品2",
        price:"200"
      },
      {
        name:"商品3",
        price:"300"
      }]
    }
  },
  methods:{
    updateNum(actionType,index){
      //初始化num
      this.goods[index].num = this.goods[index].num||1

      //数量操作
      this.goods[index].num+=actionType

    },

    allSelect(){
      this.isAllSelected=!this.isAllSelected
      console.log(this.isAllSelected);

      //同步单选状态
      this.goods.forEach(item=>{
        item.select=this.isAllSelected
      })
    },
    singleSelect(index){
      //修改当前单选商品状态
      this.goods[index].select=!this.goods[index].select

      //使用every方法循环数组,如果有一个select为false
      //整个结果为false 全部为true 整个结果为true
      //和我们单选联动 全选逻辑一致
      //直接使用返回值 赋给全选状态
      this.isAllSelected=this.goods.every(item=>item.select)
    }
  }
}
</script>


<style>

</style>

通过这个案例,主要是复习一下vue的常见指令的使用,主要是数组方法的使用。这里,将使用的四个数组方法进行详细的介绍。

①forEach

forEach 是 JavaScript 中的一个数组方法,它允许你对数组中的每个元素执行一个函数。这个方法接受一个回调函数作为参数,这个回调函数会对数组中的每个元素执行一次。此外,forEach 方法不会返回一个新数组,它仅仅是对原数组的每个元素执行了提供的函数。

forEach 的基本语法如下:

array.forEach(function(currentValue, index, arr), thisArg)

参数说明:

currentValue:数组中正在处理的当前元素。

index(可选):数组中正在处理的当前元素的索引。

arr(可选):forEach() 方法正在操作的数组。

thisArg(可选):执行回调函数时用作 this 的对象。

上面是官方的介绍,但是在实际的使用中,用的最多的还是currentValue,偶尔也会用到index,这里用一个上次的案例进行效果演示。(主要是遍历数组,记住不会返回新数组就行了)

html 复制代码
<!--
 * @Author: RealRoad1083425287@qq.com
 * @Date: 2024-07-05 21:28:45
 * @LastEditors: Mei
 * @LastEditTime: 2024-07-06 17:39:19
 * @FilePath: \Fighting\new_project_0705\my-vue-app\src\components\practice5.vue
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>

  <div>
    <div id="myList" v-for="(item,index) in arr" :key="index" @click="arrTest">{{ item.name }}

    </div>
  </div>

</template>


<script>
//列表渲染
//为什么循环的时候需要加key
//1.key的作用主要是为了高效的更新虚拟Dom,提高渲染性能
//2.key属性可以避免数据混乱的情况出现
export default{
  data(){
    return{
      arr:[{
        name:"张三"
      },
    {
      name:"李四"
    },
  {
    name:"王五"
  }]
    }
  },
  methods:{
    arrTest(){
      this.arr.forEach((item,index)=>{
        console.log("我是每一项",item);
        console.log("我是每一项的索引",index);
      })
    }
  }
}

</script>

<style scoped>
#myList{
  color: blue;
  background-color: yellow;
  margin-top: 20px;
}
</style>

效果如下:

②every

every 是 JavaScript 中的一个数组方法,用于测试数组的所有元素是否都满足提供的函数中的测试条件。如果所有元素都通过测试,则返回 true;否则,返回 false。这个方法不会改变原数组,而是返回一个布尔值。

every 方法的基本语法如下:

array.every(function(currentValue, index, arr), thisArg)

参数说明:

currentValue:数组中正在处理的当前元素。

index(可选):数组中正在处理的当前元素的索引。

arr(可选):every 方法正在操作的数组。

thisArg(可选):执行回调函数时用作 this 的值。如果省略了 thisArg 参数,或者设为 null 或 undefined,则 this 会被视为全局对象。在严格模式下,如果省略或为 null 或 undefined,则 this 会是 undefined。

还是一个案例来演示:

html 复制代码
<!--
 * @Author: RealRoad1083425287@qq.com
 * @Date: 2024-07-05 21:28:45
 * @LastEditors: Mei
 * @LastEditTime: 2024-07-06 17:53:54
 * @FilePath: \Fighting\new_project_0705\my-vue-app\src\components\practice5.vue
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>

  <div>
    <div id="myList" v-for="(item,index) in arr" :key="index" @click="arrTest">{{ item.name }}
      
    </div>
    <div>
      <button @click="arrTest2">点我看every{{ testEvery }}</button>
    </div>
  </div>

</template>


<script>
//列表渲染
//为什么循环的时候需要加key
//1.key的作用主要是为了高效的更新虚拟Dom,提高渲染性能
//2.key属性可以避免数据混乱的情况出现
export default{
  data(){
    return{
      testEvery:"",
      arr:[{
        name:"张三"
      },
    {
      name:"李四"
    },
  {
    name:"王五"
  }],
  arr2:[{
    age:10
  },
  {
    age:20
  },
  {
    age:30
  }]
    }
  },
  methods:{
    arrTest(){
      this.arr.forEach((item,index)=>{
        console.log("我是每一项",item);
        console.log("我是每一项的索引",index);
      })
    },
    arrTest2(){
      this.testEvery=this.arr2.every((item,index)=>{
        return item.age>5
      })
      
    }
  }
}

</script>

<style scoped>
#myList{
  color: blue;
  background-color: yellow;
  margin-top: 20px;
}
</style>

写一个按钮,当我们点击按钮的时候,就可以看到arrTest2返回的值,我们可以看到多了一个true,因为在执行every后,this.testEvery=true,对应页面的testEvery值也会进行显示。

③filter

filter 是 JavaScript 中的一个非常有用的数组方法,它创建一个新的数组,该数组包含通过测试函数的所有元素。换句话说,filter 方法会遍历原数组,对每个元素执行一个测试函数,如果该函数返回 true,则将该元素包含在新数组中。

filter 方法的基本语法如下:

let newArray = array.filter(function(currentValue, index, arr), thisArg)

参数说明:

currentValue:数组中正在处理的当前元素。

index(可选):数组中正在处理的当前元素的索引。

arr(可选):filter 方法正在操作的数组。

thisArg(可选):执行回调函数时用作 this 的值。

filter 方法返回一个新数组,该数组包含原数组中满足测试函数的元素。它不会改变原数组。

上代码

html 复制代码
<!--
 * @Author: RealRoad1083425287@qq.com
 * @Date: 2024-07-05 21:28:45
 * @LastEditors: Mei
 * @LastEditTime: 2024-07-06 18:03:11
 * @FilePath: \Fighting\new_project_0705\my-vue-app\src\components\practice5.vue
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>

  <div>
    <div id="myList" v-for="(item,index) in arr" :key="index" @click="arrTest">{{ item.name }}
      
    </div>
    <div>
      <button @click="arrTest2">点我看Filter</button>
      <div v-for="(item,index) in testFilter " :key=index>{{ item.age }}</div>
    </div>
  </div>

</template>


<script>
//列表渲染
//为什么循环的时候需要加key
//1.key的作用主要是为了高效的更新虚拟Dom,提高渲染性能
//2.key属性可以避免数据混乱的情况出现
export default{
  data(){
    return{
      testEvery:"",
      testFilter:"",
      arr:[{
        name:"张三"
      },
    {
      name:"李四"
    },
  {
    name:"王五"
  }],
  arr2:[{
    age:10
  },
  {
    age:20
  },
  {
    age:30
  }]
    }
  },
  methods:{
    arrTest(){
      this.arr.forEach((item,index)=>{
        console.log("我是每一项",item);
        console.log("我是每一项的索引",index);
      })
    },
    arrTest2(){
      this.testFilter=this.arr2.filter((item,index)=>{
        return item.age>15
      })
      console.log(this.testFilter);
      
    }
  }
}

</script>

<style scoped>
#myList{
  color: blue;
  background-color: yellow;
  margin-top: 20px;
}
</style>

当我点击按钮后,对应返回的新数组就会被渲染出来。

④reduce

reduce 是 JavaScript 中的一个数组方法,用于将数组中的所有元素通过某个函数(称为"reducer"函数)归并成一个单一的结果。这个方法会遍历数组中的每个元素,并使用 reducer 函数将其累积成一个单一的值。

reduce 方法的基本语法如下:

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数说明:

function(total, currentValue, currentIndex, arr): 这是 reducer 函数,它接受四个参数:

total(必需):初始值,或者计算结束后的返回值(累加器)。

currentValue(必需):当前元素。

currentIndex(可选):当前元素的索引。

arr(可选):当前元素所属的数组对象。

initialValue(可选):传递给函数的初始值。如果没有提供初始值,则将使用数组的第一个元素作为初始值,并从数组的第二个元素开始进行迭代。

上代码:

html 复制代码
<!--
 * @Author: RealRoad1083425287@qq.com
 * @Date: 2024-07-05 21:28:45
 * @LastEditors: Mei
 * @LastEditTime: 2024-07-06 18:11:41
 * @FilePath: \Fighting\new_project_0705\my-vue-app\src\components\practice5.vue
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
-->
<template>

  <div>
    <div id="myList" v-for="(item,index) in arr" :key="index" @click="arrTest">{{ item.name }}
      
    </div>
    <div>
      <button @click="arrTest2">点我看Filter</button>
      <div v-for="(item,index) in testFilter " :key=index>{{ item.age }}</div>

      <button @click="arrTest3">点我看Reduce</button>
      <!-- <div v-for="(item,index) in testFilter " :key=index>{{ item.age }}</div> -->
    </div>
  </div>

</template>


<script>
//列表渲染
//为什么循环的时候需要加key
//1.key的作用主要是为了高效的更新虚拟Dom,提高渲染性能
//2.key属性可以避免数据混乱的情况出现
export default{
  data(){
    return{
      testEvery:"",
      testFilter:"",
      testReduce:0,
      arr:[{
        name:"张三"
      },
    {
      name:"李四"
    },
  {
    name:"王五"
  }],
  arr2:[{
    age:10
  },
  {
    age:20
  },
  {
    age:30
  }]
    }
  },
  methods:{
    arrTest(){
      this.arr.forEach((item,index)=>{
        console.log("我是每一项",item);
        console.log("我是每一项的索引",index);
      })
    },
    arrTest2(){
      this.testFilter=this.arr2.filter((item,index)=>{
        return item.age>15
      })
      console.log(this.testFilter);
      
    },
    arrTest3(){
      this.testReduce=this.arr2.reduce((total,item)=>{
        return total+item.age
      },0)
      console.log(this.testReduce);
      
    }
  }
}

</script>

<style scoped>
#myList{
  color: blue;
  background-color: yellow;
  margin-top: 20px;
}
</style>

我的年龄数据为10,20,30,他们累加之后为60,如果在最后一项,我不是以0为初始值,更改为1后,累加的值就变成了61.

javascript 复制代码
 this.testReduce=this.arr2.reduce((total,item)=>{
        return total+item.age
      },0)
相关推荐
①个程序员20 分钟前
thinkphp 学习记录
学习
alfiy1 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
向上的车轮1 小时前
Django学习笔记十一:部署程序
笔记·学习·django
不灭锦鲤2 小时前
ssrf学习(ctfhub靶场)
网络·学习·安全
alfiy2 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
权^2 小时前
MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)
大数据·数据库·学习·mysql
pumpkin845142 小时前
CXO、CRO、CMO、CDMO相关概念
笔记
冷静 包容2 小时前
C语言学习之 没有重复项数字的全排列
c语言·开发语言·学习
K3njuan2 小时前
《数据结构》学习系列
学习
结衣结衣.2 小时前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法