Skip to content

Cordova - 存储

Cordova 应用程序可以利用各种客户端存储机制在设备本地存储数据。这使得离线功能成为可能,通过缓存数据提高性能,并允许保存用户偏好设置。本教程重点介绍 localStorage,一种简单的键值对存储方式,并简要提及其他选项。

localStorage 是 Web Storage API 的一部分,在所有现代 Web 视图中都可用。它允许您将数据存储为键值对(key-value pairs),其中键(key)和值(value)都是字符串。

在 www/index.html 中,创建与 localStorage 交互的按钮和一个 div 用于显示存储的数据或消息。

<body>
<h1>localStorage Demo</h1>
<input type="text" id="dataKey" placeholder="Enter Key (e.g., userTheme)">
<input type="text" id="dataValue" placeholder="Enter Value (e.g., dark)">
<br><br>
<button id="setItemBtn">SET Item</button>
<button id="getItemBtn">GET Item by Key</button>
<button id="removeItemBtn">REMOVE Item by Key</button>
<button id="listAllBtn">LIST All Items</button>
<button id="clearAllBtn">CLEAR All Storage</button>
<div id="storageOutput" style="margin-top: 20px; border: 1px solid #ccc; padding: 10px;">
Storage data will appear here...
</div>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</body>

在 www/js/index.js 中,直接访问 localStorage。它立即可用,不需要等待 deviceready 事件(尽管您的应用程序逻辑可能需要)。

// No 'deviceready' needed for localStorage itself, but good practice for app structure.
// localStorage 本身不需要 deviceready,但这对于应用程序结构而言是个好的实践。
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
console.log('Device is ready. localStorage is available.');
console.log('设备已就绪。localStorage 可用。');
const keyInput = document.getElementById('dataKey');
const valueInput = document.getElementById('dataValue');
const outputDiv = document.getElementById('storageOutput');
document.getElementById('setItemBtn').addEventListener('click', () => {
const key = keyInput.value.trim();
const value = valueInput.value.trim();
if (key && value) {
// For non-string data, serialize to JSON
// 对于非字符串数据,需要序列化为 JSON
// For this example, we assume simple strings or let users manage JSON manually.
// 在本示例中,我们假设使用简单字符串或让用户手动处理 JSON。
localStorage.setItem(key, value);
outputDiv.textContent = `Item set: ${key} = ${value}`;
console.log(`localStorage.setItem: ${key} = ${value}`);
} else {
outputDiv.textContent = 'Please provide both key and value.';
outputDiv.textContent = '请提供键和值。';
}
});
document.getElementById('getItemBtn').addEventListener('click', () => {
const key = keyInput.value.trim();
if (key) {
const value = localStorage.getItem(key);
if (value !== null) {
outputDiv.textContent = `Item found: ${key} = ${value}`;
console.log(`localStorage.getItem(${key}): ${value}`);
} else {
outputDiv.textContent = `Item with key '${key}' not found.`;
outputDiv.textContent = `未找到键为 '${key}' 的项。`;
console.log(`localStorage.getItem(${key}): null`);
}
} else {
outputDiv.textContent = 'Please provide a key to retrieve.';
outputDiv.textContent = '请提供要检索的键。';
}
});
document.getElementById('removeItemBtn').addEventListener('click', () => {
const key = keyInput.value.trim();
if (key) {
localStorage.removeItem(key);
outputDiv.textContent = `Item with key '${key}' removed (if it existed).`;
outputDiv.textContent = `已移除键为 '${key}' 的项(如果存在)。`;
console.log(`localStorage.removeItem: ${key}`);
} else {
outputDiv.textContent = 'Please provide a key to remove.';
outputDiv.textContent = '请提供要移除的键。';
}
});
document.getElementById('listAllBtn').addEventListener('click', () => {
outputDiv.innerHTML = '<h3>All localStorage Items:</h3>';
outputDiv.innerHTML = '<h3>所有 localStorage 项:</h3>';
if (localStorage.length === 0) {
outputDiv.innerHTML += '<p>localStorage is empty.</p>';
outputDiv.innerHTML += '<p>localStorage 为空。</p>';
return;
}
const ul = document.createElement('ul');
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
const li = document.createElement('li');
li.textContent = `${key}: ${value}`;
ul.appendChild(li);
}
outputDiv.appendChild(ul);
console.log('localStorage contents:', localStorage);
console.log('localStorage 内容:', localStorage);
});
document.getElementById('clearAllBtn').addEventListener('click', () => {
localStorage.clear();
outputDiv.textContent = 'All items cleared from localStorage.';
outputDiv.textContent = 'localStorage 中的所有项已清除。';
console.log('localStorage.clear() executed.');
console.log('localStorage.clear() 已执行。');
});
}
方法描述
setItem(key, value)添加或更新一个键值对。key 和 value 都会被转换为字符串。
getItem(key)检索与 key 关联的值。如果 key 不存在,则返回 null。
removeItem(key)移除与 key 关联的键值对。
key(index)返回给定整数索引处的键名。键的顺序不保证固定,可能因浏览器引擎而异。请勿依赖此顺序。
length (property)返回存储的键值对数量。
clear()移除所有键值对。
  • 仅限字符串数据: localStorage 将所有数据存储为字符串。如果需要存储对象或数组,必须先将它们序列化为 JSON 字符串(例如,使用 JSON.stringify()),然后在检索后进行解析(使用 JSON.parse())。
  • 同步: localStorage 操作是同步的,这意味着它们会阻塞主线程。对于复杂的数据或频繁的操作,这可能会影响性能。对于要求更高的场景,请考虑使用异步替代方案。
  • 存储限制: localStorage 有存储限制,通常每个源(origin)约为 5-10MB,具体可能因浏览器/WebView 而异。
  • 安全性: localStorage 中的数据未加密,可以被同一源上运行的任何脚本访问。请勿直接存储敏感信息,如密码或令牌。
  • 持久性: localStorage 中的数据会一直存在,直到被应用程序或用户(例如,通过清除浏览器数据)明确清除为止。即使应用程序更新,数据也不会被清除。
  • 键的顺序: 如前所述,localStorage.key(index) 不保证特定的顺序。如果顺序很重要,请自行管理(例如,存储一个键数组)。

虽然 localStorage 对于简单数据很方便,但 Cordova 应用程序也可以使用更高级的存储解决方案:

  • sessionStorage: 类似于 localStorage,但数据在会话结束时(例如,应用程序关闭时)会被清除。通常不用于移动应用程序中的持久性数据。
  • IndexedDB: 一个更强大、异步、支持事务的 NoSQL 数据库,内置于现代浏览器/Web 视图中。适用于存储大量结构化数据。直接使用可能很复杂;PouchDB 或 Dexie.js 等库可以简化其使用。
  • WebSQL (已废弃): 一个较旧的 API,提供 SQL 数据库访问。它已被废弃,不推荐用于新项目。支持不一致。
  • 用于存储的 Cordova 插件:
    • cordova-sqlite-storage: 提供原生 SQLite 数据库访问。非常适合关系型数据、大型数据集和复杂查询。操作是异步的。
    • cordova-plugin-nativestorage: 提供原生、异步的键值存储,对于某些用例(尤其是在某些平台上)可能比 localStorage 性能更好或更健壮。适用于偏好设置和少量数据。
    • cordova-plugin-file: 用于在设备的文件系统中以文件形式存储数据。适用于二进制数据、大型 Blob 或用户生成的文件。

最佳的存储选择取决于您应用程序的需求:

  • 简单的键值对、少量数据、非敏感的用户偏好设置: localStorage 可能足够。
  • 较大的结构化数据、离线功能、复杂查询: IndexedDB(配合辅助库)或 cordova-sqlite-storage。
  • 存储文件(图像、文档等): cordova-plugin-file。
  • 改进的异步键值存储: cordova-plugin-nativestorage。

对于更高级的存储需求,请查阅上述插件及其文档。理解简单性、性能、存储容量和数据结构能力之间的权衡是关键。