[JL’s Self-teaching Story] Series
[Net Ninja] JS Regular Expressions
[Net Ninja] Vue JS2 (Part1, Part2, Part3)
[Net Ninja] Vuex
[Net Ninja] Python3 (Part1, Part2, Part3)
[Net Ninja] Django (Part1, Part2, Part3)
[Net Ninja] Sass (Part1, Part2)
[Sean Larkin] Webpack4 (Part1, Part2, Part3, Part4)
[Sarah Drasner] VueJS (Part1, Part2, Part3, Part4,
Part5, Part6, Part7(current))
🌲 This is the last part of my summary of Sarah Drasner’s “Introduction to Vue.js” on FrontendMasters. GitHub page can be accessed here. (You can also check out her blog post on CSS-Tricks “Intro to Vue.js: Vuex”.)
[7. Vuex]
7-1. Introducing Vuex
7-2. Examining a Vuex Setup
7-3. Vuex Example Walkthrough
7-4. Challenge 6: Vuex[8. Wrapping Up]
8-1. Future Resources
8-2. Popularity of Vue
[ 7–1. Introducing Vuex ]
# Part 1: What is Vuex?
- Centralized store for shared data and logic, even shared methods or async
- Unidirectional data flow
- Influenced by Flux application architecture
- Similar to Redux
- You can still use Redux if you like but this is Vue’s version
# Part 2: Why?
- In a complex single page application, passing state between many components, and especially deeply nested or sibling components, can get complicated quickly.
- Having one centralized place to access your data can help you stay organized.
# Part 3: When?
- Multiple instances of children/siblings communicating
- I’d like to “see” what all of the state looks like and keep it organized in one place.
Warning: not a replacement for single component methods
[ 7–2. Examining a Vuex Setup ]
# Part 1: Set up
Install: npm install — save vuex
or yarn add vuex
Sarah sets it up this way: within my `/src` directory, she creates another directory named store (this is a preference, you could also just create a `store.js` file in that same directory), and a file named `store.js`.
The initial set up in `store.js` would look something like the following:
import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);export const store = new Vuex.Store({
state: {
key: value
}
});
In our main.js file, we’d perform the following updates (bold texts):
import Vue from 'vue';
import App from './App.vue';import { store } from './store/store';new Vue({
el: '#app',
store,
template: '<App/>',
components: { App }
});
> Instead of “store: store
”, we could just use “store
”. The reason is that ES6 understands that that’s what we need.
# Part 2: Core concepts — Theory
- Getters will make values able to show statically in our templates. In other words, getters can read the value, but not mutate the state.
- Mutations will allow us to update the state, but they will always be synchronous. Mutations are the only way to change data in the state in the store.
- Actions will allow us to update the state, asynchronously, but will use an existing mutation. This can be very helpful if you need to perform a few different mutations at once in a particular order, or reach out to a server.
We separate actions and mutations, because we don’t want to get into an ordering problem.
# Part 3: Core concepts — Basic abstract example
export const store = new Vuex.Store({
state: {
counter: 0
}, //showing things, not mutating state
getters: {
tripleCounter: state => {
return state.counter * 3;
}
}, //mutating the state
//mutations are always synchronous
mutations: {
//showing passed with payload, represented as num
increment: (state, num) => {
state.counter += num;
}
}, //commits the mutation, it's asynchronous
actions: {
// showing passed with payload, represented as asynchNum (an object)
asyncIncrement: ({ commit }, asyncNum) => {
setTimeout(() => {
//the asyncNum objects could also just be static amounts
commit('increment', asyncNum.by);
}, asyncNum.duration);
}
}
});
# Part 4: Step-by-step Explanation of Actions
Step 1: Create an action by using a mutation called “increment”
actions: {
increment (context) {
context.commit('increment')
}
}
Step 2: De-structure the code
actions: {
increment ({ commit }) {
commit('increment')
}
}
Step 3: Add an asynchronous calculation
actions: {
asyncIncrement ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
# Step 4: Add a method
actions: {
asyncIncrement ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}methods: {
asyncIncrement() {
this.$store.dispatch('asyncIncrement')
}
}
# Step 5: Instead of hard coding 1 sec, pass a different duration
actions: {
asyncIncrement ({ commit }, duration) {
setTimeout(() => {
commit('increment')
}, duration)
}
}methods: {
asyncIncrement() {
this.$store.dispatch('asyncIncrement', {
duration: 1000
})
}
}
> This is de-structuring, it’s an ES6. (Have questions about de-structuring? Check out Medium post “ES6 De-structuring: The Complete Guide”.)
# Step 6: Pass more than one parameters
actions: {
asyncIncrement: ({ commit }, asyncNum) => {
setTimeout(() => {
commit('increment', asyncNum.by);
}, asyncNum.dur);
}
}methods: {
asyncIncrement() {
this.$store.dispatch('asyncIncrement', {
by: 10,
dur: 1000
})
}
}
# Part 5: Simple Example
On the component itself, we would use computed for getters (this makes sense because the value is already computed for us), and methods with commit to access the mutations, and methods with dispatch for the actions:
computed: {
value() {
return this.$store.getters.tripleCounter;
}
},
methods: {
increment() {
this.$store.commit('increment', 2)
},
asyncIncrement() {
this.$store.dispatch('asyncIncrement', 2)
}
}
# Part 6: In-depth Example
A working example video.
> The bottom example “ a simple adjustment store state with a component”: People do this. But, don’t do this!
For the code, check this GitHub repository out (password: !vue!)
> Mutations are always committed, while actions are always dispatched.
> Instead of calling each getter, mutation, and action separately in store.js, you could use a spread operator.
import { mapActions } from 'vuex';export default {
// ...
methods: {
...mapActions([
'increment',
'decrement',
'asyncIncrement'
])
}
}
>> This allows us to still make our own computed properties if we wish.
>> You might need babel-preset-stage-2 or
babel-plugin-transform-object-rest-spread to use spread operators.
[ 7–3. Vuex Example Walkthrough ]
<script>
export default {
computed: {
template() {
return this.$store.state.template;
}
},
methods: {
toggle() {
this.$store.commit('toggle');
}
},
mounted() {
//enter weather
const tl = new TimelineMax();
...
}
}
</script>
> Sarah Drasner used TimelineMax, the most feature-packed (and popular) animation tool in Greensocks, an ultra high-performance, professional-grade animation for the modern web.
[ 8–1. Further Resources]
vue docs / vue repo / nuxt docs / vuex docs / css-tricks guide / vue newsletter / monterail blog / vue tips / the majesty of vue
Collection of Vue resources : awesome vue
[ 8–2. Popularity of Vue ]
As of September 14, 2017, Vue was adopted by not only Adobe, Espresso, and a few other big companies, but also companies in Asia including AliBaba and Weebo.
While Angular is funded by Google and React is funded by Facebook, Vue is not supported by such a big company. But, Vue has support from various communities including Laravel, StdLib, and GitLab.
Class instructor “Sarah Drasner” is an award-winning Speaker, Senior Developer Advocate at Microsoft, and Staff Writer at CSS-Tricks. She’s a Vue Core team member.
She can be found at her personal website, GitHub, CSS-Tricks, CodePen, LinkedIn, Twitter, and Medium(Sarah Drasner), and Frontend Masters.
Thanks for reading! đź’• If you like this blog post, please clapđź‘Ź