vue3解决切换tab页每次切换加载数据导致数据缓慢问题

发布时间:2024年01月04日
const tabchange=e=>{
data.activity = e
vedioLoad(data.activity)//加载数据 加载的时候传值过去
}

解决方法:
使用标识符来进行辨认 有两个tab页 搞个动态加载 在开头的vedioload还没开始加载的时候判断是否加载过 入股已经加载过 则返回 不要重新加载

loadvideos会根据loadedTabs的状态决定是否需要加载数据

改动

videos.value = filterSelectData 改为
 videos.value[videoTypeFilter] = filterSelectData;

由标签页的离线和在线数据 都分开管理 使用两个列表:即一个数组两个对象进行存储 数组的下标有tab0 tab1 动态决定 代替原来的直接覆盖数据
在这里插入图片描述

const loadVideos = (videoTypeFilter) => {
  if (loadedTabs.value[videoTypeFilter]) {
    // 如果数据已经加载过了,直接返回
    data.loading = false;
    return;
  }
  // 数据尚未加载,执行加载逻辑
  // ...加载数据的代码...
  loadedTabs.value[videoTypeFilter] = true; // 数据加载完成后,设置为true
}

const tabsChange = e => {
  data.activeKey = e;
  loadVideos(data.activeKey); // 调用loadVideos来加载数据
};

单页全部代码

<!-- 宣传教育 -->


<template>
  <div class="video-section">

    <div class="box-header block-interval">


      <div class="title">
        <a-tabs v-model:activeKey="activeKey" @change="tabsChange">
          <a-tab-pane key=1 tab="在线" />
          <a-tab-pane key=0 tab="离线" />
        </a-tabs>
      </div>

      
    </div>



    <div class="backcolor">
      <div class="search-bar">
        <!-- 搜索 -->
        <a-form-item label="视频课程:">
          <a-input v-model:value="where.videoTitle" placeholder="请搜索视频课程" allow-clear />
        </a-form-item>
        <a-button type="primary" @click="reload" class="searchBtn">
          <img src="@/assets/icon/archives/select.png" alt="" class="searchIcon" />
          查询
        </a-button>
      </div>
      <a-spin :spinning="loading">
        <div class="video-gallery">
          <div v-for="video in videosForCurrentTab" :key="video.id">
            
            <div class="video-container">
              <video :id="`video-${video.id}`" controls muted class="video-player">
                <source :src="video.fileUrl" type="video/mp4" />
              </video>
            </div>

            <div class="video-item-wrapper">
              <div class="video-title">{{ video.videoTitle }}</div>
            </div>
          </div>
        </div>
      </a-spin>


      <div class="pagination-style">
        <a-pagination :current="currentPage" :pageSize="pageSize" :total="total" @change="handlePageChange"
          @showSizeChange="handlePageSizeChange" />
      </div>

    </div>

  </div>
</template>

<script >
import { sysFileUploadUrl, previewFile } from '@/api/file/FileApi';
import { defineComponent, reactive, toRefs, onMounted, h, getCurrentInstance } from 'vue';
import { ref, computed } from 'vue';
import router from '@/router';
import { Modal, message } from 'ant-design-vue';
import { EducationApi } from '@/api/education/educationApi';



export default defineComponent({
  setup() {

    const videos = ref([]);
    const loadedTabs = ref({});
    //加载
    const loadVideos = (videoTypeFilter) => {
      data.loading =true;
      // 检查是否已加载该标签页的数据
      if (loadedTabs.value[videoTypeFilter]) {
        data.loading =false;
        return; // 如果已加载,直接返回
      }


      let result = EducationApi.getEducationListPage({
        videoType: videoTypeFilter,
        pageNo: data.currentPage,
        pageSize: data.pageSize,
      });

      result.then(result => {
        data.total = result.data.totalRows
        let filterSelectData = result.data.rows.map(video => ({ ...video, selected: false }));

        if (videoTypeFilter == 0) {
          //调用处理路径的方法
          filterSelectData = filterSelectData.map(video => {
            if (video.fileId && video.fileId.trim() !== '') {
              video.fileUrl = `http://172.24.8.11:9062/upms/sysFileInfo/publicDownload?fileId=${video.fileId}`;
            }
            return video
          })
        }
        
        // videos.value = filterSelectData;
        videos.value[videoTypeFilter] = filterSelectData;
        loadedTabs.value[videoTypeFilter] = true;


        debugger
        data.loading =false;

      })

    }

    const data = reactive({
      where: {},
      selection: [],
      activeKey: "1",
      id: 0,
      currentPage: 1,
      pageSize: 8, // 每页显示的条数
      total: 20, // 总数据量,需要从后端获取
      loading:false,
    })

    const tabsChange = e => {
      data.activeKey = e;
      loadVideos(data.activeKey)
    };

    onMounted(() => {
      //在线视频
      loadVideos(1)
    });

    const reload = () => {
    
      let result = EducationApi.getEducationList({ videoTitle: data.where.videoTitle, videoType: data.activeKey });
      result.then(res => {
        videos.value = res.data;
    
      })
    }

    //分页加载数据
    const handlePageChange = newPage => {
      data.currentPage = newPage;
      loadVideos(data.activeKey); // 重新加载数据
    };

    //更改每页显示的数据量

    const handlePageSizeChange = (current, size) => {
      data.pageSize = size;
      loadVideos(data.activeKey); // 重新加载数据
    };
    // 添加
    const add = () => {
      router.push('/edu/eduAdd');
    };

    const gotoDetail = (id) => {
      router.push(`/edu/eduAdd?id=${id}`);
    };

    //删除id
    const getSelectedVideoIds = () => {
      console.log("getSelectedVideoIds" + JSON.stringify(videos.value));
      return videos.value.filter(video => video.selected).map(video => video.id);
    };

    //删除
    const del = item => {
      let messages = null;
      let params = { ids: [] };
      const selectedVideoIds = getSelectedVideoIds();
      if (selectedVideoIds.length === 0) {
        return message.warning('请选择删除项');
      }

      messages = `是否要删除选中的【${selectedVideoIds.length}条】的视频?`

      Modal.confirm({
        title: h('div', {}, messages),
        okText: '确定',
        cancelText: '取消',
        closable: true,
        onOk: () => {
          data.loading =true;
          EducationApi.delEducation(selectedVideoIds).then(res => {
            message.success('删除成功');
            loadVideos(data.activeKey)
          });

        }
      });

    };




    return {
      ...toRefs(data),
      videos,
      add,
      del,
      gotoDetail,
      reload,
      tabsChange,
      previewFile,
      handlePageChange,
      handlePageSizeChange,
      videosForCurrentTab: computed(() => videos.value[data.activeKey] || []),
      // ...其他返回的属性或方法
    };
  }
})


</script>

<style lang="scss" scoped>
/* 样式保持不变 */
.ant-tabs {
  width: 100%;
  margin-top: -20px;
}


.backcolor {
  background: #fff;
  height: 100%;
}

.video-section {
  background-color: #e7f1fb !important;

}

.box-header {
  background: #fff;
  height: 60px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;

  .title {
    color: #333333;
    padding: 20px 20px;
    border-left: 4px solid #007cf0;
    height: 5px;
  }

  .title-right {
    display: flex;
    width: 200px;
    justify-content: space-between;
  }
}

.search-bar {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding: 20px 20px;
}

.video-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
  /* 使每个视频元素至少300px宽,同时填满可用空间 */
  gap: 1rem;
  padding: 1rem;
  flex-grow: 1;
}

.video-container {
  background-color: black;
  position: relative;
  padding-top: 56.25%;
  /* 16:9宽高比 */
}

.video-player {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.video-item-wrapper {

  display: flex;
  align-items: center;
  justify-content: center;

  .video-checkbox {
    margin-right: 10px;
  }

  .video-title {
    text-align: center;
    margin-top: 0.5rem;
    cursor: pointer;
  }

}

.pagination-style {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}


/* 媒体查询,针对较小屏幕调整布局 */
@media (max-width: 800px) {
  .video-gallery {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    /* 在较小屏幕上,减小视频元素的最小宽度 */
  }
}
</style>

文章来源:https://blog.csdn.net/weixin_41621686/article/details/135377311
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。