vuex
import { InjectionKey } from 'vue';
import { createStore, useStore as baseUseStore, Store} from 'vuex';
import { Product } from '../interface';
export interface State{
shoppingCart: Product[]
}
// 创建唯一类型key
export const key: InjectionKey<Store<State>> = Symbol();
export const store = createStore<State>({
state:{
shoppingCart:[]
},
getters:{
isInCart(state,data){
console.log(data)
console.log(state.shoppingCart)
return (data:any)=>{
return state.shoppingCart.findIndex(item=>item.id === data.id) > -1 ? true : false;
}
}
},
mutations:{
// 添加购物车
ADD_TO_CARD(state,data){
state.shoppingCart.push(data);
console.log(state.shoppingCart)
},
// 更新购物车数量
CHANGE_COUNT(state,{type,data}){
return state.shoppingCart.map(item=>{
if(data.id=== item.id){
item.count += type === 'add' ? 1 : -1;
}
return item;
})
},
// 删除购物车
REMOVE_BY_ID(state,id){
state.shoppingCart = state.shoppingCart.filter(item=>item.id!==id);
}
}
})
export function useStore(){
// 通过key给store提供类型
return baseUseStore(key)
}
列表页
<template>
<div class="products">
<div v-if="!loading">
<div class="product-list"
v-for="(item,index) in products"
:key="index"
>
<!-- 笔者比较懒没有封装成组件,大家请无视 -->
<span class="name">{{item.title}}</span>
<span class="price">{{item.price}}元</span>
<van-button
type="primary"
size="small"
@click="addHandle(item)"
>加入购物车</van-button>
</div>
</div>
<van-loading v-else />
</div>
</template>
<script lang="ts">
import { defineComponent,ref }from 'vue';
import { Product } from '@src/interface/index.ts';
import { apiGetProducts } from '@src/api/index.ts';
import { useStore } from '@src/store/index.ts';
import { toast } from '@src/utility/index.ts';
export default defineComponent({
name: "Products",
setup(){
const products= ref<Product[]>([]);
const loading = ref(false);
const { commit, getters } = useStore();
// 获取产品列表
const getProducts = async () => {
loading.value = true;
products.value = await apiGetProducts();
loading.value = false;
}
// 加入购物车
const addToCart = (product:Product) => {
commit('ADD_TO_CARD',{
title:product.title,
count:1,
id:product.id
})
}
// 判断是否在购物车中已存在
const isInCart = (product:Product)=>{
return getters.isInCart(product);
}
const addHandle = (product:Product) => {
// 如果已经存在
if(isInCart(product)) return toast('已存在');
addToCart(product);
toast('添加成功')
}
getProducts();
return {
loading, // 加载状态
products, // 商品列表
addHandle // 添加购物车
}
},
})
</script>
详情页
<template>
<div class="shopping-cart">
<h2>我的购物车</h2>
<div
class="product-info"
v-for="item in shoppingCart"
:key="item.id"
>
<span>{{item.title}}</span>
<div class="btn-box">
<button @click="changeCount('reduce',item)">-</button>
<span>{{item.count}}</span>
<button @click="changeCount('add',item)">+</button>
</div>
<van-button
type="danger"
size="small"
@click="removeHandle(item)"
>删除</van-button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { Product } from '@src/interface/index.ts';
import { useStore } from '@src/store/index.ts';
import { toast } from '@src/utility/index.ts';
export default defineComponent({
name: "ShoppingCart",
setup: () => {
const { state,commit } = useStore();
const shoppingCart = computed(()=>{
return state.shoppingCart
})
// 更新购物车数量
const changeCount = (type:string,data:Product) => {
// 保证购物车中最小数量为1
if(type === 'reduce' && data.count <= 1) return;
commit('CHANGE_COUNT',{type,data})
}
// 删除购物车
const removeCart = (data:Product) => {
commit('REMOVE_BY_ID',data.id);
}
// 处理函数
const removeHandle = (data:Product) => {
removeCart(data);
toast('删除成功')
}
return {
shoppingCart, // 购物车列表
changeCount, // 更新购物车数量
removeHandle // 删除购物车
}
},
})
</script>
<style lang="less" scoped>
@import './index.less';
</style>
<template>
<nav-bar :count="count" :active="activeRouteName"></nav-bar>
<div class="body">
<router-view/>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useRoute } from 'vue-router'
import { useStore } from './store/index'
import NavBar from "@components/NavBar/index.vue";
export default defineComponent({
name: 'App',
components:{
NavBar
},
setup() {
const store = useStore();
const route = useRoute();
const count = computed(():number=>{
return store.state.shoppingCart.length;
})
const activeRouteName = computed(():string =>{
// 由于name 可能有RouteRecordName | null | undefined类型
return route.name?.toString() || '';
})
return {
count,
activeRouteName
}
},
})
</script>
网友评论