【vue3.0】13.0 某東到家(十三)——商家詳情頁(yè)開發(fā)(三)

準(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"> &yen;{{ item.price }} </span>
            <span class="product__item__origin">
              &yen;{{ 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"> &yen;{{ item.price }} </span>
            <span class="product__item__origin">
              &yen;{{ 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"> &yen;{{ item.price }} </span>
            <span class="product__item__origin">
              &yen;{{ 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。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,714評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,776評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,210評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,654評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容