第二节:跨平台兼容/条件编译、页面路由(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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2023-01-09 20:47  Yaopengfei  阅读(534)  评论(2编辑  收藏  举报