第二节:跨平台兼容/条件编译、页面路由(pages.json)、页面通讯(5种)、生命周期(应用/页面/组件)
一. 跨平台兼容/条件编译
(详见官网:https://uniapp.dcloud.net.cn/tutorial/platform.html )
1. 跨平台兼容
uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。
但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
- 大量写 if else,会造成代码执行性能低下和管理混乱。
- 编译到不同的工程后二次修改,会让后续升级变的很麻烦。
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 uni-app
参考这个思路,为 uni-app
提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
2. 条件编译
(1). 目的
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
(2). 写法
以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。
- #ifdef: if defined 仅在某平台存在
- #ifndef:if not defined 除了某平台均存在
- %PLATFORM%:平台名称,具体有哪些值,详见官网
3. 支持的文件
- .vue
- .js
- .css
- pages.json
- 各预编译语言文件,如:.scss、.less、.stylus、.ts、.pug
特别注意:
在不同的文件中对应的注释写法不同,js使用 // 注释
、css 使用 /* 注释 */
、vue/nvue 模板里使用 <!-- 注释 -->
4. 快捷键编写
选中要条件编译的代码,ctrl + alt + /, 自动把选中的代码添加条件编译注释。
二. 页面路由(pages.json)
(详见官网:https://uniapp.dcloud.net.cn/collocation/pages.html)
1. 主要用途
pages.json
文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等
2. 核心功能
三. 页面通讯(5种)
1. url传递 和 EventChannel
(1). url传递 + onLoad中接收( 或者 props接收)
页面传值:
//在起始页面跳转到test.vue页面并传递参数
uni.navigateTo({url: 'test?id=1&name=uniapp'});
页面接收:
<script setup>
import { onLoad } from '@dcloudio/uni-app';
onLoad((option) => {
//option为object类型,会序列化上个页面传递的参数
console.log(option.id); //打印出上个页面传递的参数。
console.log(option.name); //打印出上个页面传递的参数。
});
</script>
Props接收
<script setup>
//方式二: ?id=1&name=uniapp
const props = defineProps({
id: String
name: String,
});
console.log('在props中接受home传递过来url的数据:', props.name, props.id);
</script>
注:
url有长度限制,太长的字符串会传递失败,可改事件总线、全局变量,
另外参数中出现空格等特殊字符时需要对参数进行编码,如下为使用encodeURIComponent
对参数进行编码的示例。
<navigator :url="'/pages/test/test?item='+ encodeURIComponent(JSON.stringify(item))"></navigator>
接收:
// 在test.vue页面接受参数
onLoad: function (option) {
const item = JSON.parse(decodeURIComponent(option.item));
}
(2). EventChannel
起始页面 home.vue:
// 起始页面home.vue
// 在起始页面home.vue跳转到test.vue页面,并监听test.vue发送过来的事件数据
uni.navigateTo({
url: 'pages/test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'data from starter page' })
}
})
跳转过去的页面 test.vue:
OptionApi写法
// 跳转到的页面test.vue
// 在test.vue页面,向起始页通过事件传递数据
onLoad: function(option) {
const eventChannel = this.getOpenerEventChannel();
//1. 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
//2. 向上一个页面回传数据
eventChannel.emit('acceptDataFromOpenedPage', {data: 'data from test page'});
eventChannel.emit('someEvent', {data: 'data from test page for someEvent'});
}
compositionApi写法
// 跳转到的页面test.vue
// 在test.vue页面,向起始页通过事件传递数据
<script setup>
import { ref, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const { proxy } = getCurrentInstance();
onLoad(options => {
const eventChanne = proxy.getOpenerEventChannel();
//1. 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
//2. 向上一个页面回传数据
eventChannel.emit('acceptDataFromOpenedPage', {data: 'data from test page'});
eventChannel.emit('someEvent', {data: 'data from test page for someEvent'});
});
</script>
剖析:
(1). home页面在success中通过 res.eventChannel.emit('acceptDataFromOpenerPage', xxx)传递数据,在test.vue页面里,通过 eventChannel.on('acceptDataFromOpenerPage',(data)=>{}); 接收数据
(2). 在test.vue页面里通过 eventChannel.emit('acceptDataFromOpenedPage', {data: 'data from test page'}); 回传数据, 在home.vue页面里的events对象下,声明acceptDataFromOpenedPage函数,进行接收数据。
2. 使用事件总线
(详见官网:https://uniapp.dcloud.net.cn/api/window/communication.html)
(1). API介绍
A. uni.$emit(eventName,OBJECT) :触发全局的自定义事件,附加参数都会传给监听器回调函数。
uni.$emit('update',{msg:'页面更新'})
B. uni.$on(eventName,callback):监听全局的自定义事件,事件由 uni.$emit
触发,回调函数会接收事件触发函数的传入参数。
uni.$on('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
C. uni.$once(eventName,callback) :监听全局的自定义事件,事件由 uni.$emit
触发,但仅触发一次,在第一次触发之后移除该监听器。
uni.$once('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
D. uni.$off([eventName, callback]):移除全局自定义事件监听器。
剖析:
(2). 注意事项
A. uni.$emit、 uni.$on 、 uni.$once 、uni.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue 等
B. 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni.$on 注册监听,onUnload 里边 uni.$off 移除,或者一次性的事件,直接使用 uni.$once 监听
C. uni.$on 定义完成后才能接收到 uni.$emit 传递的数据 (即:需先监听,再触发事件,比如:你在A界面触发,然后跳转到B页面后才监听是不行的。) 【重点!!!】
3. 全局数据 globalData
(详见官网:https://uniapp.dcloud.net.cn/collocation/App.html#globaldata)
4. 本地缓存
(详见官网:https://uniapp.dcloud.net.cn/api/storage/storage.html#)
常用API:
//1. 设置缓存
uni.setStorageSync('storage_key', 'hello');
//2. 读取缓存
const value = uni.getStorageSync('storage_key');
//3. 获取缓存相关信息
const res = uni.getStorageInfoSync();
console.log(res.keys); //当前 storage 中所有的 key
console.log(res.currentSize); //当前占用的空间大小, 单位:kb
console.log(res.limitSize); //限制的空间大小, 单位:kb
//4. 移除单个缓存
uni.removeStorageSync('storage_key');
//5. 清空所有缓存
uni.clearStorageSync();
5. 状态管理库 Vuex 或 pinia
vuex详见官网:https://uniapp.dcloud.net.cn/tutorial/vue3-vuex.html
pinia详见官网: https://uniapp.dcloud.net.cn/tutorial/vue3-pinia.html
下面仅分享uni-app中注册pinia的代码,至于如何使用,详见pinia的文章:https://www.cnblogs.com/yaopengfei/p/17053053.html
uni-app中默认内置了pinia,所以不需要单独安装。
import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';
export function createApp() {
const app = createSSRApp(App);
app.use(Pinia.createPinia());
return {
app,
Pinia, // 此处必须将 Pinia 返回
};
}
四. 生命周期(应用/页面/组件)
1. 应用生命周期
(详见官网:https://uniapp.dcloud.net.cn/collocation/App.html)
应用生命周期仅可在App.vue
中监听,在页面监听无效。
代码如下:这里不要改为 CompositionApi
<script>
export default {
onLaunch: function() {
// console.log('App Launch');
},
onShow: function() {
// console.log('App Show');
},
onHide: function() {
// console.log('App Hide');
},
};
</script>
2. 页面生命周期
(详见:https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle)
部分如下:其它详见官网
注:
(1). 页面中是可以使用vue的生命周期来替代的。
(2). onReachBottom
使用注意 可在pages.json里定义具体页面底部的触发距离onReachBottomDistance,比如设为50,那么滚动页面到距离底部50px时,就会触发onReachBottom事件。
如使用scroll-view导致页面没有滚动,则触底事件不会被触发。scroll-view滚动到底部的事件请参考scroll-view的文档
代码分享:
<script setup>
// 页面的生命周期
import {onLoad,onShow,onReady} from '@dcloudio/uni-app'
onLoad(() => {
console.log('buton-setup onLoad');
})
onShow(() => {
console.log('buton-setup onShow');
})
onReady(() => {
console.log('buton-setup onReady');
})
</script>
3. 组件生命周期
uni-app
组件支持的生命周期,与vue标准组件的生命周期相同。
注:
在Options API 语法:组件中不支持使用页面生命周期。
在Composition API语法:组件中支持页面生命周期,不同端支持情况有差异。
代码分享:
<script setup>
// 组件的生命周期
import { onBeforeMount, onMounted } from 'vue'
onBeforeMount(() => {
console.log('onBeforeMount');
})
onMounted(() => {
console.log('onMounted');
})
</script>
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。