简体   繁体   中英

Ionic-storage with vue

I'm building an application using Ionic Framework v5 with Vue 3.0.0 .

I use Vuex store to store global app informations, such as the user login token.

// file src\store.ts
export const store = createStore({
    state(){
      return { 
        loginToken;
      }
    },
    mutations: {
      updateLoginToken(state: any, token: string){
        state.loginToken = token;
      }
    },
    getters: {
      token(state: any){
        return state.loginToken;
      }
    }
})

I also need that this token is saved when the app is closed or refreshed, so i need to store it in some kind of local storage.

Official documentation suggest to use @ionic/storage to have access to a storage engines on multiple platforms.

To initialize the store i need to execute this code:

import { Storage } from '@ionic/storage';

const storage = new Storage();
await storage.create();

I'm pretty new to all this and i can't find where to place this code to initialize the storage, and also how can i then access to the storage object inside vuex store, to execute storage.set(...) and storage.get(...) ?

@ionic/storage vs @capacitor/storage

First you need to verify, if you really need @ionic/storage , or if @capacitor/storage is sufficient (in most cases it is). Using @ionic/storage requires an instance to be shared accross the app. @capacitor/storage can be used directly via imports.

A comparison between these plugins can be found here: Capacitor storage or cordova storage

In this answer, I assume you really want to use @ionic/storage so you need to create an instance first, which we want to share.

Plugin to share @ionic/storage instance accross your app

Create a vue plugin, where you create the storage instance and save it in a global variable. If needed also attach it to your VUEX store.

Somewhere in your main.js you attach the plugin to your Vue app:

app
  .use(...)
  .use(yourPlugin)

The plugin code:

import { Storage } from '@ionic/storage'

install: async (app) => {
  const storage = new Storage()
  const storageInstance = await storage.create()

  app.config.globalProperties.$ionicStorage = storageInstance
  app.config.globalProperties.$store.$ionicStorage = storageInstance // This one is only needed if you want to access the ionic storage instance in your VUEX store actions
}

Write data to Device Storage

In your case you want to write something to the Device Storage if a specific VUEX mutation occurs. There are multiple options to write to the device storage in this case.

Either you run the mutation within a VUEX action like this and save it to the Device Storage afterwards:

actions: {
  async setLoginToken ({ commit, state }, loginToken) {
    commit('updateLoginToken', loginToken)
    this.$ionicStorage.set({
      key: 'your-storage-key',
      value: JSON.stringify({ loginToken })
    })
  }
}

This approach makes sense, if you only want to sync just a few VUEX store properties. If you want to sync everything, or want to keep things more separated, you can attach a VUEX plugin to your VUEX store and subscribe to mutations.

How to attach VUEX plugins: https://vuex.vuejs.org/guide/plugins.html

In general, registering a VUEX plugin to your store allows you to subscribe to mutations. In your case the updateLoginToken mutation runs every time the login token gets updated. So the plugin needs to take care to write the new loginToken to the device storage after the mutation ran.

This will look similar to this:

const myPlugin = store => {
  // called when the store is initialized
  store.subscribe((mutation, state) => {
    // called after every mutation.
    // The mutation comes in the format of `{ type, payload }`.
    // Make sure the code runs only for the relevant mutation

    store.$ionicStorage.set({
      key: 'your-storage-key',
      value: JSON.stringify(xxx)
    })
  })
}

Read data from the Device Storage

Now you have the login token on the device storage. When the App restarts you need to grab it from there and push it to the VUEX store. There are different approaches to set this up. I personally prefer to load it in a custom Vue plugin.

First you attach the plugin to your vue app again. Make sure this plugin is attached AFTER the plugin from above (The plugin which shares the ionicStorage instance globally).

In the plugin you then just read the saved values from the device Storage and write it to your VUEX store.

export default {
  install: async (app) => {
    const storageContent = await app.config.globalProperties.$ionicStorage.get({ key: 'your-storage-key' })
    const storageContentParsed = JSON.parse(storageContent.value || '{}')
    const $store = app.config.globalProperties.$store

    $store.replaceState({
      ...$store.state,
      ...storageData
    })
  }
}

Note: These are just minimal code snippets. So make sure to adapt it to your own use case. In general this should make sure the loginToken gets synced to your device storage properly (on mobile and web).

What i've done to make this all to work:

I've created a plugin file called Storage.ts that creates the plugin instance and adds it to app global properties:

import { Storage } from '@ionic/storage'

export default async function storageFactory(wsBaseUrl: string) {

  const storage = new Storage();
  // create storage
  const storageInstance = await storage.create();

  // my custom stuff here ...

  // in the end, return the plugin installer
  return {
    install(app: any){
      app.config.globalProperties.$ionicStorage = storageInstance;
      // special copy for vuex storage
      app.config.globalProperties.$store.$ionicStorage = storageInstance; 
    }
  }
}

Then in the main.ts i've added my custom plugin to the main app:

import storageFactory from '@/plugins/Storage';

// create storage plugin 
const storagePlugin = await storageFactory(config.wsBaseUrl);

// create app
const app = createApp(App)
  // ... other stuff here
  .use(storagePlugin)

// mount when router is ready
router.isReady().then(() => {
  app.mount('#app');
});

Then, anywhere in other app's files i use the storage like this:

// set new key
await (this as any).$ionicStorage.set('token', token );
// remove the key
await (this as any).$ionicStorage.remove('token');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM