文章列表

467 阅读2分钟

一. 分析

image-20200410165825017.png

  • 数据显示
  • 实现文章列表的上拉加载
  • 下拉刷新功能
  • 使用过滤器来处理日期时间

涉及vant组件如下:

image-20200804140709397.png

单独抽出来成一个组件(articleList.vue)来处理, 目录结构如下:

|-views
|--home/articleList.vue
|--home/home.vue

二. 创建组件并导入使用

创建articleList组件并在home.vue中导入使用

1. articleList.vue的基本结构

创建文件home/articleList.vue

<template>
  <div class="scroll-wrapper">
    文章列表组件 {{Math.random()}}
    <p v-for="i in 50" :key="i">{{i}}</p>
  </div>
</template>

<script>
export default {
  name: 'ArticleList'
}
</script>

<style scoped lang='less'></style>

2. 在home.vue中使用

在src/views/home/home.vue中

2.1 引入组件

import ArticleList from './articleList'

2.2 注册组件

components: {
    ArticleList
}

2.3 使用组件

<template>
  <div class="index">
    <!-- 频道列表
    https://vant-contrib.gitee.io/vant/#/zh-CN/tab#biao-qian-lan-gun-dong
    -->
    <van-tabs>
      <van-tab
        v-for="channel in channels"
        :title="channel.name"
        :key="channel.id">
<!-- 频道与文章列表是一一对应的。每个频道都需要有一个文章列表组件。
article-list写在了v-for中,则每次循环都会生成一个文章列表组件。
van-tab具有类似于 懒加载的效果: 只有激活了当前的tab,才会去创建文章列表组件 -->
+       <article-list></article-list>

      </van-tab>
    </van-tabs>

    <!-- 文章列表 -->
  </div>
</template>
  • 每一个频道下,就会有一个articleList组件。如果有10个频道,就会创建10个aritcleList组件。

  • van-tabs有类似于懒加载的效果

image-20210607094750115.png

三. 频道信息传递(父传子)

从home.vue组件中把当前频道信息传给articleList.vue,以供在articleList.vue中根据频道信息来获取具体的文章列表内容

父传子有两步

  1. 父组件中使用子组件值传入自定义属性;

  2. 在子组件中定义props来接收;

1. 在父组件中传名为channel的属性给子组件

<template>
  <div class="index">
    <!-- 频道列表
    https://vant-contrib.gitee.io/vant/#/zh-CN/tab#biao-qian-lan-gun-dong
    -->
    <van-tabs>
      <van-tab
        v-for="channel in channels"
        :title="channel.name"
        :key="channel.id">
<!-- 频道与文章列表是一一对应的。每个频道都需要有一个文章列表组件。
article-list写在了v-for中,则每次循环都会生成一个文章列表组件。
van-tab具有类似于 懒加载的效果: 只有激活了当前的tab,才会去创建文章列表组件 -->

        <!-- 把当前的频道信息传给子组件 -->
+       <article-list :channel="channel"></article-list>
      </van-tab>
    </van-tabs>

    <!-- 文章列表 -->
  </div>
</template>

2. 在子组件articleList中接收prop

定义props

props: ['channel']

使用props

<div class="scroll-wrapper">
  {{channel}}频道的文章信息列表组件
  <p v-for="i in 50" :key="i">{{i}}</p>
</div>

四. 实现列表功能

在articleList.vue中,我们需要做两个交互:

  1. 上拉加载更多。手指向上滑动, 加载更多的内容,放在底部,类似于pc上的分页效果
  2. 下拉刷新加载最新内容。按下手指向下拉动,获取最新内容,放在头部

使用van-list组件来实现列表功能

<div class="scroll-wrapper">
    {{channel}}频道的文章信息列表组件
   /**
      van-list自带上拉加载更多 的效果
      原理:
        1)数据项在list中
        2)在显示数据时,如果当前的数据不足一屏,它会 自动触发load事件,并执行对应的回调onLoad去加载数据
           在onload中,通过ajax取回新数据
           - 把数据追加到list中(list的内容会越来越多)
           - 把loading手动设置为false
           - 判断是否所有的数据已经加载完成,如果是,则把finished设为true
        3) 如果手动向上拉,且finished不为true, 也会去调用onLoad
    **/
    <van-list
      v-model="loading"
      :finished="finished"
      finished-text="没有更多了"
      @load="onLoad"
    >
      <van-cell v-for="item in list" :key="item" :title="item" />
    </van-list>
  </div>
<script>
 data () {
    return {
      list: [], // 数据项
      loading: false, // 是否正在加载...
      finished: false // 是否所有的数据全部加载完成
    }
  },
  methods: {
    onLoad () {
      // 异步更新数据
      // setTimeout 仅做示例,真实场景中一般为 ajax 请求
      setTimeout(() => {
        for (let i = 0; i < 10; i++) {
          this.list.push(this.list.length + 1)
        }

        // 加载状态结束
        this.loading = false

        // 数据全部加载完成
        if (this.list.length >= 40) {
          this.finished = true
        }
      }, 1000)
    }
  }
</script>