├── .editorconfig ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── circle.yml ├── example └── index.js ├── package.json ├── src └── index.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | *.log 4 | dist/ 5 | dist-example/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) egoist <0x142857@gmail.com> (https://egoistian.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-persist 2 | 3 | [![NPM version](https://img.shields.io/npm/v/vue-persist.svg?style=flat)](https://npmjs.com/package/vue-persist) [![NPM downloads](https://img.shields.io/npm/dm/vue-persist.svg?style=flat)](https://npmjs.com/package/vue-persist) [![Build Status](https://img.shields.io/circleci/project/egoist/vue-persist/master.svg?style=flat)](https://circleci.com/gh/egoist/vue-persist) [![donate](https://img.shields.io/badge/$-donate-ff69b4.svg?maxAge=2592000&style=flat)](https://github.com/egoist/donate) 4 | 5 | > Persist data in localStorage or anywhere for Vue.js apps 6 | 7 | ## Install 8 | 9 | ```bash 10 | yarn add vue-persist 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | import VuePersist from 'vue-persist' 17 | 18 | Vue.use(VuePersist) 19 | 20 | new Vue({ 21 | template: '', 22 | 23 | data: { name: '' }, 24 | 25 | persist: ['name'] 26 | }) 27 | ``` 28 | 29 | Then the data of `name` will be stored at localStorage and kept in sync. 30 | 31 | Check out the [demo](https://egoist.github.io/vue-persist/), just type some words and refresh the page. 32 | 33 | You can also manually call `this.$persist(['some-data'])` instead of using the component option. 34 | 35 | ## API 36 | 37 | ### Vue.use(VuePersist, [options]) 38 | 39 | #### options 40 | 41 | ##### name 42 | 43 | Type: `string`
44 | Default: `persist:store` 45 | 46 | The name of the localStorage store. 47 | 48 | ##### expiration 49 | 50 | Type: `number`
51 | Default: `0` 52 | 53 | Expire store in a specific amount of time (in millisecond), default to never expire. 54 | 55 | ##### read 56 | 57 | Type: `function`
58 | Default: `k => localStorage.get(k)` 59 | 60 | The function we use to get stored data. 61 | 62 | ##### write 63 | 64 | Type: `function`
65 | Default: `(k, v) => localStorage.set(k, v)` 66 | 67 | The function we use to store data. 68 | 69 | ##### clear 70 | 71 | Type: `function`
72 | Default: `k => localStorage.removeItem(k)` 73 | 74 | The function we use to clear data in store. 75 | 76 | 77 | ### this.$persist(keys[, name, expiration]) 78 | 79 | #### keys 80 | 81 | Type: `Array`
82 | Required: `true` 83 | 84 | Array of keys of state you want to keep in sync with localStorage. 85 | 86 | #### name 87 | 88 | Type: `string`
89 | Default: `options.name` 90 | 91 | #### expiration 92 | 93 | Type: `number`
94 | Default: `options.expiration` 95 | 96 | 97 | ## Contributing 98 | 99 | 1. Fork it! 100 | 2. Create your feature branch: `git checkout -b my-new-feature` 101 | 3. Commit your changes: `git commit -am 'Add some feature'` 102 | 4. Push to the branch: `git push origin my-new-feature` 103 | 5. Submit a pull request :D 104 | 105 | 106 | ## Author 107 | 108 | **vue-persist** © [egoist](https://github.com/egoist), Released under the [MIT](./LICENSE) License.
109 | Authored and maintained by egoist with help from contributors ([list](https://github.com/egoist/vue-persist/contributors)). 110 | 111 | > [egoistian.com](https://egoistian.com) · GitHub [@egoist](https://github.com/egoist) · Twitter [@rem_rin_rin](https://twitter.com/rem_rin_rin) 112 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 7 4 | environment: 5 | PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin" 6 | 7 | dependencies: 8 | override: 9 | - yarn 10 | cache_directories: 11 | - ~/.cache/yarn 12 | 13 | test: 14 | override: 15 | - yarn test 16 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VuePersist from '../src' 3 | 4 | Vue.use(VuePersist, { 5 | name: 'store', 6 | expiration: 1000 * 10 // 10s 7 | }) 8 | 9 | new Vue({ 10 | el: '#app', 11 | data: { 12 | name: '' 13 | }, 14 | persist: ['name'], 15 | methods: { 16 | handleInput({ target }) { 17 | this.name = target.value 18 | } 19 | }, 20 | render() { 21 | return ( 22 |
23 | Your name? 24 |
25 | ) 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-persist", 3 | "version": "0.4.0", 4 | "description": "Persist data in localStorage or anywhere for Vue.js apps.", 5 | "repository": { 6 | "url": "egoist/vue-persist", 7 | "type": "git" 8 | }, 9 | "main": "dist/vue-persist.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "scripts": { 14 | "test": "echo 'no tests!' && npm run lint && npm run build", 15 | "lint": "xo", 16 | "build": "bili --name vue-persist --format umd --module-name VuePersist", 17 | "build:example": "poi build", 18 | "dev": "poi", 19 | "deploy": "npm run build:example && gh-pages -d example/dist" 20 | }, 21 | "author": "egoist <0x142857@gmail.com>", 22 | "license": "MIT", 23 | "devDependencies": { 24 | "bili": "^0.14.0", 25 | "eslint-config-rem": "^3.0.0", 26 | "gh-pages": "^0.12.0", 27 | "poi": "^9.2.4", 28 | "xo": "^0.17.1" 29 | }, 30 | "xo": { 31 | "extends": "rem", 32 | "esnext": true, 33 | "ignores": [ 34 | "example/**/*" 35 | ], 36 | "envs": [ 37 | "browser" 38 | ] 39 | }, 40 | "poi": { 41 | "homepage": "/vue-persist/", 42 | "entry": "example/index.js", 43 | "dist": "example/dist" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default function (Vue, { 2 | name: defaultStoreName = 'persist:store', 3 | expiration: defaultExpiration, 4 | read = k => localStorage.getItem(k), 5 | write = (k, v) => localStorage.setItem(k, v), 6 | clear = k => localStorage.removeItem(k) 7 | } = {}) { 8 | const cache = {} 9 | 10 | Vue.mixin({ 11 | beforeCreate() { 12 | this.$persist = (names, storeName = defaultStoreName, storeExpiration = defaultExpiration) => { 13 | let store = cache[storeName] = JSON.parse(read(storeName) || '{}') 14 | store.data = store.data || {} 15 | 16 | if (isExpired(store.expiration)) { 17 | clear(storeName) 18 | store = { 19 | data: {}, 20 | expiration: getExpiration(storeExpiration) 21 | } 22 | } 23 | 24 | if (!store.expiration) { 25 | store.expiration = getExpiration(storeExpiration) 26 | } 27 | 28 | this._persistWatchers = this._persistWatchers || [] 29 | 30 | for (const name of names) { 31 | if (typeof store.data[name] !== 'undefined') { 32 | this[name] = store.data[name] 33 | } 34 | 35 | if (this._persistWatchers.indexOf(name) === -1) { 36 | this._persistWatchers.push(name) 37 | 38 | this.$watch(name, val => { 39 | store.data[name] = val 40 | write(storeName, JSON.stringify(store)) 41 | }, { deep: true }) 42 | } 43 | } 44 | } 45 | }, 46 | 47 | created() { 48 | const { persist } = this.$options 49 | if (persist) { 50 | this.$persist(persist) 51 | } 52 | } 53 | }) 54 | } 55 | 56 | function getExpiration(exp) { 57 | return exp ? Date.now() + exp : 0 58 | } 59 | 60 | function isExpired(exp) { 61 | return exp && (Date.now() > exp) 62 | } 63 | --------------------------------------------------------------------------------