# key-value本地数据存储

app、小程序、web,均提供了方便的key-value模式的本地数据存储,通过键值对的方式存取数据。

uni-app的Storage在不同端的实现不同:

  • H5端为localStorage,浏览器限制5M大小,是缓存概念,可能会被清理
  • App端为原生storage,无大小限制,不是缓存,是持久化的
    • Android 端采用应用内SQLite数据库储存,储存位置为:/data/data/io.dcloud.uniappx(基座包名)/databases/DCStorage。
    • 真机运行基座下多个应用之间的storage是隔离的,同基座内的不同应用,对应一个数据库文件,但以表名区分。
  • 各个小程序端为其自带的storage api,数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。
    • 微信小程序单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
    • 支付宝小程序单条数据转换成字符串后,字符串长度最大200*1024。同一个支付宝用户,同一个小程序缓存总上限为10MB。
    • 百度小程序策略详见
    • 抖音小程序策略详见

注意

  • uni-uni_dcloud-dcloud_为前缀的key,为系统保留关键前缀。如uni_deviceIduni_id_token,请开发者为key命名时避开这些前缀。
  • 非App平台清空Storage会导致 uni.getSystemInfo/getDeviceInfo 获取到的deviceId改变

# uni.setStorage(options)

uni.setStorage函数定义 将数据存储在本地storage存储中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。

# setStorage 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
options SetStorageOptions - -
名称 类型 必备 默认值 兼容性 描述
key string - - 本地存储中的指定的 key
data any - - 需要存储的内容,只支持能通过 JSON.stringify 序列化的对象
success (res: SetStorageSuccess) => void - - uni.setStorage成功回调函数定义
fail (res: UniError) => void - - uni.setStorage失败回调函数定义
complete (res: any) => void - - uni.setStorage完成回调函数定义

# 参见

# uni.setStorageSync(key, data)

uni.setStorageSync函数定义 将 data 存储在本地storage存储中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。

# setStorageSync 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
key string - - 本地storage存储中的指定的 key
data any - - 需要存储的内容,只支持能通过 JSON.stringify 序列化的对象

WARNING

参数 data 为对象字面量时,需要通过 as UTSJSONObject 明确类型,例如:

uni.setStorageSync('obj', {"a": 1} as UTSJSONObject)

# 参见

# uni.getStorage(options)

uni.getStorage函数定义 从本地存储中异步获取指定 key 对应的内容。

# getStorage 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
options GetStorageOptions - -
名称 类型 必备 默认值 兼容性 描述
key string - - 本地存储中的指定的 key
success (res: GetStorageSuccess) => void - - uni.getStorage成功回调函数定义
fail (res: UniError) => void - - uni.getStorage失败回调函数定义
complete (res: any) => void - - uni.getStorage完成回调函数定义

# GetStorageSuccess 的属性值

名称 类型 必备 默认值 兼容性 描述
data any - - key 对应的内容

注意:

getStorageSync的返回值类型为any。因为set的时候任意类型都可以set进去。

使用any类型的数据需要as为正确的类型,才能调用类型上的方法。

对于简单类型,如string,只需要 as string。但对于复杂类型,比如 UTSJSONObject、type、class,需要参考获取复杂类型的数据章节,见下

注意:获取一个不存在的 key 会触发 fail 回调,返回错误信息为 "getStorage:fail data not found" 的错误。

# 参见

# uni.getStorageSync(key)

uni.getStorageSync函数定义 从本地存储中同步获取指定 key 对应的内容。

# getStorageSync 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
key string - - 本地存储中的指定的 key

# 返回值

类型 必备
any

注意:

getStorageSync的返回值类型为any。因为set的时候任意类型都可以set进去。

使用any类型的数据需要as为正确的类型,才能调用类型上的方法。

对于简单类型,如string,只需要 as string。但对于复杂类型,比如 UTSJSONObject、type、class,需要参考获取复杂类型的数据章节,见下

另注意,同步方法获取一个不存在的 key 会返回空字符串,而不是 null。如需准确判断是空字符串还是null,应该使用异步方法uni.getStorage

获取较大量的数据时,也推荐使用异步方法uni.getStorage,避免同步阻塞。

# 参见

# uni.getStorageInfo(options)

uni.getStorageInfo函数定义 异步获取当前 storage 的相关信息。

# getStorageInfo 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
options GetStorageInfoOptions - -
名称 类型 必备 默认值 兼容性 描述
success (res: GetStorageInfoSuccess) => void -
uni.getStorageInfo成功回调函数定义
fail (res: UniError) => void -
uni.getStorageInfo失败回调函数定义
complete (res: any) => void -
uni.getStorageInfo完成回调函数定义

# GetStorageInfoSuccess 的属性值

名称 类型 必备 默认值 兼容性 描述
keys Array<string> -
当前 storage 中所有的 key
currentSize number -
当前占用的空间大小, 单位:kb
limitSize number -
限制的空间大小, 单位:kb

# 参见

# uni.getStorageInfoSync()

uni.getStorageInfoSync函数定义 同步获取当前 storage 的相关信息。

# getStorageInfoSync 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 返回值

类型 描述
GetStorageInfoSuccess uni.getStorageInfo成功回调参数
名称 类型 必备 默认值 兼容性 描述
keys Array<string> -
当前 storage 中所有的 key
currentSize number -
当前占用的空间大小, 单位:kb
limitSize number -
限制的空间大小, 单位:kb

# 参见

# uni.removeStorage(options)

uni.removeStorage函数定义 从本地存储中异步移除指定 key。

# removeStorage 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
options RemoveStorageOptions - -
名称 类型 必备 默认值 兼容性 描述
key string -
本地存储中的指定的 key
success (res: RemoveStorageSuccess) => void -
uni.removeStorage成功回调函数定义
fail (res: UniError) => void -
uni.removeStorage失败回调函数定义
complete (res: any) => void -
uni.removeStorage完成回调函数定义

# 参见

# uni.removeStorageSync(key)

uni.removeStorageSync函数定义 从本地存储中同步移除指定 key。

# removeStorageSync 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
key string - - 本地存储中的指定的 key

# 参见

# uni.clearStorage(option?)

uni.clearStorage函数定义 清除本地数据存储。

# clearStorage 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参数

名称 类型 必填 默认值 兼容性 描述
option ClearStorageOptions - - uni.removeStorage参数定义
名称 类型 必备 默认值 兼容性 描述
success (res: ClearStorageSuccess) => void -
uni.clearStorage 成功回调函数定义
fail (res: UniError) => void -
uni.clearStorage 失败回调函数定义
complete (res: any) => void -
uni.clearStorage 完成回调函数定义

# 参见

# uni.clearStorageSync()

uni.clearStorageSync函数定义 清除本地数据存储。

# clearStorageSync 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9.0 4.11 4.61

# 参见

# 示例

hello uni-app x

扫码体验(手机浏览器跳转到App直达页)

Template

Script

<template>
  <!-- #ifdef APP -->
  <scroll-view class="page-scroll-view">
  <!-- #endif -->
    <view>
      <page-head :title="title"></page-head>
      <view class="uni-common-mt">
        <view class="uni-list">
          <view class="uni-list-cell uni-list-cell-line">
            <view class="uni-list-cell-left">
              <view class="uni-label">key</view>
            </view>
            <view class="uni-list-cell-db">
              <input class="uni-input" type="text" placeholder="请输入key" name="key" :value="key" maxlength="-1"
                @input="keyChange" />
            </view>
          </view>
          <view class="uni-list-cell">
            <view class="uni-list-cell-left">
              <view class="uni-label">value</view>
            </view>
            <view class="uni-list-cell-db">
              <input class="uni-input" type="text" placeholder="请输入value" name="data"
                :value="typeof data === 'string' ? data : JSON.stringify(data)" maxlength="-1" @input="dataChange" />
            </view>
          </view>
        </view>
        <view class="uni-padding-wrap">
          <view class="uni-btn-v">
            <button class="uni-btn btn-getStorageInfoASync" type="primary" @tap="getStorageInfo">
              获取存储概述信息-异步
            </button>
            <button class="uni-btn btn-getStorageInfoSync" @tap="getStorageInfoSync">
              获取存储概述信息-同步
            </button>
          </view>
          <text>{{ storageInfo }}</text>
          <view class="uni-flex uni-row">
            <button type="default" style="width:50%" @tap="strMock">
              填充字符串
            </button>
            <button type="default" style="width:50%" @tap="complexMock">
              填充复杂对象
            </button>
          </view>
          <view class="uni-flex uni-row">
            <button type="default" style="width:50%" @tap="numberMock">
              填充整型
            </button>
            <button type="default" style="width:50%" @tap="floatMock">
              填充浮点型
            </button>
          </view>
          <view class="uni-flex uni-row">
            <button type="default" style="width:50%" @tap="jsonLikeMock">
              填充json字符串
            </button>
            <button type="default" style="width:50%" @tap="longLikeMock">
              填充整数字符串
            </button>
          </view>
          <view class="uni-flex uni-row">
            <button type="default" style="width:50%" @tap="floatLikeMock">
              填充浮点字符串
            </button>
            <button type="default" style="width:50%" @tap="negativeLikeMock">
              填充负数字符串
            </button>
          </view>
          <view class="uni-flex uni-row">
            <button type="default" class="uni-btn btn-complexStaticTest" style="width:100%" @tap="complexStaticTest">
              字面量读写测试
            </button>
          </view>
        </view>
        <view class="uni-padding-wrap">
          <view class="uni-btn-v">
            <button type="primary" class="uni-btn btn-setstorageAsync" @tap="setStorage">
              存储数据-异步
            </button>
            <button class="uni-btn btn-getstorageAsync" @tap="getStorage">读取数据-异步</button>
            <button class="uni-btn btn-removeStorageInfoASync" @tap="removeStorage">移除数据-异步</button>
            <button class="uni-btn btn-clearStorageInfoASync" @tap="clearStorage">清理数据-异步</button>
          </view>

          <view class="uni-btn-v">
            <button type="primary" class="uni-btn btn-setstorageSync" @tap="setStorageSync">
              存储数据-同步
            </button>
            <button class="uni-btn btn-getstorageSync" @tap="getStorageSync">读取数据-同步</button>
            <button class="uni-btn btn-removeStorageInfoSync" @tap="removeStorageSync">
              移除数据-同步
            </button>
            <button class="uni-btn btn-clearStorageInfoSync" @tap="clearStorageSync">
              清理数据-同步
            </button>
          </view>
        </view>
      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>



<style>
</style>

# 通用类型

# GeneralCallbackResult

名称 类型 必备 默认值 兼容性 描述
errMsg string -
错误信息

# 类型数据的存取说明

首先明确一个原则,Storage实际储存到各终端文件系统的是序列化后的数据

也就是当我们使用setStorage/setStorageSync 储存一个带类型的数据时,插件内部会自动将其序列化为字符串后进行储存。当我们调用 getStorage/getStorageSync 插件内部也会尝试对字符串进行类型还原,分为以下几种情况:

# UTSJSONObject

如果是UTSJSONObject 类型,不会有类型的丢失

let json1 = {
	id:1001,
	name:"jack"
}

uni.setStorageSync("test-json",json1)
let json2 = uni.getStorageSync("test-json")
// json2 ‍[⁠UTSJSONObject⁠]‍ {id: 1001, name: "jack"}
console.log("json2",json2)

# type类型

如果是type类型,可以正常写入,但是当读取时得到是是UTSJSONObject类型,需要进行类型转换。

type User = {
	name:string,
	age:number
}
let u1 = {
	name : "张三",
	age:123
}
uni.setStorageSync("test-a",u1)
uni.getStorage({
	key:'test-a',
	success:function(res:GetStorageSuccess){
		// 此时只能得到的UTSJSONObject类型
		let jsonObject = res.data
		// 再次进行类型转换
		let userObject = JSON.parse<User>(JSON.stringify(jsonObject))
		// jsonObject ‍[⁠UTSJSONObject⁠]‍ {age: 123, name: "张三"}
		console.log("jsonObject",jsonObject)
		// userObject ‍[⁠User⁠]‍ {age: 123, name: "张三"}
		console.log("userObject",userObject)
	}
})

# 自定义class

还有一种情况,如果开发者使用class而非type定义类型,默认情况下无法读写的。

大多数情况下,我们更推荐使用type,而不是自定义class。 因为自定义class的行为在不同终端可能表现不一致。

class Person {
	// 声明属性类型(必须显式初始化或在构造函数中赋值)
	name: string;
	age: number;

	// 构造函数
	constructor(name: string, age: number) {
		this.name = name;
		this.age = age;
	}

	// 方法
	greet(): string {
		return `Hello, I'm ${this.name} and I'm ${this.age} years old.`;
	}
}

// 使用类
const alice = new Person("Alice", 30);
console.log(alice.greet()); // "Hello, I'm Alice and I'm 30 years old."

uni.setStorageSync("test-class-0",alice)
let dataObj = uni.getStorageSync("test-class-0")
// 此时只能得到空的UTSJSONObject {}
console.log("data",dataObj)

如果要支持读写,开发者需要实现 IJSONStringify接口。关于IJSONStringify的更多介绍

class Person implements IJSONStringify {
	// 声明属性类型(必须显式初始化或在构造函数中赋值)
	name: string;
	age: number;	  

	// 构造函数
	constructor(name: string, age: number) {
		this.name = name;
		this.age = age;
	}
	// 自定义序列化规则
	toJSON():any{
		let jsonRet = UTSJSONObject()
		jsonRet["name"] = this.name
		jsonRet["age"] = this.age
		return jsonRet
	}
	
	// 方法
	greet(): string {
		return `Hello, I'm ${this.name} and I'm ${this.age} years old.`;
	}
}

// 使用类
const alice = new Person("Alice", 30);
console.log(alice.greet()); // "Hello, I'm Alice and I'm 30 years old."

uni.setStorageSync("test-class-0",alice)
let dataObj = uni.getStorageSync("test-class-0")
// [⁠UTSJSONObject⁠]‍ {name: "Alice", age: 30}
console.log("dataObj",dataObj)
//  ‍[⁠Person⁠]‍ {age: 30, name: "Alice"}
let personObj = JSON.parse<Person>(JSON.stringify(dataObj))
console.log("personObj",personObj)

此时,我们就可以让自定义class实现类似自定义type的效果了。