探讨uniapp的页面问题
1 新建页面
uni-app中的页面,默认保存在工程根目录下的pages目录下。

每次新建页面,均需在pages.json中配置pages列表;

未在pages.json -> pages 中注册的页面,uni-app会在编译阶段进行忽略。pages.json的完整配置参考:页面配置。
通过HBuilderX开发 uni-app 项目时,在 uni-app 项目上右键“新建页面”,HBuilderX会自动在pages.json中完成页面注册,开发更方便。
同时,HBuilderX 还内置了常用的页面模板(如图文列表、商品列表等),选择这些模板,可以大幅提升你的开发效率。

新建页面时,可以选择vue或nvue,还可以选择是否创建同名目录。创建目录的意义在于,如果你的页面较复杂,需要拆分多个附属的js、css、组件等文件,则使用目录归纳比较合适。如果只有一个页面文件,大可不必多放一层目录。
2 删除页面
删除页面时,需做两件工作:
- 删除.vue文件或.nvue文件
- 删除pages.json -> pages列表项中的配置(如使用HBuilderX删除页面,会在状态栏提醒删除pages.json对应内容)
pages.json是工程的页面管理配置文件,包括:页面路由注册、页面参数配置(原生标题栏、下拉刷新…)、首页tabbar等众多功能。
其篇幅较长,另见 pages.json
3 应用首页
pages.json -> pages 配置项中的第一个页面,作为当前工程的首页(启动页)。
{"pages": [{"path": "pages/index/index", //名字叫不叫index无所谓,位置在第一个,就是首页"style": {"navigationBarTitleText": "首页" //页面标题}},{"path": "pages/my","style": {"navigationBarTitleText": "我的"}},]
}
4 页面内容构成
uni-app 页面基于 vue 规范。一个页面内,有3个根节点标签 、
<template><view class="content"><button @click="buttonClick">{{title}}</button></view>
</template><script>export default {data() {return {title: "Hello world", // 定义绑定在页面上的data数据}},onLoad() {// 页面启动的生命周期,这里编写页面加载时的逻辑},methods: {buttonClick: function () {console.log("按钮被点了")},}}
</script><style>.content {width: 750rpx;background-color: white;}
</style>
4.1 template模板区
vue的template中写的全都是vue组件,每个组件支持属性、事件、vue指令,还可以绑定vue的data数据。
4.2 script脚本区
在vue的选项式(option)规范中,script下包含export default {}。(除了选项式,还有组合式)
页面级的代码大多写在export default {}中。写在里面的代码,会随着页面关闭而关闭。

export default 外的代码
先来介绍写在export default {}外面的代码,一般有几种情况:
- import三方js模块
- import非easycom的组件(一般组件推荐使用easycom,无需导入注册)
- 定义作用域更大的变量
- 在ts/uts中,对data的类型进行type定义
<script>const TAB_OFFSET = 1; // 外层静态变量不会跟随页面关闭而回收import charts from 'charts.ts'; // 导入外部js/ts模块import swiperPage from 'swiper-page.vue'; //导入非easycom的组件type GroupType = {id : number,title : string} // 在ts中,为下面data数据的 groupList 定义类型export default {components: {swiperPage}, // 注册非easycom组件data() {return {groupList: [{ id: 1, title: "第一组" },{ id: 2, title: "第二组" },] as GroupType[], // 为数据groupList定义ts类型}},onLoad() {},methods: {}}
</script>
开发者应谨慎编写export default {}外面的代码,这里的代码有2个注意事项:
- 在应用启动时执行。也就是这里的代码执行时机是应用启动、而不是页面加载。如果这里的代码写的太复杂,会影响应用启动速度和内存占用。
- 不跟随页面关闭而回收。在外层的静态变量不会跟随页面关闭而回收。
export default 里的代码
export default {} 里的内容,是页面的主要逻辑代码。包括几部分:
- data:template模板中需要使用的数据。data 必须声明为返回一个初始数据对象的函数(注意函数内返回的数据对象不要直接引用函数外的对象)。
- 页面生命周期:如页面加载、隐藏、关闭
- methods方法,如按钮点击、屏幕滚动
如下页面代码的逻辑是:

- 在data中定义了title,初始值是"点我"
- 在页面中放置了一个button组件,按钮文字区使用{{}}模板写法,里面写title,把data里的title绑定到按钮的文字区,即按钮的初始文字是"点我"
- 按钮的点击事件@click,指向了methods里的一个方法buttonClick,点击按钮即触发这个方法的执行
- buttonClick方法里通过this.title的方式,访问data数据,并重新赋值为"被点了"。由于vue中data和界面是双向绑定,修改data中的title后,因为按钮文字绑定了title,会自动更新按钮的文字。
整体效果就是,刚开始按钮文字是"点我",点一下后按钮文字变成了"被点了"
5 页面生命周期
uni-app 页面除支持 Vue 组件生命周期外还支持下方页面生命周期函数.


5.1 页面加载时序介绍
接下来我们介绍onLoad、onReady、onShow的先后关系,页面加载的详细流程。

- uni-app框架,首先根据pages.json的配置,创建页面 。所以原生导航栏是最快显示的。页面背景色也应该在这里配置。
- 根据页面template里的组件,创建dom。
这里的dom创建仅包含第一批处理的静态dom,对于通过js更新data,然后通过v-for再创建的列表数据,不在第一批处理。要注意一个页面静态dom元素过多,会影响页面加载速度。在uni-app x Android版本上,可能会阻碍页面进入的转场动画。 因为此时,页面转场动画还没有启动。 - 触发onLoad
此时页面还未显示,没有开始进入的转场动画,页面dom还不存在。所以这里不能直接操作dom(可以修改data,因为vue框架会等待dom准备后再更新界面);
在 app-uvue 中获取当前的activity拿到的是老页面的activity,只能通过页面栈获取activity。
onLoad比较适合的操作是:接受上页的参数,联网取数据,更新data。
手机都是多核的,uni.request或云开发联网,在子线程运行,不会干扰UI线程的入场动画,并行处理可以更快的拿到数据、渲染界面。
但onLoad里不适合进行大量同步耗时运算,因为此时转场动画还没开始。 尤其uni-app x 在 Android上,onLoad里的代码(除了联网和加载图片)默认是在UI线程运行的,大量同步耗时计算很容易卡住页面动画不启动。除非开发者显式指定在其他线程运行。 - 转场动画开始
新页面开始进入的转场动画,动画默认耗时300ms,可以在路由API中调节时长。 - 页面onReady
第2步 创建dom是虚拟dom,dom创建后需要经历一段时间,UI层才能完成了页面上真实元素的创建,即触发了onReady。
onReady后,页面元素就可以自由操作了,比如ref获取节点。同时首批界面也渲染了。
注意:onReady和转场动画开始、结束之间,没有必然的先后顺序,完全取决于dom的数量和复杂度。
如果元素排版和渲染够快,转场动画刚开始就渲染好了;
大多情况下,转场动画走几格就看到了首批渲染内容;
如果元素排版和渲染过慢,转场动画结束都没有内容,就会造成白屏。
联网进程从onLoad起就在异步获取数据更新data,如果服务器速度够快,第二批数据也可能在转场动画结束前渲染。 - 转场动画结束
再次强调,5和6的先后顺序不一定,取决于首批dom渲染的速度。
5.2 页面加载常见问题
了解了页面加载时序原理,我们就知道如何避免页面加载常见的问题:
优化白屏的方法:
- 页面dom太多,注意有的组件写的不好,会拖累整体页面。uni-app x 里减少dom数量的策略,详见
- 联网不要在onReady里,那样太慢了,在onLoad里早点联网
- 在pages.json里配置原生导航栏和背景色
- 有的页面template内容非常少,整页就是一个需要联网加载的列表,这会造成虽然首批dom飞快渲染了,但页面其实还是白的,联网后才能显示字和图。
此时需要在template里做一些简单占位组件,比如loading组件、骨架屏,让本地先显示一些内容。
卡住动画不启动的原因:
- 页面dom太多,注意有的组件写的不好,会拖累整体页面。uni-app x 里减少dom数量的策略,详见
- onLoad里执行了耗时的同步计算
5.3 onShow和onHide
- 注意页面显示,是一个会重复触发的事件。
- a页面刚进入时,会触发a页面的onShow。
- 当a跳转到b页面时,a会触发onHide,而b会触发onShow。
- 但当b被关闭时,b会触发onUnload,此时a再次显示出现,会再次触发onShow。
- 在tabbar页面(指pages.json里配置的tabbar),不同tab页面互相切换时,会触发各自的onShow和onHide。
5.4 onInit
不建议使用
5.5 onReachBottom



onPageScroll : function(e) { //nvue暂不支持滚动监听,可用bindingx代替console.log("滚动距离为:" + e.scrollTop);
},
- 可在pages.json里定义具体页面底部的触发距离onReachBottomDistance,比如设为50,那么滚动页面到距离底部50px时,就会触发onReachBottom事件。
- 如使用scroll-view导致页面没有滚动,则触底事件不会被触发。scroll-view滚动到底部的事件请参考scroll-view的文档
- onPageScroll里不要写交互复杂的js,比如频繁修改页面。因为这个生命周期是在渲染层触发的,在非h5端,js是在逻辑层执行的,两层之间通信是有损耗的。如果在滚动过程中,频发触发两层之间的数据交换,可能会造成卡顿。
5.6 onBackPress


- onBackPress上不可使用async,会导致无法阻止默认返回
当用户进行以下操作时,会触发该函数:
- Android 实体返回键 (from = backbutton)
- 顶部导航栏左边的返回按钮 (from = backbutton)
- 返回 API,即 uni.navigateBack() (from = navigateBack)
注意事项:
- 只有在该函数中返回值为 true 时,才表示不执行默认的返回,自行处理此时的业务逻辑。
场景示例:

页面中的遮罩处于显示状态时,点击返回不希望直接关闭页面,而是隐藏掉遮罩。遮罩隐藏后,继续点击返回再执行默认的逻辑。
自定义遮罩 通常自定义的遮罩/弹出层,都会做成组件,这样方便复用。新建 uni-app 项目->components->mask.vue 文件,代码如下:
<template> <view> <view class="cpt-mask"> </view> </view>
</template> <script> export default {}
</script> <style> .cpt-mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #000000; opacity: 0.5; z-index: 99; }
</style>
引用遮罩组件 在页面中引入 mask 自定义组件后,通过一个状态值来控制其隐藏/显示。
<mask v-if="showMask"></mask>
这里用 v-if,不要用 v-show,自定义组件存在一些问题待优化。
在 onBackPress 中,判定当前遮罩是否处于显示状态。如果显示,则关闭遮罩并返回 true。
onBackPress() {if (this.showMask) {console.log('onBackPress close mask');this.showMask = false;return true;} else {uni.showModal({title: '提示',content: '自定义是否退出uni-app?',success: function(res) {if (res.confirm) {// 退出当前应用,改方法只在App中生效plus.runtime.quit();} else if (res.cancel) {console.log('用户点击取消');}}});return true;}},
5.7 onTabItemTap

- onTabItemTap常用于点击当前tabitem
onTabItemTap : function(e) {console.log(e);// e的返回格式为json对象: {"index":0,"text":"首页","pagePath":"pages/index/index"}
},
5.8 onNavigationBarButtonTap
点击导航栏 buttons 时触发



{"fontSrc": "/static/yticon.ttf","text": "","fontSize": "26","color": "#303133","float": "left","background": "rgba(0,0,0,0)","onclick": "function() { [native code] }","__cb__": {"id": "plus71692953577889","htmlId": "__uniapp__service"},"index": 0
}
6 组件生命周期

7 页面调用接口
7.1 getApp()
getApp() 函数用于获取当前应用实例VUE,一般用于获取globalData。也可通过应用实例调用 App.vue methods 中定义的方法。

7.2 getCurrentPages()
getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,数组中的元素为页面实例,第一个元素为首页,最后一个元素为当前页面。

getCurrentPages()仅用于展示页面栈的情况,请勿修改页面栈,以免造成页面状态错误。页面关闭时,对应页面实例会在页面栈中删除。

var pages = getCurrentPages();var page = pages[pages.length - 1];
8 页面通讯
8.1 uni.$emit(eventName,OBJECT)
触发全局的自定义事件。附加参数都会传给监听器回调。

uni.$emit('update',{msg:'页面更新'})
8.2 uni.$on(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。

uni.$on('update',function(data){console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);})
8.3 uni.$once(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。

uni.$once('update',function(data){console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);})
8.3 uni.$off([eventName, callback])
移除全局自定义事件监听器。

- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器;
- 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;
$emit、$on、$off常用于跨页面、跨组件通讯,这里为了方便演示放在同一个页面
8.4 如何使用uni.$emit()和uni.$on() 进行页面间通讯:
监听事件
// 我的页面
onLoad(){ // 监听事件 uni.$on('login',(usnerinfo)=>{ this.usnerinfo = usnerinfo; })
},
onUnload() { // 移除监听事件 uni.$off('login'); },
因为事件监听是全局的,所以使用 uni.$on ,需要使用 uni.$off 移除全局的事件监听,避免重复监听。
触发事件
// 登陆页面
uni.$emit('login', { avatarUrl: 'https://img-cdn-qiniu.dcloud.net.cn/uploads/nav_menu/10.jpg', token: 'user123456', userName: 'unier', login: true });
使用 uni.$emit 触发事件后,对应的 uni.$on 就会监听到事件触发,在回调中去执行相关的逻辑。

9 路由
uni-app 有两种页面路由跳转方式:使用navigator组件跳转、调用API跳转。
- 页面返回时会自动关闭 loading 及 toast, modal 及 actionSheet 不会自动关闭。
- 页面关闭时,只是销毁了页面实例,未完成的网络请求、计时器等副作用需开发者自行处理。
10 页面栈
框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:

相关文章:
探讨uniapp的页面问题
1 新建页面 uni-app中的页面,默认保存在工程根目录下的pages目录下。 每次新建页面,均需在pages.json中配置pages列表; 未在pages.json -> pages 中注册的页面,uni-app会在编译阶段进行忽略。pages.json的完整配置参考&am…...
【跨域异常】
想在前端使用vue获取后端接口的数据,但是报了跨域异常,如下图所示。 一种解决的方式是,在后端Controller接口上加上CrossOrigin,从后端解决跨域问题。 还要注意前端请求的url要加上协议,比如http://...
上市公司环境信息披露(含环境负债、管理、监管、业绩与治理披露,2008-2022)
数据简介:环境信息披露是督促企业履行社会责任,推动国民经济社会全面绿色转型和加快实现“双碳”目标的重要抓手。环境信息披露理论缘起于社会责任理论,发展于合法性理论、利益相关者理论、制度理论和信号传递理论等。 结合相关理论…...
网络基础入门
认识协议 协议其实是一种约定 网络协议初识: 1.内核上以结构体形式呈现 2.操作系统要进行协议管理--先描述,在管理 3.协议的本质是软件,软件是可以分层的,(联系C继承多态的知识 ) 可以参考 ࿱…...
Oracle工具之SQLLDR
1. 什么是SQLLDR SQLLDR是Oracle服务端自带的工具,用于快速导入大批量数据。 2. 常规路径加载/直接路径加载 sqlldr导入有两种模式,常规路径加载和直接路径加载,默认使用常规路径加载,当directy或者directtrue时,使用…...
探索pytest:Python自动化测试的新境界
在当今的软件开发领域,测试已经不仅仅是一个简单的步骤,而是确保软件质量的核心环节。Python,作为全球最受欢迎的编程语言之一,拥有丰富的测试框架和工具。而在这其中,pytest无疑是最受欢迎和最具影响力的一个。本文将…...
K8s学习笔记4
场景: 项目研发部门最近要进行应用运行基础环境迁移,需要由原先的虚拟机环境迁移到K8s集群环境中,以便应对开发快速部署和快速测试的需要,因此,需要准备一套可以用于开发需求的K8s集群,但是对于仅有容器基…...
Kafka 学习笔记
😀😀😀创作不易,各位看官点赞收藏. 文章目录 Kafka 学习笔记1、消息队列 MQ2、Kafka 下载安装2.1、Zookeeper 方式启动2.2、KRaft 协议启动2.3、Kafka 集群搭建 3、Kafka 之生产者3.1、Java 生产者 API3.2、Kafka 生产者生产分区3…...
vue实现表格的动态高度
需求:表格能够根据窗口的大小自动适配页面高度 防抖和节流函数的使用场景是当需要对频繁触发的事件进行限制时,例如: 防抖函数常用于限制用户在短时间内多次触发某一事件,例如搜索框输入并搜索,当用户一直在输入时,我们可以使用防抖函数来避免多次请求搜索结果,减轻服…...
HodlSoftware-免费在线PDF工具箱 加解密PDF 集成隐私保护功能
HodlSoftware是什么 HodlSoftware是一款免费在线PDF工具箱,集合编辑 PDF 的简单功能,可以对PDF进行加解密、优化压缩PDF、PDF 合并、PDF旋转、PDF页面移除和分割PDF等操作,而且工具集成隐私保护功能,文件只在浏览器本地完成&…...
09 数据库开发-MySQL
文章目录 1 数据库概述2 MySQL概述2.1 MySQL安装2.1.1 解压&添加环境变量2.1.2 初始化MySQL2.1.3 注册MySQL服务2.1.4 启动MySQL服务2.1.5 修改默认账户密码2.1.6 登录MySQL 2.2 卸载MySQL2.3 连接服务器上部署的数据库2.4 数据模型2.5 SQL简介2.5.1 SQL通用语法2.3.2 分类…...
QT通过ODBC连接GBase 8s数据库(Windows)示例
示例环境: 操作系统:Windows 10 64位数据库及CSDK版本:GBase 8s V8.8_3.0.0_1 64位QT:5.12.0 64位 1,CSDK安装及ODBC配置 1.1,免安装版CSDK 下载免安装版的CSDK驱动,地址:https:…...
Java-三个算法冒泡-选择排序,二分查找
Java算法: 冒泡排序; 解析:将前后两个数对比,将大的数(或小的)调换至后面,每轮将对比过程中的最大(或最小)数,调到最后面。每轮对比数减一;初始对比数为数组…...
docker版jxTMS使用指南:使用jxTMS提供数据
本文讲解了如何jxTMS的数据访问框架,整个系列的文章请查看:docker版jxTMS使用指南:4.4版升级内容 docker版本的使用,请查看:docker版jxTMS使用指南 4.0版jxTMS的说明,请查看:4.0版升级内容 4…...
阿里 MySQL 规范
阿里 MySQL 规范 1. 建库建表规范 【推荐】库名与应用/服务名称尽量一致。 【强制】表名不使用复数名词。 说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于DO类名也是单数形式,符合表达习惯。 【推荐】表的…...
C++ Primer阅读笔记--动态内存和智能指针
目录 1--动态内存管理 2--shared_ptr类 2-1--make_shared 函数 2-2--引用计数 2-3--get 3--new和delete 4--shared_ptr和new结合使用 5--unique_ptr 6--weak_ptr 1--动态内存管理 new:在动态内存中为对象分配空间并返回一个指向该对象的指…...
git分支管理策略
git的基础操作以及常用命令在上篇博客哦~ git原理与基本使用 1.分支管理 1.主分支 在版本回退⾥,我们已经知道,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。截⽌到⽬前,只有⼀条时间线&…...
IntelliJ IDEA maven配置,设置pom.xml的配置文件
IntelliJ IDEA项目,选择 文件 设置,弹窗 构建、执行、部署 构建工具 Maven就可以 maven配置好以后,在pom.xml的配置文件中就可以设置对应的jar包了,这样构建的时候自动需要的jar,在项目中导入即 settings.xml文件apa…...
C#__使用Thread启动线程和传输数据
class Program{static void Test(){Console.WriteLine("Start……");Thread.Sleep(2000); // 1s等于1000ms,暂停2sConsole.WriteLine("end");}static void Download(Object ob){string str ob as string; // 遍历传递过来的ob字符串Console.Wr…...
appium2.0+ 单点触控和多点触控新的解决方案
在 appium2.0 之前,在移动端设备上的触屏操作,单手指触屏和多手指触屏分别是由 TouchAction 类,Multiaction 类实现的。 在 appium2.0 之后,这 2 个方法将会被舍弃。 "[Deprecated] TouchAction action is deprecated. Ple…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
