# NativeScript 应用程序中的客户端存储
在研究我想创建(并撰写!)的新 NativeScript-Vue 演示的大纲时,我发现了我尚未探索的 NativeScript 开发的另一个方面-客户端存储。我非常了解在 Web 应用程序中将数据存储在客户端上的各种方式,但是我还没有研究 NativeScript 支持什么。在本文中,我将讨论您可以做什么,显示一些示例,并对它们与标准 Web API 的关系进行比较。是的,将会有一个猫演示。
# 网络存储
尽管一段时间以来,浏览器一直在不断变化,但浏览器已经能够在客户端上存储数据了一段时间。从广义上讲,并且忽略了我们不会谈论的过时技术,网络存储归结为两种核心技术:
- Web 存储(通常称为本地存储)是一种用于存储少量数据的简单“键/值”系统。当与大量数据一起使用时,它存在性能问题,但是我认为这是对技术的不当使用,而并不是规范本身的失败。它非常易于使用,非常适合诸如保存表格,购物车和用户首选项之类的事情。
- IndexedDB 的是不是一个简单的 API,但对于大数据进行搜索和过滤的需求更加合适。大致上,您可以将其与 MongoDB 和其他 NoSQL 类型的解决方案进行比较。
两者都有令人难以置信的良好支持。据 CanIUse 称,对网络存储的支持在所有浏览器中的支持率接近 97%,而 IndexedDB 的支持率接近 96%。显然,这些技术都不能替代“真正的”企业级存储服务器,但是它们都通过允许浏览器在页面视图上保留和持久保存数据,在存储数据和提高性能方面都非常有用。
# 用 NativeScript 存储
因此,我已经清楚地表明,我是从 Web 开发人员的角度进入 NativeScript 的,当我计划下一个演示应用程序时,我什至没有考虑存储方面的问题,因为我只是假设这是基于我的观点而定的。网站开发经验。当我意识到必须真正弄清楚我要用什么时,我迅速停下了脚步。幸运的是,我发现了多种存储数据的有用方法,这些方法实际上与我现有的知识非常相似。
# 使用 ApplicationSettings 保持简单
NativeScript 应用程序最简单的存储选项是 ApplicationSettings。如果您熟悉本地存储,则可以轻松使用此功能。与本地存储类似,ApplicationSettings 用于通过键名存储简单值。该 API 支持:
- 设定值(duh)
- 获取价值(当然)
- 检查值是否存在
- 删除值
- 删除所有内容
- 如果需要较低级别的访问,还可以提供对 ApplicationSettings 包装的基础本机 API 的快速访问
ApplicationSettings 唯一真正的“复杂性”是存在用于处理布尔值,字符串和数字值的单独的 API。让我们来看一个实际的令人难以置信的简单示例。
以下应用程序将仅跟踪其打开次数。琐碎,但实际上可能是您想要跟踪的一种很酷的指标。这是初始模板。
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar" />
<ScrollView>
<StackLayout class="home-panel">
<!--Add your page content here-->
<Label textWrap="true" :text="numberOfVisits" />
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
export default {
data () {
return {
hits:0
};
},
computed:{
numberOfVisits() {
return "You've been here " + this.hits + " times.";
}
}
}
</script>
我的观点只是Label
绑定到我用来创建描述性消息的计算变量的元素。它 hits 现在利用的只是 0。现在让我们添加 ApplicationSettings 支持。首先,我们导入库:
const appSettings = require('tns-core-modules/application-settings');
接下来,我们可以在created
安装组件时添加方法来执行代码:
created() {
this.hits = appSettings.getNumber("hits");
if(!this.hits) this.hits = 0;
appSettings.setNumber("hits", ++this.hits);
}
我们首先从中加载值appSettings
。注意事项getNumber
。如我所说,ApplicationSettings
支持加载布尔值,字符串和数字。所有的 API 都是一样的,只是方法名称在变化。因此,如果您想获取布尔值,则可以使用getBoolean
并且显然getString
用于字符串。
如果未定义该值,则将其设置为 0,这可能看起来很奇怪,因为我已在代码 data 块中将其默认设置为 0 ,但否则会有所undefined
不同。最后,在将值递增一之后,我将其存储回去。
对此进行几次测试,每次保存代码并重新运行项目时,您都会看到数字递增。如果您使用的是 NativeScript Playground,它将是自动的。我们可以使代码更简单一些。
与本地存储不同,它 ApplicationSettings
支持为尚不存在的值提供默认值。只需提供默认值作为第二个参数即可完成此操作:
this.hits = appSettings.getNumber('hits', 0);
appSettings.setNumber('hits', ++this.hits);
TIP
您可以在此处查看和创建此简单项目的副本。
让我们考虑另一个更真实的例子。想象一个应用程序,它允许用户自定义应用程序的配色方案。一种简单的方法是更改ActionBar
顶部的颜色。为此,我们可以先将颜色绑定到一个值:
<ActionBar title="Home" class="action-bar" :color="color" />
接下来,我们可以添加一个简单的字段,以允许用户编辑该值:
<Label text="Enter RGB Color" />
<TextField v-model="color" hint="Try #00ff00" />
最后,这是处理读取当前值并在更改后对其进行更新的代码。
export default {
data() {
return {
color: '#ff0000'
};
},
created() {
this.color = appSettings.getString('color', '#ff0000');
},
watch: {
color(val) {
appSettings.setString('color', val);
}
}
};
现在,在加载应用程序后,将从本地设置中读取颜色,并且用户可以随意更改颜色。
TIP
你可以在这里玩这个项目。
要了解有关 ApplicationSettings 的更多信息,请务必阅读文档并记住,像所有客户端数据一样,绝对不应将其用于敏感数据!
在继续之前,一定要知道有一个添加了 LocalStorage 和 SessionStorage API 的 NativeScript 插件:nativescript-localstorage。如果您只是想使用已经熟悉的 API,那么此插件可能会很方便。另一个原因是试图合并另一个需要 API 的库。
# 使用 CouchDB 使其变得复杂
好的,“复杂”不一定是最好的术语,但是对于更复杂的存储需求,Osei Fortune 的 CouchDB 插件是一个很好的解决方案。这个插件使存储各种临时数据变得容易,同时还提供了检索,更新,删除甚至搜索和排序数据的功能。不仅如此,您还可以在 NativeScript 应用程序和远程 CouchDB 服务器之间建立同步。
首先,您需要通过将插件添加到您的应用程序中tns plugin add nativescript-couchbase-plugin
。该插件无法在 Playground 上使用,因此您需要在本地进行测试。
接下来,导入代码并创建一个数据库对象:
import { Couchbase } from 'nativescript-couchbase-plugin';
const database = new Couchbase('my-database');
在上面的代码中,my-database
是 CouchDB 数据库的名称,并且可以是对您的应用程序有意义的任何名称。让我们看一个简单的示例,该示例简单地处理随机但持久的数据。
应用程序的屏幕截图
在上面的屏幕截图中,您可以看到猫的列表。列表下方是添加新猫的按钮。在一个更好的应用程序中,我将使用一种表格让您输入有关猫的详细信息,但为了简单起见,我使用了一些随机性来命名(和年龄)猫。现在让我们看一下代码。
<template>
<Page class="page">
<ActionBar class="action-bar">
<Label class="action-bar-title" text="Home"></Label>
</ActionBar>
<StackLayout>
<ListView for="cat in cats">
<v-template>
<Label :text="cat.name"></Label>
</v-template>
</ListView>
<Button @tap="addCat" text="Add Cat"></Button>
</StackLayout>
</Page>
</template>
<script>
import { Couchbase } from 'nativescript-couchbase-plugin';
const database = new Couchbase('cat-db');
// function to make some mock data
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomName() {
var initialParts = ["Fluffy","Scruffy","King","Queen","Emperor","Lord","Hairy","Smelly","Most Exalted Knight","Crazy","Silly","Dumb","Brave","Sir","Fatty"];
var lastParts = ["Sam","Smoe","Elvira","Jacob","Lynn","Fufflepants the III","Squarehead","Redshirt","Titan","Kitten Zombie","Dumpster Fire","Butterfly Wings","Unicorn Rider"];
return initialParts[getRandomInt(0, initialParts.length - 1)] + ' ' + lastParts[getRandomInt(0, lastParts.length - 1)];
}
function getCats() {
return database.query({
select: [], // Leave empty to query for all
order: [{ property: 'name', direction: 'asc' }]
});
}
export default {
data() {
return {
cats:[]
}
},
created() {
this.cats = getCats();
},
methods: {
addCat() {
let documentId = database.createDocument({
"name": randomName(),
"age": getRandomInt(1,10)
});
this.cats = getCats();
}
}
};
</script>
UI 处理遍历显示名称的 cat 猫数据。我的猫有名字和年龄,但显然您不必显示所有数据。底部的按钮负责执行我的逻辑以添加一只新猫。
在应用程序逻辑内部,您可以看到我在哪里打开 CouchDB 数据库。我有一个实用程序函数,getCats
它利用了query
数据库对象的方法。我在这里没有进行任何过滤,只是进行排序,但是您可以按照自己的意愿对数据进行“切片和切块”。
最后,addCat
利用createDocumentAPI
添加 cat。名称和年龄都是随机值,但是正如我上面所说,可以基于表单字段。
基本上就是这样,但是一定要查看插件文档以获取更多示例,包括我上面提到的同步以及如何使用事务。
# 其他选择?
除了上面列出的内容外,还有其他选择。一种可能是使用 SQLite,如果您更加熟悉基于 SQL 的数据库,则该选项可能比 CouchDB 更可取。
您也可以使用设备上的文件系统。我可能会避免将其用于“抽象数据”,而是将其用于存储图片和音频文件。
和往常一样,我很想看看你做了什么。在下面为我提供您的示例以及对您有用(或无效)的评论!