Vue computed properties getters and/or setters generator with the ability to intercept each property change and dispatch vuex action or commit mutation or just hook your own callback. Also you can use plugins.
The main idea of this tool is to have mapState()
-like helper with an ability to set additional configuration using chainable methods.
There are some other packages on github - vuex-map-fields and vuex-bound for example, but after reading their docs and sources I've decided to create own package from scratch with such benefits
- lightweight - 3.41 KB after rollup && babel-minify
- flexible - actions dispatching and hooks abilities adds to your code one place for handling reactive changes of target. Plugins support gives you full control of your data flow.
- simple - less code footprint with same features. You need to import only one helper method into your code, which provides a short set of chainable methods for configuring.
- no foreign code injection to your state - no weird logic ("core" mutations, actions, etc) shall be injected into your vuex store, no additional setup of
vuex
orvm
needed. This tool just generates getters and setters, which are done with performance in mind. - dot notation - with usage of very fast and well tested library get-value
npm i vuex-dot
https://codepen.io/anon/pen/ERmBqK
<template>
<button @click.stop="step++">next</button>
</template>
<script>
import { takeState } from 'vuex-dot';
export default {
computed: {
step: takeState('wizard.step')
.commit('setWizardStep')
.map()
}
}
</script>
store/index.js
export default new Vuex.Store({
state: {
wizard: {
step: 1
}
},
mutations: {
setWizardStep(state, step) {
state.wizard.step = step;
}
}
});
https://codepen.io/anon/pen/eKWqOm
<template>
<form>
<input v-model="name"/>
<input v-model="email"/>
</form>
</template>
<script>
import { takeState } from 'vuex-dot';
export default {
computed: {
...takeState('user')
.expose(['name', 'email'])
.dispatch('editUser')
.map()
}
}
</script>
<template>
<form>
<input v-model="name"/>
<input v-model="email"/>
</form>
</template>
<script>
import { takeState } from 'vuex-dot';
import validate from 'validate';
const constraints = {name: {presence: true}};
export default {
computed: {
...takeState('user')
.expose([
'name',
'email'
])
.hook(({ dispatch }, value, key) => {
if(validate.single(value, constraints[key])) {
dispatch('userEditAction', { key, value });
}
})
.map()
}
}
</script>
- Target
Target mapper
- TargetExposition
Exposes some properties of target object into computed properties compatible bunch of getters or/and setters
- take(path) ⇒
Target
returns Target instance with specified path
- takeState(namespace, path) ⇒
Target
returns Target instance with specified state path
Target mapper
- Target
- new Target(path)
- instance
- inner
- ~dispatcher :
function
- ~dispatcher :
Param | Type | Description |
---|---|---|
path | string |
dot-notation path to some property of your vm instance |
target.expose(projection) ⇒ TargetExposition
Should be used if you need to map some properties of the object, selected as a target into your computed properties. It allows to attach action dispatcher or hook callback on each property change.
Also, both dispatch()
and hook()
can provide object mapped by Target instance to the callee, while setting
the second argument true
(you can read more in the documentation for them)
Param | Type | Description |
---|---|---|
projection | array |
target object properties to be exposed |
target.commit(mutation) ⇒ Target
In fact, that's syntax sugar for hook()
method.
Sets mutation
to be commited on mapped property change
mutation
shall be called in the format:
commit(mutation, newValue)
Param | Type | Description |
---|---|---|
mutation | string |
mutation name |
target.dispatch(action) ⇒ Target
In fact, that's syntax sugar for hook()
method.
Sets action
to be dispatched on mapped property change
Your action
shall be called in the format:
dispatch(action, newValue)
Param | Type | Description |
---|---|---|
action | string |
action name |
target.hook(dispatcher) ⇒ Target
Set hook that should be run on mapped property change.
Param | Type |
---|---|
dispatcher | dispatcher |
returns computed property pair of getters or/and setters for specified projection.
If an alias is set, it can be used with spread operator setting provided alias as the computed property name
Param | Type | Description |
---|---|---|
alias | String |
name of computed field target to be accessible |
target.use(plugin) ⇒ Target
apply plugin
plugin is described by object, composed in such format:
{
setter: function(key, value, nextSetter) { //setter is mandatory
nextSetter(value);
},
getter: function(key, nextGetter) { //getter is optional
return nextGetter();
},
inject: { // optional, here you can describe additional fields, you want to inject into result map
$internal: {
get() { ... },
set(value) { ... }
}
}
}
Param | Type | Description |
---|---|---|
plugin | Object |
object, describing your plugin. |
Param | Type | Description |
---|---|---|
store | Store |
vuex store |
value | mixed |
Exposes some properties of target object into computed properties compatible bunch of getters or/and setters
Param | Type |
---|---|
target | Target |
projection | Array |
targetExposition.commit(mutation, sendTarget) ⇒ TargetExposition
Sets mutation
to be commited on exposed field change
if sendTarget
is false
, action
shall be called in format:
commit(mutation, { key, value })
otherwise, if sendTarget
is set to true
commit(mutation, { target, key, value })
Hint: That's just syntax sugar for hook()
method.
Param | Type | Default | Description |
---|---|---|---|
mutation | String |
name of mutation | |
sendTarget | Boolean |
false |
send target to action |
targetExposition.dispatch(action, sendTarget) ⇒ TargetExposition
Sets action
to be dispatched on exposed field change.
if sendTarget
is false
, action
shall be called in format:
dispatch(action, { key, value })
otherwise, if sendTarget
is set to true
dispatch(action, { target, key, value })
Hint: That's just syntax sugar for hook()
method.
Param | Type | Default | Description |
---|---|---|---|
action | String |
name of action | |
sendTarget | Boolean |
false |
send target to action |
targetExposition.hook(dispatcher, sendTarget) ⇒ TargetExposition
set callback to be run on property change
Param | Type |
---|---|
dispatcher | dispatcher |
sendTarget | Boolean |
generates map of getters or/and setters for specified projection
targetExposition.use(plugin) ⇒ TargetExposition
look Target.use(plugin)
Param |
---|
plugin |
Param | Type | Description |
---|---|---|
store | Store |
vuex store |
value | * |
changed value |
key | String |
key of changed field |
target | * |
parent object of changed field |
take(path) ⇒ Target
returns Target instance with specified path
Param | Type | Description |
---|---|---|
path | string |
dotted path to target property of your component instance |
takeState(namespace, path) ⇒ Target
returns Target instance with specified state path
Param |
---|
namespace |
path |