我们是一个整体
image.png

  1. <template>
  2. <div class="list-container">
  3. <!-- 排序区域 -->
  4. <div class='sub-sort'>
  5. <div class="sort">
  6. <a
  7. :class="{ active: sortField === null }"
  8. @click="changeSort(null)"
  9. href="javascript:;">默认排序</a>
  10. <a
  11. :class="{ active: sortField === 'publishTime' }"
  12. @click="changeSort('publishTime')"
  13. href="javascript:;">最新商品</a>
  14. <a
  15. :class="{ active: sortField === 'orderNum' }"
  16. @click="changeSort('orderNum')"
  17. href="javascript:;">最高人气</a>
  18. <a
  19. :class="{ active: sortField === 'evaluateNum' }"
  20. @click="changeSort('evaluateNum')"
  21. href="javascript:;">评论最多</a>
  22. <a
  23. :class="{ active: sortField === 'price' }"
  24. @click="changeSort('price')"
  25. href="javascript:;">价格
  26. <i class="arrow up" :class="{active:sortParams.sortField==='price'&&sortParams.sortMethod=='asc'}" />
  27. <i class="arrow down" :class="{active:sortParams.sortField==='price'&&sortParams.sortMethod=='desc'}" />
  28. </a>
  29. </div>
  30. </div>
  31. </div>
  32. </template>
  33. <script>
  34. export default {
  35. setup () {
  36. const sortParams = reactive({
  37. inventory: false,
  38. onlyDiscount: false,
  39. sortField: null,
  40. sortMethod: 'desc'
  41. })
  42. // publishTime(最新), orderNum(人气), price(价格), evaluateNum(评论)
  43. function changeSort (sortField) {
  44. sortParams.sortField = sortField
  45. // 对价格特殊处理
  46. if (sortField === 'price') {
  47. // 不是第一次点击:当前排序取反
  48. sortParams.sortMethod = sortParams.sortMethod === 'desc' ? 'asc' : 'desc'
  49. } else {
  50. // 如果排序未改变停止逻辑
  51. sortParams.sortMethod = 'desc'
  52. }
  53. console.log(sortParams.sortField, sortParams.sortMethod)
  54. }
  55. watch(sortParams, () => {
  56. // 通知父组件重发请求
  57. emit('sort-change', sortParams)
  58. })
  59. return { changeSort, sortParams }
  60. }
  61. }
  62. </script>

1.定义获取数据的API

src/api/category.js

  1. /**
  2. * @description: 获取筛选商品
  3. * @param {*} params
  4. * @return {*}
  5. */
  6. export const findSubCategoryGoods = (params) => {
  7. return request('/category/goods', 'post', params)
  8. }

2.编写获取数据逻辑

sub.vue

  1. <script>
  2. import { findSubCategoryGoods } from '@/api/category'
  3. import { useRoute } from 'vue-router'
  4. import { onMounted, ref} from 'vue'
  5. export default {
  6. setup () {
  7. // 省略其他...
  8. // 获取list
  9. const goodList = ref([])
  10. // 请求参数
  11. const reqParams = {
  12. page: 1,
  13. pageSize: 20,
  14. categoryId: route.params.id,
  15. sortField: null, // 排序类别
  16. attrs: [], // 商品属性
  17. brandId: null // 品牌名称
  18. }
  19. const loadData = () => {
  20. findSubCategoryGoods(reqParams).then(res => {
  21. goodList.value = res.result.items
  22. })
  23. }
  24. loadData()
  25. return { subCategoryData, goodList }
  26. }
  27. }
  28. </script>

3.渲染模板

引入goods-item组件

  1. <script>
  2. import GoodsItem from '@/views/Category/components/goods-item'
  3. </script>

使用

  1. <!-- 商品列表 -->
  2. <div class="sort-list-container">
  3. <GoodsItem v-for="good in goodList" :key="good.id" :goods="good"/>
  4. </div>

样式

  1. <style>
  2. .sort-list-container {
  3. display: flex;
  4. flex-wrap: wrap;
  5. }
  6. </style>

4.从组件sub-filter抛出事件

  1. const getFilter = () => {
  2. // 收集目前的参数
  3. const params = {
  4. brandId: null,
  5. // attrs: [
  6. // {groupName: '款式', propertyName: '富士山款'},
  7. // {groupName: '颜色', propertyName: '经典夜空黑'},
  8. // ......
  9. // ]
  10. attrs: []
  11. }
  12. // 更新brandId
  13. // 1.找出selected为true的那一项
  14. const brand = props.subCate.brands.find(it => it.selected)
  15. // 2.找到就用它的id,否则就是null
  16. params.brandId = brand ? brand.id : null
  17. // 更新attrs
  18. params.attrs = props.subCate.saleProperties.forEach(item => {
  19. const groupName = item.name
  20. const propertyName = item.properties.find(it => it.selected).name
  21. if (propertyName !== '全部') {
  22. params.attrs.push({ groupName, propertyName })
  23. }
  24. })
  25. return params
  26. }
  27. // 1.更新品牌数据
  28. const selectBrand = (brand) => {
  29. console.log(brand)
  30. props.subCate.brands.forEach(it => {
  31. it.selected = false
  32. })
  33. brand.selected = true
  34. // 2.收集目前的参数,通知父组件重做查询
  35. // 字传父:emit
  36. emit('filter-change', getFilter())
  37. }
  38. const selectAttr = (prop, sale) => {
  39. // 1.更新属性数据
  40. console.log(prop, sale)
  41. sale.properties.forEach(it => {
  42. it.selected = false
  43. })
  44. prop.selected = true
  45. // 2.收集目前的参数,通知父组件重做查询
  46. emit('filter-change', getFilter())
  47. }

5.监听事件

sub.vue

  1. <SubFilter :cate="subCategoryData" @filter-change="filterChange" />
  1. const loadData = () => {
  2. findSubCategoryGoods(reqParams).then(res => {
  3. goodList.value = res.result.items
  4. })
  5. }
  6. loadData()
  7. const filterChange = (sortParams) => {
  8. console.log('查询条件', sortParams)
  9. reqParams = { ...reqParams, ...sortParams }
  10. reqParams.page = 1
  11. goodList.value = []
  12. isFinished.value = false
  13. loadData()
  14. }

6.从组件sub-sort抛出事件

  1. setup (props, { emit }) {
  2. const sortParams = reactive({
  3. inventory: false, // 仅显示有货商品
  4. onlyDiscount: false, // 仅显示特惠商品
  5. sortField: null, // 排序字段 publishTime(最新), orderNum(人气), price(价格), evaluateNum(评论)
  6. sortMethod: 'desc'// 顺序:asc升序 desc降序
  7. })
  8. const shangeSort = type => {
  9. sortParams.sortField = type
  10. if (type === 'price') {
  11. sortParams.sortMethod = (sortParams.sortMethod === 'asc') ? 'desc' : 'asc'
  12. } else { // 不是价格
  13. sortParams.sortMethod = 'desc'
  14. }
  15. }
  16. watch(sortParams, () => {
  17. // 通知父组件重发请求
  18. emit('sort-change', sortParams)
  19. })
  20. return { sortParams, shangeSort }
  21. }

7.监听事件

  1. <SubSort :cate="subCategoryData" @sort-change="sortChange"/>
  1. const hSortChange = (sortParam) => {
  2. console.log('父组件收到了排序条件', sortParam)
  3. // 更新条件
  4. // reqParams.inventory = sortParam.params.inventory
  5. // reqParams.onlyDiscount = sortParam.params.onlyDiscount
  6. reqParams = { ...reqParams, ...sortParam }
  7. // 重置页码,清空数据
  8. reqParams.page = 1
  9. goodList.value = []
  10. isFinished.value = false
  11. // 重发请求
  12. loadData()
  13. }