记一次elementui时间线的实现

实现效果

点击展开,每次累加五条数据进行展示

实现思路

  1. 起始本质上就是一个分页查询,只不过按新的形式展示,然后也不统计总数,每次只展示固定的5条数据
  2. 点击加载更多,就展示下一页,页的页数进行+1,请求后端接口获取下一页数据
  3. 获取到的新数据,通过与原数据集合找一个唯一维度比如ID,进行对比,不存在于原数据集中的,进行添加
  4. 还有一些小优化,比如数据为0时,以及最后一页时就不展示显示更多

具体代码

时间线自定义组件

vue 复制代码
<template>
  <div style="display: flex; justify-content: center;">
    <el-timeline style="max-width: 600px">
      <el-timeline-item v-for="item in eventLogTableData" :timestamp="item.occurredAt" placement="top">
        <el-card>
          <h4>{{ item.channelName }}</h4>
          <p>{{ item.actionDesc }}</p>
        </el-card>
      </el-timeline-item>
    </el-timeline>
  </div>
  <div style="display: flex; justify-content: center;" v-if="eventLogTableData.length >0">
    <el-button link type="primary" :icon="ArrowDownBold" @click="loadMore">加载更多</el-button>
  </div>
  <el-empty description="暂无数据" v-else/>

</template>

<script>
import {
  h,
  onUnmounted,
  computed,
  watch,
  onMounted,
  toRefs,
  reactive,
  ref,
} from "vue";
import {ArrowDownBold} from "@element-plus/icons-vue";
import {useStore} from "vuex";

export default {
  components: {},
  props: {
    getDataSource: Function,
  },
  setup: function (props, context) {
    const store = useStore();
    const eventLogTableData = computed(() => store.state.member.eventLogTableData);
    const eventLogPageSize = computed(() => store.state.member.eventLogPageSize);
    const eventLogCurPage = computed(() => store.state.member.eventLogCurPage);

    onUnmounted(() => {
      store.commit("member/SET_EVENT_LOG_TABLE_PAGE_SIZE", 5, {root: true});
      store.commit("member/SET_EVENT_LOG_TABLE_CUR_PAGE", 1, {root: true});
      store.commit("member/SET_EVENT_LOG_TABLE_LIST", []);
    });

    const loadMore = () => {
      store.commit("member/SET_EVENT_LOG_TABLE_CUR_PAGE", (eventLogCurPage.value + 1), {root: true});
      // 调用父组件传来的加载数据函数
      props.getDataSource();
    };
    return {
      loadMore,
      ArrowDownBold,
      eventLogTableData,
      eventLogPageSize,
      eventLogCurPage
    };
  }
}

</script>

<style scoped lang="scss">

</style>

全局状态管理

jsx 复制代码
import requestHttp from "@/server/request";
import {ElMessage} from "element-plus";
import util from "@/utils/utils";
import apiConstants from "@/api/apiConstants";

const state = {
  eventLogTableData: [],
  // 当前页
  eventLogCurPage: 1,
  // 页数量
  eventLogPageSize: 5,
};

const mutations = {
  SET_EVENT_LOG_TABLE_LIST: (state, payload) => {
    state.eventLogTableData = payload || [];
  },
  SET_EVENT_LOG_TABLE_CUR_PAGE: (state, payload) => {
    state.eventLogCurPage = payload;
  },
  SET_EVENT_LOG_TABLE_PAGE_SIZE: (state, payload) => {
    state.eventLogPageSize = payload;
  },
};


const actions = {
  async pageQueryMemberEventLog({commit}, params) {
    try {
      const result = await requestHttp({
        // 这里按情况写自己的
        url: apiConstants.HOST_HOME_GET_MEMBER_EVENT_LOG_INFO,
        method: "POST",
        data: params,
      });
      if (result.data && result.data.code == 200) {
        let data = result.data?.data.list;
        let copiedArray = state.eventLogTableData.slice();
        let ids = copiedArray.map(item => item.id);
        // 这里将不存在于原数据的返回结果写入
        let canUseData = data.filter(item => !ids.includes(item.id));
        copiedArray.push(...canUseData);
        commit("SET_EVENT_LOG_TABLE_LIST", copiedArray);
      } else {
        ElMessage.warning(result.data.message);
      }
    } catch (e) {
      console.log(e);
    }
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
};

父组件

jsx 复制代码
<template>
<MemberEventLogTimeLine :getDataSource="getMemberEventLogDataSource"></MemberEventLogTimeLine>
</template>

<script>
import MemberEventLogTimeLine from "views/member/MemberEventLogTimeLine.vue";
import {useStore} from "vuex";
// 分页查询事件
export default {
  components: {MemberEventLogTimeLine},
  props: {},
  setup: function (props, context) {
    const store = useStore();
    const memberId = computed(() => store.state.member.currentMemberId);
    const eventLogCurPage = computed(() => store.state.member.eventLogCurPage);
    const eventLogPageSize = computed(() => store.state.member.eventLogPageSize);
    const getMemberEventLogDataSource = () => {
      const params = {
        pageNum: eventLogCurPage?.value,
        pageSize: eventLogPageSize?.value,
        param: {memberId: memberId?.value}
      };
      store.dispatch("member/pageQueryMemberEventLog", params);
    }
  }
}
</script>
相关推荐
小二·8 分钟前
前端监控体系完全指南:从错误捕获到用户行为分析(Vue 3 + Sentry + Web Vitals)
前端·vue.js·sentry
阿珊和她的猫1 小时前
`require` 与 `import` 的区别剖析
前端·webpack
+VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
谎言西西里2 小时前
零基础 Coze + 前端 Vue3 边玩边开发:宠物冰球运动员生成器
前端·coze
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
努力的小郑2 小时前
2025年度总结:当我在 Cursor 里敲下 Tab 的那一刻,我知道时代变了
前端·后端·ai编程
GIS之路2 小时前
GDAL 实现数据空间查询
前端
OEC小胖胖2 小时前
01|从 Monorepo 到发布产物:React 仓库全景与构建链路
前端·react.js·前端框架
2501_944711433 小时前
构建 React Todo 应用:组件通信与状态管理的最佳实践
前端·javascript·react.js
困惑阿三3 小时前
2025 前端技术全景图:从“夯”到“拉”排行榜
前端·javascript·程序人生·react.js·vue·学习方法