Skip to content
This repository has been archived by the owner on Jun 9, 2019. It is now read-only.

Vuex support #46

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ A minimalistic framework for demonstrating your Vue components, inspired by [rea
* [Loading Scenarios Dynamically](#loading-scenarios-dynamically)
* [Register Components](#register-components)
* [Use Component as `play()` argument](#use-component-as-play-argument)
* [Using with Vuex](#using-with-vuex)
- [Component Shorthand](#component-shorthand)
- [Additional Component Properties](#additional-component-properties)
* [example](#example)
Expand Down Expand Up @@ -221,6 +222,54 @@ play(MyButton)
.add('with text', '<my-other-button>text</my-other-button>')
```

### Using with [Vuex](https://github.com/vuejs/vuex)

If your component is using [Vuex](https://github.com/vuejs/vuex) data store, you can pass store as an argument for a full component, just like you would in a normal Vue instance.

First, load Vuex in your `./play/index.js` file:

```js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
```

And then pass a Vuex Store instance like so:

```js
import Vuex from 'vuex'

play('Monster', module)
.add('mutating tentacle monster', {
store: new Vuex.store({
state: {
type: 'TENTACLE_MONSTER',
tentacles: 12
},
getters: {
attack: state => tentacles * TENTACLE_DAMAGE
},
mutations: {
mutateTentacle(state, mutagenStrength) {
state.tentacles = state.tentacles * mutagenStrength
}
},
actions: {
mutateTentacle({ commit }, data) {
asyncServerOperation(data, (err, mutagenStrength) => {
commit('mutateTentacle', mutagenStrength)
})
}
}
}),
render(h) {}
// ...
})
```

You can use multiple Vuex Store instances. State always resets to the initial value when you switch between scenarios.

## Component Shorthand

If you only need `template` or `render` property for your component, you can use `component shorthand`, which means you can directly set the value of scenario to a template string or render function:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"dependencies": {
"array-find-index": "^1.0.2",
"highlight.js": "^9.8.0",
"lodash": "^4.17.4",
"query-string": "^4.2.3",
"uid": "0.0.2",
"vue-router": "^2.0.3",
Expand Down
27 changes: 27 additions & 0 deletions play/Storage-counter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div>
<p>{{ count }}</p>
<p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</p>
</div>
</template>

<script>
export default {
computed: {
count () {
return this.$store.state.count
}
},
methods: {
increment () {
this.$store.commit('increment')
},
decrement () {
this.$store.commit('decrement')
}
}
}
</script>
13 changes: 13 additions & 0 deletions play/Storage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<p>This component is <strong v-if="!enabled">not</strong> using Vuex</p>
</template>

<script>
export default {
computed: {
enabled() {
return (this.$store.state.enabled === true && this.$store.getters.isAlive === true) ? true : false
}
}
}
</script>
5 changes: 5 additions & 0 deletions play/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import Vue from 'vue'
import Vuex from 'vuex'

import MyButton from './MyButton.vue'
import Box from './Box.vue'

Vue.use(Vuex)

const load = requireContext => {
return requireContext.keys().map(requireContext)
}
Expand Down
33 changes: 33 additions & 0 deletions play/storage.play.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Vuex from 'vuex'
import {play} from '../src/play'
import Storage from './Storage.vue'
import StorageCounter from './Storage-counter.vue'

play('Storage', module)
.add('static', {
store: new Vuex.Store({
state: {
enabled: true
},
getters: {
isAlive: s => s.enabled
}
}),
render(h) {
return h(Storage)
}
})
.add('counter', {
store: new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
decrement: state => state.count--
}
}),
render(h) {
return h(StorageCounter)
}
})
15 changes: 14 additions & 1 deletion src/preview.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Vue from 'vue'
import qs from 'query-string'
import get from 'lodash/get'
import findScenario from './utils/find-scenario'
import filterVuex from './utils/filter-vuex'
import {parseKey} from './utils/key-events'
import {getSpots} from './play'

Expand Down Expand Up @@ -33,6 +35,12 @@ export default function () {
const scenario = findScenario(spots, data.payload)
if (scenario) {
this.current = scenario.component

// Handle Vuex state if found
// If we have a cached initial state, use that
if (get(this.current, 'store.constructor.name') === 'Store' && this.current._initialState) {
this.current.store.replaceState(JSON.parse(this.current._initialState))
}
}
}
})
Expand All @@ -44,10 +52,15 @@ export default function () {
}
parent.postMessage({
type: 'SET_SPOTS',
payload: JSON.stringify(spots)
payload: JSON.stringify(spots, filterVuex)
}, location.origin)
},
render(h) {
// Save original store state on the first render
if (get(this.current, 'store.constructor.name') === 'Store' && !this.current._initialState) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why do we need to cache this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I envision Vuex in vue-play is that you get you app/component to a certain state, defined in Vuex state.

So if I have a scenario Popup opened and my state is set to popupVisible: true and I close the popup in UI, thus setting state to popupVisible: false I want to see the original state when I open that scenario again.

this.current._initialState = JSON.stringify(this.current.store.state)
}

return h('div', {attrs: {id: 'app'}}, [h(this.current)])
}
})
Expand Down
10 changes: 10 additions & 0 deletions src/utils/filter-vuex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Replacer function for JSON.stringify to filter Vuex instance from the tree
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
import get from 'lodash/get'

export default (key, value) => {
if (key === 'store' && get(value, 'constructor.name') === 'Store') {
return undefined
}
return value
}