uni-app 本地存储
核心知识点
本地存储 API
uni-app 提供了多种本地存储 API,包括同步和异步方法,用于在不同平台上实现数据的本地存储。
1. 同步方法
// 存储数据
uni.setStorageSync('key', 'value');
// 获取数据
const value = uni.getStorageSync('key');
// 删除数据
uni.removeStorageSync('key');
// 清空所有数据
uni.clearStorageSync();
// 获取所有键
const keys = uni.getStorageInfoSync().keys;2. 异步方法
// 存储数据
uni.setStorage({
key: 'key',
data: 'value',
success: () => {
console.log('存储成功');
},
fail: (err) => {
console.log('存储失败:', err);
}
});
// 获取数据
uni.getStorage({
key: 'key',
success: (res) => {
console.log('获取成功:', res.data);
},
fail: (err) => {
console.log('获取失败:', err);
}
});
// 删除数据
uni.removeStorage({
key: 'key',
success: () => {
console.log('删除成功');
},
fail: (err) => {
console.log('删除失败:', err);
}
});
// 清空所有数据
uni.clearStorage({
success: () => {
console.log('清空成功');
},
fail: (err) => {
console.log('清空失败:', err);
}
});
// 获取存储信息
uni.getStorageInfo({
success: (res) => {
console.log('存储键列表:', res.keys);
console.log('当前存储大小:', res.currentSize);
console.log('存储限制大小:', res.limitSize);
}
});数据持久化
确保数据在应用重启后仍然存在,实现数据的持久化存储。
1. 基本数据类型
对于字符串、数字、布尔值等基本数据类型,可以直接存储:
// 存储字符串
uni.setStorageSync('username', 'admin');
// 存储数字
uni.setStorageSync('age', 25);
// 存储布尔值
uni.setStorageSync('isLogin', true);2. 复杂数据类型
对于对象、数组等复杂数据类型,需要先转换为 JSON 字符串:
// 存储对象
const user = {
id: 1,
username: 'admin',
email: 'admin@example.com'
};
uni.setStorageSync('user', JSON.stringify(user));
// 获取对象
const storedUser = JSON.parse(uni.getStorageSync('user'));
console.log(storedUser.username); // 输出: admin
// 存储数组
const list = [1, 2, 3, 4, 5];
uni.setStorageSync('list', JSON.stringify(list));
// 获取数组
const storedList = JSON.parse(uni.getStorageSync('list'));
console.log(storedList.length); // 输出: 5缓存策略
设计合理的缓存策略,提高应用性能和用户体验。
1. 缓存过期时间
为缓存数据设置过期时间,定期清理过期数据:
// 存储带过期时间的数据
function setCacheWithExpire(key, data, expire = 3600000) {
const cacheData = {
data,
expire: Date.now() + expire
};
uni.setStorageSync(key, JSON.stringify(cacheData));
}
// 获取缓存数据
function getCacheWithExpire(key) {
const cached = uni.getStorageSync(key);
if (!cached) return null;
const cacheData = JSON.parse(cached);
if (Date.now() > cacheData.expire) {
// 缓存过期,删除数据
uni.removeStorageSync(key);
return null;
}
return cacheData.data;
}
// 使用示例
setCacheWithExpire('userList', [{ id: 1, name: '张三' }], 5 * 60 * 1000); // 5分钟过期
const userList = getCacheWithExpire('userList');2. 缓存大小管理
监控和管理缓存大小,避免超出平台限制:
// 检查缓存大小
function checkStorageSize() {
const info = uni.getStorageInfoSync();
console.log(`当前存储大小: ${info.currentSize}KB`);
console.log(`存储限制大小: ${info.limitSize}KB`);
// 当存储大小超过限制的 80% 时,清理过期数据
if (info.currentSize > info.limitSize * 0.8) {
clearExpiredCache();
}
}
// 清理过期数据
function clearExpiredCache() {
const info = uni.getStorageInfoSync();
info.keys.forEach(key => {
const cached = uni.getStorageSync(key);
try {
const cacheData = JSON.parse(cached);
if (cacheData.expire && Date.now() > cacheData.expire) {
uni.removeStorageSync(key);
console.log(`清理过期缓存: ${key}`);
}
} catch (e) {
// 非 JSON 格式数据,跳过
}
});
}
// 定期检查缓存大小
setInterval(checkStorageSize, 5 * 60 * 1000); // 每5分钟检查一次3. 缓存键命名规范
使用统一的缓存键命名规范,方便管理和维护:
// 缓存键命名规范
const CACHE_KEYS = {
USER_INFO: 'user_info',
TOKEN: 'token',
USER_SETTINGS: 'user_settings',
SEARCH_HISTORY: 'search_history',
CACHE_PREFIX: 'cache_',
// 生成带前缀的缓存键
generateKey: function(key) {
return this.CACHE_PREFIX + key;
}
};
// 使用示例
uni.setStorageSync(CACHE_KEYS.USER_INFO, JSON.stringify(userInfo));
const userInfo = JSON.parse(uni.getStorageSync(CACHE_KEYS.USER_INFO));
// 生成带前缀的缓存键
const cacheKey = CACHE_KEYS.generateKey('api_data_' + Date.now());
uni.setStorageSync(cacheKey, JSON.stringify(apiData));实用案例
实现用户登录状态管理
1. 登录状态存储
// utils/auth.js
// 存储登录状态
export function saveLoginState(userInfo, token) {
try {
uni.setStorageSync('userInfo', JSON.stringify(userInfo));
uni.setStorageSync('token', token);
uni.setStorageSync('isLogin', true);
return true;
} catch (error) {
console.error('存储登录状态失败:', error);
return false;
}
}
// 获取登录状态
export function getLoginState() {
try {
const isLogin = uni.getStorageSync('isLogin');
const userInfo = uni.getStorageSync('userInfo');
const token = uni.getStorageSync('token');
if (isLogin && userInfo && token) {
return {
isLogin: true,
userInfo: JSON.parse(userInfo),
token
};
}
return { isLogin: false };
} catch (error) {
console.error('获取登录状态失败:', error);
return { isLogin: false };
}
}
// 清除登录状态
export function clearLoginState() {
try {
uni.removeStorageSync('userInfo');
uni.removeStorageSync('token');
uni.removeStorageSync('isLogin');
return true;
} catch (error) {
console.error('清除登录状态失败:', error);
return false;
}
}
// 检查登录状态
export function checkLogin() {
const loginState = getLoginState();
if (!loginState.isLogin) {
uni.showToast({
title: '请先登录',
icon: 'none'
});
uni.navigateTo({
url: '/pages/login/login'
});
return false;
}
return true;
}2. 登录页面
<template>
<view class="login-container">
<view class="form-item">
<text>用户名</text>
<input v-model="username" placeholder="请输入用户名" />
</view>
<view class="form-item">
<text>密码</text>
<input v-model="password" type="password" placeholder="请输入密码" />
</view>
<button class="login-button" @click="login">登录</button>
<button class="logout-button" @click="logout" v-if="isLogin">退出登录</button>
</view>
</template>
<script>
import { saveLoginState, clearLoginState, getLoginState } from '../../utils/auth';
import request from '../../utils/request';
export default {
data() {
return {
username: '',
password: '',
isLogin: false
};
},
onLoad() {
// 检查登录状态
const loginState = getLoginState();
this.isLogin = loginState.isLogin;
},
methods: {
async login() {
if (!this.username || !this.password) {
uni.showToast({
title: '请输入用户名和密码',
icon: 'none'
});
return;
}
try {
const res = await request.post('/login', {
username: this.username,
password: this.password
});
// 保存登录状态
const success = saveLoginState(res.user, res.token);
if (success) {
this.isLogin = true;
uni.showToast({
title: '登录成功',
icon: 'success'
});
uni.switchTab({
url: '/pages/index/index'
});
} else {
uni.showToast({
title: '登录失败,请重试',
icon: 'none'
});
}
} catch (error) {
console.error('登录失败:', error);
uni.showToast({
title: '登录失败,请检查账号密码',
icon: 'none'
});
}
},
logout() {
const success = clearLoginState();
if (success) {
this.isLogin = false;
uni.showToast({
title: '退出登录成功',
icon: 'success'
});
} else {
uni.showToast({
title: '退出登录失败',
icon: 'none'
});
}
}
}
};
</script>
<style scoped>
.login-container {
padding: 40rpx;
}
.form-item {
margin-bottom: 30rpx;
}
.form-item text {
display: block;
margin-bottom: 10rpx;
font-size: 28rpx;
color: #333;
}
.form-item input {
width: 100%;
height: 80rpx;
border: 1rpx solid #e5e5e5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.login-button {
width: 100%;
height: 80rpx;
background-color: #007aff;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
margin-top: 40rpx;
}
.logout-button {
width: 100%;
height: 80rpx;
background-color: #ff3b30;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
margin-top: 20rpx;
}
</style>3. 全局登录状态检查
在 App.vue 中检查登录状态:
<script>
import { getLoginState } from './utils/auth';
export default {
onLaunch() {
console.log('App Launch');
// 检查登录状态
const loginState = getLoginState();
if (loginState.isLogin) {
console.log('用户已登录:', loginState.userInfo.username);
// 可以在这里执行登录后的初始化操作
} else {
console.log('用户未登录');
}
},
onShow() {
console.log('App Show');
},
onHide() {
console.log('App Hide');
}
};
</script>
<style>
/* 全局样式 */
page {
background-color: #f5f5f5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
</style>实现搜索历史管理
<template>
<view class="search-container">
<view class="search-bar">
<input v-model="keyword" placeholder="请输入搜索关键词" />
<button class="search-button" @click="search">搜索</button>
</view>
<view class="history-section" v-if="searchHistory.length > 0">
<view class="history-header">
<text>搜索历史</text>
<button class="clear-button" @click="clearHistory">清空</button>
</view>
<view class="history-tags">
<view class="tag" v-for="(item, index) in searchHistory" :key="index" @click="selectHistory(item)">
{{ item }}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
keyword: '',
searchHistory: []
};
},
onLoad() {
// 获取搜索历史
this.getSearchHistory();
},
methods: {
search() {
if (!this.keyword.trim()) return;
// 执行搜索操作
console.log('搜索:', this.keyword);
// 保存搜索历史
this.saveSearchHistory(this.keyword.trim());
// 跳转到搜索结果页面
uni.navigateTo({
url: `/pages/search-result/search-result?keyword=${encodeURIComponent(this.keyword)}`
});
},
// 获取搜索历史
getSearchHistory() {
const history = uni.getStorageSync('searchHistory');
if (history) {
this.searchHistory = JSON.parse(history);
}
},
// 保存搜索历史
saveSearchHistory(keyword) {
// 去重,将新关键词放在最前面
let history = uni.getStorageSync('searchHistory');
if (history) {
history = JSON.parse(history);
// 移除重复项
history = history.filter(item => item !== keyword);
} else {
history = [];
}
// 添加到开头
history.unshift(keyword);
// 限制历史记录数量
if (history.length > 10) {
history = history.slice(0, 10);
}
// 保存到本地存储
uni.setStorageSync('searchHistory', JSON.stringify(history));
this.searchHistory = history;
},
// 清空搜索历史
clearHistory() {
uni.removeStorageSync('searchHistory');
this.searchHistory = [];
},
// 选择历史记录
selectHistory(item) {
this.keyword = item;
this.search();
}
}
};
</script>
<style scoped>
.search-container {
padding: 20rpx;
}
.search-bar {
display: flex;
margin-bottom: 30rpx;
}
.search-bar input {
flex: 1;
height: 80rpx;
border: 1rpx solid #e5e5e5;
border-radius: 8rpx 0 0 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
background-color: #fff;
}
.search-button {
width: 120rpx;
height: 80rpx;
background-color: #007aff;
color: #fff;
border-radius: 0 8rpx 8rpx 0;
font-size: 28rpx;
}
.history-section {
margin-top: 20rpx;
}
.history-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.history-header text {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.clear-button {
font-size: 24rpx;
color: #999;
background-color: transparent;
}
.history-tags {
display: flex;
flex-wrap: wrap;
}
.tag {
padding: 10rpx 20rpx;
background-color: #f0f0f0;
border-radius: 16rpx;
font-size: 24rpx;
margin-right: 10rpx;
margin-bottom: 10rpx;
}
</style>学习目标
通过本集的学习,你应该能够:
- 掌握 uni-app 本地存储 API 的使用方法,包括同步和异步方法
- 学会存储和获取不同类型的数据,包括基本数据类型和复杂数据类型
- 熟悉数据持久化的实现方法,确保数据在应用重启后仍然存在
- 掌握缓存策略的设计方法,包括缓存过期时间、缓存大小管理和缓存键命名规范
- 能够通过实用案例实现用户登录状态管理和搜索历史管理等功能
小结
本地存储是 uni-app 开发中的重要部分,合理的本地存储策略可以提高应用的性能和用户体验。通过本集的学习,你已经掌握了本地存储 API、数据持久化、缓存策略等核心知识点,并通过实际案例了解了如何实现用户登录状态管理和搜索历史管理。在后续的开发中,你可以根据实际需求,灵活运用这些知识,构建更加功能强大的应用。