使用loading动画让你的条件渲染页面更高级

news/2024/9/20 1:25:29/

前言

在我们做项目的使用常常会使用条件渲染有选择的给用户展示相关页面,如果渲染的数据或场景比较多比较复杂,那么往往需要3、4s的时间去完成,用户点击了之后就会陷入3、4s的空白期,并且这段时间屏幕是处于一种”未响应“的状态,用户并不知道自己是否点击生效了。这篇文章主要是介绍一种让条件渲染展示页面更丝滑的方法,这样能大大提高用户的体验。


效果图

在渲染还未完成时展现loading动画给用户

这个看上去是在多个页面进行跳转,实则是只有一个页面,不过是用了条件渲染和loading动画让用户感觉自己跳转了页面。这里就不具体介如何使用条件渲染来将多个页面整合成一个页面了,我之前的博客有详细的描述(https://blog.csdn.net/Zchengjisihan/article/details/129016013?spm=1001.2014.3001.5501)。这篇博客我们将重点放在loading动画上。


核心思想

  • 使用外部组件库的vant-weapp的Popup组件

  • 使用CSS的animation动画

  • 使用JS的setTimeout来等全部数据渲染完成后再隐藏loading动画


vant-weapp的Popup组件

我使用的是样式是从上方弹出并且是圆角的形式,你可以根据自己的需求来调整从哪个方向弹出,是否显示 ”× “ 等等,这些Popup组件支持的api你均可以在官方文档下找的到,在这我就不赘述了


在Popup上添加loading样式

这里需要用到相关CSS的animation知识,如果你想换个更炫酷的loading动画可以直接在相关网站上搜索,很多源码的。我把自己的loading动画放在下面了(这个是参考一个博主的,修改了主色调)

<!-- 弹出层 -->
<van-popup show="{{ popShow }}" position="top" custom-style="height: 300rpx;" round><!-- loading盒子,用来装loading动画的 --><view class="loadingBox"  style="margin-top: 200rpx;"><view class="loader-dots"><view></view><view></view><view></view><view></view><view></view></view></view> 
</van-popup>

.loader-dots view{width: 40rpx;height: 40rpx;background: brown;border-radius: 30%;display:inline-block;animation: slide 1s infinite;}
.loader-dots view:nth-child(1){animation-delay:.1s;
}
.loader-dots view:nth-child(2){animation-delay:.2s;
}
.loader-dots view:nth-child(3){animation-delay:.3s;background: linear-gradient(to bottom right,rgb(155, 55, 55),#FFFFFF)
}
.loader-dots view:nth-child(4){animation-delay:.4s;background: linear-gradient(to bottom right,rgb(145, 55, 55),#FFFFFF)
}
.loader-dots view:nth-child(5){animation-delay:.5s;background:linear-gradient(to bottom right,rgb(135, 55, 55),#FFFFFF)
}
@keyframes slide{
0%{transform: scale(1)
}
50%
{opacity:0.3;transform:scale(2);
}
100%{transform: scale(1)
}

若渲染数据较大或增加loading的时间需使用延迟函数setTimeout

除了上诉情况,我们也可以在登录页面的跳转的时候添加这个loading动画。

使用setTimeout的好处一方面是可以等待数据全部渲染完成后再展示给用户,从而避免了数据残留以及数据错位的情况;另一方面则是可以自主设置最短loading动画的时间

例:如上图:虽然渲染完全部的数据只花了几毫秒,但是为了稍微的延迟登录时间,我将setTimeout的时间参数调整到了1000(1s)。我将所有代码放在下面了,需要的自取~

<!-- wxml -->
<!-- 原始内容层 -->
<view class="box"><van-divider contentPosition="center" customStyle="color: grey; border-color: grey; font-size: 36rpx; width: 90% ; margin-left:40rpx ; margin-right:40rpx ; margin-top:150rpx">团团活动管理</van-divider><button bindtap="goIndex" class="button_location" style="width: 450rpx; height: 100rpx"> <text style="font-size: 36rpx; float: left; margin-left: 80rpx;">用户端登录</text><van-icon name="friends-o" size="60rpx" custom-style="height:60rpx; margin-top:15rpx;"/></button><button bindtap="goNext" class="Teacherbutton_location" style="width: 450rpx; height: 100rpx"> <text style="font-size: 36rpx; float: left; margin-left: 80rpx;">审批端登录</text><van-icon name="manager-o" size="60rpx" custom-style="height:60rpx; margin-top:15rpx;"/> </button><!-- 右下角的图书和提示字 --><view style="width: 140rpx;height: 180rpx;position: absolute; right: 40rpx; bottom: 70rpx;" bindtap="lookGuide"><view style="width: 140rpx;height: 40rpx; font-size: 28rpx; text-align: center; font-weight: 700; color: brown;">手册及日志</view><image src="../../icon/guide.png" style="width: 140rpx;height: 140rpx;"></image></view><van-divider contentPosition="center" customStyle="color: grey; border-color: grey; font-size: 36rpx; width: 90% ; position: absolute;margin-left:40rpx ; margin-right:40rpx ; bottom:0px">Copyright© STU引力弹簧工作室</van-divider>
</view>
<!-- 遮罩层 -->
<van-overlay show="{{ show }}" z-index="2"><view class="wrapper"><view class="login"><view class="loginHead"><image src="../../icon/tuantuan.png" class="tuantuan"></image><view class="cross"><van-icon name="cross" size="40px" custom-style="position:relative; margin-top:20rpx; margin-left:80rpx" bindtap="onClickHide"/></view></view><view class="loginBody"><van-dividercontentPosition="left"customStyle="color: grey; border-color: grey; font-size: 36rpx; width: 520rpx ; position:relative; padding-top:80rpx; padding-left:40rpx; ">Account</van-divider><input bindinput="getAccount" class="inputborder1" placeholder="输入账号"></input><van-dividercontentPosition="left"customStyle="color: grey; border-color: grey; font-size: 36rpx; width: 520rpx ; position:relative; padding-left:40rpx;">Password</van-divider><input class="inputborder2" type="password"  placeholder="输入密码" value='{{password}}' bindinput='getPassWord'></input> <view bindtap="goRegister" class="goRegister">注册账号</view><view bindtap="goRetrieve" class="goRetrieve">忘记密码</view></view><view class="loginFeet"><view class="loginButton"><button bindtap="enterIndex" style="width: 88%;border-radius: 40rpx;background-color: #D43030; color:#FFFFFF;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.35);">登录</button></view><image src="../../icon/client-side.png" class="client-side"></image></view></view></view><!-- 由于不显示导航栏故loading盒子需要修改margin-top值 --><van-popup show="{{ popShow }}" position="top" custom-style="height: 300rpx;" round><view class="loadingBox"  style="margin-top: 200rpx;"><view class="loader-dots"><view></view><view></view><view></view><view></view><view></view></view></view> </van-popup>
</van-overlay>       

const db  = wx.cloud.database()
Page({data: {popShow:false,show:false,password :'',account :''},goNext(e){console.log('点击了审批端登录')wx.navigateTo({url: '../nextChoice/nextChoice',})},goIndex(e){console.log('点击了用户登录')//显示用户端的遮罩层this.setData({show:true})},// 隐藏遮罩层onClickHide() {this.setData({ show: false });},//点击登录enterIndex(){let that = thislet account = this.data.accountlet password = this.data.passworddb.collection("studentUser").where({account:account}).get({}).then(res=>{console.log("查询数据库成功",res.data)if(password == res.data[0].password){console.log('登录成功')this.setData({popShow:true})setTimeout(() => {wx.switchTab({url: '../index/index',success(){that.setData({popShow:false})}})}, 1000);}else{console.log("登录失败")wx.showToast({title: '登录失败,账号或密码不正确',icon : "none"})}}).catch(res=>{wx.showToast({title: '登录失败,账号或密码不正确',icon : "none"})})},//获取输入的账号getAccount(e){this.setData({account : e.detail.value})},//获取输入的密码getPassWord: function(e) {var password = e.detail.value;this.setData({password: password})},//进入注册界面goRegister(){wx.navigateTo({url: '../closeRegister/closeRegister',})},//进入找回账号密码页面goRetrieve(){wx.navigateTo({url: '../retrieve/retrieve',})}
})

{//json"usingComponents": {"van-icon": "@vant/weapp/icon/index","van-overlay": "@vant/weapp/overlay/index","van-divider": "@vant/weapp/divider/index","van-popup": "@vant/weapp/popup/index"},"navigationStyle": "custom"
}

当前页面的CSS
text{padding-right: 10px;
}
.loginHead{width: 100%;height: 160rpx;
}
.cross{float: right;width: 160rpx;height: 120rpx;padding-top: 40rpx;padding-right: 40rpx;
}
/* 团团图片样式 */
.tuantuan{width: 160rpx;height: 120rpx;padding-top: 40rpx;padding-left: 40rpx;
}
.loginBody{width: 100%;height: 700rpx;
}
.loginFeet{width: 100%;height: 300rpx;
}/* 遮罩层内嵌盒子包装层 */
.wrapper {display: flex;align-items: center;justify-content: center;height: 100%;}
/* 遮罩层内嵌盒子内容层 */
.login{background-color: #FFFFFF;width: 600rpx;height: 1200rpx;border-radius: 40rpx;
}
/* 输入账号的input */
.inputborder1{margin-left: 40rpx;margin-right:40rpx;margin-bottom: 30rpx;padding-top: 30rpx;padding-bottom: 30rpx;padding-left: 30rpx;padding-right:30rpx;border-radius: 20rpx;border: 2rpx solid #F2E6E6;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.15);
}
/* 输入密码的input */
.inputborder2{margin-left: 40rpx;margin-right:40rpx;margin-bottom: 30rpx;padding-top: 30rpx;padding-bottom: 30rpx;padding-left: 30rpx;padding-right:30rpx;border-radius: 20rpx;border: 2rpx solid #F2E6E6;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.15);
}
/* button在wxss里面修改不了宽度和高度,故在wmxl里面添加style属性来实现 */
.loginButton{position: relative;padding-top: 100rpx;}.goRegister{position: relative;top: 5rpx;float: right; right: 40rpx; font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}
.goRetrieve{position: relative;top: 5rpx; left: 40rpx;float: left; font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}
.client-side{width: 120rpx;height: 80rpx;float: right;margin-top:10rpx ;margin-right:20rpx;
}

总页面的CSS
/* choicePage 和 nextChoice的两个按钮 */
.Teacherbutton_location{margin-top: 20rpx;border-radius: 80rpx;color:black;background-color: #FFFFFF;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.15);border: 2rpx solid brown;
}
.button_location{border-radius: 80rpx;margin-top: 420rpx;color:#FFFFFF;background-color: #D43030;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.15);border: 2rpx solid #FFFFFF;
}
/* 无数据时显示的图片和文字格式 */
.noData{height: 700rpx;width: 100%;position: absolute;top: 200rpx;left: 0px;margin-top: 50rpx;
}
.fail{height: 700rpx;width: 100%;position: absolute;top: 100rpx;margin-top: 50rpx;
}
.tip{position: relative;margin-top: 800rpx;font-size: 36rpx;color:gray;text-align: center;
}
/* 所有状态标签的样式 */
.state_0{float: right;width: 160rpx;height: 80rpx;background-color:#FFC300;border-radius: 0 30rpx 0 30rpx;
}
.state_1{width: 160rpx;height: 80rpx;background-color:#43CF7C;border-radius: 0 30rpx 0 30rpx;z-index: 2;
}
.state_2{width: 160rpx;height: 80rpx;background-color:#FF5733;border-radius: 0 30rpx 0 30rpx;z-index: 2;
}
.state_4{float: right;width:160rpx;height:80rpx;background-color:#CCCCCC;border-radius:0 30rpx 0 30rpx;z-index: 2;flex-direction: row;position: relative;margin-left: 40rpx;
}
/* 用来装标签的盒子 */
.state_content{position: relative;margin-top:20rpx ;margin-left: 30rpx;font-size: 30rpx;color: white;
}
/* 预约老师和申请活动的盒子 */
.mine_application{margin-left: 50rpx;margin-right: 50rpx;
}
.mine_application_title{height: 90rpx;border-bottom: 5rpx solid #A6A6A6;font-size: 56rpx;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.mine_application_content{height: 300rpx;width: 100%;display: flex;position: relative;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.1);margin-top: 40rpx;border-radius:30rpx;background-color: rgb(252, 252, 252);border: 1rpx solid rgb(210, 210, 210);
}
.mine_appointment_title{height: 90rpx;border-bottom: 5rpx solid #A6A6A6;font-size: 56rpx;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}.mine_appointment_content{height: 500rpx;width: 100%;display: flex;position: relative;box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.1);margin-top: 30rpx;border-radius: 30rpx;background-color: rgb(252, 252, 252);border: 1rpx solid rgb(210, 210, 210);
}
/* 活动的具体样式 */
.event{font-size: 40rpx;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;position: relative;margin:30rpx;width: 90%;flex: 1;
}
.eventTime{margin-top: 10rpx;font-size: 28rpx;color: #A0A9BD;
}
/* loading盒子的样式 */
.loadingBox{margin-top: 60rpx;padding-left: 260rpx;
}
.loader-dots view{width: 40rpx;height: 40rpx;background: brown;border-radius: 30%;display:inline-block;animation: slide 1s infinite;}
.loader-dots view:nth-child(1){animation-delay:.1s;
}
.loader-dots view:nth-child(2){animation-delay:.2s;
}
.loader-dots view:nth-child(3){animation-delay:.3s;background: linear-gradient(to bottom right,rgb(155, 55, 55),#FFFFFF)
}
.loader-dots view:nth-child(4){animation-delay:.4s;background: linear-gradient(to bottom right,rgb(145, 55, 55),#FFFFFF)
}
.loader-dots view:nth-child(5){animation-delay:.5s;background:linear-gradient(to bottom right,rgb(135, 55, 55),#FFFFFF)
}
@keyframes slide{
0%{transform: scale(1)
}
50%
{opacity:0.3;transform:scale(2);
}
100%{transform: scale(1)
}
}

结语

如果有疑问欢迎大家留言讨论,你如果觉得这篇文章对你有帮助可以给我一个免费的赞吗?我们之间的交流是我最大的动力!


http://www.ppmy.cn/news/26742.html

相关文章

Spring IOC 容器 Bean 加载过程

Spring IOC 容器 Bean 加载过程 Spring 对于我们所有的类对象进行了统一抽象&#xff0c;抽象为 BeanDefinition &#xff0c;即 Bean 的定义&#xff0c;其中定义了类的全限定类名、加载机制、初始化方式、作用域等信息&#xff0c;用于对我们要自动装配的类进行生成。 Sprin…

漫画 | Python是一门烂语言?

这个电脑的主人是个程序员&#xff0c;他相继学习了C、Java、Python、Go&#xff0c; 但是似乎总是停留在Hello World的水平。 每天晚上&#xff0c;夜深人静的时候&#xff0c;这些Hello World程序都会热火朝天地聊天但是&#xff0c;这一天发生了可怕的事情随着各个Hello wor…

离散数学笔记_第一章:逻辑和证明(1)

1.1命题逻辑1.1.1 命题 1.1.2 逻辑运算符 定义1&#xff1a; 否定联结词定义2&#xff1a; 合取联结词定义3&#xff1a; 析取联结词定义4&#xff1a; 异或联结词1.1.3 条件语句 定义5&#xff1a; 条件语句定义6&#xff1a; 双条件语句1.1.1 命题 1.命题&#xff1a;是…

记一次 .NET 某医保平台 CPU 爆高分析

一&#xff1a;背景 1. 讲故事 一直在追这个系列的朋友应该能感受到&#xff0c;我给这个行业中无数的陌生人分析过各种dump&#xff0c;终于在上周有位老同学找到我&#xff0c;还是个大妹子&#xff0c;必须有求必应 &#x1f601;&#x1f601;&#x1f601;。 妹子公司的…

【结构体版】通讯录

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;项目 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x…

数据库期末复习总结-hnu

基本把所有知识点都罗列了&#xff08;吧&#xff09;&#xff0c;小部分知识点&#xff08;求闭包、多值依赖&#xff09;留到以后再补吧&#xff0c;先把坑留在这里。 整理不易&#xff0c;多多点赞&#xff08;orz&#xff09; 第一章 数据库系统 数据库&#xff1a;可长期…

Allegro无法打开10度走线命令的原因和解决办法

Allegro无法打开10度走线命令的原因和解决办法 做PCB设计的时候,10度走线也是较为常见的设计方式,Allegro支持10度走线,如下图 需要10度走线的时候,Options只需要勾选Route offset命令即可 但有时options处会看不到10度走线的命令,如下图

python--matplotlib(3)

前言 Matplotlib画图工具的官网地址是 http://matplotlib.org/ Python环境下实现Matlab制图功能的第三方库&#xff0c;需要numpy库的支持&#xff0c;支持用户方便设计出二维、三维数据的图形显示&#xff0c;制作的图形达到出版级的标准。 其他matplotlib文章 python--matpl…

力扣(LeetCode)418. 屏幕可显示句子的数量(2023.02.20)

给你一个 rows x cols 的屏幕和一个用 非空 的单词列表组成的句子&#xff0c;请你计算出给定句子可以在屏幕上完整显示的次数。 注意&#xff1a; 一个单词不能拆分成两行。 单词在句子中的顺序必须保持不变。 在一行中 的两个连续单词必须用一个空格符分隔。 句子中的单词总…

预告|2月25日 第四届OpenI/O 启智开发者大会昇腾人工智能应用专场邀您共启数字未来!

如今&#xff0c;人工智能早已脱离科幻小说中的虚构想象&#xff0c;成为可触及的现实&#xff0c;并渗透到我们的生活。随着人工智能的发展&#xff0c;我们正在迎来一个全新的时代——数智化时代。数据、信息和知识是这个时代的核心资源&#xff0c;而人工智能则是这些资源的…

react源码中的协调与调度

requestEventTime 其实在React执行过程中&#xff0c;会有数不清的任务要去执行&#xff0c;但是他们会有一个优先级的判定&#xff0c;假如两个事件的优先级一样&#xff0c;那么React是怎么去判定他们两谁先执行呢&#xff1f; // packages/react-reconciler/src/ReactFibe…

边玩边学,13个 Python 小游戏真有趣啊(含源码)

经常听到有朋友说&#xff0c;学习编程是一件非常枯燥无味的事情。其实&#xff0c;大家有没有认真想过&#xff0c;可能是我们的学习方法不对&#xff1f; 比方说&#xff0c;你有没有想过&#xff0c;可以通过打游戏来学编程&#xff1f; 今天我想跟大家分享几个Python小游…

Linux 学习指南

Linux 学习指南 文章目录Linux 学习指南前言一、在线教程1.1鸟哥的 Linux 私房菜1.2Linux 工具快速教程1.3快乐的 Linux 命令行1.4Linux 教程 | 菜鸟教程1.5Linux 教程 | W3Cschool二、社区网站2.1Linux 中国2.2Linux 公社2.3Linux Today2.4ChinaUnix2.5Linux 运维部落三、在线…

python filtermapreducezip

一、filter 过滤 filter 过滤&#xff0c; 从可迭代对象中&#xff0c;筛选出满足条件的元素&#xff0c;再将这些满足条件的元素&#xff0c;组成一个新的可迭代对象。 方式一&#xff1a;filter(过滤方法&#xff0c;可迭代对象&#xff09; 举例&#xff1a;将一个list中…

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(一)

在最后一个例程中笔者精挑细选了一个较为综合性的项目实战&#xff0c;其中覆盖了很多知识点&#xff0c;也是从一个转产产品中所提炼出来的&#xff0c;所以非常贴近实战项目。 整个工程实现了用户通过对上位机PC端人机界面的操作&#xff0c;即可达到控制豌豆开发并行DAC输出…

基于springboot+vue的校园社团管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

华为OD机试 - 最差产品奖 | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …

第一个Java程序(初识Java)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录1.Java概述1.1什么是Java1.2Java之父2.0第一个Java程序编译运行.class3.0程序如何跑起来的&#xff1f;3.1J…

【无标题】对象池,大量创建对象时提高性能

在开发中&#xff0c;我们经常会遇到以下场景&#xff1a; 1.对象的大量创建和销毁&#xff0c;比如网口接收数据&#xff0c;进行数据解析。 2.场景中存在大量相同物体的创建和销毁&#xff0c;导致性能下降。 3 循环中大量new对象 看到微软帮助中有一个ConcurrentBag的用法&…

快乐的shell命令行

快乐的shell命令行 PART1——基础 1.权限 #超级用户权限$普通用户 2.复制粘贴 复制&#xff1a;鼠标左键沿着文本拖动高亮的文本被复制到X管理的缓冲区&#xff08;或者双击一个单词&#xff09;粘贴&#xff1a;鼠标中键 3.简单命令 时间和日期date当前月份的日历cal磁…