vue2 数组18 some erver filter reduce axios 购物车案例
some:
return true是固定写法,终止some循环
erver:
filter:
优化写法:
arr.filter(item=>item.state).reduce((累加的结果,当前循环项)=>{},初始值)
拿上面的arr优化写法示例:
arr.filter(item=>item.state).reduce((amt,item)=>{
return amt += item.price*item.count
},0)
reduce:
二次简写:
const count = arr.filter(item=>item.state).reduce((amt,item)=>amt += item.price*item.count,0)
axios:
导入:
npm i axios -S
使用:
methods:{
// 封装请求列表数据
async initCar(){
// 调用axios的get方法数据
const {data:res}=await axios.get('接口')
console.log(res);
}
},
created(){
this.initCar()
}
案例:
<Goods v-for="item in list" :key="item.id" :title="item.goods_name" :img="item.goods_img" :Price="item.goods_price" :state="item.goods_state">
</Goods>
import Goods from './components/Goods/Goods.vue'
import axios from 'axios'
components: {
Header, Goods
},
data() {
return {
// 储存购物车的列表数据,默认空数组
list: [],
}
},
methods: {
// 封装请求列表数据
async initCar() {
// 调用axios的get方法数据
const { data: res } = await axios.get('https://www.escook.cn/api/cart')
// 请求到的数据需要渲染,则必须要转存到data上
console.log(res);
if (res.status === 200) {
this.list = res.list
}
}
},
created() {
this.initCar()
console.log(this.list);
}
APP页面:
<template>
<div class="app-container">
<!-- 头部组件 -->
<Header title="购物车"></Header>
<Goods v-for="item in list" :key="item.id" :id="item.id" :title="item.goods_name" :img="item.goods_img"
:Price="item.goods_price" :state="item.goods_state" @state-change="getnewState" :count="item.goods_count">
</Goods>
<Footer :isfull="fallState" :amm="amo" :all="total" @full-change="getFullState" ></Footer>
</div>
</template>
<script>
import Header from './components/Header/Header.vue'
import Goods from './components/Goods/Goods.vue'
import Footer from './components/Footer/Footer.vue'
import bus from './components/eventerBus.js'
import axios from 'axios'
export default {
components: {
Header, Goods, Footer
},
data() {
return {
// 储存购物车的列表数据,默认空数组
list: [],
}
},
computed: {
// 通过计算属性动态计算状态是false还是true
fallState() {
return this.list.every(item => item.goods_state === true)
},
amo() {
return this.list.filter(item => item.goods_state).reduce((total, item) => (total += item.goods_price * item.goods_count), 0)
},
total() {
return this.list.filter(item=>item.goods_state).reduce((t,item)=>(t+=item.goods_count),0)
}
},
methods: {
// 封装请求列表数据
async initCar() {
// 调用axios的get方法数据
const { data: res } = await axios.get('https://www.escook.cn/api/cart')
// 请求到的数据需要渲染,则必须要转存到data上
console.log(res);
if (res.status === 200) {
this.list = res.list
}
},
getnewState(e) {
this.list.some(item => {
if (item.id === e.id) {
item.goods_state = e.value
// return true
}
})
},
// 接受子组件传递过来的状态
getFullState(val) {
this.list.forEach(item => (item.goods_state = val))
}
},
created() {
this.initCar()
bus.$on('plus', val => {
this.list.some(item => {
if (item.id === val.id) {
item.goods_count = val.value
return
}
})
}),
bus.$on('reduce', val => {
this.list.some(item => {
if (item.id === val.id) {
item.goods_count = val.value
}
})
})
}
}
</script>
<style lang="less" scoped>
.app-container {
padding-top: 45px;
padding-bottom: 50px;
}
</style>
Header组件:
<template>
<div class="header-container">{{title}}</div>
</template>
<script>
export default {
props:{
title:{
default:'',
type:String,
}
}
}
</script>
<style lang="less" scoped>
.header-container {
font-size: 12px;
height: 45px;
width: 100%;
background-color: #1d7bff;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
position: fixed;
top: 0;
z-index: 999;
}
</style>
Goods 组件:
<template>
<div class="goods-container">
<!-- 左侧图片 -->
<div class="thumb">
<div class="custom-control custom-checkbox">
<!-- 复选框 -->
<input type="checkbox" class="custom-control-input" :id="'cb' + id" :checked="state" @change="statechange" />
<label class="custom-control-label" :for="'cb' + id">
<!-- 商品的缩略图 -->
<img :src="img" alt="" />
</label>
</div>
</div>
<!-- 右侧信息区域 -->
<div class="goods-info">
<!-- 商品标题 -->
<h6 class="goods-title">{{ title }}</h6>
<div class="goods-info-bottom">
<!-- 商品价格 -->
<span class="goods-price">¥{{ Price }}</span>
<!-- 商品的数量 -->
<Counter :num="count" :id="id"></Counter>
</div>
</div>
</div>
</template>
<script>
import Counter from '../Counter/Counter.vue'
export default {
props: {
//在这里封装一个id是因为将来商品勾选状态变化后,需要子传父的形式,通知父组件,通知父组件,根据id修改对应商品的勾选状态
id: {
required: true,
type: true,
},
title: {
default: '',
type: String,
},
img: {
default: '',
type: String,
},
Price: {
default: '',
type: Number,
},
// 勾选状态
state: {
default: true,
type: Boolean,
},
count:{
default:1,
type:Number,
}
},
components:{
Counter
},
methods: {
statechange(e) {
const newState = e.target.checked
this.$emit('state-change', { id: this.id, value: newState })
}
},
}
</script>
<style lang="less" scoped>
.goods-container {
+.goods-container {
border-top: 1px solid #efefef;
}
padding: 10px;
display: flex;
.thumb {
display: flex;
align-items: center;
img {
width: 100px;
height: 100px;
margin: 0 10px;
}
}
.goods-info {
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1;
.goods-title {
font-weight: bold;
font-size: 12px;
}
.goods-info-bottom {
display: flex;
justify-content: space-between;
.goods-price {
font-weight: bold;
color: red;
font-size: 13px;
}
}
}
}
</style>
Footer组件:
<template>
<div class="footer-container">
<!-- 左侧的全选 -->
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="cbFull" :checked="isfull" @change="fullChange" />
<label class="custom-control-label" for="cbFull">全选</label>
</div>
<!-- 中间的合计 -->
<div>
<span>合计:</span>
<span class="total-price">¥{{ amm.toFixed(2) }}</span>
</div>
<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ all }})</button>
</div>
</template>
<script>
export default {
props:{
// 全选的状态
isfull:{
type:Boolean,
default:true,
},
amm:{
type:Number,
default:0,
},
all:{
type:Number,
default:0,
}
},
methods:{
fullChange(e){
this.$emit('full-change',e.target.checked)
},
}
}
</script>
<style lang="less" scoped>
.footer-container {
font-size: 12px;
height: 50px;
width: 100%;
border-top: 1px solid #efefef;
position: fixed;
bottom: 0;
background-color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
}
.custom-checkbox {
display: flex;
align-items: center;
}
#cbFull {
margin-right: 5px;
}
.btn-settle {
height: 80%;
min-width: 110px;
border-radius: 25px;
font-size: 12px;
}
.total-price {
font-weight: bold;
font-size: 14px;
color: red;
}
</style>
Counter组件:
<template>
<div class="number-container d-flex justify-content-center align-items-center">
<!-- 减 1 的按钮 -->
<button type="button" class="btn btn-light btn-sm" @click="sub">-</button>
<!-- 购买的数量 -->
<span class="number-box">{{num}}</span>
<!-- 加 1 的按钮 -->
<button type="button" class="btn btn-light btn-sm" @click="add">+</button>
</div>
</template>
<script>
import bus from '../eventerBus.js'
export default {
props:{
id:{
required:true,
type:Number,
},
num:{
default:1,
type:Number,
}
},
methods:{
add(){
const obj ={
id:this.id,
value:this.num+1
}
bus.$emit('plus',obj)
},
sub(){
if(this.num - 1 === 0 )return
const obj = {
id:this.id,
value:this.num-1
}
bus.$emit('reduce',obj)
}
}
}
</script>
<style lang="less" scoped>
.number-box {
min-width: 30px;
text-align: center;
margin: 0 5px;
font-size: 12px;
}
.btn-sm {
width: 30px;
}
</style>
eventerBus.js
import Vue from "vue"
export default new Vue()
代码改变了我们,也改变了世界