使用Vue构建Ionic混合APP系列教程(四):数据存储

来源:互联网 发布:团伙研发作弊软件 编辑:程序博客网 时间:2024/06/03 13:04

大多数应用程序基本都需要保存一些在应用重新加载时需要的数据。我们经常使用用户设备上的本地存储来实现。当使用Ionic/Angular的时候,我们可以简单的使用Ionic内置的Storage API,并不需要知道背后的原理——Ionic会自动地选择最合适的存储方式。

再说一次,在Vue里我们没有现成的东西可以用,是安装一个库还是自己搭建解决方案全决定于我们自己。

在这篇教程,我们将扩展上篇教程里的Reddit应用,允许我们可以切换多个不同的subreddits方法。我们会存储用户的选择,当重新进入应用时会使用保存的数据。

开始

本教程紧跟前面的教程。如果你想一步步走, 你应该先完成之前的教程。不过, 您可以轻松地将本教程中的概念应用于任何应用程序, 因此如果您不想完成前面的教程也无大碍。

localForage 和 Ionic 存储模块

进入代码之前我们先讨论一点理论知识。我们会在ionic-angular库的Ionic Storage Module代码的基础上进行。具体点说,我们会参考 the Storage class的代码。

Ionic使用 localForage来和存储后台交互。通过使用 localForage我们可以有一些外部的API进行交互,不用管具体使用了哪个技术:Native SQLite storage, IndexedDB, WebSQL或者是简单的浏览器的local storage

Ionic的存储模块封装了localForage ,而且根据可用的选择,去自动的设置合适的方法。这意味着如果你使用Cordova搭建的应用而且安装了SQLite 插件,那这个就会用于存储数据。如果SQLite 不可用它会回头使用IndexedDB 或者 WebSQL,如果这些都不可用那么local storage API就是最后的选择 。

我们想在Ionic/Vue应用里模拟这种行为,所以来看看Ionic是怎么做的。我们会专注于 storage.ts里最关键的部分:

import LocalForage from 'localforage';import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';

localForage 库必须安装和导入,如果我们想支持使用SQLite,还需要安装CordovaSQLiteDriver 。使用SQLite 的好处是我们不需要担心浏览器数据被系统清空。

constructor(config: StorageConfig) {  this._dbPromise = new Promise((resolve, reject) => {    let db: LocalForage;    const defaultConfig = getDefaultConfig();    const actualConfig = Object.assign(defaultConfig, config || {});    LocalForage.defineDriver(CordovaSQLiteDriver).then(() => {      db = LocalForage.createInstance(actualConfig);    })      .then(() => db.setDriver(this._getDriverOrder(actualConfig.driverOrder)))      .then(() => {        this._driver = db.driver();        resolve(db);      })      .catch(reason => reject(reason));  });}

在构造函数constructor 里创建了一个实例化localForagePromise。我们先要定义CordovaSQLiteDriver,一旦完成我们可以用构造对象创建一个Local Forage实例。

默认的Ionic Storage API 的构造是这样的:

{  name: '_ionicstorage',  storeName: '_ionickv',  driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']};

这个配置最重要的部分就是drivers,这决定了存储机制的性能。在这个例子里,sqlite是首选,localstorage 是最后的选择。为了确保这些驱动命名正确,用到了下面这个方法:

_getDriverOrder(driverOrder) {  return driverOrder.map((driver) => {    switch (driver) {      case 'sqlite':        return CordovaSQLiteDriver._driver;      case 'indexeddb':        return LocalForage.INDEXEDDB;      case 'websql':        return LocalForage.WEBSQL;      case 'localstorage':        return LocalForage.LOCALSTORAGE;    }  });}

这个方法会映射driver order数组来使用由localForage提供的合适的值。如果你不熟悉数组的map方法,你可能会对这个视频感兴趣。基本概念就是map操作会对数组里的每个元素进行一些转换。在这个例子里,我们会使用由localForage定义的实际的名称来替换数组里的值。

剩下的API基本都是一些围绕着localForage 的方法的简单封装:

get(key: string): Promise<any> {  return this._dbPromise.then(db => db.getItem(key));}set(key: string, value: any): Promise<any> {  return this._dbPromise.then(db => db.setItem(key, value));}

所有Ionic存储模块在做的事情就是通过检查dbPromise 的类成员,来确保存储已经完成了正确的实例化。一旦promise完成,getItemsetItem 方法就会被用来在存储空间里设置(或者销毁)值。

在Vue里创建Storage服务

我们可以直接在我们的组件里使用localForage 接口,但是如果我们想做的像Ionic的Staorage API那样智能,把它独立到它自己的服务里会更有意义。我们将使用刚才学习到的那些概念,用它们在Ionic/Vue应用里来创建一个Storage服务。

首先,我们需要安装必要的依赖库:

npm install localforage --savenpm install localforage-cordovasqlitedriver --save

创建src/services/storage.js文件:

import LocalForage from 'localforage';import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';export default class Storage {  dbPromise;  constructor(){    this.dbPromise = new Promise((resolve, reject) => {      let db;      let config = {          name: '_vuestorage',          storeName: '_vuekv',          driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']      }      LocalForage.defineDriver(CordovaSQLiteDriver).then(() => {        db = LocalForage.createInstance(config);      })        .then(() => db.setDriver(this.getDriverOrder(config.driverOrder)))        .then(() => {          resolve(db);        })        .catch(reason => reject(reason));    });  }  ready(){    return this.dbPromise;  }  getDriverOrder(driverOrder){    return driverOrder.map((driver) => {      switch(driver){        case 'sqlite':          return CordovaSQLiteDriver._driver;        case 'indexeddb':          return LocalForage.INDEXEDDB;        case 'websql':          return LocalForage.WEBSQL;        case 'localstorage':          return LocalForage.LOCALSTORAGE;      }    });  }  get(key){    return this.dbPromise.then(db => db.getItem(key));  }  set(key, value){    return this.dbPromise.then(db => db.setItem(key, value));  }  remove(key){    return this.dbPromise.then(db => db.removeItem(key));  }  clear(){    return this.dbPromise.then(db => db.clear());  }}

这只是Ionic Storage API 相同代码的简化版——它或多或少地以同样的方式起作用。为了看起来更友好我留下了一些功能没封装,但是你没有理由不去实现剩下的那些功能。

使用Storage服务保存和获取数据

现在,我们要做的是使用我们的服务。保存数据很简单:

storage.set('something', 'somevalue');

获取数据:

storage.get('something').then((value) => {  console.log(value);});

修改 src/components/HelloWorld.vue如下:

<template>  <ion-app>    <ion-header>        <ion-navbar>            <ion-title>REDDIT!</ion-title>        </ion-navbar>    </ion-header>    <ion-content>      <ion-button @click="switchSubreddit('funny')">Funny</ion-button>      <ion-button @click="switchSubreddit('gifs')">Gifs</ion-button>      <ion-button @click="switchSubreddit('worldnews')">Worldnews</ion-button>      <ion-list>        <ion-item v-for="post in posts" v-bind:key="post.data.id">          {{post.data.title}}        </ion-item>      </ion-list>    </ion-content>  </ion-app></template><script>import RedditService from '../services/reddit';import Storage from '../services/storage';const storage = new Storage();export default {  name: 'HelloWorld',  data () {    return {      posts: []    }  },  created() {    storage.get('subreddit').then((value) => {      if(value === null){        value = 'gifs';      }      RedditService.getPosts(value).then(response => {        this.posts = response.body.data.children;      });    });  },  methods: {    switchSubreddit(subreddit){      storage.set('subreddit', subreddit);      RedditService.getPosts(subreddit).then(response => {        this.posts = response.body.data.children;      });         }  }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h1, h2 {  font-weight: normal;}ul {  list-style-type: none;  padding: 0;}li {  display: inline-block;  margin: 0 10px;}a {  color: #42b983;}</style>

我们引入了刚创建的storage服务,我们首先在created里调用了get方法。created 方法会在组件已创建就执行,所以它会立即检查storagesubreddit存不存在,如果存在,subreddit值会被用于调用API,如果不存在,默认的使用gifs代替。

我们也设置了三个按钮以不同的值触发switchSubreddit 。这个方法会保存新的值到storage,然后调用getPosts。下次应用重启的时候,保存在Storage的值会代替默认的gifs 被使用。

备注:如果你没有看之前的教程,你可能不知道如何使用这个模板的组件。

总结

没有做太多额外的工作,我们就创建了自己的storage服务,和Ionic/Angular应用的存储机制一样的便利和有用。

阅读全文
0 0
原创粉丝点击