uniapp 笔记第三天(修改数组对象的某个值、watch、computed)

发布于:2023-02-01 ⋅ 阅读:(1983) ⋅ 点赞:(1)

一、给数组绑定点击事件

在之前的学习中都是给一些基本的元素(button、view)绑定了元素 ,但从来没给每个循环元素绑定过

	<view class="box1 flexA" v-for="(item,index) in list"  @click="getItem(item,index)">
			<view class="" style="margin-left: 100rpx;">
				<view class="flexJ" style="width: 400rpx;">
					<view class="">商品名称 </view>
					<view class="">{{item.name}}</view>
				</view>
				<view class="flexJ" style="width: 400rpx;">
					<view class="">数量</view>
					<view class="">{{item.num}}</view>
				</view>
				<view class="flexJ" style="width: 400rpx;">
					<view class="">价钱</view>
					<view class="">¥{{item.price}}</view>
				</view>
			</view>
		</view>


        list: [{
					name: '奥特曼1',
					num: 6,
					price: 50,
					id: 1,
					status: false,
				}, {
					name: '奥特曼2',
					num: 5,
					price: 30,
					id: 2,
					status: false,
				}, {
					name: '奥特曼3',
					num: 8,
					price: 16,
					id: 3,
					status: false,
				}],

上面是一组基础数据 我们要实现点击哪个组 就拿到哪组的数据  记得给谁绑定谁就会生效,绑定了点击事件 记得要在methods里面定义

	getItem(item, index) {
				console.log(item, index);
	},

 注意在循环中 我们是可以把循环的变量当做参数传给 methods里定义的方法里的, 注意传过去的参数 和接受的参数 要对应

<view class="box1 flexA" v-for="(item,index) in list"  @click="getItem(item,index)"></view>

	getItem(item, index) {
				console.log(item, index);
	},

 可以看到从上面 点击哪个值 在控制台就可以打印出对应的值

二、修改数组对象中的某个值

这时候有一个场景哈 如果让你实现点击哪一项让当前的哪一项 的价钱加1你会怎么做

先来说一种错误写法 直接修改item里面的变量 让里面的价钱+1

getItem(item, index) {
				 item.price = item.price + 1
	},

 

本质上是可以这么修改的,但是不推荐哈,原因就是 传过来的对象和data里面定义的对象 指向的都是同一个地址,所以可以修改,如果你去定义一个简单的数据类型

// template
	<view @click="add(num)"> {{num}} </view>

//data:
	num: 0,

// methods
	add(num) {
		 num=num+1
	},

如果你试过的话 你会发现这么修改简单数据类型并没有任何作用,原因是简单数据类型没有地址的概念 现在修改的num是一个简单数据类型传过来的 num 并非data里定义的 num 传过来的只是值而已

如果你想修改变量的话 直接赋值data里的变量即可

add(num) {
				this.num = this.num + 1
		},

如果你想直接修改 复杂数据类型里的某个值 也是同理,我们既然可以拿到上面的索引 直接根据索引找某个值就好了

getItem(item, index) {
				console.log(item, index);
				// 1. 第一种写法 拿到list对应的当前项的值去+1
				 this.list[index].price = this.list[index].price + 1 
			},
	getItem(item, index) {
				console.log(item, index);
				// 2. 第二种写法  拿到item 当前项的值去+1
				 this.list[index].price = item.price + 1
			},

 三、切换变量小demo

<template>
	<view class="">
		<view class="box1 flexA" v-for="(item,index) in list" >
			<view class="" @click="toggleStatus(item,index)">
				<image v-if="item.status==true" src="/static/yes.png" mode=""></image>
				<image v-else src="/static/noCur.png" mode=""></image>
			</view>
			<view class="" style="margin-left: 100rpx;">
				<view class="flexJ" style="width: 400rpx;">
					<view class="">商品名称 </view>
					<view class="">{{item.name}}</view>
				</view>
				<view class="flexJ" style="width: 400rpx;">
					<view class="">数量</view>
					<view class="">{{item.num}}</view>
				</view>
				<view class="flexJ" style="width: 400rpx;">
					<view class="">价钱</view>
					<view class="">¥{{item.price}}</view>
				</view>
			</view>
		</view>
	</view>
</template>

//data
list: [{
					name: '奥特曼1',
					num: 6,
					price: 50,
					id: 1,
					status: false,
				}, {
					name: '奥特曼2',
					num: 5,
					price: 30,
					id: 2,
					status: false,
				}, {
					name: '奥特曼3',
					num: 8,
					price: 16,
					id: 3,
					status: false,
				}],

我们想呢 点击哪个按钮 就让谁切换它的状态,看上面的数据哈 每一项都有一个status  你就可以根据索引拿到当前的状态赋值 做法就是取反哈!

toggleStatus(item, index) {
				this.list[index].status = !item.status
			},

 四、计算选中的价格

 我们还是通过上面定义的点击事件哈

1.先不考虑当前选没选中 先把所有的价钱算出来

错误写法:

toggleStatus(item, index) {
				this.list[index].status = !item.status
		    	this.list.forEach(it=>this.allPrice = it.price*it.num)
			},

这么写的话永远拿的都是 最后一次循环的值 每次都在替换 知道替换到最后一次 变成了128

 正确写法:

				 this.list.forEach(it=> this.allPrice = this.allPrice + it.price*it.num)

这样写呢 就会把之前把之前计算过的带着再算一次

 这样我们就可以拿到 所有的价钱哈

2.计算选中的

我们想要的并不是所有的总价钱 肯定是拿到选中的 

第一种写法

toggleStatus(item, index) {
				this.list[index].status = !item.status
				
				// 第一种写法
				 this.allPrice = 0
				 this.list.forEach((it, idx) => {
				 	if (it.status == true) {
				 		this.allPrice = this.allPrice + it.price * it.num
				 	}
				 })
				
			},

 记得每次都赋值一下初始值哈,如果 你不知道什么原因 我建议你把赋值一行代码注释了 看看有没有什么影响

第二种写法

toggleStatus(item, index) {
				this.list[index].status = !item.status
				// 思路:把选中的数组过滤出来 再去计算
				 let arr = this.list.filter(item=> item.status) // 把选中的数组过滤出来 赋值给arr
				 let sum = 0 // 算出总价钱用的
				 arr.forEach(it=> sum = sum +  it.price * it.num) //计算价钱
				 this.allPrice = sum // 赋值给上面的变量
				 console.log('总价钱',sum,'当前选中的数组',arr);
				
			},

四、computed

computed 计算属性通常适合做一些映射、多对一时进行的操作,多对一:例如 一个数组中 判断每项算出一个结果出来 

语法:

	computed: {
			getAllPrice() {
				return this.num+1
			}
		},

我们来看vue 给我提供的例子 

{{ message.split('').reverse().join('') }}

上面呢 在一个差值表达式里调用了很多方法 如果说在上面操作中在加一些方法会不会感觉很凌乱,所以vue提供给我们了计算属性,它会实时根据data里的变量实时映射

	{{reverseStr}}


    computed: {
			reverseStr(){
				return this.str.split('').reverse().join('')
			}
		},

例如通过上面例子中计算总价格 我们就可以通过计算属性去实现它

	getAllPrice() {
				return this.list.filter(it => it.status).reduce((acc, it) => acc + it.price * it.num, 0)
			},

reduce 的执行过程 

 

五、watch

watch监听 他会实时监听这某一个、或某一组值的变化

简单数据类型监听

watch: {
			num(newValue, oldValue) {
				console.log('num新值:',newValue, 'num旧值',oldValue);
                // 做一些操作代码
				this.watchNum = newValue + 999
			}
}

 复杂数据类型

watch: {
			list:{
				deep:true, // 开启深度监听 专门对付复杂数据类型
				immediate:true, // 首次监听 一打开页面就想监听
				handler: function (newValue, oldValue){
					this.watchAllPrice = 0
					this.list.forEach((it, idx) => {
						if (it.status == true) {
							this.watchAllPrice = this.watchAllPrice + it.price * it.num
						}
					})				
				}
				
			}
},

注意:handler的函数格式不要写成箭头函数,否则拿不到当前的vue实例

总结 :watch能做的computed都可以实现,如果说你发现了哪个好玩的功能点 可以考虑试一下这两个是否都能实现呢

扩展:watch和computed 的区别