Skip to content

Commit

Permalink
change data -> keys
Browse files Browse the repository at this point in the history
  • Loading branch information
maple3142 committed Mar 16, 2018
1 parent 1467f82 commit 542dc62
Show file tree
Hide file tree
Showing 16 changed files with 109 additions and 196 deletions.
136 changes: 21 additions & 115 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# vuejs-storage

[![Greenkeeper badge](https://badges.greenkeeper.io/maple3142/vuejs-storage.svg)](https://greenkeeper.io/)
*vue.js and vuex plugin to persistence data with localStorage/sessionStorage*
> vue.js and vuex plugin to persistence data with localStorage/sessionStorage
[![Build Status](https://travis-ci.org/maple3142/vuejs-storage.svg?branch=master)](https://travis-ci.org/maple3142/vuejs-storage)

[![Greenkeeper badge](https://badges.greenkeeper.io/maple3142/vuejs-storage.svg)](https://greenkeeper.io/)

## Usage

Expand All @@ -20,22 +19,29 @@ Vue.use(vuejsStorage)
new Vue({
//...
data: {
//data here won't be saved
count: 0,
text: ''
},
storage: {
data: {
count: 0//this will be saved in localStorage
},
keys: ['count'], //keep data.count in localStorage
namespace: 'my-namespace',
}
})

//vuex example
const store = new Vuex.Store({
//state...
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
plugins: [
vuejsStorage({
//don't use "data" here
keys: ['increment'],
namespace: 'my-namespace',
storage: window.sessionStorage //if you want to use sessionStorage instead of localStorage
})
Expand Down Expand Up @@ -67,120 +73,20 @@ Option object, can be used when create **Vuex** plugin or in **Vue** option `sto

```javascript
{
data: {
//Vue data object,REQUIRED only in Vue's storage field
},
keys: [], //array of string
/*
this option is different when use in vue and vuex
when used in Vue constructor option, keys means which data should be keep in localStorage
when used in Vuex plugin, keys mean which state should be keep in localStorage
*/
storage: sessionStorage, //any object has 'setItem' 'getItem' api, default: localStorage
namespace: 'ns', //a string, REQUIRED
parse: JSON.parse, //deserialize function, default: JSON.parse
stringify: JSON.stringify //serialize function, default: JSON.stringify
}
```

## [Example](https://rawgit.com/maple3142/vuejs-storage/master/example.html)
```html
<!DOCTYPE html>
<html lang="en">

<head>
<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>example</title>
<script src="dist/vuejs-storage.js"></script>
<!--import from cdn-->
<!--script src="https://unpkg.com/vuejs-storage"></script-->
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
</head>

<body>
<div id="app">
<div>
<span>Vue counter: {{count}}</span>
<button @click="add">add</button>
</div>
<div>
<span>Vuex counter: {{vuexcount}}</span>
<button @click="vuexadd">add</button>
</div>
</div>
<div id="app2">
<div>
<span>sessionStorage counter: {{count}} {{message}}</span>
<button @click="add">add</button>
</div>
</div>
<div>
Try open this page in another tab.
</div>
<script>
Vue.use(Vuex)
Vue.use(vuejsStorage)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
plugins: [
vuejsStorage({ namespace: 'vuex-app' }) //call vuejsStorage with options will return a plugin
]
})
var app = new Vue({
el: '#app',
storage: { //provide options in storage
data: {
count: 0
},
namespace: 'app'
},
methods: {
add: function () {
this.count++
},
vuexadd: function () {
store.commit('increment')
}
},
computed: {
vuexcount() {
return store.state.count
}
}
})
//advanced example
var app2 = new Vue({
el: '#app2',
data: {
message: 'Hello'
},
storage: function () { //function syntax is ok
return {
data: {
count: 0
},
storage: sessionStorage,
namespace: 'app2'
}
},
methods: {
add: function () {
this.count++
}
}
})
</script>
</body>

</html>
```
> [Example](https://rawgit.com/maple3142/vuejs-storage/master/example.html)
## Other Example

Expand Down
2 changes: 1 addition & 1 deletion dist/vuejs-storage.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/vuejs-storage.js.map

Large diffs are not rendered by default.

24 changes: 11 additions & 13 deletions example.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,19 @@
}
},
plugins: [
vuejsStorage({ namespace: 'vuex-app' }) //call vuejsStorage with options will return a plugin
vuejsStorage({ namespace: 'vuex-app' ,keys: ['count']}) //call vuejsStorage with options will return a plugin
]
})

var app = new Vue({
el: '#app',
storage: { //provide options in storage
data: {
count: 0
},
keys: ['count'],
namespace: 'app'
},
data: {
count: 0
},
methods: {
add: function () {
this.count++
Expand All @@ -78,16 +79,13 @@
var app2 = new Vue({
el: '#app2',
data: {
message: 'Hello'
message: 'Hello',
count: 0
},
storage: function () { //function syntax is ok
return {
data: {
count: 0
},
storage: sessionStorage,
namespace: 'app2'
}
storage: {
keys: ['count'],
storage: sessionStorage,
namespace: 'app2'
},
methods: {
add: function () {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vuejs-storage",
"version": "1.1.0",
"version": "2.0.0",
"main": "./dist/vuejs-storage.js",
"types": "./types/vuejs-storage.d.ts",
"license": "MIT",
Expand All @@ -15,6 +15,7 @@
"@types/chai": "^4.0.4",
"@types/lodash.assignin": "^4.2.3",
"@types/mocha": "^2.2.44",
"@types/object-assign": "^4.0.30",
"chai": "^4.1.2",
"karma": "^2.0.0",
"karma-chai": "^0.1.0",
Expand All @@ -23,6 +24,7 @@
"karma-typescript": "^3.0.8",
"lodash.assignin": "^4.2.0",
"mocha": "^5.0.4",
"object-assign": "^4.1.1",
"ts-loader": "^4.0.1",
"typescript": "^2.6.1",
"uglifyjs-webpack-plugin": "^1.2.3",
Expand Down
35 changes: 20 additions & 15 deletions src/install.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
import { VueConstructor, StorageOption } from './interfaces'
import { VueConstructor, Option } from './interfaces'

import { createLSStorage } from './lsstorage'

const assign = (<any>Object).assign
import * as assign from 'object-assign'

export function install(Vue: VueConstructor) {
Vue.mixin({
beforeCreate() {
if ('storage' in this.$options) {
let option: StorageOption = this.$options.storage
if (this.$options.storage instanceof Function) {
//storage(){...} syntax
option = this.$options.storage.apply(this)
}
let option: Option = this.$options.storage

const ls = createLSStorage(option)
option.data = assign(option.data, ls.getItem(option.namespace))
ls.setItem(option.namespace, option.data)

let data = this.$options.data || {}
let optdata = this.$options.data || {}
if (this.$options.data instanceof Function) {
//data(){...} syntax
data = this.$options.data.apply(this)
optdata = this.$options.data.apply(this)
}

let data = null
if (!ls.has(option.namespace)) {
const tmp = {}
option.keys.forEach(k => (tmp[k] = optdata[k]))
data = tmp
ls.setItem(option.namespace, data)
} else {
data = ls.getItem(option.namespace)
}
this.$options.data = assign(data, option.data) //merge storage's data into data

this.$options.data = assign(optdata, data) //merge storage's data into data

//if no 'watch' option
if (!('watch' in this.$options)) {
this.$options.watch = {}
}
for (let key in option.data) {
for (const key of option.keys) {
//create watchers
let watcher: Function = null
if (key in this.$options.watch) {
//backup original watcher
watcher = <Function>this.$options.watch[key]
}
this.$options.watch[key] = value => {
option.data[key] = value
ls.setItem(option.namespace, option.data)
data[key] = value
ls.setItem(option.namespace, data)
if (watcher !== null) watcher.call(this, value)
}
}
Expand Down
12 changes: 4 additions & 8 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@ export { Plugin as VuexPlugin, Store } from 'vuex/types/index'
export interface Option {
storage?: Storage,
stringify?(obj: any): string,
parse?(str: String): any
}
export interface VuexOption extends Option{
namespace: string
}
export interface StorageOption extends Option {
parse?(str: String): any,
namespace: string,
data?: object
keys?: string[]
}
export interface lsStorage {
setItem(key: string, value: any)
removeItem(key: string)
getItem(key: string): any
getItem(key: string): any,
has(key: string): boolean
}
5 changes: 4 additions & 1 deletion src/lsstorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export function createLSStorage({
},
getItem(key) {
return parse(storage.getItem(key))
},
has(key) {
return storage.getItem(key) !== null
}
}
}
}
24 changes: 16 additions & 8 deletions src/vuexplugin.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { Store, VuexPlugin, VuexOption } from './interfaces'
import { Store, VuexPlugin, Option } from './interfaces'

import { createLSStorage } from './lsstorage'

const assign = (<any>Object).assign
import * as assign from 'object-assign'

/**
* Create Vuex plugin
*/
export function createVuexPlugin(option: VuexOption): VuexPlugin<Object> {
export function createVuexPlugin(option: Option): VuexPlugin<Object> {
const ls = createLSStorage(option)
return (store: Store<Object>) => {
let data = store.state
data = assign(data, ls.getItem(option.namespace)) //merge data
store.replaceState(data) //set state
let data = null
if(!ls.has(option.namespace)){
data=store.state
ls.setItem(option.namespace,data)
}
else{
data=ls.getItem(option.namespace)
}
store.replaceState(assign(store.state, data)) //merge state
store.subscribe((mutation, state) => {
ls.setItem(option.namespace, state)
const obj={}
option.keys.forEach(k=>obj[k]=state[k])
ls.setItem(option.namespace, obj)
})
}
}
}
Loading

0 comments on commit 542dc62

Please sign in to comment.