Vue 实现商品分类、列表、详情、购物车、搜索(vant)
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
商品分类Classify:
<template>
<div>
<div style="display: flex;">
<div class="oneNav">
<!-- vant侧边导航 -->
<van-sidebar style="height: 617px; white-space: nowrap; overflow-y: scroll;" v-model="activeKey">
<van-sidebar-item
v-for="(item,index) in oneClass"
:title="item.cname"
@click="oneNav(index)"/>
</van-sidebar>
</div>
<div class="twoNav">
<!-- vant宫格 -->
<van-grid :gutter="10" column-num="3" :border="false" icon-size="60px">
<van-grid-item
v-for="(item,index) in twoClass"
:icon="item.scpic"
:text="item.subcname"
@click="onList(item.subcid)"/>
</van-grid>
</div>
</div>
</div>
</template>
<script>
export default{
data(){
return{
oneClass:[], //一级分类数据
activeKey:0,
twoClass:[] //二级分类数据
}
},
mounted() {
this.$axios.get('http://api.kudesoft.cn/tdk/category').then(res=>{
// console.log(res.data.data.data)
this.oneClass = res.data.data.data
this.twoClass = this.oneClass[0].subcategories
})
},
methods:{
oneNav(index){ //点击一级导航切换
this.$axios.get('http://api.kudesoft.cn/tdk/category').then(res=>{
// console.log(res.data.data.data)
this.oneClass = res.data.data.data
this.twoClass = this.oneClass[index].subcategories
})
},
onList(id){ //点击二级导航跳转列表页
this.$router.push({
path:'/list',
query:{
id
}
})
}
}
}
</script>
<style scoped>
.van-sidebar::-webkit-scrollbar {
display: none;
}
</style>
商品列表List:
<template>
<div>
<!-- vant搜索 -->
<div class="list-nav">
<van-search @click="toSearch" v-model="kw" shape="round" placeholder="请输入搜索关键词">
<template #left>
<van-icon @click="back" style="margin-right: 5px;" size="22px" name="arrow-left" />
</template>
</van-search>
</div>
<!-- 排序 -->
<div class="list-sort">
<div @click="onSort" :class="{'active':isActive==0}">综合排序</div>
<div @click="saleSort" :class="{'active':isActive==1}">销量</div>
<div @click="priceSort" style="display: flex;">
<div>价格</div>
<div style="margin-left: 5px;">
<div :class="{'active':isActive==2}" class="iconfont icon-jiantou"></div>
<div :class="{'active':isActive==3}" class="iconfont icon-jiantouxia"></div>
</div>
</div>
<div><!-- 下拉菜单 -->
<van-dropdown-menu>
<van-dropdown-item v-model="value1" :options="option1" @change="screen" />
</van-dropdown-menu>
</div>
</div>
<!-- vant骨架屏 -->
<van-skeleton v-for="i in 18" title :row="3" :loading="list.length<=0" style="background-color: white;"/>
<div style="margin-top: 96px;">
<!-- 商品卡片 -->
<van-card
v-for="(item,index) in list"
:tag="item.shopType == 1 ? '天猫':'淘宝'"
:price="item.actualPrice"
:title="item.title"
:thumb="item.mainPic"
@click="toDetails(item.id)">
<template #num>
<span>30天销量:{{item.monthSales}}</span>
</template>
</van-card>
</div>
</div>
</template>
<script>
export default{
data(){
return{
kw:'',
list:[],
value1: -1,
option1: [
{ text: '店铺类型', value: -1 },
{ text: '淘宝', value: 0 },
{ text: '天猫', value: 1 }
],
isActive:-1 //0综合排序,1销量,2价格升序,3价格降序
}
},
mounted() {
this.kw = this.$route.query.kw //把搜索页面搜索的值传过来
let id = this.$route.query.id
this.$axios.get('http://api.kudesoft.cn/tdk/goods',{
params:{
pageId:1,
subcid:id
}
}).then(res=>{
// console.log(res.data.data.data.list)
let list = res.data.data.data.list
if(this.kw == '' || this.kw == undefined){
this.list = list
}else{
list.map(item=>{
if(item.title.includes(this.kw)){
this.list.push(item)
}
})
}
})
},
methods:{
back(){ //返回分类页面
this.$router.push({
path:'/classify'
})
},
toSearch(){ //跳转到搜索页面
this.$router.push({
path:'/search'
})
},
toDetails(id){ //跳转到详情页面
this.$router.push({
path:'/details',
query:{
id
}
})
},
priceSort(){ //价格排序
if(this.isActive < 2){
this.isActive = 2
this.list.sort((a,b)=>{
return a.actualPrice - b.actualPrice
})
}else if(this.isActive == 2){
this.isActive = 3
this.list.sort((a,b)=>{
return b.actualPrice - a.actualPrice
})
}else if(this.isActive == 3){
this.isActive = 2
this.list.sort((a,b)=>{
return a.actualPrice - b.actualPrice
})
}
},
onSort(){ //综合排序
this.isActive = 0
this.list.sort((a,b)=>{
return b.shopLevel - a.shopLevel
})
},
saleSort(){ //销量排序
this.isActive = 1
this.list.sort((a,b)=>{
return b.monthSales - a.monthSales
})
},
screen(value){ //筛选
this.isActive = -1
this.list = []
if(value == -1){
this.$axios.get('http://api.kudesoft.cn/tdk/goods').then(res=>{
this.list = res.data.data.data.list
})
}else{
this.$axios.get("http://api.kudesoft.cn/tdk/goods").then(res=>{
let list = res.data.data.data.list
list.map(item=>{
if(item.shopType == value){
this.list.push(item)
}
})
})
}
}
}
}
</script>
<style scoped>
.list-title{
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.list-nav{
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.iconfont{
font-size: 8px;
margin: 0 3px;
}
.active{
color: red;
}
.list-sort{
position: fixed;
top: 54px;
left: 0;
z-index: 99;
width: 100%;
background-color: #FFFFFF;
display: flex;
justify-content: space-around;
align-items: center;
margin-top: -1px;
font-weight: 300;
}
</style>
商品详情Details:
<template>
<div>
<!-- element-ui返回顶部 -->
<el-backtop :bottom="100" :right="0">
<div
style="{
height: 100%;
width: 100%;
background-color: #f2f5f6;
box-shadow: 0 0 6px rgba(0,0,0, .12);
text-align: center;
line-height: 40px;
color: #000000;
border-radius: 50%;
}"
>
<span class="el-icon-upload2"></span>
</div>
</el-backtop>
<div>
<!-- vant轮播 -->
<div style="background-color: #FFFFFF; border-radius: 0 0 15px 15px; margin-bottom: 15px;">
<van-swipe class="my-swipe" indicator-color="white">
<van-swipe-item v-for="(item,index) in details.imgs">
<img :src="item" width="100%">
</van-swipe-item>
</van-swipe>
<div style="padding: 10px 10px;">
<div style="display: flex; justify-content: space-between;">
<span style="color: #F2270C;">¥<span style="font-size: 30px;">{{details.actualPrice}}</span></span>
<img :src="details.shopLogo" width="30px" height="30px">
</div>
<div>
<span style="margin-right: 5px; font-size: 12px; background-color: #FF0000; color: white; padding: 2px 2px; border-radius: 2px;">{{details.shopName}}</span>
<span style="font-weight: 700;">{{details.title}}</span>
</div>
</div>
</div>
<div>
<div v-for="(item,index) in details.detailPics">
<img :src="item.img" width="100%">
</div>
</div>
</div>
<div style="height: 50px;"></div>
<!-- vant商品导航 -->
<van-goods-action>
<van-goods-action-icon icon="chat-o" text="客服" dot />
<van-goods-action-icon icon="cart-o" text="购物车" :badge="this.carts.length" @click="toCarts"/>
<van-goods-action-icon icon="shop-o" text="店铺" />
<van-goods-action-button @click="addCart" type="warning" text="加入购物车" />
<van-goods-action-button type="danger" text="立即购买" />
</van-goods-action>
</div>
</template>
<script>
import Vue from 'vue';
import { Toast } from 'vant';
Vue.use(Toast);
export default{
data(){
return{
details:[],
carts:[] //购物车商品
}
},
created() {
let carts = localStorage.carts
if(carts){
this.carts = JSON.parse(carts)
}
},
mounted() {
let id = this.$route.query.id
this.$axios.get('http://api.kudesoft.cn/tdk/details',{
params:{
id:id
}
}).then(res=>{
// console.log(res.data.data.data)
this.details = res.data.data.data
this.details.imgs = this.details.imgs.split(',')
//this.details.detailPics = this.details.detailPics.split(',')
this.details.detailPics = JSON.parse(this.details.detailPics)
})
},
methods:{
toCarts(){ //跳转购物车页面
this.$router.push({
path:'/carts'
})
},
addCart(){ //添加购物车
Toast.success('加入购物车成功');
let rel = true
this.carts.map(item=>{
if(item.data.id == this.details.id){
item.num++;
rel = false;
}
})
if(rel){
this.carts.push({
data:this.details,
num:1
})
}
localStorage.carts = JSON.stringify(this.carts)
}
}
}
</script>
<style>
</style>
购物车Carts:
<template>
<div>
<!-- vant空状态 -->
<van-empty v-show="isShow" description="购物车目前还没有商品" image="https://img.yzcdn.cn/vant/custom-empty-image.png">
<van-button round type="danger" class="bottom-button" @click="gotoClassify">
去购物
</van-button>
</van-empty>
<div v-for="(item,index) in carts">
<!-- vant复选框组 --> <!-- vant布局 --> <!-- vant滑动单元格 -->
<!-- vant商品卡片 --> <!-- vant步进器 -->
<van-checkbox-group v-model="result" @change="onChecked">
<van-row style="background-color: white;">
<van-col span="2" style="margin-top: 35px;">
<van-checkbox :name="item"></van-checkbox>
</van-col>
<van-col span="22">
<van-swipe-cell>
<van-card
:price="item.data.actualPrice"
:desc="item.data.desc"
:title="item.data.dtitle"
:thumb="item.data.mainPic"
class="goods-card"
>
<template #num>
<van-stepper v-model="item.num" @change="onNum"/>
</template>
</van-card>
<template #right >
<van-button @click="del(item,index)" square text="删除" type="danger" class="delete-button" />
</template>
</van-swipe-cell>
</van-col>
</van-row>
</van-checkbox-group>
</div>
<!-- vant提交订单栏 -->
<van-submit-bar :price="total" button-text="提交订单">
<van-checkbox v-model="checkedAll" @click="onAll">全选</van-checkbox>
</van-submit-bar>
</div>
</template>
<script>
export default {
data(){
return{
carts:[], //添加到购物车的商品
result:[], //所有复选框选中的商品
checkedAll:false, //全选的状态
total:0, //总价
isShow:true
}
},
created() {
let carts = localStorage.carts
if(carts){
this.carts = JSON.parse(carts)
}
if(this.carts.length > 0){ //显示或隐藏空状态
this.isShow = false
}else{
this.isShow = true
}
},
methods:{
onNum(){ //商品数量发生变化时触发
this.onChecked()
localStorage.carts = JSON.stringify(this.carts)
},
onChecked(){ //点击复选框选中商品并计算总价
this.total = 0
this.result.map(item=>{
this.total += item.data.actualPrice*100*item.num
})
if(this.result.length == this.carts.length){
this.checkedAll = true
}else{
this.checkedAll = false
}
},
onAll(){ //点击全选按钮
if(this.checkedAll){ //如果为true的话全部选中,否则全不选
this.result = this.carts
}else{
this.result = []
}
},
del(item,index){ //删除
if(this.result.includes(item)){
this.$notify({ type: 'danger', message: '删除前请取消选中' });
}else{
this.carts.splice(index,1)
this.checkedAll = this.result.length == this.carts.length
localStorage.carts = JSON.stringify(this.carts)
}
if(this.carts.length > 0){ //显示或隐藏空状态
this.isShow = false
}else{
this.isShow = true
this.checkedAll = false
}
},
gotoClassify(){ //跳转到分类页
this.$router.push({
path:'/classify'
})
}
}
}
</script>
<style scoped="scoped">
.goods-card {
background-color: white;
}
.delete-button {
height: 100%;
}
.bottom-button {
width: 180px;
height: 40px;
}
</style>
搜索Search:
<template>
<div>
<!-- vant搜索 -->
<van-search @input="showSearch" @search="onSearch" autofocus show-action shape="round" v-model="kw" placeholder="请输入搜索关键词">
<template #left>
<van-icon @click="back" style="margin-right: 5px;" size="22px" name="arrow-left" />
</template>
<template #action>
<van-button @click="onSearch" size="small" type="danger" style="border-radius: 5px; font-size: 14px;">搜索</van-button>
</template>
</van-search>
<!-- 搜索记录 -->
<div v-show="isShow">
<div style="display: flex; justify-content: space-between; padding: 5px;">
<div>
搜索记录:
</div>
<div>
<van-icon @click="onDel" size="18px" name="delete" />
</div>
</div>
<div>
<van-tag style="margin: 5px;" v-for="(item,index) in saveList">{{item}}</van-tag>
</div>
</div>
<!-- 搜索提示 -->
<van-cell-group v-show="!isShow">
<van-cell v-for="(item,index) in showList" :title="item.dtitle" />
</van-cell-group>
</div>
</template>
<script>
export default{
data(){
return{
kw:'',
isShow:true,
list:[], //所有数据
saveList:[], //搜索记录的数据
showList:[] //搜索提示的数据
}
},
created() {
let saveList = localStorage.saveList
if(saveList){
this.saveList = JSON.parse(saveList)
}
},
mounted() {
this.$axios.get(' http://api.kudesoft.cn/tdk/goods').then(res=>{
// console.log(res.data.data.data.list)
this.list = res.data.data.data.list
})
},
methods:{
back(){ //返回上一级
window.history.back()
},
onSearch(val){ //点击enter和点击搜索时触发
if(val.trim() == ''){ //如果搜索的值为空则不会跳转
return
}
this.$router.push({ //点击跳转到列表页,并把输入的值传过去
path:'/list',
query:{
kw:val
}
})
if(!this.saveList.includes(val.trim())){ //判断是否重复添加相同记录
this.saveList.push(val) //把搜索的值添加到搜索记录
localStorage.saveList = JSON.stringify(this.saveList)
}
},
showSearch(){ //输入框内容发生变化时触发
this.showList = []
this.list.map(item=>{
if(item.dtitle.includes(this.kw)){
this.showList.push(item)
}
})
if(this.kw.trim() == ''){ //判断显示或隐藏搜索提示
this.isShow = true
}else{
this.isShow = false
}
},
onDel(){ //删除
this.$dialog.confirm({
title: '确定要清空搜索记录吗'
})
.then(() => {
this.saveList = []
localStorage.saveList = JSON.stringify(this.saveList)
})
.catch(() => {
// on cancel
});
}
}
}
</script>
<style>
</style>
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
更多推荐
已为社区贡献1条内容
所有评论(0)