获取数据:
const rawData = ref([]) onMounted(async () => { const response = await axios.get('/api/data') // 假设返回的数据结构类似:[ [item1], [item2], ... ] rawData.value = response.data })或者:// 创建响应式数据 fetchList const newList = ref([]); const getList = async() => { // console.log(777721) // loading.value = true; await getnewsList() .then(data => { // console.log(777722,data.data.titlelist) // 更新newList的值 newList.value = data.data.titlelist }) .catch((e) => { // console.log(777727,e) // loading.value = false; }); // console.log(777728) }其中 getnewsList() 方法为:import { getnewsList } from "@/api/api";其中 /api/api 为:import axios from "@/utils/axios";/** * news */export function getnewsList(params) { return axios({ url: "/websiteapi/api/base/lists", method: "get", data: params });}其中 /utils/axios 为:import axios from "axios";// import store from "@/store";// import { ElMessage } from "element-plus";// import {// VERSION,// MODEL_TEST_VERSION,// SERVER_TYPE,// AXIOS_TIMEOUT// } from "@/constant";// import { switchServerUrl } from "@/utils/index";/** * axios请求拦截器 * @param {object} config axios请求配置对象 * @return {object} 请求成功或失败时返回的配置对象或者promise error对象 **/axios.interceptors.request.use(config => { return config;}, error => { return Promise.reject(error);});/** * axios 响应拦截器 * @param {object} response 从服务端响应的数据对象或者error对象 * @return {object} 响应成功或失败时返回的响应对象或者promise error对象 **/axios.interceptors.response.use(response => { return response;}, error => { return Promise.reject(error);});export default function http(options) { // 获取不同环境的请求域名 const server_url = 'http://192.168.8.15:222'; let opt = {}; const method = options.method || "post"; const url = options.url; const data = options.data || {}; if (!options.url) { console.error("url参数缺失"); return; } // if (store.getters.token) { // data.sys_token = store.getters.token; // } if (method == "get") { opt = { method, baseURL: "", url: url.indexOf("//") > -1 ? url : (server_url + url), params: data, timeout: 50000 }; } else if (method == "post") { opt = { method, baseURL: "", url: url.indexOf("//") > -1 ? url : (server_url + url), data, // qs.stringify(data) timeout: 50000 }; } return new Promise((resolve, reject) => { axios(opt).then(res => { // console.log(77770,res); if (res && (res.status === 200 || res.status === 304 || res.status === 400)) { const data = res.data; if (data.code && data.code == 200) { resolve(data); } else if (data.code && (data.code == 101 || data.code == 102 || data.code.error == "您还没有登录")) { // 101请获取权限 102登录失效 // ElMessage.error(data.status.error); // 提示错误信息 // 登出操作 // store.dispatch("user/logout"); console.log(data.error); } else { // ElMessage.error(data.status.error || "网络异常,请稍后重试!"); // 提示错误信息 reject(data); } } else { // ElMessage.error(res || "网络异常,请稍后重试!"); // 提示错误信息 reject("[lison]网络异常,请稍后重试"); } }, err => { // ElMessage.error(err); // 提示错误信息 reject(err); }); });}
接口返回的数据分类:
const categorizedData = computed(() => { const result = {} for (const group of newList.value) { // console.log(777731,group.list) // group 本身也是一个数组 [obj1, obj2, ...] for (const item of group.list[0]) { // console.log(777732,item) const category = item.type if (!result[category]) { result[category] = [] } result[category].push(item) } } // console.log(777735,result) return result })
动态生成 tab(切换标签项)
const categories = computed(() => Object.keys(categorizedData.value))
当组件挂载、生命周期钩子
const currentCategory = ref('') // 当组件挂载时,调用 getList 函数 // 生命周期钩子 // 当一个时:onMounted(getList); // 当多个时: onMounted(async () => { // await tabTitle(); // 在获取数据后调用 newList 函数 await getList(); // 默认选中第一个类别tab if (categories.value.length > 0) { currentCategory.value = categories.value[0] } });
分页功能
const currentPage = ref(1) const pageSize = 4 function handleTabChange(cat) { // console.log('handleTabChange',cat) currentCategory.value = cat currentPage.value = 1 } const pagedData = computed(() => { const allItems = categorizedData.value[currentCategory.value] || [] const startIndex = (currentPage.value - 1) * pageSize const endIndex = startIndex + pageSize // console.log('pagedData',allItems.slice(startIndex, endIndex)) return allItems.slice(startIndex, endIndex) })
计算总页数
const totalPages = computed(() => { const allItems = categorizedData.value[currentCategory.value] || [] return Math.ceil(allItems.length / pageSize) })
点击文章跳转
const goUrl = (url) => open(url)
前端页面渲染示例
<template> <div class="news"> <y-title en="News updates" cn="新闻动态"></y-title> <div class="news-tabs"> <div class="news-tabs-li" :class="{ 'news-tabs-li-sd': item === currentCategory }" v-for="item in categories" :key="item" @click="handleTabChange(item)">{{ item }}</div> </div> <div class="news-list"> <div class="news-list-li" v-for="item in pagedData" :key="item.id" @click="goUrl(item.url)"> <div class="news-list-li-title">{{ item.title }}</div> </div> </div> <div class="news-navs"> <button class="news-navs-box" @click="currentPage > 1 && (currentPage = currentPage - 1)">上一页</button> <span class="news-navs-box">{{ currentPage }} / {{ totalPages }}</span> <button class="news-navs-box" @click="currentPage < totalPages && (currentPage = currentPage + 1)">下一页</button> </div> </div></template>
样式
<style lang="scss" scoped>.news { display: flex; flex-direction: column; align-items: center; margin-top: 120px; margin-bottom: 270px; &-tabs { width: 1360px; display: flex; margin-top: 65px; &-li { background: #DCE9FF; width: 250px; height: 65px; display: flex; justify-content: center; align-items: center; border-top-left-radius: 10px; border-top-right-radius: 10px; margin-right: 15px; font-size: 30px; font-weight: bold; color: #000; cursor: pointer; transition: all .3s; } &-li-sd { background: #4A7CEE; color: #fff; } } &-list { background: #FAFBFF; height: 300px; width: 1360px; padding: 50px 60px; box-sizing: border-box; overflow: hidden; &-li { font-size: 24px; line-height: 24px; color: #252525; margin-top: 40px; cursor: pointer; &-url { margin-top: 12px; } &:first-child { margin-top: 0; } &:hover { color: #4A7CEE; } } } &-navs { display: flex; margin-top: 20px; &-box { width: 150px; height: 50px; background: #DCE9FF; border-radius: 10px; margin: 0 10px; display: flex; justify-content: center; align-items: center; cursor: pointer; font-size: 24px; &-sd { background: #4A7CEE; color: #fff; } } }}</style>