uniapp页面间传递值的几种方式
使用参数传递
最常用,最简单的是使用参数进行值的传递:
https://uniapp.dcloud.net.cn/api/router.html#navigateto
比如uni.navigateTo,只需要在url中拼接页面所需要的参数即可。适用于大多数情况,适用于uni.reLaunch等等方法。
如 'path?key=value&key2=value2',path为下一个页面的路径,下一个页面的onLoad函数可得到传递的参数
比如我打开一个详情页,封装的方法:
export function goDetail(sid, nid) {
const url = `/pages/detail/detail?sid=${sid}&nid=${nid}`;
return new Promise((resolve, reject) => {
uni.navigateTo({
url: url,
animationType: 'pop-in',
animationDuration: 200,
success: function() {
resolve(true);
},
fail: function() {
reject(false);
}
});
});
}
以上方法就是在url中拼接detail页需要的sid和nid参数
比如在index.vue页:goDetail(sid, nid);
在detail.vue页中接收参数:
async onLoad(option) {
console.log(option.nid, option.sid);
// 使用异步方法请求接口数据 获得详细页的信息
this.detailObj = await getDetail(option.sid, option.nid);
// 设置标题
uni.setNavigationBarTitle({
title: this.detailObj.ntitle
});
},
在onload钩子中,可以获得上一个页面传递来的参数对象,option。但是这种方法不能用来传递过长的字符串,,以下为官网说明:
url有长度限制,太长的字符串会传递失败,可改用窗体通信(opens new window)、全局变量 (opens new window),另外参数中出现空格等特殊字符时需要对参数进行编码。
// A
<navigator :url="'/pages/test/test?item='+ encodeURIComponent(JSON.stringify(item))"></navigator>
// B
onLoad: function (option) {
const item = JSON.parse(decodeURIComponent(option.item));
}
使用events
当要传递的数据过长,比如不确定的网址、格式化的json的时候,就需要使用events的方法了。此方法初见于小程序,现在也支持APP的开发。官网解释:
events Object 页面间通信接口,用于监听被打开页面发送到当前页面的数据。2.8.9+ 开始支持。
比如,我将webview单独作为一个页面,且将打开webview页面封装成了一个方法。
webview页面:
<template>
<view class="web-view">
<web-view :webview-styles="webviewStyles"
:src="webUrl"
fullscreen="true"
></web-view>
</view>
</template>
<script>
export default {
name: 'webview',
data() {
return {
webUrl: '',
title: '',
webviewStyles: {
// 进度条
progress: {
color: '#FF3333'
}
}
}
},
//option为object类型,会序列化上个页面传递的参数
async onLoad() {
// #ifdef APP-NVUE
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
// #endif
// #ifndef APP-NVUE
const eventChannel = this.getOpenerEventChannel();
// #endif
// 监听eventChannel传递过来的事件
eventChannel.on('getData', data => {
this.webUrl = data.weburl;
this.title = data.title;
console.log(data);
});
},
watch: {
title(newval) {
if(newval) {
uni.setNavigationBarTitle({
title: newval
});
}
}
}
}
</script>
<style>
</style>
某处打开webview页面的方法:
opendetail(obj) {
goWebview(obj.weburl, obj.ntitle);
},
封装的webview方法:
export function goWebview(weburl, title = '') {
// 为避免url太长,使用events传递数据
const url = `/pages/webview/webview`;
return new Promise((resolve, reject) => {
uni.navigateTo({
url: url,
animationType: 'pop-in',
animationDuration: 200,
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
events:{},
success: function(res) {
res.eventChannel.emit('getData', {
weburl: weburl,
title: title
}) //触发事件
resolve(true);
},
fail: function() {
reject(false);
}
});
});
}
原理就是使用uni-app提供的eventChannel,当webview(B)页面打开成功后,向原页(A)发送成功的事件,A页面监听到事件后,再向B页面发送数据,如此便实现了AB页面之间的通信。
基本实现,可以参考:https://blog.csdn.net/a1441574/article/details/118959681
备忘
eventChannel 新增页面间通信接口,用于监听被打开页面发送到当前页面的数据 ; 需要基础 2.7.3 ,低版本肯定要做兼容处理。
**
A页面
* 例子中 eventChannel 为新增路由events事件
res 中可直接获取到实例 调用emit 触发事件,
类似vue中的组件间通信 on emit 方法;
之后我们在接收页面onLoad onShow 中获取监听
*/
uni.navigateTo({ //跳转页面
url: './afterSale',
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
events: {},
// 可以理解为当B页面打开成功后,向A发送了事件,success就代表了B页面打开成功
success: function (res) {
// A通过eventChannel向B页面发送getData事件
res.eventChannel.emit('getData', item)
}
})
/**
* B页面
* onLoad onShow 中通过
this.getOpenerEventChannel() 获取 eventChannel 实例
同时使用 on 方法进行监听接收传参数据
*/
onLoad: function(options) {
//接收页面 注意 这里应该使用兼容性写法
// #ifdef APP-NVUE
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
// #endif
// #ifndef APP-NVUE
const eventChannel = this.getOpenerEventChannel();
// #endif
/* const eventChannel = this.getOpenerEventChannel(); */
// 通过eventChannel监听A页面发来的信息
eventChannel.on("getData",data => {
console.log(data)
});
}
例子中 eventChannel 的只是部分能力的使用 , eventChannel 更多的功能可参考文档结合实际场景扩展使用,https://uniapp.dcloud.net.cn/api/router.html#navigateto。
使用encodeURIComponent
用法不再赘述 , 用到的方法容易理解 , 用法也简单:
//跳转页面
uni.navigateTo({
url: './afterSale?id=' + id + '&orderData=' + encodeURIComponent(JSON.stringify(item))
})
//接收页面
onLoad: function(options) {
const order = JSON.parse(decodeURIComponent(options.order));
console.log(order)
}
使用全局变量 globalData
https://uniapp.dcloud.net.cn/collocation/App.html#globaldata
全局数据globalData的设置、获取、修改:
http://t.zoukankan.com/hellocd-p-14255284.html
以下是 App.vue 中定义globalData的相关配置:
<script>
export default {
globalData: {
text: 'text'
}
}
</script>
js中操作globalData的方式如下:getApp().globalData.text = 'test'
在应用onLaunch时,getApp对象还未获取,暂时可以使用this.globalData获取globalData。
如果需要把globalData的数据绑定到页面上,可在页面的onShow页面生命周期里进行变量重赋值。
globalData是简单的全局变量,如果使用状态管理,请使用vuex
(main.js中定义)
修改globalData中的数据,也很简单:
getApp().globalData.car = 'xxxx';
使用Storage
使用此方法即是使用了APP的缓存,比如,将JSON转化为字符串后,存入storage中,使用的时候,再从缓存中取出。相关API如下:
https://uniapp.dcloud.net.cn/api/storage/storage.html#setstorage
比如,我在实现一个开屏广告时候,就用了此方法(开屏广告实现,可以点击此处):
// 存储信网开屏广告信息的键
export const KEY_POPING = '__xinPop__';
仅供参考的开屏广告接口信息:
{
loading: {
has: true,
type: "image",
title: "12中全会顺利闭幕",
bg_url: "http://statics.qdxin.cn/uploadfile/zt_imgh5/2022/04/d285023328caaec5156eeb9246bb9213.jpg",
link_mode: "browser",
link: "weixin://"
}
}
在app.vue中:
<script>
import { getSetting } from '@/api/get_api.js';
import { KEY_POPING } from '@/common/js/pop-loading.js';
export default {
onLaunch: async function() {
const setting = await getSetting();
// console.log(setting);
// 如果存在开屏广告 接口中定义的参数 仅参考
if(setting.loading.has) {
const objStr = JSON.stringify(setting.loading);
// 使用同步的方法,将对象转化为字符串,存入缓存
uni.setStorageSync(KEY_POPING, objStr);
// 不保留任何记录的跳转道开屏广告页,
uni.reLaunch({
url: '/pages/pop/pop',
success() {
// 关闭APP默认的等待界面
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen();
// #endif
}
})
} else {
// 如果没有开屏广告,直接跳到首屏
uni.reLaunch({
url:'/pages/index/index',
success() {
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen();
// #endif
}
});
}
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
在pop界面中,实现读取广告信息(此处省略):
const popStr = uni.getStorageSync(KEY_POPING);
const popObj = JSON.parse(popStr);
const url = encodeURI(popObj.link);
.....