準(zhǔn)備mock數(shù)據(jù):
{
"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": "成功"
}
image.png
修改調(diào)整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">時(shí)令蔬菜</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' // 路由跳轉(zhuǎn)方法
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>
效果如下:
image.png
左側(cè)“全部商品”等欄目切換開發(fā)
首先優(yōu)化一下此部分代碼
<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>
效果如下:
image.png
增加點(diǎn)擊事件:
<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' // 路由跳轉(zhuǎn)方法
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)"
點(diǎn)擊標(biāo)簽:
image.png
實(shí)現(xiàn)點(diǎn)擊再次發(fā)起請(qǐng)求很簡(jiǎn)單:
const handleCategoryClick = tab => {
console.log('click:' + tab)
getContentData(tab)
}
將mock數(shù)據(jù)刪掉一條,點(diǎn)擊,發(fā)現(xiàn)效果實(shí)現(xiàn):
image.png
進(jìn)一步優(yōu)化細(xì)節(jié):
<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' // 路由跳轉(zhuǎn)方法
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>
效果如下:
image.png
通過(guò)watchEffect再次優(yōu)化代碼:
<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' // 路由跳轉(zhuǎn)方法
import { get } from '@/utils/request.js'
const categories = [
{
name: '全部商品',
tab: 'all'
},
{
name: '秒殺',
tab: 'seckill'
},
{
name: '新鮮水果',
tab: 'fruit'
},
{
name: '休閑食品',
tab: 'snack'
}
]
// 和tab切換相關(guān)的邏輯
const useTabEffect = () => {
const currentTab = ref(categories[0].tab)
const handleTabClick = tab => {
console.log('click:' + tab)
currentTab.value = tab
}
return { currentTab, handleTabClick }
}
// 當(dāng)前列表內(nèi)容相關(guān)的函數(shù)
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:當(dāng)首次頁(yè)面加載時(shí),或當(dāng)其中監(jiān)聽的數(shù)據(jù)發(fā)生變化時(shí)執(zhí)行
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。