准备mock数据:
{
"code": 200,
"data": [{
_id: '1',
name: '番茄250g/份',
imgUrl: '/i18n/9_16/img/tomato.png',
sales: 10,
price: 33.6,
oldPrice: 39.6
},
{
_id: '2',
name: '草莓250g/份',
imgUrl: '/i18n/9_16/img/tomato.png',
sales: 10,
price: 33.6,
oldPrice: 39.6
},
{
_id: '3',
name: '提子250g/份',
imgUrl: '/i18n/9_16/img/tomato.png',
sales: 10,
price: 33.6,
oldPrice: 39.6
},
{
_id: '4',
name: '提子250g/份',
imgUrl: '/i18n/9_16/img/tomato.png',
sales: 10,
price: 92.6,
oldPrice: 85.6
}
],
"desc": "成功"
}
修改调整src\views\shop\Content.vue:
<template>
<div class="content">
<div class="category">
<div class="category__item category__item--active">全部商品</div>
<div class="category__item">折扣</div>
<div class="category__item">新鲜水果</div>
<div class="category__item">休闲食品</div>
<div class="category__item">时令蔬菜</div>
<div class="category__item">肉蛋家禽</div>
</div>
<div class="product">
<div class="product__item" v-for="item in contentList" :key="item._id">
<img class="product__item__img" :src="item.imgUrl" />
<div class="product__item__detail">
<h4 class="product__item__title">{{ item.name }}</h4>
<p class="product__item__sales">月售{{ item.sales }}件</p>
<p class="product__item__price">
<span class="product__item__yen"> ¥{{ item.price }} </span>
<span class="product__item__origin">
¥{{ item.oldPrice }}
</span>
</p>
</div>
<div class="product__number">
<span class="product__number__minus">-</span>
0
<span class="product__number__plus">+</span>
</div>
</div>
</div>
</div>
</template>
<script>
// eslint-disable-next-line no-unused-vars
import { reactive, refs, toRefs } from 'vue' // 路由跳转方法
import { get } from '@/utils/request.js'
export default {
name: 'Content',
props: {
id: String
},
setup() {
const data = reactive({ contentList: [] })
const getContentData = async () => {
const result = await get('/api/shop/' + '1' + '/products', {
tab: 'all'
})
console.log('result:' + result)
if (result?.code === 200 && result?.data?.length) {
data.contentList = result.data
}
}
getContentData()
const { contentList } = toRefs(data)
return { contentList }
}
}
</script>
<style lang="scss" scoped>
......
</style>
效果如下:
左侧“全部商品”等栏目切换开发
首先优化一下此部分代码
<template>
<div class="content">
<div class="category">
<!-- category__item--active -->
<div class="category__item " v-for="item in categories" :key="item.tab">
{{ item.name }}
</div>
</div>
<div class="product">
......
</div>
</div>
</template>
<script>
......
setup() {
const categories = [
{
name: '全部商品',
tab: 'all'
},
{
name: '秒杀',
tab: 'seckill'
},
{
name: '新鲜水果',
tab: 'fruit'
},
{
name: '休闲食品',
tab: 'snack'
}
]
......
return { contentList, categories }
}
}
</script>
<style lang="scss" scoped>
......
</style>
效果如下:
增加点击事件:
<template>
<div class="content">
<div class="category">
<!-- category__item--active -->
<div
class="category__item "
v-for="item in categories"
:key="item.tab"
@click="handleCategoryClick(item.tab)"
>
{{ item.name }}
</div>
</div>
<div class="product">
......
</div>
</div>
</template>
<script>
// eslint-disable-next-line no-unused-vars
import { reactive, refs, toRefs } from 'vue' // 路由跳转方法
import { get } from '@/utils/request.js'
export default {
name: 'Content',
props: {
id: String
},
setup() {
const categories = [
{
name: '全部商品',
tab: 'all'
},
{
name: '秒杀',
tab: 'seckill'
},
{
name: '新鲜水果',
tab: 'fruit'
},
{
name: '休闲食品',
tab: 'snack'
}
]
......
const handleCategoryClick = tab => {
console.log('click:' + tab)
}
getContentData('all')
const { contentList } = toRefs(data)
return { contentList, categories, handleCategoryClick }
}
}
</script>
<style lang="scss" scoped>
......
</style>
其中@click="handleCategoryClick(item.tab)"
可以写成@click="() => handleCategoryClick(item.tab)"
点击标签:
实现点击再次发起请求很简单:
const handleCategoryClick = tab => {
console.log('click:' + tab)
getContentData(tab)
}
将mock数据删掉一条,点击,发现效果实现:
进一步优化细节:
<template>
<div class="content">
<div class="category">
<div
:class="{
category__item: true,
'category__item--active': currentTab === item.tab
}"
v-for="item in categories"
:key="item.tab"
@click="handleCategoryClick(item.tab)"
>
{{ item.name }}
</div>
</div>
<div class="product">
<div class="product__item" v-for="item in contentList" :key="item._id">
<img class="product__item__img" :src="item.imgUrl" />
<div class="product__item__detail">
<h4 class="product__item__title">{{ item.name }}</h4>
<p class="product__item__sales">月售{{ item.sales }}件</p>
<p class="product__item__price">
<span class="product__item__yen"> ¥{{ item.price }} </span>
<span class="product__item__origin">
¥{{ item.oldPrice }}
</span>
</p>
</div>
<div class="product__number">
<span class="product__number__minus">-</span>
0
<span class="product__number__plus">+</span>
</div>
</div>
</div>
</div>
</template>
<script>
// eslint-disable-next-line no-unused-vars
import { reactive, refs, toRefs } from 'vue' // 路由跳转方法
import { get } from '@/utils/request.js'
export default {
name: 'Content',
props: {
id: String
},
setup() {
const categories = [
{
name: '全部商品',
tab: 'all'
},
{
name: '秒杀',
tab: 'seckill'
},
{
name: '新鲜水果',
tab: 'fruit'
},
{
name: '休闲食品',
tab: 'snack'
}
]
const data = reactive({ contentList: [], currentTab: categories[0].tab })
const getContentData = async tab => {
const result = await get('/api/shop/' + '1' + '/products', {
tab: tab
})
console.log('result:' + result)
if (result?.code === 200 && result?.data?.length) {
data.contentList = result.data
}
}
const handleCategoryClick = tab => {
console.log('click:' + tab)
getContentData(tab)
data.currentTab = tab
}
getContentData('all')
const { contentList, currentTab } = toRefs(data)
return { contentList, categories, handleCategoryClick, currentTab }
}
}
</script>
<style lang="scss" scoped>
......
</style>
效果如下:
通过watchEffect再次优化代码:
<template>
<div class="content">
<div class="category">
<div
:class="{
category__item: true,
'category__item--active': currentTab === item.tab
}"
v-for="item in categories"
:key="item.tab"
@click="handleTabClick(item.tab)"
>
{{ item.name }}
</div>
</div>
<div class="product">
<div class="product__item" v-for="item in list" :key="item._id">
<img class="product__item__img" :src="item.imgUrl" />
<div class="product__item__detail">
<h4 class="product__item__title">{{ item.name }}</h4>
<p class="product__item__sales">月售{{ item.sales }}件</p>
<p class="product__item__price">
<span class="product__item__yen"> ¥{{ item.price }} </span>
<span class="product__item__origin">
¥{{ item.oldPrice }}
</span>
</p>
</div>
<div class="product__number">
<span class="product__number__minus">-</span>
0
<span class="product__number__plus">+</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { reactive, ref, toRefs, watchEffect } from 'vue'
import { useRoute } from 'vue-router' // 路由跳转方法
import { get } from '@/utils/request.js'
const categories = [
{
name: '全部商品',
tab: 'all'
},
{
name: '秒杀',
tab: 'seckill'
},
{
name: '新鲜水果',
tab: 'fruit'
},
{
name: '休闲食品',
tab: 'snack'
}
]
// 和tab切换相关的逻辑
const useTabEffect = () => {
const currentTab = ref(categories[0].tab)
const handleTabClick = tab => {
console.log('click:' + tab)
currentTab.value = tab
}
return { currentTab, handleTabClick }
}
// 当前列表内容相关的函数
const useContentListEffect = currentTab => {
const route = useRoute() // 获取路由
const routeId = route.params.id
const content = reactive({ list: [] })
const getContentData = async tab => {
const result = await get(`/api/shop/${routeId}/products`, {
tab: currentTab.value
})
console.log('result:' + result)
if (result?.code === 200 && result?.data?.length) {
content.list = result.data
}
}
// watchEffect:当首次页面加载时,或当其中监听的数据发生变化时执行
watchEffect(tab => {
getContentData(tab)
})
const { list } = toRefs(content)
return { list }
}
export default {
name: 'Content',
props: {
id: String
},
setup() {
const { currentTab, handleTabClick } = useTabEffect()
const { list } = useContentListEffect(currentTab)
return { list, categories, handleTabClick, currentTab }
}
}
</script>
<style lang="scss" scoped>
......
</style>
代码抽离和封装yyds。