河流之所以让人如此平静,是因为它没有任何疑虑,一定会到达它要去的地方,而且它不想去任何其他地方。 ---艾伦·亚历山大·米恩-

最早星宿UI导航栏也是在中间,因为无法处理点击请求数据后,页面重新渲染高度丢失导致闪屏问题,后续灵沐因为采用点击滚动页面方式,可以缓解之外 ,今天采用最简单的补一个占位符方式
缘由
当我们滑动页面点击选项卡,需要重新发送请求渲染数据,不同选项卡内容不同因此的先清空之前的内容在渲染;
数据清空也会让容器高度丢失,高度已丢失页面就会往下跌落;这就是前端噩梦,当选项卡在页面中间点击后闪屏的原因

解决
我们明白页面闪屏是因为内容高度丢失,我们只要给他补充一个有高度的容器即可
容器的高度可以直接固定一个1000rpx之类的都可,或者动态获取屏幕高度赋值给容器
最后只要思考容器什么时候出现,什么时候关闭;点击选择卡之后重新渲染内容,这时候数据空了,显示占位容器,请求接口得到数据后在隐藏容器
效果图
适用于:选项卡在页面中间,基础教程,最简单的思路;基于UNI-app

案例
<template>
<view class="container">
<!-- 顶部红色背景容器 -->
<view class="top-container">
<text class="top-title">测试案例</text>
</view>
<!-- 选项卡 -->
<view class="tabs">
<view :class="currentTab == 0 ? 'active tab-item' : 'tab-item'" @click="switchTab(0)">
文章
</view>
<view :class="currentTab == 1 ? 'active tab-item' : 'tab-item'" @click="switchTab(1)">
新闻
</view>
</view>
<!-- 内容区域 -->
<view class="content">
<!-- 内容列表 -->
<view class="news-list">
<view class="news-item" v-for="(item, index) in newsList" :key="index">
<image class="news-img" :src="item.imgUrl"></image>
<view class="news-info">
<text class="news-title">{{item.title}}</text>
<text class="news-desc">{{item.desc}}</text>
<text class="news-time">{{item.time}}</text>
</view>
</view>
</view>
<!-- 占位符 -->
<view v-if="tapHeight" style="height: 800px;"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
tapHeight:false,
currentTab: 0, // 当前选中的选项卡
newsList: [], // 新闻列表数据
page: 1, // 当前页码
pageSize: 10, // 每页数量
// 模拟数据
mockData: [{
title: "这是一篇文章标题",
desc: "这是文章的简要描述内容,一般会显示前几句...",
time: "2025-05-10",
imgUrl: "https://picsum.photos/200/150?random=1"
},
{
title: "科技创新引领未来发展",
desc: "随着科技的不断进步,人工智能、大数据等新技术正在改变我们的生活...",
time: "2025-05-09",
imgUrl: "https://picsum.photos/200/150?random=2"
},
{
title: "健康生活小常识",
desc: "合理饮食、适量运动是保持健康的关键,这里有一些实用的健康小知识...",
time: "2025-05-08",
imgUrl: "https://picsum.photos/200/150?random=3"
},
{
title: "全球经济形势分析",
desc: "当前全球经济面临诸多挑战,贸易摩擦、通货膨胀等问题影响着各国经济...",
time: "2025-05-07",
imgUrl: "https://picsum.photos/200/150?random=4"
},
{
title: "教育改革新动态",
desc: "教育部门近日发布了一系列教育改革措施,旨在提高教育质量...",
time: "2025-05-06",
imgUrl: "https://picsum.photos/200/150?random=5"
},
{
title: "环保行动,从我做起",
desc: "环境污染问题日益严重,每个人都应该为环保出一份力...",
time: "2025-05-05",
imgUrl: "https://picsum.photos/200/150?random=6"
},
{
title: "文化艺术展览活动",
desc: "近期将有多个重要的文化艺术展览在本市举行,丰富市民文化生活...",
time: "2025-05-04",
imgUrl: "https://picsum.photos/200/150?random=7"
},
{
title: "体育赛事精彩回顾",
desc: "上周末的足球比赛精彩纷呈,主队以3:1战胜对手...",
time: "2025-05-03",
imgUrl: "https://picsum.photos/200/150?random=8"
},
{
title: "美食探店:发现城市美味",
desc: "今天带大家探访一家隐藏在小巷子里的特色餐厅,味道令人惊艳...",
time: "2025-05-02",
imgUrl: "https://picsum.photos/200/150?random=9"
},
{
title: "旅游攻略:最佳出行目的地",
desc: "五一假期即将到来,这里为您推荐几个适合出行的旅游胜地...",
time: "2025-05-01",
imgUrl: "https://picsum.photos/200/150?random=10"
}
]
}
},
onLoad() {
// 页面加载时初始化数据
this.loadData();
},
methods: {
// 切换选项卡
switchTab(index) {
this.tapHeight = true;//显示占位符
this.currentTab = index;
this.newsList = [];
this.loadData();
},
// 加载数据
loadData() {
// 模拟网络请求延迟
setTimeout(() => {
// 生成30条模拟数据
let mockType = this.currentTab === 0 ? '文章' : '新闻';
let newData = [];
for (let i = 0; i < this.pageSize; i++) {
// 随机选择一条基础数据进行修改
let randomIndex = Math.floor(Math.random() * this.mockData.length);
let item = JSON.parse(JSON.stringify(this.mockData[randomIndex]));
// 修改标题以区分文章和新闻
item.title = `${mockType} ${this.page * this.pageSize + i + 1}: ${item.title}`;
newData.push(item);
this.tapHeight = false;//关闭占位符
}
this.newsList = [...this.newsList, ...newData];
this.page++;
// 判断是否还有更多数据
if (this.newsList.length >= 30) {
this.hasMore = false;
}
}, 500);
},
}
}
</script>
<style>
.container {
margin: 28rpx;
}
.top-container {
height: 400rpx;
background-color: #ff0000;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 28rpx;
}
.top-title {
color: #ffffff;
font-size: 48rpx;
font-weight: bold;
}
.tabs {
display: flex;
height: 88rpx;
line-height: 88rpx;
background-color: #ffffff;
border-bottom: 1rpx solid #eeeeee;
}
.tab-item {
flex: 1;
text-align: center;
font-size: 32rpx;
color: #333333;
}
.active {
color: #ffffff;
background-color: #000000;
font-weight: bold;
}
.content {
padding: 20rpx;
}
.loading {
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
color: #999999;
font-size: 28rpx;
}
.news-list {
background-color: #ffffff;
border-radius: 12rpx;
}
.news-item {
display: flex;
padding: 24rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.news-img {
width: 200rpx;
height: 150rpx;
border-radius: 8rpx;
object-fit: cover;
}
.news-info {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.news-title {
font-size: 32rpx;
color: #333333;
font-weight: 500;
line-height: 40rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.news-desc {
font-size: 28rpx;
color: #666666;
line-height: 36rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
margin-top: 8rpx;
}
.news-time {
font-size: 24rpx;
color: #999999;
margin-top: 8rpx;
}
.load-more {
height: 88rpx;
line-height: 88rpx;
text-align: center;
color: #666666;
font-size: 28rpx;
}
page {
background-color: #f8f8f8;
}
</style>