Vue2之简单深入

计算属性

何为计算属性?

基于现有的数据,计算出新的数据

特性

1.会依赖数据变化,自动更新,重新计算
2.具有缓存特性,便于提升性能:一旦计算结果算出来,就会进行缓存,
  当下一次读取是,会直接从缓存中获取数据(在没改变数据的基础上,只需计算一次即可)

语法

1.声明

简单写法

computed: {
	计算属性名(){
		计算过程...
		return 结果
	}
}

完整写法

computed: {
	计算属性名: {
		get(){
			//计算逻辑代码块
			return 结果
		},
		set(修改的值){
			//修改逻辑代码块
		}
	}
}

2.使用

{{ 计算属性名 }}

清单统计数量案例

<div id="app">
  <h3>清单表</h3>
  <table>
    <tr>
      <th>名字</th>
      <th>数量</th>
    </tr>
    <tr v-for="(item, index) in list" :key="item.id">
      <td>{{ item.name }}</td>
      <td>{{ item.num }}个</td>
    </tr>
  </table>
  <p>礼物总数:{{ total }} 个</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      // 现有的数据
      list: [
        { id: 1, name: '足球', num: 5 },
        { id: 2, name: '玩具', num: 8 },
        { id: 3, name: '学习用品', num: 5 },
      ]
    },
    computed: {
      total(){
        let total = this.list.reduce((sum,item) => {
          sum+=item.num
          return sum
        }
        ,0)
        return total
      }
    }
  })
</script>

结果展示

Watch侦听器

用途

监听数据变化,执行一些 业务逻辑 或 异步操作

语法

简单写法

data: {
	name: '小王',
	obj: {
		fruit: '芒果'
	}
},
//注意:一般oldValue可以省略
watch: {
	//属性名称
	name(newValue[,oldValue]){
		//业务实现代码
	},
	
	//'对象.属性名'
	'obj.fruit'(newValue[,oldValue]){
		//业务实现代码
	}
}

完整写法

data: {
	obj: {
		fruit: '芒果'
	}
},

watch: {
	数据属性名: {
		deep: true,	//对复杂类型深度检测
		immediate: true,	//一进入页面handler就立刻执行一次
		handler(newValue){
			//操作内容
		}
	}
}

购物车案例

<div class="app-container" id="app">
  <!-- 顶部banner -->
  <div class="banner-box"><img src="./img/fruit.jpg" alt="" /></div>
  <!-- 面包屑 -->
  <div class="breadcrumb">
    <span>🏠</span>
    /
    <span>购物车</span>
  </div>
  <!-- 购物车主体 -->
  <div class="main" v-if="fruitList.length > 0">
    <div class="table">
      <!-- 头部 -->
      <div class="thead">
        <div class="tr">
          <div class="th">选中</div>
          <div class="th th-pic">图片</div>
          <div class="th">单价</div>
          <div class="th num-th">个数</div>
          <div class="th">小计</div>
          <div class="th">操作</div>
        </div>
      </div>
      <!-- 身体 -->
      <div class="tbody">
        <div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }">
          <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 :disabled="item.num <= 1" class="decrease" @click="sub(item.id)"> - </button>
              <span class="my-input__inner">{{ item.num }}</span>
              <button class="increase" @click="add(item.id)"> + </button>
            </div>
          </div>
          <div class="td">{{ item.num * item.price }}</div>
          <div class="td"><button @click="del(item.id)">删除</button></div>
        </div>
      </div>
    </div>
    <!-- 底部 -->
    <div class="bottom">
      <!-- 全选 -->
      <label class="check-all">
        <input type="checkbox" v-model="isAll"/>
        全选
      </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>
  </div>
  <!-- 空车 -->
  <div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
  // 2.持久化到本地
  const defaultArr = [
            {
              id: 1,
              icon: 'http://autumnfish.cn/static/火龙果.png',
              isChecked: true,
              num: 2,
              price: 6,
            },
            {
              id: 2,
              icon: 'http://autumnfish.cn/static/荔枝.png',
              isChecked: false,
              num: 7,
              price: 20,
            },
            {
              id: 3,
              icon: 'http://autumnfish.cn/static/榴莲.png',
              isChecked: false,
              num: 3,
              price: 40,
            },
            {
              id: 4,
              icon: 'http://autumnfish.cn/static/鸭梨.png',
              isChecked: true,
              num: 10,
              price: 3,
            },
            {
              id: 5,
              icon: 'http://autumnfish.cn/static/樱桃.png',
              isChecked: false,
              num: 20,
              price: 34,
            },
          ]
  const app = new Vue({
    el: '#app',
    data: {
      // 水果列表
      // 3.持久化到本地
      fruitList: JSON.parse(localStorage.getItem('list')) || defaultArr,
    },
    computed: {
      // 全选和反选功能
      // 完整写法 = get + set
      isAll: {
        get () {
          return this.fruitList.every(item => item.isChecked)
        },
        set (value) {
          // 基于拿到的布尔值,要让所有的小选框 同步状态
          this.fruitList.forEach(item => item.isChecked = value)
        }
      },
      // 统计选中的总数 reduce
      totalCount () {
        return this.fruitList.reduce((sum, item) => {
          if (item.isChecked) {
            // 选中 → 需要累加
            return sum + item.num
          } else {
            // 没选中 → 不需要累加
            return sum
          }
        }, 0)
      },
      // 总计选中的总价 num * price
      totalPrice () {
        return this.fruitList.reduce((sum, item) => {
          if (item.isChecked) {
            return sum + item.num * item.price
          } else {
            return sum
          }
        }, 0)
      }
    },
    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--
      }
    },
    // 1.持久化到本地
    watch: {
      fruitList: {
        deep: true,
        handler (newValue) {
          // 需要将变化后的 newValue 存入本地 (转JSON)
          localStorage.setItem('list', JSON.stringify(newValue))
        }
      }
    }
  })
</script>
posted @ 2024-02-12 16:36  Nakano_Miku  阅读(14)  评论(0)    收藏  举报
返回顶端