分享一个小需求用vue的实现过程

今天用vue实现了一个小需求,里面涉及到了不少知识点,在此对这个需求的实现做一个记录。

首先上效果图

1682051008978.png

说下需求:

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

实现思路:

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

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

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

  4. 全选和反选

    • 必须所有的小选框
    • 必须所有的小选框都选中,全选按钮才选中 → every
    • 如果全选按钮选中,则所有小选框都选中
    • 如果全选取消,则所有小选框都取消选中
    • 声明计算属性,判断数组中的每一个checked属性的值,看是否需要全部选
  5. 统计 选中的 总价 和 总数量 :通过计算属性来计算选中的总价和总数量

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

下面对需求一个个进行实现

    //先看下数据结构
    const fruitList = [
            {
              id: 1,
              icon: "http://autumnfish.cn/static/火龙果.png",
              isChecked: true,
              num: 2,
              price: 6,
            },
            ...
           ]
    
    //渲染功能
    <div
      class="tr"
      :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">
        <div class="my-input-number">
          <button
            class="decrease"
            @click="count(item.id)"
            :disabled="item.num <= 1"
          >
            -
          </button>
          <span class="my-input__inner">{{item.num}}</span>
          <button class="increase" @click="add(item.id)">+</button>
        </div>
      </div>
      <div class="td">{{item.price * item.num}}</div>
      <div class="td">
        <button @click="cancleBtn(item.id)">删除</button>
      </div>
    </div>
    
    //删除功能
    给对应的按钮添加点击事件,然后配合filter进行删除功能实现
    methods: {
        cancleBtn(id) {
            this.fruitList = this.fruitList.filter(item => item.id !== id)
        }
    }
    
    //修改商品的数量个数:这里面要注意的一点是在点击--的时候需要判断是否小于或等于1,若满足这个条件需要将对应的按钮设置disabled禁用。
        方法一:可以直接在对应的标签里面通过vue添加点击事件然后直接将相应的属性++或者--。
        <button class="increase" @click="add(item.num++)">+</button>
        <button
            class="decrease"
            @click="count(item.id)"
            :disabled="item.num <= 1"
          >
            -
          </button>
         
         方法二:给对应的按钮添加函数,使用find
         methods: {
             add(id){
                 this.fruitList.find(item => item.id === id).num++
             },
             count(id){
                 this.fruitList.find(item => item.id === id).num--
             }
         }
    
    
    //全选反选
    全选反选在用原生js实现的时候,会让你的头上着火,但是随着vue等一些mvvm框架的出现,这个需求变得简单了很多。在vue中,可以使用计算属性computed来实现这个需求:
      <!-- 底部 -->
    <div class="bottom">
      <!-- 全选 -->
      <label class="check-all">
        <input type="checkbox" v-model="allCheck" />全选
      </label>
      <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>
    </div>
    
    computed: {
        allCheck: {
            get(){
                return this.fruitList.every(item => item.isChecked)
            },
            set(newValue){
                this.fruitList.forEach(item => item.isCheckes = newValue)
            }
            
        }
    }
    
    //统计选中的 总价 和 总数量
    总价是更具商品的数量*商品的单价来决定的,所以这里我们也可以用计算属性来实现需求
    computed: {
        //总价
        totalPrice(){
            this.fruitList.reduce((sum, item) => {
                //这里要做个判断,因为商品的总价是选中的商品
                if(item.isChecked) {
                    return item.price * item.num
                }else{
                    return sum
                }
            }, 0)
        },
        totalCount(){
            this.fruitList.reduce((sum, item) => {
                //这里要做个判断,因为商品的总价是选中的商品
                if(item.isChecked) {
                    return item.num
                }else{
                    return sum
                }
            }, 0)
        }
    //持久化到本地:这里我们需要用到vue的侦听器watch配合localStorage
        watch: {
            //因为持久化数据到本地,我们知道这里变化的就是数组fruitList,所以我们通过侦听数组的变化来实现这个需求
            fruitList: {
                deep: true, 这个属性保证侦听器能进行深度侦听,也就是能侦听复杂数据类型的数据
                handler(newVal){ //newVal是变化后的新数据
                    localStorage.setItem('fruitList', JSON.stringify(newVal)) //复杂数据需要先转化成JSON字符串才能存储
                }
            }
        }
        
        //为了保证在界面刷新的时候,界面的状态不变,所以我们需要在界面加载的时候从本地存储取出数据(注意:此处需要JSON.parse转换成对象),然后将取出的对象赋值给fruitList.
    }
    

以上就是我对这一需求的编写过程,本人水平有限,若有不足之处还望各位大佬指出。欢迎评论区讨论~