vue-the-storages
Version:
A vue plugin that enhances localStorage/sessionStorage (supports vue2 and vue3). It allows two-way binding of storage data, multi-page data binding, storage event listener, and rich api (async/sync)
643 lines (482 loc) • 15.2 kB
Markdown
# vue-the-storages
### A Vue plugin that enhances localStorage/sessionStorage (supports vue2, vue3).
### It allows two-way binding of storage data, multi-page data binding, storage event listener, and rich api (async/sync).
### Based on: [the-storages](https://github.com/pure-peace/the-storages)
### Description
- Vue plugins
- Support Vue2, vue3, and Vue-Cli project
- Multi-page data binding and sync.
- Provide storage change event listeners.
- Various calling methods.
- Automatic JSON parsing.
- Mainly written using es6 and proxy.
## Simple Demos:
You can open multiple pages at the same time and experience data binding between multiple pages
- #### [the-storages in Vue.js 3](http://miya.ink/the-storages/index.html)
- #### [the-storages in Vue.js 2](http://miya.ink/the-storages/vue2.html)
- #### [the-storages in Vue.js 2 zh](http://miya.ink/the-storages/vue2_zh.html)
## Usage:
### vue-the-storages
- 1. install
```
npm i vue-the-storages
```
- 2. use
### main.js (registered)
```javascript
import vueTheStorages from 'vue-the-storages'
// vue2
Vue.use(vueTheStorages)
// vue3 (just use)
createApp(App).use(vueTheStorages).mount('#app')
```
#### Default global names:
$localData (localStorage mirror object)
$local (localStorage proxy object)
$sessionData (sessionStorage mirror object)
$session (sessionStorage proxy object)
#### You can pass in options when registering to modify the global name:
```javascript
import vueTheStorages from 'vue-the-storages'
// default, you can modify
const vueTheStoragesOptions = {
localMirrorKey: '$localData',
localStorageKey: '$local',
sessionMirrorKey: '$sessionData',
sessionStorageKey: '$session',
options: {
vueModule: null,
strict: true,
mirrorOperation: false,
updateMirror: true
}
}
// vue2
Vue.use(vueTheStorages, vueTheStoragesOptions)
// vue3 (just use)
createApp(App).use(vueTheStorages, vueTheStoragesOptions).mount('#app')
```
### App.vue or any components (test)
```html
<template>
<div>
<div>{{ $localData }}</div>
<div>{{ $local }}</div>
<button @click="test">test</button>
</div>
</template>
<script>
export default {
methods: {
test() {
this.$local.set('hello', { message: 'halo' })
// the same:
// this.$local.hello = { message: 'halo' }
// this.$local.hello.message 'halo'
}
}
}
</script>
```
#### ↑ The above is the usage of vue plugin
All APIs are completely consistent, you can refer to
### [Read Samples](#samples)
### [Read Docs](#docs)
## ↓ Below is the description of [the-storages](https://github.com/pure-peace/the-storages)
### Import:
```javascript
// npm i the-storages
import { createLocal, createSession } from 'the-storages'
const mirror = createLocal() // create localStorage; createSession is sessionStorage
const storage = mirror._prx
console.log(storage, mirror)
storage.set('hello', 'world')
console.log(storage, mirror)
```
### Vue-Cli: [vue-the-storages](https://github.com/pure-peace/vue-the-storages)
### Vue (common):
See [index.html](https://github.com/Pure-Peace/the-storages/blob/master/index.html) for details (vue3).
[vue2.html](https://github.com/Pure-Peace/the-storages/blob/master/vue2.html),
[vue2_zh.html](https://github.com/Pure-Peace/the-storages/blob/master/vue2_zh.html)
```html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- storages test page for vue2 -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>the-storages | vue2</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<h1>the-storage | vue2</h1>
<div>storageData (storage mirror object): {{ storageData }}</div>
<div>storageProxyObj (storage proxy object): {{ storageProxyObj }}</div>
<div>
<button @click="test">click me, set a message</button>
</div>
</div>
<script>
import { createLocal, createSession, createStorage } from 'the-storages'
// create storage mirror object (localStorage)
// mirror object used for data binding, get data
const mirror = createLocal()
// storage proxy object (enhanced storage)
// used to operate storage
const storage = mirror._prx
new Vue({
el: '#app',
data() {
return {
// the mirror object can make the data update automatically
// so it's more suitable for obtaining storage data
storageData: mirror,
// the storage proxy object has all the methods and features
// (but it is not recommended to put it directly into the view)
// so it's more suitable for storage operation
storage: storage
}
},
created() {
// ensure that the storage data on the view can be updated automatically
this.storage.bindVm(this)
console.log(this.storageData)
this.storage.set('hello', 'firstData')
console.log(this.storageData)
},
methods: {
test () {
this.storage.set('foo', { bar: 1 })
}
}
})
</script>
</body>
</html>
```
### Samples:
```javascript
// set data to localStorage
storage.set('test', { message: 'im an object' }) // set a object
storage.setItem('test2', 'hello2') // set a string
storage.test3 = { hello111: 'im an object too' } // set a object
// set multiple data to localStorage
storage.set(['a','b','c'], [1,2,'g']) // parameter [keys ... ]:[values... ]
storage.set({a: 1, b: 2, c: 'g'}) // { key1: value1, key2: value2 ... }
// set data to localStorage, recursive creation
storage.a.b.c.d.e = 'test'
storage.setChain('aa.bb.cc.dd', 'testChain')
// each sync method has a sync copy method
storage.setAsync('async foo', 'bar').then(res => { console.log('set async complete') })
storage.setChainAsync('gg.ee.rr', 'haha').then(res => { console.log('set asyncChain complete') })
// get data from localStorage
storage.get('test') // will get object
console.log(storage.test) // the same
storage.getItem('test') // the same
localStorage.getItem('test') // the same
storage.get('test', false) // will get json string
// get multiple results
storage.get(['test', 'test2', 'test3']) // will get object { key1: value1, key2: value2 ... }
// recursive acquisition
storage.getChain('a.b.c.d.e')
storage.a.b.c.d.e
// each sync method has a sync copy method
storage.getAsync('test').then(res => { console.log(res) })
// remove key from localStorage
storage.remove('test') // none return
storage.remove('test', true) // will return test's value
storage.pop('test') // the same
// watchers
// active: events triggered by the current page
storage.watchActive('get', e => { console.log(e) })
// passive: events triggered by the other page
storage.watchPassive('set', e => { console.log(e) })
// valid events
console.log(storage._activeEvents) // active events
console.log(storage._passiveEvents) // passive events
// unwatch
storage.unwatchActive('get')
storage.unwatchPassive('get')
```
## Docs:
Some docs here...
```javascript
import { createLocal, createSession, Storage } from 'the-storages'
const mirror = createLocal() // create localStorage; createSession is sessionStorage
const storage = mirror._prx // storage proxy
```
- ### createLocal
> create enhanced localStorage <br>
> only localstorage supports multi-page data binding
```javascript
createLocal(options)
```
##### options: Object
> Default options
```javascript
{
vueModule: null,
strict: true,
mirrorOperation: false,
updateMirror: true
}
```
- ### createSession
> create enhanced sessionStorage
> Since the session of each page is independent, multi-page data binding is not supported
```javascript
createSession(options)
```
##### options: Object
> Default options: same
## storage (proxy) object methods
- ### getItem
> get item from storage
```javascript
storage.getItem(key, parse = true)
```
##### key: String, Array
> if key is an Array, get multiple, return object.
##### parse: Boolean
> if parse, try to return JSON.parse(result)
- ### get
> Shorthand method name for getItem
```javascript
storage.get(key, parse = true)
```
- ### getAsync
> Asynchronous method of getItem
```javascript
storage.getAsync(...args).then(res => {})
```
- ### setItem
> set item from storage
```javascript
storage.setItem(key, value)
```
##### key: String, Array, Object
> If both key and value are array types, set multiple. [...keys] -> [...values] <br>
> If key is an Object, set multiple. { key1: value1, key2: value2 }
##### value: Any
> The value will fix with JSON.stringify
- ### set
> Shorthand method name for setItem
```javascript
storage.set(key, value)
```
- ### setAsync
> Asynchronous method of setItem
```javascript
storage.setAsync(...args).then(res => {})
```
- ### removeItem
> remove item from storage
```javascript
storage.removeItem(key, pop = false)
```
##### key: String, Array
> If key is an Array, remove multiple keys.
##### pop: Boolean
> If pop, removeItem will return the deleted value
- ### remove
> Shorthand method name for removeItem
```javascript
storage.remove(key, pop = false)
```
- ### removeAsync
> Asynchronous method of removeItem
```javascript
storage.removeAsync(...args).then(res => {})
```
- ### clear
> clear the storage
```javascript
storage.clear()
```
- ### clearAsync
> Asynchronous method of clear
```javascript
storage.clearAsync().then(res => {})
```
- ### setChain
> Set storage data recursively, try not to overwrite the attributes on the chain.
```javascript
storage.setChain(keyChain, value)
```
##### keyChain: String
> sample: storage.setChain('a.b.c.d.e', 1) == (storage.a.b.c.d.e = 1)
##### value: Any
> Value will be set on the last object of keyChain
- ### setChainAsync
> Asynchronous method of setChain
```javascript
storage.setChainAsync(...args).then(res => {})
```
- ### getChain
> Get storage data recursively, will get the value of the last object on keyChain.
```javascript
storage.setChain(keyChain, value)
```
##### key: String
> sample: storage.getChain('a.b.c.d.e') == storage.a.b.c.d.e
- ### setChainAsync
> Asynchronous method of getChain
```javascript
storage.getChainAsync(...args).then(res => {})
```
- ### watch
> Add a listener for the specified type of storage change event
```javascript
storage.watch(triggerType, eventType, handler)
```
##### triggerType: String
> Must be 'active' or 'passive'. <br>
> active: events triggered by the current page <br>
> passive: events triggered by the other page
##### eventType: String
> Add handler function for specified event. <br>
> active: must in ["get", "set", "remove", "pop", "clear"] <br>
> passive: must in ["set", "remove", "clear"]
##### handler: Function
> Handler will receives a parameter: event
- ### watchActive
> Asynchronous method of watch, triggerType is 'active'
```javascript
storage.watchActive(eventType, handler)
```
- ### watchPassive
> Asynchronous method of watch, triggerType is 'passive'
```javascript
storage.watchPassive(eventType, handler)
```
- ### unwatch
> Remove listener for the specified type of storage change event
```javascript
storage.unwatch(triggerType, eventType)
```
##### triggerType: String
> Must be 'active' or 'passive'. <br>
> active: events triggered by the current page <br>
> passive: events triggered by the other page
##### eventType: String
> Remove listener for specified event. <br>
> active: must in ["get", "set", "remove", "pop", "clear"] <br>
> passive: must in ["set", "remove", "clear"]
- ### unwatchActive
> Asynchronous method of unwatch, triggerType is 'active'
```javascript
storage.unwatchActive(eventType)
```
- ### watchPassive
> Asynchronous method of unwatch, triggerType is 'passive'
```javascript
storage.unwatchPassive(eventType)
```
- ### bindVm
> Binding the Vue module (instance) object to ensure that the Vue view can be updated.
```javascript
storage.bindVm(vueModule)
```
##### vueModule: Vue instance
> Equivalent to "this" in the vue instance. <br>
> Please call this function to bind "this" when the page is initialized.
- ### toString
> return storage data as JSON string
```javascript
storage.toString()
```
- ### _data
> return storage data as Object
```javascript
storage._data()
```
## Storage constructor methods
```javascript
const _Storage = new Storage()
```
- ### create
> create and return an enhanced storage mirror object. <br>
```javascript
_Storage.create(type, options)
```
##### type: String
> must be 'localStorage' or 'sessionStorage'.
##### options: Object
> Please see the default options of createLocal
- ### _asyncWrapper
> Convert sync functions to async functions and return
```javascript
_Storage._asyncWrapper(func)
```
##### func: Function
> sync functions
- ### _createObject
> Create Object through Array
```javascript
_Storage._asyncWrapper(list, defaultValue = null))
```
##### list: Array
> keys Array
##### defaultValue: any
> every key's value
- ### _notNull
> is val === null || undefined || nan ?
```javascript
_Storage._notNull(val)
```
##### val: any
- ### _parse
> Try to parse the JSON string (return the original value if it fails)
```javascript
_Storage._parse(value)
```
##### value: any
- ### _stringify
> Try to stringify the value (return the original value if it fails)
```javascript
_Storage._stringify(value)
```
##### value: any
- ### _zip
> Compress two Arrays into an object corresponding to a key value
```javascript
_Storage._zip(array1, array2)
```
##### array1: Array
> keys Array
##### array2: Array
> values Array
## Development / test
You are willing to help me improve this project. Or you need to do some testing.
#### 1. Clone this repository
```
git clone https://github.com/Pure-Peace/the-storages
```
#### 2. Installation dependencies
```
npm i
```
#### 3. Start
```
npm run dev
```
#### 4. Open the test page (Default port is 8080)
I provide two sample pages: vue.js 3 and vue.js 2 (CDN unpkg.com)
You can open two pages to experience multi-page data binding and data synchronization.
##### vue.js 3
```
http://localhost:8080
```
##### vue.js 2
```
http://localhost:8080/vue2
```
##### vue.js 2 中文版页面
```
http://localhost:8080/vue2_zh
```
### Snowpack
It is recommended to use snowpack to run or build (instead of webpack with babel, beacuse snowpack natively supports es6, and faster)
## MIT