探讨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 删除页面

删除页面时,需做两件工作:

  1. 删除.vue文件或.nvue文件
  2. 删除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方法,如按钮点击、屏幕滚动

如下页面代码的逻辑是:
在这里插入图片描述

  1. 在data中定义了title,初始值是"点我"
  2. 在页面中放置了一个button组件,按钮文字区使用{{}}模板写法,里面写title,把data里的title绑定到按钮的文字区,即按钮的初始文字是"点我"
  3. 按钮的点击事件@click,指向了methods里的一个方法buttonClick,点击按钮即触发这个方法的执行
  4. buttonClick方法里通过this.title的方式,访问data数据,并重新赋值为"被点了"。由于vue中data和界面是双向绑定,修改data中的title后,因为按钮文字绑定了title,会自动更新按钮的文字。

整体效果就是,刚开始按钮文字是"点我",点一下后按钮文字变成了"被点了"

5 页面生命周期

uni-app 页面除支持 Vue 组件生命周期外还支持下方页面生命周期函数.
在这里插入图片描述
在这里插入图片描述

5.1 页面加载时序介绍

接下来我们介绍onLoad、onReady、onShow的先后关系,页面加载的详细流程。
在这里插入图片描述

  1. uni-app框架,首先根据pages.json的配置,创建页面 。所以原生导航栏是最快显示的。页面背景色也应该在这里配置。
  2. 根据页面template里的组件,创建dom。
    这里的dom创建仅包含第一批处理的静态dom,对于通过js更新data,然后通过v-for再创建的列表数据,不在第一批处理。要注意一个页面静态dom元素过多,会影响页面加载速度。在uni-app x Android版本上,可能会阻碍页面进入的转场动画。 因为此时,页面转场动画还没有启动。
  3. 触发onLoad
    此时页面还未显示,没有开始进入的转场动画,页面dom还不存在。所以这里不能直接操作dom(可以修改data,因为vue框架会等待dom准备后再更新界面);
    在 app-uvue 中获取当前的activity拿到的是老页面的activity,只能通过页面栈获取activity。
    onLoad比较适合的操作是:接受上页的参数,联网取数据,更新data。
    手机都是多核的,uni.request或云开发联网,在子线程运行,不会干扰UI线程的入场动画,并行处理可以更快的拿到数据、渲染界面。
    但onLoad里不适合进行大量同步耗时运算,因为此时转场动画还没开始。 尤其uni-app x 在 Android上,onLoad里的代码(除了联网和加载图片)默认是在UI线程运行的,大量同步耗时计算很容易卡住页面动画不启动。除非开发者显式指定在其他线程运行。
  4. 转场动画开始
    新页面开始进入的转场动画,动画默认耗时300ms,可以在路由API中调节时长。
  5. 页面onReady
    第2步 创建dom是虚拟dom,dom创建后需要经历一段时间,UI层才能完成了页面上真实元素的创建,即触发了onReady。
    onReady后,页面元素就可以自由操作了,比如ref获取节点。同时首批界面也渲染了。
    注意:onReady和转场动画开始、结束之间,没有必然的先后顺序,完全取决于dom的数量和复杂度。
    如果元素排版和渲染够快,转场动画刚开始就渲染好了;
    大多情况下,转场动画走几格就看到了首批渲染内容;
    如果元素排版和渲染过慢,转场动画结束都没有内容,就会造成白屏。
    联网进程从onLoad起就在异步获取数据更新data,如果服务器速度够快,第二批数据也可能在转场动画结束前渲染。
  6. 转场动画结束
    再次强调,5和6的先后顺序不一定,取决于首批dom渲染的速度。

5.2 页面加载常见问题

了解了页面加载时序原理,我们就知道如何避免页面加载常见的问题:

优化白屏的方法:

  1. 页面dom太多,注意有的组件写的不好,会拖累整体页面。uni-app x 里减少dom数量的策略,详见
  2. 联网不要在onReady里,那样太慢了,在onLoad里早点联网
  3. 在pages.json里配置原生导航栏和背景色
  4. 有的页面template内容非常少,整页就是一个需要联网加载的列表,这会造成虽然首批dom飞快渲染了,但页面其实还是白的,联网后才能显示字和图。
    此时需要在template里做一些简单占位组件,比如loading组件、骨架屏,让本地先显示一些内容。

卡住动画不启动的原因:

  1. 页面dom太多,注意有的组件写的不好,会拖累整体页面。uni-app x 里减少dom数量的策略,详见
  2. 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 页面栈

框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

知更鸟语音训练

现在哪还有人读小说、看视频&#xff0c;谁还用真人朗读呢&#xff1f; 现在给大家介绍&#xff0c;假人朗读是怎么来的&#xff0c;提供一些音频&#xff0c;进行训练&#xff0c;然后就能合成属于自己的音频了。这里只讲训练部分&#xff0c;使用请自己看github知更鸟&#…

Python2021年06月Python二级 -- 编程题解析

题目一 没有重复数字的两位数统计 编写一段程序&#xff0c;实现下面的功能: (1)检查所有的两位数; (2)程序自动分析两位数上的个位与十位上的数字是否相同&#xff0c;相同则剔除&#xff0c; 不同则保留(例:12符合本要求&#xff0c;个位是2&#xff0c;十位是1&#xff0c;两…

what(): NCCL Error 1: unhandled cuda error解决方法

文章目录 遇到问题解决方法参考 遇到问题 运行项目&#xff1a;ACL2021的一篇工作&#xff0c;LM-BFF (Better Few-shot Fine-tuning of Language Models) https://github.com/princeton-nlp/LM-BFF 遇到环境问题。 我的机器环境如下&#xff1a; 服务器上CUDA版本为11.4 GPU…

常见的下载方式

一. 使用 window.open() 使用场景 // 1. 先封装一个实习下载的函数 export const download (path) > {window.open(下载的接口&#xff0c;例如&#xff1a;/fs/download?path path) } // 2. 使用&#xff1a;在需要下载的地方调用download函数&#xff0c;传入下载的u…

视频批量剪辑矩阵分发系统源码开源分享----基于PHP语言

批量剪辑视频矩阵分发&#xff1a; 短视频seo主要基于抖音短视频平台&#xff0c;为企业实现多账号管理&#xff0c;视频分发&#xff0c;视频批量剪辑&#xff0c;抖音小程序搭建&#xff0c;企业私域转化等&#xff0c;本文主要介绍短视频矩阵系统抖音小程序开发详细及注意事…

linux创建进程

linux创建进程 准备工作 准备工作 在Ubuntu64系统上 1、安装GCC和Make工具 编译器GCC&#xff1a;把C源码转为二进制程序 Make&#xff1a;自动编译多源文件项目 sudo apt-get update #更新存储库 sudo apt-get install build-essential #安装build-essential包 gcc --versio…

docker之 Consul(注册与发现)

目录 一、什么是服务注册与发现&#xff1f; 二、什么是consul 三、consul 部署 3.1建立Consul服务 3.1.1查看集群状态 3.1.2通过 http api 获取集群信息 3.2registrator服务器 3.2.1安装 Gliderlabs/Registrator 3.2.2测试服务发现功能是否正常 3.2.3验证 http 和 ng…

关于异数OS服务器CPU效能分析工具

该工具发布背景 近年来&#xff0c;国产服务器CPU产业的逐渐发展&#xff0c;但由于专业性较差&#xff0c;与国外存在40年以上技术差距&#xff0c;一些服务器CPU厂商利用信息差来制造一些非专业的数据夸大并虚假宣传混淆视听&#xff0c;成功达到劣币驱良币的目标&#xff0…

【论文笔记】最近看的时空数据挖掘综述整理8.27

Deep Learning for Spatio-Temporal Data Mining: A Survey 被引用次数&#xff1a;392 [Submitted on 11 Jun 2019 (v1), last revised 24 Jun 2019 (this version, v2)] 主要内容&#xff1a; 该论文是一篇关于深度学习在时空数据挖掘中的应用的综述。论文首先介绍了时空数…

react css 污染解决方法

上代码 .m-nav-bar {background: #171a21;.content {height: 104px;margin: 0px auto;} }import React from "react"; import styles from ./css.module.scssexport default class NavBar extends React.Component<any, any> {constructor (props: any) {supe…

数组(个人学习笔记黑马学习)

一维数组 1、定义方式 #include <iostream> using namespace std;int main() {//三种定义方式//1.int arr[5];arr[0] 10;arr[1] 20;arr[2] 30;arr[3] 40;arr[4] 50;//访问数据元素/*cout << arr[0] << endl;cout << arr[1] << endl;cout &l…

Redis怎么测试?

有些测试朋友来问我&#xff0c;redis要怎么测试&#xff1f;首先我们需要知道&#xff0c;redis是什么&#xff1f;它能做什么&#xff1f; redis是一个key-value类型的高速存储数据库。 redis常被用做&#xff1a;缓存、队列、发布订阅等。 所以&#xff0c;“redis要怎么…

web自动化框架:selenium学习使用操作大全(Python版)

目录 一、浏览器驱动下载二、selenium-python安装&#xff08;打开网站、操作元素&#xff09;三、网页解析&#xff08;HTML、xpath&#xff09;四、selenium基本操作1、元素定位八种方法2、元素动态定位3、iframe切换4、填充表单_填充文本框5、填充表单_单选按钮6、填充表单_…

山海优选卷轴模式源码实例分享

山海优选通过与绿色有机产品供应商和生产商的合作&#xff0c;建立起稳定的供应链关系&#xff0c;确保产品的绿色、有机、健康。通过产品认证和检测&#xff0c;为会员提供可信赖的绿色产品。积分激励机制设计 山海优选引入“绿色积分”机制&#xff0c;通过会员购买产品、参与…

docker 搭建私有仓库和制作镜像

目录 1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 1.1 启动mysql镜像 1.2 启动owncloud镜像 1.3 浏览器访问 1.4 总结 2、安装搭建私有仓库 Harbor 2.1 下载docker-compose并赋予执行权限 2.2 磁盘挂载&#xff0c;保存harbor 2.3 修改配置文件…

4G WiFi LoRa无线外夹式超声波管道流量计MQTT/http协议 json数据说明

ip&#xff1a;114.128.112.131 port&#xff1a;1883 uname&#xff1a;scwl_flowmeter pwd&#xff1a;b123 topic&#xff1a;iot/data/scwlflowmeter { “deviceId”:“设备序列号”, “flow”:“瞬时流量&#xff08;浮点数&#xff09;”, “heatFlow”:“瞬时热流量&am…

Web 自动化神器 TestCafe—页面高级操作篇

♥ 前 言 在【Web 自动化神器 TestCafe — 页面基本操作篇】这篇文章中我们介绍了TestCafe页面交互的一些基本使用 Web 自动化神器 TestCafe — 页面基本操作篇 这篇文章接着上一篇来给大家介绍一下 TestCafe 页面交互的一些高级操作。 一、鼠标拖拽 鼠标拖拽鼠标拖拽 …

JavaScript常见的运算符

一、运算符和运算元 1.认识运算符 在小学的时候我们就学习了各种运算符&#xff0c;比如加号 、乘号 *、减号 - 、除号/ 几乎所有的编程语言都有各种各样的运算符(也被称之为操作符&#xff0c;operators) 初次接触这些运算符, 你会感觉种类繁多, 难以记忆.但是并不需要特别…

Kotlin判断null比较let布尔值Boolean

Kotlin判断null比较let布尔值Boolean class MyData {val count: Int? 2023val number: Int? null }fun main(args: Array<String>) {val data MyData()val year 2022if (data.count ! null) {if (data.count > year) {println("data.count ! null")}}…