6步开发
1.使用mock数据构建list基本结构
2.美化样式
3.tab切换,获取真实数据
4.渲染真实数据
5,让list具备左右切换的能力
6完成list与tabs联动的能力

使用mock数据,构建list基本结构

hot-list-item/ hot -ranking
image.png

  1. <template>
  2. <view class="item-container" @click="$emit('click')">
  3. <view class="item-box">
  4. <!-- 左侧 -->
  5. <view class="item-box-left">
  6. <!-- 排名 -->
  7. <hot-ranking :ranking="ranking" />
  8. </view>
  9. <view class="item-box-right">
  10. <!-- 标题 -->
  11. <view class="item-title line-clamp-2">{{ data.title }}</view>
  12. <!-- 简介 -->
  13. <view class="item-desc line-clamp-2">{{ data.desc }}</view>
  14. <view class="item-bottom-box">
  15. <!-- 作者 -->
  16. <text class="item-author">{{ data.nickname }}</text>
  17. <!-- 热度 -->
  18. <view class="hot-box">
  19. <image class="hot-icon" src="@/static/images/hot-icon.png" />
  20. <text class="hot-text">{{ data.views | hotNumber }} 热度</text>
  21. </view>
  22. </view>
  23. </view>
  24. </view>
  25. </view>
  26. </template>
  1. hot-ranking<br />现在用的mock假数据<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2509947/1632797008501-39d36e3d-9f15-42f4-8939-8549da035f75.png#clientId=uc749b313-b8c5-4&from=paste&height=77&id=u8bea11fe&margin=%5Bobject%20Object%5D&name=image.png&originHeight=154&originWidth=785&originalType=binary&ratio=1&size=84880&status=done&style=none&taskId=uaceac4a5-25e7-42a2-b03d-89cef16d844&width=392.5)

渲染items,for循环

image.png

美化样式

  1. .item-container {
  2. padding-bottom: $uni-spacing-col-lg;
  3. .item-box {
  4. display: flex;
  5. margin: 0 $uni-spacing-col-base;
  6. padding: $uni-spacing-row-lg $uni-spacing-col-base;
  7. background-color: $uni-bg-color;
  8. border-radius: $uni-border-radius-lg;
  9. box-shadow: 2px 2px 5px 1px rgba(143, 143, 143, 0.1);
  10. .item-box-left {
  11. margin-right: $uni-spacing-row-sm;
  12. }
  13. .item-box-right {
  14. width: 100%;
  15. .item-title {
  16. font-size: $uni-font-size-lg;
  17. font-weight: bold;
  18. color: $uni-text-color-title;
  19. }
  20. .item-desc {
  21. padding-top: $uni-spacing-row-sm;
  22. font-size: $uni-font-size-base;
  23. color: $uni-text-color;
  24. }
  25. .item-bottom-box {
  26. margin-top: $uni-spacing-col-sm;
  27. display: flex;
  28. justify-content: space-between;
  29. align-items: center;
  30. .item-author {
  31. font-size: $uni-font-size-sm;
  32. color: $uni-text-color-grey;
  33. }
  34. .hot-box {
  35. .hot-icon {
  36. width: $uni-img-size-sm;
  37. height: $uni-img-size-sm;
  38. vertical-align: top;
  39. }
  40. .hot-text {
  41. margin-left: $uni-spacing-row-sm;
  42. font-size: $uni-font-size-sm;
  43. color: $uni-text-color-hot;
  44. }
  45. }
  46. }
  47. }
  48. }
  49. }

根据tab切换,获取真实数据

tabClick监听,完成list与tab联动的能力
对于点击事件,可以接受当前的激活项·
image.png
hot-vue
有了激活项后,可以修改
image.png
在data添加激活项
image.png
在template里。currentIndex绑定上defaultIndex
image.png
当用户点击的时候,让currentIndex = 传递过来的index
image.png
这样完成了绑定

数据请求

hot。js
获取tab下面对应的列表,请求文档中的热搜文章列表
image.png
接受一个type参数,就是tab的id

  1. export function getHotListFromTabType (type) {
  2. return request({
  3. url:'/hot/list',
  4. data: {
  5. type
  6. }
  7. })
  8. }

在hot.vue调用接口

  1. import { getHotTabs,getHotListFromTabType } from 'api/hot'

创建对应方法methods ,获取list列表数据

先写上临时id,后来完成调用方法TODO

  1. async loadHotListFromTab(){
  2. await getHotListFromTabType(0)
  3. }

调用时机是在获取热搜文章类型后 调用list 列表数据
因为,获取list数据时候,需要tab中对应的id

  1. async loadtHotTabs() {
  2. // uniapp 支持 async await
  3. const { data: res } = await getHotTabs();
  4. this.tabData = res.list;
  5. // 获取列表数据
  6. this.loadHotListFromTab();
  7. },

现在问题是数据怎么获取?
2个情况

  1. 如果没有获取到数据

1.1 展示对应loading
1.2 调用接口获取数据
1.3 把数据保存到本地
1.4 隐藏loading

  1. 已经获取到数据

2.1 直接渲染数据有了缓存之后

需要有一个对应数据源,把数据保存到位置
listData
还需要loading展示内容

  1. data() {
  2. return {
  3. // tabs 数据源
  4. tabData: [],
  5. // list 列表数据加载过程
  6. isLoading: true,
  7. // 以 index 为 key,对应的 list 为 val
  8. listData: {},

去完成1-2步骤

  1. async getHotListFromTab() {
  2. if (!this.listData[this.currentIndex]) {
  3. //1.没有获取到数据
  4. //1.1 展示 loading
  5. this.isLoading = true;
  6. //1.2 调用接口获取数据
  7. // 获取列表数据
  8. const id = this.tabDate[this.currentIndex].id
  9. const { data: res } = await getHotListFromTabType(id);
  10. // 1.3 把数据保存到本地
  11. this.listData[this.currentIndex] = res.list;
  12. // 1.4隐藏 loading
  13. this.isLoading = false;
  14. }
  15. // 因为 this.$nextTick 存在一定的兼容性问题,所以更加推荐使用 setTimeout
  16. setTimeout(async () => {
  17. // 获取当前 swiper 的高度
  18. this.currentSwiperHeight = await this.getCurrentSwiperHeight();
  19. // 放入缓存
  20. this.swiperHeightData[this.currentIndex] = this.currentSwiperHeight;
  21. }, 0);
  22. },

创建loading
uni展示加载动画的组件 state表示当前动画的类型

  1. <uni-load-more status="loading" v-if="isLoading"></uni-load-more>

hot-list-item希望在loading False时候展示
用block包裹

  1. //加载动画
  2. <uni-load-more status="loading" v-if="isLoading" />
  3. //列表
  4. <block v-else>
  5. <!-- 列表循环数据更改为 listData[tabIndex] -->
  6. <hot-list-item
  7. :class="'hot-list-item-' + tabIndex"
  8. v-for="(item, index) in listData[tabIndex]"
  9. :key="index"
  10. :data="item"
  11. :ranking="index + 1"
  12. @click="onItemClick(item)"
  13. ></hot-list-item>
  14. </block>

目前数据没有获取,是因为没有调用方法
方法需要在两个地方调用
1,刚获取到文章类型后,调用一次
image.png
2.用户点击tab时候再调用一次·1
image.png

渲染真实数据

image.png

//hot.vue
循环编理item换成真实数据源,里面是key value

  1. <hot-list-item
  2. v-for="(item, index) in listData[currentIndex]" :key="index"

在//hot-list-item里面接受2个参数
data和ranking

  1. props: {
  2. //item的数据
  3. data: {
  4. type: Object,
  5. required: true
  6. },
  7. //排名
  8. ranking: {
  9. type: Number,
  10. required: true
  11. }

把data和item传递给hot.vue 模板里的循环

  1. <hot-list-item
  2. v-for="(item, index) in listData[tabIndex]"
  3. :key="index"
  4. :data="item"
  5. :ranking="index + 1"
  6. ></hot-list-item>

数据传递过来后,去显示对应的数据
//hot-list-item
结合文档去写
image.png

  1. <view class="item-box-right">
  2. <!-- 标题 -->
  3. <view class="item-title line-clamp-2">{{ data.title }}</view>
  4. <!-- 简介 -->
  5. <view class="item-desc line-clamp-2">{{ data.desc }}</view>
  6. <view class="item-bottom-box">
  7. <!-- 作者 -->
  8. <text class="item-author">{{ data.nickname }}</text>
  9. <!-- 热度 -->
  10. <view class="hot-box">
  11. <image class="hot-icon" src="@/static/images/hot-icon.png" />
  12. <text class="hot-text">{{ data.views | hotNumber }} 热度</text>
  13. </view>
  14. </view>
  15. </view>

功能:简介最多展示2行
样式抽离到styles/global.scss
定义公共样式
固定的zhan’shi

  1. .line-clamp-2 {
  2. overflow: hidden;
  3. text-overflow: ellipsis;
  4. display: -webkit-box;
  5. -webkit-box-orient: vertical;
  6. -webkit-line-clamp: 2;
  7. }

在mai’n.js里引入
import ‘./styles/global.scss’
处理前面排名,把排名传递给hot-ranking里面去
props:{}