Replace Vuex with Vue.observable
From the beginning when Vue was v0.12 (5 years ago) and Vuex didn’t exist yet and I had to make own “global” state storage. I had to use $root
to access the properties from any component with ease and Crossroads.js for the routing. The Root component didn’t need template
, just components
, data
and sometimes computed
to make it one-direction data flow and watch
for saving data in localStorage. You add components on your page very easily like you do today.
When Vue getting older, I see great community, making awesome features. Suddenly there’s Vuex that really look like Redux (React). What an awful way to implement, and the whole flock is flocking and hyping them too.
Never add feature that add more complexity. Keep It Simple Stupid. Hell, I didn’t like Vue (.vue
) files; prefer Node-way, but after hearing Evan explaining it, it’s actually great.
Without further ado, I create some file structure I use, to build my cv-builder Nuxt app, but first I show a simple concept.
Vue.observable(object)
Concept
const state = Vue.observable({
list: [],
note: 'Ping!'
})
Vue.observable
Getting started
<!-- component: Note -->
<script type="text/html" id="note-tpl">
<div>
<main>{{note}}</main>
<footer><button @click="onPong">Pong!</button></footer>
</div>
</script>
<!-- Target Element -->
<div id="app">
{{ message }}
<ul>
<li v-for="item in list" v-text="item" />
</ul>
<button @click="onAddItem">Add me</button>
<Note/>
</div>
const store = {
state: Vue.observable({
list: [],
note: 'Ping!'
})
}
Vue.prototype.$$store = store
// Component: Note
const Note = {
name: 'Note',
template: '#note-tpl',
computed: {
note: () => this.$$store.state.note
},
methods: {
onPong() {
this.$$store.state.note = 'Pong!!!'
}
}
}
// Vue Root Component
var app = new Vue({
el: '#app',
components: {
Note
},
data: {
message: 'Hello Vue!'
},
computed: {
list: () => this.$$store.state.list
},
methods: {
onAddItem () {
this.$$store.state.list.push('You’ve added me')
}
}
})
You have access $$store
in every Vue component
Modular option
ES6 Without any building tools or CLI generators
/project/
lib/store/
• storeNote.js
• storeAppSettings.js
• storeUserPreference.js
components/
• Note.js
• main.js
* index.html
In storeNote.js
we create a state with object properties and some methods that mutates some values.
import Vue from 'vue'
const state = Vue.observable({
list: [],
note: 'Ping!'
})
const methods = {
onAddItem () {
state.list.push('You’ve added me')
},
onPong() {
state.note = 'Pong!!!'
}
}
export {
state,
methods
}
/project/lib/store/storeNote.js
Havestate
andmethods
exposed.
Make index.html
with templates
<!-- component: Note -->
<script type="text/html" id="note-tpl">
<div>
<main>{{note}}</main>
<footer><button @click="onPong">Pong!</button></footer>
</div>
</script>
<!-- Target Element -->
<div id="app">
{{ message }}
<ul>
<li v-for="item in list" v-text="item" />
</ul>
<button @click="onAddItem">Add me</button>
<Note/>
</div>
/project/index.html
Import Vue and other libraries & components and with spread ...
operator to include methods from the Store storeNote
.
import Vue from 'vue'
import storeNote from './lib/store/storeNote'
import Note from './components/Note'
// Vue Root Component
var app = new Vue({
el: '#app',
components: {
Note
},
data: {
message: 'Hello Vue!'
},
computed: {
list: () => storeNote.state.list
},
methods: {
...storeNote.methods
}
})
/project/main.js
Easy access storeNote
by importing it and include methods from it.
import storeNote from '../lib/store/storeNote'
exports default {
name: 'Note',
template: '#note-tpl',
computed: {
note: () => storeNote.state.note
},
methods: {
...storeNote.methods
}
}
/project/components/Note.js
Conclusion
That’s what it’s about. Make things simple.
I will include example with Routes or probably use with Crossroads.js, I haven't decided. vue-router
looks pretty solid, seeing from the examples.