这是学习的第7天,根据视频,把前期的所有做一个小案例,是一个购物车的案例,主要是使用了js中的各种循环
<template>
<view class="out">
<checkbox-group @change="onChange">
<view class="item" v-for="(item,index) in goods" :key="item.id">
<checkbox :value="item.id" :checked="item.checked"></checkbox>
<text class="title">{{item.name}}</text>
<text class="price">{{item.price}}元</text>
<text class="del" @click="remove(index)">删除</text>
</view>
</checkbox-group>
<view class="card">
<checkbox-group @change="allChange">
<label>
<checkbox :checked="allChecked" /><text>全选</text>
</label>
</checkbox-group>
<view class="text">
<view class="number">共{{toalNumber}}件商品</view>
<view class="total">总计:{{toalPrice}}元</view>
</view>
</view>
{{goods}}
</view>
</template>
<script setup>
import {
computed,
ref,
watch
} from "vue";
const goods = ref([{
id: "11",
name: "小米",
price: 4999,
checked: false
},
{
id: "22",
name: "华为",
price: 8899,
checked: false
},
{
id: "33",
name: "oppo",
price: 2688,
checked: false
},
{
id: "44",
name: "苹果",
price: 9999,
checked: false
},
])
const selectNumber = ref([]);//选中的数组
//这里使用一个计算属性,虽然在组件中使用变量也可以得到,但是总是不严谨
const toalNumber=computed(()=> selectNumber.value.length);
const allChecked=ref(false)
// 这是选择后得到的价格集合,这里记录下:使用reduce的时候,本地不能使用简化的方式,最后把所有的删除,
// 重新复制了一份就可以了
const toalPrice=computed(()=>{
return goods.value.filter(item => item.checked).reduce((prev, curr) => prev + curr.price, 0)
})
//删除
function remove(index) {
goods.value.splice(index, 1);
selectNumber.value=goods.value.filter(item=> item.checked==true).map(item => item.id);
}
//点击复选框后得到具体个数
function onChange(e) {
//在这里需要再组件上定义value和点击状态,不然得到的event是空的
selectNumber.value = e.detail.value;
// 根据map方法,将选择的条目状态赋值给数据源
goods.value = goods.value.map(item => ({
...item,
checked: selectNumber.value.includes(item.id) //includes:是判断是否包含,包含就返回true,不包含就返回false
}));
}
// 这是点击全选后更改数据源的状态
function allChange(e){
//这是得到全选的状态,是true的时候,就把所有的数据源更改为false,如果是false的时候,更改状态
// 因为在默认的时候,就是false
let newValue=!allChecked.value
goods.value=goods.value.map(item=>({
...item,
checked:newValue
}));
selectNumber.value= newValue ? goods.value.map(item => item.id): [];
}
// 这里需要监听事件,不然会出现只有全选状态是true的时候,是正常的,但是没有和数据源关联起来
// every,这是判断数据源中的所有是否都满足条件就返回true
watch(goods,()=>{
allChecked.value=goods.value.every(item=>item.checked)
})
</script>
<style lang="scss" scoped>
.out {
padding: 10px;
.item {
padding: 10px 0;
.price {
margin: 0 20px;
}
.del {
color: #c00;
margin-left: 30px;
}
}
.card {
border-top: 1px solid #eee;
margin-top: 20px;
padding: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
.text {
display: flex;
align-items: center;
.total {
margin-left: 20px;
}
}
}
}
</style>
这就里面有各种for循环、forEach、map等方法的使用,对小白来说,各种不懂,虽然最后弄出来,但是根据老师视频进行的,幸好老师有课程,专门讲解,然后根据文档,进行深入学习
老师的博客地址:各种类型的for循环遍历,forEach/map/filter/for…in/for…of/every/some/includes/reduce的详细用法
下面是根据老师博客内容,进行的for循环等数据测试:
<template>
<view class="">
<!-- <view>第一种:使用for循环大数据耗时:{{countTime}}</view>
<view>第二种:使用for循环大数据耗时:{{countTime1}}</view>
<view>第三种:使用forEach循环大数据耗时:{{countTime2}}</view>
<view>第四种:使用forEach循环大数据耗时:{{countTime3}}</view>
<view>第五种:使用forEach循环大数据耗时:{{countTime4}}</view> -->
<view class="layout">
<input type="text" v-model="obj.name" placeholder="请输入姓名">
<input type="text" v-model="obj.age" placeholder="请输入年龄">
<input type="text" v-model="obj.gender" placeholder="请输入性别">
<input type="text" v-model="obj.like" placeholder="请输入爱好">
<button type="primary" :disabled="state" @click="onSubmit">提交</button>
</view>
</view>
</template>
<script setup>
import {
ref,computed
} from 'vue';
// for和forEach的差异化
/*
let arrs = [...Array(9999999).keys()]
// 下面是遍历大量数据,使用for循环后,整体遍历完所需要的耗时
let total = 0;
let startTime = Date.now();
for(let i=0; i<arrs.length; i++) total+=i;
let endTime = Date.now();
let countTime = endTime - startTime;
console.log("计数---->"+total);
console.log("消耗时间---->"+countTime);
let total1 = 0;
let startTime1 = Date.now();
for(let i=0; i<arrs.length; i++){
if(i==10) break;
total1+=i;
}
let endTime1 = Date.now();
let countTime1 = endTime1 - startTime1;
console.log("计数---->"+total1);
console.log("消耗时间---->"+countTime1);
// 以上是使用for循环遍历的两种情况,一种是有条件判断,一种是全部遍历的,
// 下面是使用forEach进行的遍历,效果和使用for循环差不多,这里是不添加其他,直接记录耗时的,
let total2 = 0;
let startTime2 = Date.now();
arrs.forEach(item=>{
return;
})
let endTime2 = Date.now();
let countTime2 = endTime2 - startTime2;
console.log("计数---->"+total2);
console.log("消耗时间---->"+countTime2);
// 下面是在forEack中计数的,最后的结果比for循环还要耗时
let total3 = 0;
let startTime3 = Date.now();
arrs.forEach(item=>{
total3+=item;
})
let endTime3 = Date.now();
let countTime3 = endTime3- startTime3;
console.log("计数---->"+total3);
console.log("消耗时间---->"+countTime3);
let total4 = 0;
let startTime4 = Date.now();
arrs.forEach(item=>{
if(item>10)return;
total4+=item;
})
let endTime4 = Date.now();
let countTime4 = endTime4 - startTime4;
console.log("计数---->"+total4);
console.log("消耗时间---->"+countTime4); */
// 上面是在forEach中添加了条件判断,对比同方法for循环,还是耗时较多
// 异步同步化的支持度
/*
let arrs = Array.from({length:3},(_,index)=>index+1);
let datas=[];
arrs.forEach(async item=>{
const {data} = await uni.request({
url:"http://jsonplaceholder.typicode.com/posts/"+item
})
datas.push(data)
})
console.log(datas);
async function fetchData() {
let arrs = Array.from({length:3},(_,index)=>index+1);
let datas=[];
for (let i = 0; i < arrs.length; i++) {
const {data} = await uni.request({
url:"http://jsonplaceholder.typicode.com/posts/"+arrs[i]
});
datas.push(data);
}
console.log(datas);
}
fetchData();
*/
// 使用map方法 map() 方法是数组原型的一个函数,对数组遍历不破坏原数组,将会创建一个新数组,
// 按照原始数组元素顺序依次执行给定的函数,map方法非常适合用于处理数组中的每个元素并生成新的数组。
// 将数组内每个元素×2后,获取新数组
let arrs = [1, 2, 3, 4];
let newArrs = arrs.map(item => item * 2);
console.log(newArrs);
// 将数组对象内每个元素的名称拿出来,作为一个新数组
let arrs0 = [{
name: "华为",
price: 6999
}, {
name: "苹果",
price: 9888
}, {
name: "小米",
price: 4999
}]
let newArrs0 = arrs0.map(item => item.name);
console.log(newArrs0);// ['华为', '苹果', '小米']
// 将数组中原来的name不做任何改变,原有price:6999改为price:“6999元”,并且新增number属性值为888
let arrs1 = [{
name: "华为",
price: 6999
}, {
name: "苹果",
price: 9888
}, {
name: "小米",
price: 4999
}]
let newArrs1 = arrs1.map(item => {
return {
...item,
price: item.price + "元",
number: 888
}
});
console.log(newArrs1);//[{name: '华为', price: '6999元', number: 888},....]
// 将原数组中属性进行更换,配合对象解构,可以更直观
let arrs2 = [{
key: 0,
content: "篮球"
}, {
key: 1,
content: "足球"
}, {
key: 2,
content: "排球"
}];
let newArrs2 = arrs2.map(({key,content}) => ({value: key,text: content}));
console.log(newArrs2);// [{value: 0, text: '篮球'},{value: 1, text: '足球'},{value: 2, text: '排球'}]
// 将异步请求map到新数组中,使用Promise.all同事处理多个Promise
let arrs3 = Array.from({length:3},(_,index)=>index+1);
const promises = arrs3.map(async (num) => {
const result = await uni.request({
url:"http://jsonplaceholder.typicode.com/posts/"+num
})
return result;
});
Promise.all(promises).then(res=>{
console.log(res);
})
//filter()方法 filter()过滤方法,会对原数组中的每个元素应用指定的函数,并返回一个新数组,其中包含符合条件的元素。原数组不会受到影响
// 找出数组中大于10的数据放到新数组中
let arrs4 = [5,7,8,15,22,1,2];
let newArrs4 = arrs4.filter(item=>{
return item>10
})
console.log(newArrs4);// [15,22]
// 如果是数组对象的话也是一样的,只需要找到满足的对象属性即可,比如找到数组对象中,年龄小于30岁的数据
let arrs5 = [{name:"张三",age:16},{name:"李四",age:40},{name:"王五",age:28},{name:"汤姆",age:20}];
let newArrs5 = arrs5.filter(item=>{
return item.age<30
})
console.log(newArrs5);//[{name:"张三",age:16},...]
// 数组去重,结合indexOf方法
let arrs6 = [6,1,2,3,5,3,6];
let newArrs6 = arrs6.filter((item,index,self)=>{
return self.indexOf(item) === index
})
console.log(newArrs6);// [6, 1, 2, 3, 5]
// 数组对象中过滤掉无用数据
let arrs7 = [{id:1,name:"HTML5"},{id:2,name:"JavaScript"},{id:null,name:"小程序"},{name:"NodeJS"},{id:3,name:"VueJS"}];
let newArrs7 = arrs7.filter(item=>{
return item.id
})
console.log(newArrs7);// [ {id: 1, name: 'HTML5'},...]
// filter和map组合使用,可以使用链式写法;首先去除无用数据,然后给每一条增加一个属性author
let arrs8 = [{id:1,name:"HTML5"},{id:2,name:"JavaScript"},{id:null,name:"小程序"},{name:"NodeJS"},{id:3,name:"VueJS"}];
let newArrs8 = arrs8.filter(item=>{
return item.id
}).map(item=>{
return {
...item,
author:"咸虾米"
}
})
console.log(newArrs8);// [{id: 1, name: 'HTML5', author: '咸虾米'},...]
//reduce()方法 reduce() 方法对数组中的每个元素按序执行一个指定方法,每一次运行 reducer 会将先前元素的计算结果作为参数传入。
// 数组求和 / 求积
let arrs9 = [1,2,3,4];
let result = arrs9.reduce((prev,current,index)=>{
console.log(prev,current,index);
return prev+current;
},0)
console.log("最终结果:"+result);
// 求数组中最大值:
let arrs10 = [5,6,1,22,3,7];
let result2 = arrs10.reduce((prev,current,index)=>{
return Math.max(prev,current);
},0)
console.log(result2);// 22
// 求数组中最小值:
let arrs11 = [5,6,1,22,3,7];
let result3 = arrs11.reduce((prev,current,index)=>{
return Math.min(prev,current);
},0)
console.log(result3);// 0
// 数组对象求和,求数组对象中age的和:
let arrs12 = [{name:"张三",age:29},{name:"李四",age:16},{name:"王五",age:50},{name:"小明",age:21}];
let result4 = arrs12.reduce((prev,current,index)=>{
return prev+current.age
},0)
console.log(result4);// 116
// every()方法 判断数组中所有元素是否满足函数中给定的条件,全部满足返回true,只要有一项不满足则返回false
// 检查数组中的所有元素是否满足特定条件
let arrs13 = [1, 2, 3, 4, 5];
let result5 = arrs13.every(num => num > 0);
console.log(result5);//true
// 检测数组对象中,是否所有商品都有库存
let arrs14 = [{name:"华为",price:5899,stock:true},
{name:"苹果",price:9999,stock:false},
{name:"小米",price:4399,stock:true},{name:"红米",price:899,stock:true}];
let result6 = arrs14.every(item=>item.stock);
console.log(result6);// false
// 检测对象内所有属性是否都有值,配合Object.values()
const obj = ref({
name:"",
age:"",
gender:"",
like:""
})
const state = computed(()=>{
if(obj.value.name && obj.value.age && obj.value.gender && obj.value.like){
return false;
}
return true;
})
function onSubmit(){
console.log("提交表单");
}
// 简化计算属性也可以这样写
// const state = computed(() => !(obj.value.name && obj.value.age && obj.value.gender && obj.value.like));
// 如果使用Object.values()方法,可以将所有的值放入到一个数组中,然后对数组进行every循环遍历,最后得到条件的true或false,计算属性就可以这样做了:
// const state = computed(()=>{
// return !Object.values(obj.value).every(item=>item)
// })
// 或
// const state = computed(()=>!Object.values(obj.value).every(item=>item))
// some()方法 some方法和every方法基本类似,只是some方法检测数组中,只要有一个满足条件即返回true,全部不满足条件才会返回false。
// 检查数组中的是否有满足特定条件的元素
let arrs15 = [55,26,3,12,39];
let result7 = arrs15.some(item=>item<10);
console.log(result7);// true
// 检查数组对象中,是否有满足price小于1000的元素,并且有stock库存
let arrs16 = [{name:"华为",price:5899,stock:true},{name:"苹果",price:9999,stock:false},{name:"小米",price:4399,stock:true},{name:"红米",price:899,stock:true}];
let result8 = arrs16.some(item=>item.price<1000 && item.stock);
console.log(result8);// true
// 将every表单示例改造成some方法
// 使用some完成全部对象有值的判断
const state1 = computed(()=>Object.values(obj.value).some(item=>!item))
// 只要有一个表单有值就将禁用改可用
const state2 = computed(()=>!Object.values(obj.value).some(item=>item))
// includes()方法 includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
// 注意:includes() 方法只能用于检测基础数据类型(如数字、字符串、布尔值),而不能用于检测包含对象或其他数组的二维数组。如果需要检测对象或其他复杂数据类型,可以使用其他方法或自定义函数来实现
const arrs18 = [1, 2, 3];
console.log(arrs18.includes(2));// true
// every和includes配合,检测一个数组是否包含另一个数组
let arrs111 = [1,2,3,4,5,6,7];
let arrs222 = [2,5,7];
let arrs333 = [1,6,9];
let result111 = arrs222.every(item=>arrs111.includes(item));
let result222 = arrs333.every(item=>arrs111.includes(item));
console.log(result111);// true
console.log(result222);// false
</script>
<style lang="scss" scoped>
.layout{
padding:30rpx;
input{
border:1px solid #e4e4e4;
height: 80rpx;
margin-bottom:20rpx;
padding:0 20rpx;
}
}
</style>
以上就是根据视频和文档,自己进行的整合,还是有很多不懂,需要继续在深入学习
这里做一个记录,这是前几天发布的文章,今天在回过头去看,突然出现一个情况,页面布局出现错误,刷新就好,最后更改了view的class的名称,每次打开就好了,什么原因,不清楚,先记录下。
上次记录的汰匆忙,今天有试了试这个问天,发现是class的名称,在其他地方也定义了,但是设置了css的scoped,么效果,这真不知道什么原因,这个还是只在h5页面出现,在小程序中并未出现,也怀疑是不是缓存的问题,但是清理后还是没效果,这里只能是做个记录,后期如果知道原因在做记录更新。。。。。刚重新清理了浏览器的缓存,这个问题不在出现,那应该就是缓存的问题了