uniApp 实战:setStorageSync 存储与 navigateTo 传递数组对象

在 uniApp 跨端开发中,数组对象的存储(如缓存用户列表、订单数据)与页面间传递(如列表页跳转详情页携带多条数据)是高频需求。uniApp 提供的 uni.setStorageSync 可实现本地缓存,uni.navigateTo 支持页面跳转传参,但直接传递数组对象会面临格式转换、数据丢失等问题。本文详解数组对象的缓存存储、跨页面传递技巧与避坑指南,附完整实战案例,帮助开发者快速落地功能。

一、核心原理与适用场景

1. 关键技术原理

  • uni.setStorageSync 存储限制:本地缓存仅支持存储字符串类型数据,数组对象需通过 JSON.stringify() 转为 JSON 字符串后存储,读取时用 JSON.parse() 解析回原格式;
  • uni.navigateTo 传参限制:URL 传参长度有限(通常不超过 2KB),且仅支持字符串 / 数字类型,数组对象需先序列化为 JSON 字符串,接收页再反序列化。

2. 典型应用场景

场景

技术选择

核心价值

缓存用户收藏列表

uni.setStorageSync + JSON 序列化

持久化存储,下次打开应用仍可用

列表页跳转详情页传递多条数据

uni.navigateTo + JSON 序列化

无需重复请求接口,直接传递完整数据

跨页面共享临时数组

缓存 + 页面传参结合

兼顾性能与数据完整性

二、实战一:uni.setStorageSync 存储数组对象

1. 核心步骤

  1. 定义数组对象(如订单列表、商品数据);
  1. 通过 JSON.stringify() 转为 JSON 字符串;
  1. 调用 uni.setStorageSync 存储到本地缓存;
  1. 读取时用 JSON.parse() 解析为原数组对象。

2. 完整代码实现


<template>

<view class="storage-demo">

<button @click="saveArray">存储订单数组</button>

<button @click="readArray" style="margin-top: 20rpx;">读取订单数组</button>

<view class="list" v-if="orderList.length">

<view class="list-item" v-for="(item, index) in orderList" :key="index">

<text>订单号:{{ item.orderNo }}</text>

<text>金额:{{ item.amount }} 元</text>

</view>

</view>

</view>

</template>

<script>

export default {

data() {

return {

orderList: [] // 存储读取后的订单数组

};

},

methods: {

// 存储数组对象到本地缓存

saveArray() {

// 1. 定义原始数组对象(模拟接口返回数据)

const originalOrders = [

{ orderNo: "LA20240520001", amount: 99, status: "已完成" },

{ orderNo: "LA20240520002", amount: 129, status: "洗护中" },

{ orderNo: "LA20240520003", amount: 69, status: "待接单" }

];

try {

// 2. 序列化:数组对象 → JSON 字符串

const ordersStr = JSON.stringify(originalOrders);

// 3. 存储到本地缓存(key 为自定义标识)

uni.setStorageSync("laundry_orders", ordersStr);

uni.showToast({ title: "存储成功" });

} catch (err) {

console.error("存储失败:", err);

uni.showToast({ title: "存储失败", icon: "none" });

}

},

// 从本地缓存读取数组对象

readArray() {

try {

// 1. 读取缓存的 JSON 字符串

const ordersStr = uni.getStorageSync("laundry_orders");

if (ordersStr) {

// 2. 反序列化:JSON 字符串 → 数组对象

this.orderList = JSON.parse(ordersStr);

uni.showToast({ title: `读取到 ${this.orderList.length} 条订单` });

} else {

uni.showToast({ title: "无缓存数据", icon: "none" });

}

} catch (err) {

console.error("读取失败:", err);

uni.showToast({ title: "读取失败", icon: "none" });

}

}

}

};

</script>

<style scoped>

.storage-demo {

padding: 20rpx;

}

button {

padding: 15rpx;

background-color: #2c3e50;

color: #fff;

border-radius: 8rpx;

}

.list {

margin-top: 30rpx;

}

.list-item {

padding: 20rpx;

border-bottom: 1px solid #eee;

display: flex;

justify-content: space-between;

font-size: 28rpx;

}

</style>

3. 关键注意事项

  • 异常捕获:存储 / 读取时需用 try-catch 包裹,避免 JSON 格式错误或缓存空间不足导致崩溃;
  • 数据类型限制:数组对象中不能包含 Function、Date 等无法序列化的类型(Date 可先转为时间戳存储);
  • 缓存上限:本地缓存总容量通常为 10MB,避免存储过大数组对象。

三、实战二:uni.navigateTo 传递数组对象

1. 核心步骤

  1. 列表页:数组对象 → JSON 字符串 → URL 编码(避免特殊字符导致传参失败);
  1. 跳转时通过 URL 传递序列化后的字符串;
  1. 详情页:接收 URL 参数 → URL 解码 → JSON 解析 → 还原数组对象。

2. 列表页(传参方)代码


<template>

<view class="list-page">

<view class="list-item" v-for="(item, index) in orderList" :key="index" @click="goToDetail(item)">

<text>订单号:{{ item.orderNo }}</text>

<text>状态:{{ item.status }}</text>

<uni-icons type="right" color="#ccc"></uni-icons>

</view>

</view>

</template>

<script>

export default {

data() {

return {

orderList: [

{ orderNo: "LA20240520001", amount: 99, status: "已完成", items: ["衬衫", "裤子"] },

{ orderNo: "LA20240520002", amount: 129, status: "洗护中", items: ["外套", "毛衣"] },

{ orderNo: "LA20240520003", amount: 69, status: "待接单", items: ["T恤", "袜子"] }

]

};

},

methods: {

goToDetail(order) {

try {

// 1. 序列化数组对象(此处单条订单对象,多条同理)

const orderStr = JSON.stringify(order);

// 2. URL 编码:解决特殊字符(如引号、空格)导致的传参失败

const encodeOrder = encodeURIComponent(orderStr);

// 3. 跳转页面并传递参数

uni.navigateTo({

url: `/pages/detail/detail?order=${encodeOrder}`

});

} catch (err) {

console.error("传参失败:", err);

uni.showToast({ title: "跳转失败", icon: "none" });

}

}

}

};

</script>

<style scoped>

.list-page {

padding: 20rpx;

}

.list-item {

padding: 20rpx;

border-bottom: 1px solid #eee;

display: flex;

justify-content: space-between;

align-items: center;

font-size: 28rpx;

}

</style>

3. 详情页(接收方)代码


<template>

<view class="detail-page">

<view class="detail-item">

<text class="label">订单号:</text>

<text class="value">{{ orderInfo.orderNo }}</text>

</view>

<view class="detail-item">

<text class="label">金额:</text>

<text class="value">{{ orderInfo.amount }} 元</text>

</view>

<view class="detail-item">

<text class="label">状态:</text>

<text class="value">{{ orderInfo.status }}</text>

</view>

<view class="detail-item">

<text class="label">洗护物品:</text>

<text class="value">{{ orderInfo.items.join("、") }}</text>

</view>

</view>

</template>

<script>

export default {

data() {

return {

orderInfo: {} // 接收后的订单详情

};

},

onLoad(options) {

// 页面加载时接收参数

this.getOrderData(options);

},

methods: {

getOrderData(options) {

try {

// 1. 接收 URL 参数并解码

const decodeOrder = decodeURIComponent(options.order);

// 2. 反序列化:JSON 字符串 → 数组对象

this.orderInfo = JSON.parse(decodeOrder);

} catch (err) {

console.error("解析参数失败:", err);

uni.showToast({ title: "数据加载失败", icon: "none" });

}

}

}

};

</script>

<style scoped>

.detail-page {

padding: 30rpx;

}

.detail-item {

margin-bottom: 30rpx;

font-size: 28rpx;

display: flex;

flex-direction: column;

}

.label {

color: #666;

margin-bottom: 10rpx;

font-size: 26rpx;

}

.value {

color: #333;

font-weight: 500;

}

</style>

四、进阶方案:缓存 + 传参结合(大数据量场景)

当数组对象较大(超过 2KB)时,直接通过 navigateTo 传参会导致数据截断,推荐采用 “缓存存储 + 传参标识” 方案:

1. 核心逻辑

  1. 列表页:将数组对象存储到本地缓存,生成唯一标识(如时间戳);
  1. 跳转时仅传递标识,不传递完整数据;
  1. 详情页:通过标识读取本地缓存中的数组对象。

2. 代码示例(列表页)


goToDetail(orderList) {

try {

// 1. 生成唯一标识(避免缓存覆盖)

const cacheKey = "order_list_" + Date.now();

// 2. 存储数组对象到缓存

uni.setStorageSync(cacheKey, JSON.stringify(orderList));

// 3. 跳转时仅传递缓存标识

uni.navigateTo({

url: `/pages/detail/detail?cacheKey=${cacheKey}`

});

} catch (err) {

console.error("跳转失败:", err);

}

}

3. 代码示例(详情页)


onLoad(options) {

const cacheKey = options.cacheKey;

// 读取缓存中的数组对象

const orderListStr = uni.getStorageSync(cacheKey);

const orderList = JSON.parse(orderListStr);

// 按需清理缓存(可选,避免占用空间)

uni.removeStorageSync(cacheKey);

}

五、关键优化与避坑指南

1. 核心优化点

  • URL 编码解码:必须使用 encodeURIComponent/decodeURIComponent 处理 JSON 字符串,避免引号、斜杠等特殊字符导致传参失败;
  • 数据清理:临时缓存的数据的在使用后通过 uni.removeStorageSync 清理,避免占用缓存空间;
  • 类型校验:解析后通过 typeof 或 Array.isArray 校验数据类型,防止解析失败导致页面报错。

2. 常见问题与解决方案

问题现象

原因分析

解决方案

传参后解析为 null

JSON 字符串格式错误或 URL 编码遗漏

确保序列化后无语法错误,传参前执行 URL 编码

数据截断 / 丢失

数组对象过大,超过 URL 传参限制

采用 “缓存 + 标识” 方案,避免直接传大数据

缓存覆盖

多个数组对象使用相同缓存 key

用时间戳、唯一 ID 生成动态 key

解析失败(Date 类型)

Date 对象无法被 JSON 序列化

先将 Date 转为时间戳或字符串,解析后还原

六、多端适配注意事项

  • App 端:本地缓存容量较大(通常 10-50MB),支持存储较大数组对象;
  • 微信小程序:缓存容量限制为 10MB,且 URL 传参长度限制更严格(建议不超过 1KB);
  • H5 端:缓存受浏览器限制,且跨域跳转时缓存不可共享,需谨慎使用。

总结

uniApp 中存储与传递数组对象的核心是 “JSON 序列化与反序列化”,uni.setStorageSync 负责持久化存储,uni.navigateTo 结合 URL 编码实现跨页面传递。简单场景可直接序列化传参,大数据量场景推荐 “缓存 + 标识” 方案,兼顾性能与数据完整性。实际开发中需注意异常捕获、特殊字符处理与多端适配,避免出现数据丢失、解析失败等问题。掌握该技巧可高效解决跨页面数据共享需求,提升应用开发效率与用户体验。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐