Vue学习day_02

2023-12-28 20:42:42

水果店的案例:

?要求:

可以动态删除 一个对个数的修改,以及点击全选的时候,水果前面的按钮都要标记为选中,要把价格,结算的个数等都要动态变化出来.

分析:

1:渲染功能:

v-if进行条件的判断,要是数组里面有数据的话,就把主页面显示出来,要是没数据的话,就显示另外一个盒子v-else

v-for 进行循环产生数据

每一行的模板都是一样的,就是数据不一样,那就变一下数据就行了,其他都保持一致

v-for="(item, index) in fruitList " :key="item.id"
:class修改样式

对每一行进行监控,看看是否被选中isChecked,选中的话就加上active这个class, 这个class是让这一行的背景颜色变得浅灰色的, :class的用法 {}里面写的这个类名为false,还是true,要是true的话 就加上这个class反之就除去

:class="{active: item.isChecked}"

2.删除功能:?

点击传参数,filter过滤覆盖原数组,写的时候一定要加上this, filter参数的介绍,filter(数组里面其中的一个元素 => 保留这个当前元素满足的条件),有点类似于foreach

<button @click="del(item.id)" class="del">删除</button>
  methods: {
        del(id) {
          this.fruitList = this.fruitList.filter(item => item.id != id)
        }
      },

3.修改个数:?

对加减按钮做一个点击的监听,要是加的话,数++,减的话--, 需要注意的话,要是减的话,不能低于1,这里用到了 :disabled = "数和1的关系", disabled为true了就表示这个按钮不能用,也就是被禁了

在Vue中,可以使用:disabled绑定属性来动态地设置表单元素的禁用状态。:disabled绑定属性有两种写法,分别是v-bind:disabled和简写的:disabled。

   <button :disabled="item.num <= 1" @click="item.num--">-</button>
          <span>{{item.num}}</span>
          <button @click="item.num++">+</button>

4.全选反选:?

计算属性computed 完整的写法get/set

.every的用法:

.every()方法用于判断一个数组中的所有元素是否都满足指定的条件。

.every((num => num 满足什么条件))

示例代码:
const numbers = [1, 2, 3, 4, 5];
const allPositive = numbers.every((num) => num > 0);
console.log(allPositive); // 输出 true
?.foreach的用法:

.forEach()方法用于对数组中的每个元素执行一次指定的函数。.foreach((num) => {想让每个数据做什么})

示例代码:
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
  console.log(num);
});

给每个按钮进行双向绑定v-model?

   <div class="td"><input type="checkbox" v-model="item.isChecked"></div>
   isAll: {//默认的是只能获取 不能设置
          //全部的都选中才全选 -> every
          get() {
            return this.fruitList.every(item => item.isChecked)
          },
          set(value) {
            //拿到布尔值 让全部的小选框 同步状态
            //这个也算是forEach的遍历了
            this.fruitList.forEach(item => item.isChecked = value)
          }
        },

5.统计选中的总价和总个数:?

统计,就是计算属性computed reduce条件求和,只有被选中之后才把这个里面的数据给求和

computed是用于定义计算属性的一个选项。计算属性是一种根据现有的数据计算得出的属性,它们的值会根据依赖的数据的变化而自动更新。需要注意的是,reduce()方法不会修改原始数组,而是返回一个新的累计值。

reduce的用法:

用于对数组中的元素进行累积计算。

reduce示例代码:
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);
console.log(sum); // 输出15

在 reduce() 方法中,accumulator(累计值)是回调函数中的一个参数,表示上一次回调的返回值,也就是累计值
在使用 reduce() 方法时,初始值或者上一次回调的返回值会被赋给 accumulator。然后,回调函数会对当前值进行处理,并将结果返回作为下一次回调的累计值,以此类推。?

   computed: {
        //统计总数
        totalCount() {
          //注意 加的是选中的
          return this.fruitList.reduce((sum, item) => {
            if (item.isChecked) {
              return sum + item.num
            } else {
              return sum
            }
          }, 0)
        },
        //统计选中的总价
        totalPrice() {
          return this.fruitList.reduce((sum, item) => {
            if (item.isChecked) {
              return sum + item.num * item.price
            } else {
              return sum
            }
          }, 0)
        }
      },

6.持久化到本地:?

watch监视,localStorage, JSON.stringify, JSON.parse

watch 是一个用于监听某个数据变化的功能。当被监听的数据发生变化时,watch 会自动执行对应的回调函数。

watch 和 v-model 都可以用于实现数据的动态变化。

虽然它们都可以用于监听数据的变化,但它们的应用场景和使用方式有所不同。
v-model 主要用于在表单元素(如输入框、复选框、下拉列表等)和数据属性之间建立双向绑定关系。当用户在表单元素中输入内容时,数据属性会自动更新;反之,当数据属性的值发生变化时,表单元素会自动更新显示。这使得用户输入和数据的动态变化保持同步。watch 则更适用于在数据发生变化时执行一些自定义的操作。通过 watch,你可以监听指定的数据属性,并在其变化时执行相应的回调函数。

总体代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    #app {
      width: 100%;
    }

    .main {
      width: 100%;
      /* height: ; */
    }

    .tr {
      float: left;
      width: 16%;
      /* border: 1px solid skyblue; */
      text-align: center;
      padding-top: 40px;
    }

    .empty {
      width: 100%;
      color: #c6c6c6;
      font-size: 40px;
      text-align: center;
      /* margin-top: 100px; */
    }

    .table {
      width: 100%;
      height: 100px;
      /* background-color: pink; */
    }

    .td {
      width: 16%;
      float: left;
      line-height: 100px;
      text-align: center;
    }

    .tbody {
      width: 100%;
      height: 140px;
      margin-bottom: 10px;
    }

    .td img {
      width: 100%;
      height: 100px;
    }

    .active {
      background-color: #f5f7fb;
    }

    .tbody button {
      width: 60px;
      height: 40px;
      font-size: 20px;
    }

    .left {
      margin-left: 125px;
      float: left;
    }

    .right {
      float: right;
    }

    .right p {
      display: inline;
      color: red;
      font-size: 30px;
    }

    .del {
      background-color: #e5473b;
      border: none;
      color: white;
    }
  </style>
</head>

<body>
  <div id="app">
    <div class="main" v-if="fruitList.length > 0">
      <div class="table">
        <div class="thread">
          <div class="tr">选中</div>
          <div class="tr">图片</div>
          <div class="tr">单价</div>
          <div class="tr">个数</div>
          <div class="tr">小计</div>
          <div class="tr">操作</div>
        </div>
      </div>

      <div class="tbody" :class="{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">
          <!-- 这个需要注意的是 当数量小于等于1的时候减号按钮要被禁掉 -->
          <button :disabled="item.num <= 1" @click="item.num--">-</button>
          <span>{{item.num}}</span>
          <button @click="item.num++">+</button>
        </div>
        <div class="td">{{item.price * item.num}}</div>
        <div class="td"><button @click="del(item.id)" class="del">删除</button></div>
      </div>

      <div class="sum">
        <div class="left"><input type="checkbox" v-model="isAll">全选</div>
        <div class="right">
          总价: ¥ <p>{{totalPrice}}</p>
          <button
            style="background-color: #3781fe; border: none; width: 80px; height: 30px; color: white;">结算({{totalCount}})</button>
        </div>
      </div>
    </div>
    <div class="empty" v-else>
      🛒空空如也
    </div>
  </div>

  <script src="../vue.js"></script>
  <script>
    const defaultArr = [
      {
        id: 1,
        icon: '../images/水果1.png',
        isChecked: true,
        num: 2,
        price: 6
      },
      {
        id: 2,
        icon: '../images/水果2.png',
        isChecked: false,
        num: 7,
        price: 20
      },
      {
        id: 3,
        icon: '../images/水果3.png',
        isChecked: true,
        num: 4,
        price: 12
      },
    ]
    const app = new Vue({
      el: '#app',
      data: {
        fruitList: JSON.parse(localStorage.getItem('list')) || defaultArr,
      },
      methods: {
        del(id) {
          this.fruitList = this.fruitList.filter(item => item.id != id)
        }
      },
      watch: {
        fruitList: {
          deep: true,
          handler(newValue) {
            //需要把变化后的数据 存取到本地里面(转JSON)
            localStorage.setItem('list', JSON.stringify(newValue))
          }
        }
      },
      computed: {
        isAll: {//默认的是只能获取 不能设置
          //全部的都选中才全选 -> every
          get() {
            return this.fruitList.every(item => item.isChecked)
          },
          set(value) {
            //拿到布尔值 让全部的小选框 同步状态
            //这个也算是forEach的遍历了
            this.fruitList.forEach(item => item.isChecked = value)
          }
        },
        //统计总数
        totalCount() {
          //注意 加的是选中的
          return this.fruitList.reduce((sum, item) => {
            if (item.isChecked) {
              return sum + item.num
            } else {
              return sum
            }
          }, 0)
        },
        //统计选中的总价
        totalPrice() {
          return this.fruitList.reduce((sum, item) => {
            if (item.isChecked) {
              return sum + item.num * item.price
            } else {
              return sum
            }
          }, 0)
        }
      },
    })
  </script>
</body>

</html>

文章来源:https://blog.csdn.net/m0_74304371/article/details/135274242
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。