Nano Stores Vue
Vue integration for Nano Stores, a tiny state manager with many atomic tree-shakable stores.
- Small. Less than 1 KB with all helpers. Zero dependencies.
- Fast. With small atomic and derived stores, you do not need to call
the selector function for all components on every store change. - Tree Shakable. The chunk contains only stores used by components
in the chunk. - Helpers. To save a few keystrokes and keep code clean.
- Devtools. Plugin with full support of Vue Devtools.
- Was designed to move logic from components to stores.
- It has good TypeScript support.
Install
npm install @nanostores/vue
Usage
Store state
Subscribe to store changes and use reactive store state.
<template>
<header>{{ post.title }} for {{ user.name }}</header>
</template>
<script>
import { useStore } from '@nanostores/vue'
import { profile } from '../stores/profile.js'
import { Post } from '../stores/post.js'
export default {
setup (props) {
const user = useStore(profile)
const post = useStore(Post(props.postId))
return { user, post }
}
}
</script>
Multiple store states
Generate multiple store states and save a few keystrokes.
<template>
<header>{{ project.name }} / {{ user.name }}</header>
</template>
<script>
import { mapStores } from '@nanostores/vue'
import { project } from '../stores/project.js'
import { user } from '../stores/user.js'
export default {
setup () {
return {
...mapStores({ project, user })
}
}
}
</script>
Form handling
Since the store state is deep read-only, you cannot directly mutate it.
But for v-model
you can create model via useVModel(store, keys, opts)
.
It will explicitly mutate the store via store.set()
/ store.setKey()
.
<template>
<input v-model="username"/>
</template>
<script>
import { useVModel } from '@nanostores/vue'
import { profile } from '../stores/profile.js'
export default {
setup () {
const username = useVModel(profile, 'username')
return { username }
}
}
</script>
The keys
argument can be an array of keys to create multiple models.
Each model will be prefixed with Model
. You can change it via opts.prefix
.
<template>
<input v-model="firstNameModel"/>
<input v-model="lastNameModel"/>
</template>
<script>
import { useVModel } from '@nanostores/vue'
import { profile } from '../stores/profile.js'
export default {
setup () {
return {
...useVModel(profile, ['firstName', 'lastName'])
}
}
}
</script>
Devtools
Install
npm install --save-dev @vue/devtools-api
Usage
Store detector
Install Vue Devtools plugin as usual. It will detect nanostores
in selected component and add their states to the component inspector.
import { createApp } from 'vue'
import { devtools } from '@nanostores/vue/devtools'
import { User } from '../stores/user.js'
const app = createApp(…)
app.use(devtools)
Notice: if you are using SSR, there is no Vue Devtools on server.
Check it’s a browser environment:if (window) app.use(devtools)
Attach stores to add them to the nanostores inspector
and see their builds, lifecycles and changes on the timeline.
import { createApp } from 'vue'
import { devtools, attachStores } from '@nanostores/vue/devtools'
import { User } from '../stores/user.js'
const app = createApp(…)
app.use(devtools)
attachStores(app, { User })
You can connect several stores in different places of your application
and set custom names to simplify the work with devtools.
attachStores(app, {
'Current User': User,
Post
})
For MapTemplate
you can create a custom nameGetter
to set suitable names for each store built from template.
attachStores(app, { User }, {
nameGetter: (store, templateName) => {
return `User:${store.get().id}`
}
})
Settings
The states of all detected stores in component inspector are updated
in real time. You can disable this in the the plugin settings
via the Real-time update detected property.
By default, we removes unmounted stores from nanostores inspector
to keep it clean. You can change this via the Keep unmounted property.