1. Introduction
According to VueX homepage, it is state management pattern + library.
And as far as I understand it is like Ngrx with Angular 2+, Redux with ReactJS. It was born to handle data as Singleton (Few changes in the app), or to transmit events or it can also be understood to manage state and share data between components.
Because the thinking is the same, any friend who has gone through Ngrx or Redux will learn VueX very quickly, as I commented, Ngrx is quite difficult to use @@, Redux is easier to understand – easier to implement.
2. Details
In this section I will introduce in general the components around this diagram.
As you can see here we have some Core concepts to keep in mind: State, Store, Getters, Actions, Mutations. In the lower part we will go over from the first one and I will introduce briefly to you guys.
Before going into the details of each part, you need to understand that when using VueX, the singleton data will be saved to the store. And once saved here, if you want to change these states, you cannot change it directly, but you must change it through an action to a certain mutations, here the new mutations can change our state.
State
Here you need to understand the state that stores data in each component. For Angular 2+ it is the properties of the class (component), for React it is clearly the parts in this.state (For Class component type) and useState (For function component). As for VueJS, it is part of your data.
And when we add VueX to Vue, you simply understand that it is not local in each Component anymore but it will be shared with other components and services in the system.
So have you asked: So everything is put into the State of Redux à, is there too much? The answer is not all put in there, guys. @@ you put so much in that you die ^^. Note that the only part to be attached is singleton. Here we will need to understand that singleton means little change, or no change throughout the life of the app.
Store
Store is a state manager, it will have methods that allow you to change the state in the next time via dispatch (sounds like React too) or a commit. Store is unique within an app, it will be initialized with root.
Getters
Here you can understand it is kind of a computed to calculate data, handle a common logic that many components use. The function written here can only be used to retrieve data but cannot modify (Contact it a bit like Getter in OOP – showing closures).
Actions
Action will usually contain logic related to the business and you should understand that it does not directly change the state. If you want to change the State, you need to use a Commit defined at Mutations. The reason is because Actions are often run asynchronously (your code will still run when actions are not completed) and so when it is finished, we will go to Commit to change data.
Mutations
The functions in mutations usually should not contain any logic or business, they should only have one update state. You should understand that it runs synchronously and should know that a function inside a Mutations is called a Commit.
Ok, that’s enough for saying – the parts above are Core parts. Now we will make a small example to understand more of you.
First, you will need to create a Vue app and the VueX, by running the following command: (If you do not know why there is a vue command, please search the Vue cli)
vue create demo-vuex
yarn add vuex
ornpm install vuex
When you’re done, we’ll do it together. First we will create a folder store and write an index.js file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import Vuex from 'vuex'; import Vue from 'vue'; Vue.use(Vuex); export default new Vuex.Store({ state: { username: 'Chamdev.com', age: 10 }, getters: { // Here we will create getter }, mutations: { // Here we will create commit }, actions: { // Here we will create action } }); |
To use this file we will need to import and inject it inside the Vue root object. You adjust the main.js file as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import Vue from 'vue'; import App from './App.vue'; import store from './store'; Vue.config.productionTip = false; new Vue({ store, render: h => h(App), }).$mount('#app'); Tiếp theo chúng ta sẽ cho hiện state trong store ra để xem thử nhé các bạn ^^, hãy cùng tạo ra một component và import nó vào bên trong App component root nhé. <template> <div> <h1>Info</h1> <h2>{{username}}</h2> <h2>{{age}}</h2> </div> </template> <script> import { mapState } from 'vuex'; export default { name: "Info", computed: { ...mapState(['username', 'age']), } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> |
Here I am using mapState because I am using more than one state in the store, if you only use one, then change it like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <template> <div> <h1>Info</h1> <h2>{{username}}</h2> <h2>{{age}}</h2> </div> </template> <script> export default { name: "Info", computed: { username() { return this.$store.state.username; }, age() { return this.$store.state.age; } } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> |
Compare the above two ways and feel (feeling ^^), which is simpler, the answer is optional: if you do not want to write more logic then use the first method, and if you want to write more logic to show it, then you You still have to write it down and then insert the logic.
Next, we will update store / index.js together to see more actions and mutations how it works ^^.
Let’s change file store / index.js okay, here you pay attention to the actions and mutations section.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import Vuex from 'vuex'; import Vue from 'vue'; Vue.use(Vuex); export default new Vuex.Store({ state: { username: 'Chamdev.com', age: 10 }, getters: { // Here we will create getter }, mutations: { changeUsername(state, newUsername) { state.username = newUsername; } }, actions: { handleChangeUsername(context, newUsername) { context.commit('changeUsername', newUsername); } } }); |
Next we are going to change our component part.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <template> <div> <h1>Info</h1> <h2>{{username}}</h2> <br /> <div> <input v-model="usernameInput"/> <button @click="changeUsername">Change username</button> </div> </div> </template> <script> export default { name: "Info", data() { return { usernameInput: '' } }, computed: { username() { return this.$store.state.username; } }, methods: { changeUsername() { this.$store.dispatch('handleChangeUsername', this.usernameInput); } } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> |
Here if you succeed, when changing usernameInput, then click the [Change username] button, our username will be updated. If there are any errors, please do not hesitate to comment.
Next we will see how to getter how it works. As I mentioned earlier, this is the part where the logic handles, in order to retrieve the state that has been calculated. You write to getter if many components reuse this function, otherwise take the state out and recalculate each component only.
We modify store / index.js to read as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import Vuex from 'vuex'; import Vue from 'vue'; Vue.use(Vuex); export default new Vuex.Store({ state: { username: 'Chamdev.com', age: 10 }, getters: { getUsername: state => { return "Username: " + state.username; }, getAge: state => { return state.age + " year old."; } }, mutations: { changeUsername(state, newUsername) { state.username = newUsername; } }, actions: { handleChangeUsername(context, newUsername) { context.commit('changeUsername', newUsername); } } }); |
Next to display it outside, we will modify the component file as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <template> <div> <h1>Info</h1> <h2>{{username}}</h2> <br /> <div> <input v-model="usernameInput"/> <button @click="changeUsername">Change username</button> </div> <br /> <div> <div>{{getUsername}}</div> <div>{{getAge}}</div> </div> </div> </template> <script> // import { mapGetters } from 'vuex'; export default { name: "Info", data() { return { usernameInput: '' } }, computed: { username() { return this.$store.state.username; }, ...mapGetters(['getUsername', 'getAge']), // getUsername() { // return this.$store.getters.getUsername; // }, // getAge() { // return this.$store.getters.getAge; // } }, methods: { changeUsername() { this.$store.dispatch('handleChangeUsername', this.usernameInput); } } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> |
Here you can also use additional features of VueX to make the code shorter: mapGetters, mapActions, mapState, mapMutations. It is too convenient ^^.
3. Conclusion
So, you probably understand the most basic part of VueX already. But the pool is boundless, this is only a very small part that you can do with VueX. But I’m confident it is the most important core. If you are very basic like this then you will get acquainted with the project using VueX very quickly.
A little more, until now React is still the most popular framework, and right after it is Vue. And Angular2 + is only at the end because it is bulky – harder to use than these 2 guys.
3s of advertising. I have just been blogging since the beginning of March, so there are many things I hope you give up for it https://chamdev.com/vuex-getting-started/ .