Halo teman ngide! Kali ini kita akan melanjukan belajar tentang vuejs, lebih tepatnya tentang bagaimana mengatur state di dalam aplikasi vue js yang kita punya.
Kalau di React mereka punya Redux, di VueJS, mereka punya yang namanya Vuex.
Daftar Isi
Lalu kenapa kita harus menggunakan Vuex untuk state management?
Kemudahan utama kenapa kita harus menggunakan Vuex sebagai centralized state management adalah mempermudah mengakses state atau data di beberapa component sekaligus.
Catatan
Penggunaan state management tidak selalu harus dilakukan. Jadi jika data yang diperlukan hanya sedikit dan bisa di hadle dengan data flow yang standar seperti menggunakan props atau emit event maka itu udah cukup. Tapi jika casenya kalian butuh mengakses data yang banyak dan bisa di reuse di component lain maka Vuex menjadi pilihan yang tepat.
Apa itu Vuex?
Saya kutip dari dokumentasi official, Vuex adalah sebuah state management pattern dan library untuk aplikasi VueJS. Vuex bertugas sebagai centralized store untuk semua component yang di dalam aplikasi kamu, yang memastikan bahwa state hanya bisa di rubah dengan cara yang pasti.
Konsep Utama Vuex
Jadi sebelum langsung ngoding, ada baiknya kita mengenal beberapa konsep dasar yang ada di dalam Vuex. Pusat dari Vuex adalah sebuah “_store” _yang akan berfungsi sebagai kontainer dari semua state yang ada di dalem aplikasi kamu. Di dalam store memilki beberapa bagian-bagian yang dengan fungsinya masing-masing yaitu:
1. State
State adalah sebuah object dimana tempat semua data aplikasi berada. Contohnya kurang lebih seperti ini:
const store = new Vuex.Store({
state: {
count: 1,
color: 'red'
}
})
Jadi state ini saya bilangnya sebuah json yang berisi data-data yang akan kita akses dari component yang ada.
Untuk cara mengaksesnya state langsung seperti contoh di atas dengan menggunakan store.state.count
atau store.state.color
. Atau menggunakan global vuex tanpa harus di import di setiap component dengan this.$store.state.count
.
2. Getter
Sesuai namanya, Getter berfungsi untuk mengakses state.
Lalu apa bedanya mengakses state secara langsung dan melalu Getter?
Dengan menggunakan Getter kita bisa mengolah terlebih dahulu state yang akan kita ambil seperti fungsi computed yang ada di VueJS. Jadi kita bisa memfilter data state sebelum di panggil.
Contohnya:
getters: {
doneTodos(state){
return state.todos.filter(function(item){
return item.done == true
})
},
pendingTodos(state){
return state.todos.filter(function(item){
return item.done == false
})
},
},
3. Mutation
Mutation adalah satu-satunya cara untuk merubah state. Jadi mutation ini bisa dibilang mirip event yang ada di dalam store. Mutation terdiiri dari sebuah string nama dan handlernya.
Contohnya gini:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// mutate state
state.count++
}
}
})
Nah di atas kita punya sebuah mutations dengan type name increment yang memilki handler dimana jika dipanggil akan menambah nilai dari state count sebanyak 1.
Lalu cara memanggillnya di dalam component adalah dengan this.$store.commit('nama mutation')
.
4. Action
Apa lagi nih action? Action mirip dengan mutation, bedanya adalah mutation hanya bisa di akses secara synchronous sedangankan action bisa di akses secara asynchronous.
Tidak tahu apa bedanya synchronous dengan assynchronous? Google haha.
Nah action ini tidak merubah state, tapi action akan memanggil mutation dan mutation yang akan merubah state.
Kita butuh action ketika melakukan proses asynchronous dan perlu untuk merubah state. Misalnya saat selesai melakukan request ajax. Cara memanggil state di component atau biasa dibilang dispatch adalah dengan this.$store.dispatch('nama action')
5. Modules
Seperti yang kita bahas soal state sebagai sebuah single tree json dan harus menampung semua state disana. Maka saat kita punya banyak sekali state yang harus di handle maka datanya akan membengkak dan susah untuk di maintenance.
Solusinya adalah dengan menggunakan modules.
Jadi store yang tadi besar itu kita bisa pecah-pecah lagi menjadi module yang lebih kecil. Menariknya masing-masing module ini selain berisi state, juga bisa berisi mutation, getter, dan action sendiri.
Kita lihat saja contohnya di bawah ini:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state
Nah kita sudah belajar sedikit konsep dasar seperti apa sih Vuex itu.
Selanjutnya kita coba implementasikan Vuex ke dalam aplikasi VueJS yang sudah pernah kita buat sebelumnya yaitu tentang bagaimana cara membuat todolist, kalian bisa baca disini: Mebuat Todolist Dengan VueJS. Kalian wajib mengikuti tutorial sebelumnya karena code yang di pakai adalah code todolist app sebelumnya.
Include Vuex
Buka file index.html
dan tambahkan script vuex ini di bawah script vuejs.
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
Membuat Store
Buka file app.js, kita akan membuat Vuex store.
tambahkan const store
seperti di bawah ini sebelum pemanggilan VueJS. Lalu tambahkan const store
itu ke dalam pemanggilan VueJS.
const store = new Vuex.Store({
state: {
},
mutations: {
},
getters: {
},
})
var app = new Vue({
el: '#app',
store,
data: {
'message': 'Hello world'
},
});
Sekarang kita coba buka di browser, disini saya memakai Chrome dan buka developer console dan di tab Vue, kamu bisa mengecek apakah Vuex sudah terinstall dengan baik di aplikasi yang kita buat
Memindahkan data todos ke dalam State
Sekarang saatnya memindahkan data todos yang sebelumnya ada di dalam component ke dalam state di “store”
Pindahkan seperti di bawah ini:
state: {
todos: [
{
name: 'Todo 1',
done: false,
},
{
name: 'Todo 2',
done: false,
},
{
name: 'Todo 3',
done: false,
},
],
},
Karena data todos sudah berpindah ke state, tentu cara memanggilnya dari dalam component sudah berbeda. Kita edit component todo dan tambahkan sebuah computed function todos untuk mengambil data todo dari state.
Vue.component('todo',{
template: '<div class="container">'+
'<div class="row justify-content-center">'+
'<div class="col-md-6">'+
'<h1 class="text-center">Todolist</h1>'+
'<hr>'+
'<input type="text" class="form-control" placeholder="Input todolist & enter" v-model="todo.name" v-on:keyup.enter="addTodo">'+
'<hr>'+
'<ul class="list-group">'+
'<todo-item v-for="item,index in todos" v-bind:item="item" v-bind:key="index" ></todo-item>'+
'</ul>'+
'</div>'+
'</div>'+
'</div>',
data: function(){
return {
status: 'all',
todo: {
name: '',
done: false
}
}
},
computed: {
todos(){
return this.$store.state.todos
},
},
methods: {
addTodo(){
}
}
});
Sekarang coba buka aplikasi todolist di browser, harusnya kamu akan melihat tampilan seperti di bawah ini.
Merubah Event Create Todo, Toggle Todo dan Delete Todo
Karena kita sekarang menggunakan Vuex, jadi untuk melakukan perubahan pada state, harus menggunakan _mutations. _Buat 3 mutations yaitu addTodo, toggleTodo, dan deleteTodo
Edit store dan tambahkan 3 mutations tadi
mutations: {
addTodo (state,payload) {
state.todos.push(payload)
},
deleteTodo (state,payload) {
let index = state.todos.indexOf(payload);
state.todos.splice(index)
},
toggleTodo(state,payload){
let index = state.todos.indexOf(payload);
state.todos[index].done = !state.todos[index].done
}
},
Edit component todo-item dan ubah bagian methodnya dengan memanggil mutations dari store
Vue.component('todo-item',{
props: ['item'],
template: '<li class="list-group-item" v-bind:style="isActive">{{ item.name }}'+
'<button type="button" class="btn btn-success float-right" v-on:click="toggleTodo">'+
'∨'+
'</button>'+
'<button type="button" class="btn btn-danger float-right" aria-label="Close" v-on:click="deleteTodo">'+
'<span aria-hidden="true">×</span>'+
'</button>'+
'</li>',
methods: {
toggleTodo(){
this.$store.commit('toggleTodo',this.item)
},
deleteTodo(){
this.$store.commit('deleteTodo',this.item)
}
},
computed: {
isActive(){
if(this.item.done){
return 'text-decoration:line-through'
}
}
}
});
Kita sudah hampir selesai.
Kamu bisa mencobanya sekarang, untuk menambah todo baru, enable & disable todo, maupun menghapus todo.
Langkah terkahir adalah saya mau menambahkan fungsi filter untuk menampilkan todolist yang sudah dikerjakan atau belum.
Pertama adalah membuat 2 buah getters di store yaitu doneTodos & pendingTodos
Edit store dan tambahkan getter di bawah ini
getters: {
doneTodos(state){
return state.todos.filter(function(item){
return item.done == true
})
},
pendingTodos(state){
return state.todos.filter(function(item){
return item.done == false
})
},
},
Kita sudah memilik getters, saatnya melakukan filter di component. Buka component todo dan edit bagian template dan bagian computed.
Tambahkan beberapa button di template yang akan merubah value dari data status
.....
'<hr>'+
'<button @click="status='all'">All</button>'+
'<button @click="status='pending'">Pending</button>'+
'<button @click="status='done'">Done</button>'+
'<ul class="list-group">'+
.....
Buat sebuah data baru dengan nama status dengan default value = all.
Edit bagian computed todos
todos(){
if(this.status == 'all')
return this.$store.state.todos
else if(this.status == 'done')
return this.$store.getters.doneTodos
else if(this.status == 'pending')
return this.$store.getters.pendingTodos
},
Jadi saat status berubah menjadi pending atau done, maka todos yang di panggil juga mengikuti apakah todo item tersebut statusnya pending atau done.
Nah sekarang saatnya mencoba aplikasi todolist yang sudah kita update sehingga memakai Vuex.
Kesimpulan
Jadi apa kesimpulan yang bisa kita ambil setelah mencoba mengimplementasikan Vuex sebagai state management di aplikasi todolist tersebut?
Data yang terpusat. Jadi karena datanya jadi 1 di dalam store maka lebih mudah untuk memanage dan maintenancenya.
Semua component bisa mengakses state yang ada dan melakukan perubahan lewat mutations
Kalian tidak harus menggunakan Vuex jika scope projectnya tidak terlalu besar atau jika hanya dengan menggunakan props atau emit event saja cukup maka Vuex tidak diperlukan. Jika kalian membutuhkan state yang komplek yang harus dan mudah di akses oleh semua component maka Vuex bisa jadi pilihan wajib untuk kamu implementasikan.
Terakhir kamu wajib baca-baca lagi dokumentasi Vuex di sini: https://vuex.vuejs.org
Untuk project ini sudah saya upload di github, bisa di cek sini ya: vuex-todo
Semoga tutorial kali ini bermanfaat, silakan like & share ya.