Jen Looper
a6478daa7f
|
4 years ago | |
---|---|---|
.. | ||
README.es.md | 4 years ago | |
README.it.md | 4 years ago | |
README.ja.md | 4 years ago | |
README.ko.md | 4 years ago | |
README.ms.md | 4 years ago | |
assignment.es.md | 4 years ago | |
assignment.hi.md | 4 years ago | |
assignment.it.md | 4 years ago | |
assignment.ja.md | 4 years ago | |
assignment.ko.md | 4 years ago | |
assignment.ms.md | 4 years ago |
README.ms.md
Bina Aplikasi Perbankan Bahagian 4: Konsep State Management
Kuiz Pra Kuliah
Pengenalan
Apabila aplikasi web berkembang, menjadi cabaran untuk mengawasi semua aliran data. Kod mana yang mendapat data, halaman mana yang menggunakannya, di mana dan kapan ia perlu dikemas kini ... mudah untuk berakhir dengan kod tidak kemas yang sukar dijaga. Ini benar terutamanya apabila anda perlu berkongsi data di antara halaman aplikasi anda yang berbeza, misalnya data pengguna. Konsep state management selalu ada dalam semua jenis program, tetapi ketika aplikasi web terus berkembang dalam kerumitan, kini menjadi titik penting untuk dipikirkan semasa pembangunan.
Pada bahagian akhir ini, kita akan melihat aplikasi yang kita buat untuk memikirkan kembali bagaimana keadaan dikendalikan, yang membolehkan sokongan penyegaran penyemak imbas pada bila-bila masa, dan data yang berterusan sepanjang sesi pengguna.
Prasyarat
Anda perlu menyelesaikan bahagian pengambilan data pada aplikasi web untuk pelajaran ini. Anda juga perlu memasang Node.js dan jalankan API pelayan secara tempatan supaya anda dapat menguruskan data akaun.
Anda boleh menguji bahawa pelayan berjalan dengan betul dengan menjalankan perintah ini di terminal:
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
Fikirkan semula state management
Dalam pelajaran sebelumnya, kami memperkenalkan konsep dasar keadaan dalam aplikasi kami dengan pemboleh ubah akaun
global yang mengandungi data bank untuk pengguna yang sedang log masuk. Walau bagaimanapun, pelaksanaan kami sekarang mempunyai beberapa kekurangan. Cuba muat semula halaman semasa anda berada di papan pemuka. Apa yang berlaku?
Terdapat 3 masalah dengan kod semasa:
- Keadaan tidak berterusan, kerana penyegaran penyemak imbas membawa anda kembali ke halaman log masuk.
- Terdapat pelbagai fungsi yang mengubah keadaan. Apabila aplikasinya berkembang, ini akan menyukarkan untuk mengesan perubahan dan mudah untuk melupakan pembaharuan.
- Keadaan tidak dibersihkan, apabila anda mengklik Logout data akaun masih ada walaupun anda berada di halaman log masuk.
Kami dapat mengemas kini kod kami untuk mengatasi masalah ini satu demi satu, tetapi ini akan membuat lebih banyak pendua kod dan menjadikan aplikasi lebih rumit dan sukar untuk dijaga. Atau kita boleh berhenti sebentar dan memikirkan semula strategi kita.
Masalah apa yang sebenarnya ingin kita selesaikan di sini?
State Management adalah mengenai mencari pendekatan yang baik untuk menyelesaikan dua masalah tertentu:
- Bagaimana agar aliran data dalam aplikasi dapat difahami?
- Bagaimana cara menjaga data keadaan selalu selari dengan antara muka pengguna (dan sebaliknya)?
Setelah menyelesaikan masalah ini, masalah lain yang mungkin anda miliki mungkin sudah selesai atau menjadi lebih mudah untuk diselesaikan. Terdapat banyak kemungkinan pendekatan untuk menyelesaikan masalah ini, tetapi kami akan menggunakan penyelesaian bersama yang terdiri daripada memusatkan data dan cara mengubahnya. Aliran data akan seperti ini:
Kami tidak akan membahas di sini bahagian di mana data secara automatik mencetuskan kemas kini paparan, kerana ia berkaitan dengan konsep Pemrograman Reaktif. Ini adalah subjek susulan yang baik jika anda ingin menyelam.
✅ Terdapat banyak perpustakaan di luar sana dengan pendekatan yang berbeza untuk pengurusan negeri, Redux menjadi pilihan yang popular. Lihat konsep dan corak yang digunakan kerana ini sering kali merupakan kaedah yang baik untuk mengetahui potensi masalah yang mungkin anda hadapi dalam aplikasi web besar dan bagaimana ia dapat diselesaikan.
Tugas
Kita akan mulakan dengan sedikit refactoring. Ganti pernyataan akaun
:
let account = null;
With:
let state = {
account: null
};
Ideanya adalah untuk memusatkan semua data aplikasi kami dalam satu objek keadaan. Kami hanya mempunyai akaun
untuk saat ini di negeri ini sehingga tidak banyak berubah, tetapi ini menciptakan jalan untuk evolusi.
Kita juga harus mengemas kini fungsi menggunakannya. Dalam fungsi register()
dan login()
, ganti account = ...
dengan state.account = ...
;
Di bahagian atas fungsi updateDashboard()
, tambahkan baris ini:
const account = state.account;
Pemfaktoran semula ini dengan sendirinya tidak membawa banyak peningkatan, tetapi ideanya adalah untuk meletakkan asas untuk perubahan selanjutnya.
Jejak perubahan data
Sekarang kita telah meletakkan objek state
untuk menyimpan data kita, langkah seterusnya adalah memusatkan kemas kini. Tujuannya adalah untuk menjadikannya lebih mudah untuk mengikuti setiap perubahan dan kapan ia berlaku.
Untuk mengelakkan berlakunya perubahan pada objek state
, adalah praktik yang baik untuk mempertimbangkannya tidak berubah, yang bermaksud bahawa ia tidak dapat diubah sama sekali. Ini juga bermaksud bahawa anda harus membuat objek keadaan baru jika anda ingin mengubah apa-apa di dalamnya. Dengan melakukan ini, anda membina perlindungan mengenai kesan sampingan, dan membuka kemungkinan untuk ciri baru dalam aplikasi anda seperti melaksanakan undo / redo, sambil mempermudah debug. Sebagai contoh, anda boleh mencatat setiap perubahan yang dibuat ke negeri dan menyimpan sejarah perubahan untuk memahami sumber pepijat.
Dalam JavaScript, anda boleh menggunakan Object.freeze()
untuk membuat versi yang tidak berubah dari sebuah objek. Sekiranya anda cuba membuat perubahan pada objek yang tidak dapat diubah, pengecualian akan ditimbulkan.
✅ Adakah anda tahu perbezaan antara objek cetek dan dalam tidak berubah? Anda boleh membacanya di sini.
Tugas
Mari buat fungsi updateState()
baru:
function updateState(property, newData) {
state = Object.freeze({
...state,
[property]: newData
});
}
Dalam fungsi ini, kami membuat objek keadaan baru dan menyalin data dari keadaan sebelumnya menggunakan operator spread (...
) operator. Kemudian kami menimpa harta benda objek tertentu dengan data baru menggunakan notasi kurungan [property]
untuk tugasan. Akhirnya, kita mengunci objek untuk mengelakkan pengubahsuaian menggunakan Object.freeze()
. Kami hanya menyimpan harta akaun
di negeri ini buat masa ini, tetapi dengan pendekatan ini anda dapat menambahkan seberapa banyak harta tanah yang anda perlukan di negeri ini.
Kami juga akan mengemas kini inisialisasi state
untuk memastikan keadaan awal juga dibekukan:
let state = Object.freeze({
account: null
});
After that, update the register
function by replacing the state.account = result;
assignment with:
updateState('account', result);
Do the same with the login
function, replacing state.account = data;
with:
updateState('account', data);
Kami sekarang akan mengambil kesempatan untuk memperbaiki masalah data akaun yang tidak dihapus ketika pengguna mengklik Logout.
Buat fungsi baru logout()
:
function logout() {
updateState('account', null);
navigate('/login');
}
Di updateDashboard()
, ganti pengalihan return navigate('/login');
dengan return logout()
;
Cuba daftarkan akaun baru, log keluar dan masuk sekali lagi untuk memeriksa bahawa semuanya masih berfungsi dengan betul.
Petua: anda dapat melihat semua perubahan keadaan dengan menambahkan
console.log(state)
di bahagian bawahupdateState()
dan membuka konsol di alat pengembangan penyemak imbas anda.
Kekalkan keadaan
Sebilangan besar aplikasi web perlu mengekalkan data agar dapat berfungsi dengan betul. Semua data kritikal biasanya disimpan di pangkalan data dan diakses melalui API pelayan, seperti data akaun pengguna dalam kes kami. Tetapi kadang-kadang, juga menarik untuk mengekalkan beberapa data pada aplikasi klien yang berjalan di penyemak imbas anda, untuk pengalaman pengguna yang lebih baik atau untuk meningkatkan prestasi pemuatan.
Apabila anda ingin menyimpan data dalam penyemak imbas anda, terdapat beberapa soalan penting yang harus anda tanyakan kepada diri sendiri:
- Adakah data sensitif? Anda harus mengelakkan menyimpan data sensitif pada pelanggan, seperti kata laluan pengguna.
- Berapa lama anda perlu menyimpan data ini? Adakah anda merancang untuk mengakses data ini hanya untuk sesi semasa atau adakah anda ingin menyimpannya selamanya?
Terdapat banyak cara untuk menyimpan maklumat di dalam aplikasi web, bergantung pada apa yang ingin anda capai. Sebagai contoh, anda boleh menggunakan URL untuk menyimpan pertanyaan carian, dan menjadikannya boleh dibagikan antara pengguna. Anda juga boleh menggunakan kuki HTTP jika data perlu dikongsi dengan pelayan, seperti pengesahan maklumat.
Pilihan lain adalah menggunakan salah satu dari banyak API penyemak imbas untuk menyimpan data. Dua daripadanya sangat menarik:
localStorage
: a Key/Value store yang memungkinkan untuk mengekalkan data khusus untuk laman web semasa di pelbagai sesi. Data yang disimpan di dalamnya tidak akan luput.sessionStorage
: ini berfungsi sama sepertilocalStorage
kecuali data yang disimpan di dalamnya dibersihkan semasa sesi berakhir (semasa penyemak imbas ditutup).
Perhatikan bahawa kedua-dua API ini hanya membenarkan menyimpan string. Sekiranya anda ingin menyimpan objek yang kompleks, anda perlu membuat siri ke siri JSON menggunakan JSON.stringify()
.
✅ Sekiranya anda ingin membuat aplikasi web yang tidak berfungsi dengan pelayan, anda juga boleh membuat pangkalan data pada klien menggunakan IndexedDB
API. Yang ini dikhaskan untuk kes penggunaan lanjutan atau jika anda perlu menyimpan sejumlah besar data, kerana lebih kompleks untuk digunakan.
Tugas
Kami mahu pengguna kami terus masuk sehingga mereka mengklik butang Logout secara eksplisit, jadi kami akan menggunakan localStorage
untuk menyimpan data akaun. Pertama, mari tentukan kunci yang akan kami gunakan untuk menyimpan data kami.
const storageKey = 'savedAccount';
Kemudian tambahkan baris ini pada akhir fungsi updateState()
:
localStorage.setItem(storageKey, JSON.stringify(state.account));
Dengan ini, data akaun pengguna akan dikekalkan dan sentiasa terkini semasa kami memusatkan semua kemas kini negeri sebelumnya. Di sinilah kita mula mendapat manfaat daripada semua reaktor kita sebelumnya 🙂.
Semasa data disimpan, kita juga harus menjaga memulihkannya ketika aplikasi dimuat. Oleh kerana kita akan mempunyai lebih banyak kod inisialisasi, mungkin ada baiknya membuat fungsi init
baru, yang juga merangkumi kod sebelumnya di bahagian bawah app.js
:
function init() {
const savedAccount = localStorage.getItem(storageKey);
if (savedAccount) {
updateState('account', JSON.parse(savedAccount));
}
// Kod permulaan kami sebelumnya
window.onpopstate = () => updateRoute();
updateRoute();
}
init();
Di sini kami mengambil data yang disimpan, dan jika ada, kami akan mengemas kini keadaan dengan sewajarnya. Penting untuk melakukan ini sebelum mengemas kini laluan, kerana mungkin ada kod yang bergantung pada keadaan semasa kemas kini halaman.
Kami juga dapat menjadikan halaman Dashboard sebagai halaman lalai aplikasi kami, karena kami sekarang masih menyimpan data akun. Sekiranya tidak ada data, dashboard akan mengalihkan ke halaman Login. Dalam updateRoute()
, ganti fallback return navigate ('/login');
dengan return navigate('dashboard');
.
Sekarang log masuk dalam aplikasi dan cuba memuat semula halaman, anda harus terus berada di papan pemuka. Dengan kemas kini itu, kami telah menangani semua masalah awal kami ...
Muat semula data
... Tetapi kita mungkin juga telah membuat yang baru. Alamak!
Pergi ke papan pemuka menggunakan akaun test
, kemudian jalankan perintah ini di terminal untuk membuat transaksi baru:
curl --request POST \
--header "Content-Type: application/json" \
--data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
http://localhost:5000/api/accounts/test/transactions
Cuba muat semula halaman papan pemuka anda di penyemak imbas sekarang. Apa yang berlaku? Adakah anda melihat transaksi baru?
Keadaan ini berterusan selama-lamanya berkat localStorage
, tetapi itu juga bermaksud ia tidak akan dikemas kini sehingga anda log keluar dari aplikasi dan log masuk semula!
Salah satu strategi yang mungkin untuk diperbaiki adalah memuat semula data akaun setiap kali dashboard dimuat, untuk mengelakkan data terhenti.
Tugas
Buat fungsi baru updateAccountData
:
async function updateAccountData() {
const account = state.account;
if (!account) {
return logout();
}
const data = await getAccount(account.user);
if (data.error) {
return logout();
}
updateState('account', data);
}
Kaedah ini memeriksa bahawa kita sedang log masuk dan memuat semula data akaun dari pelayan.
Buat fungsi lain bernama refresh
:
async function refresh() {
await updateAccountData();
updateDashboard();
}
Yang ini mengemas kini data akaun, kemudian mengurus mengemas kini HTML halaman papan pemuka. Inilah yang perlu kita panggil semasa laluan papan pemuka dimuat. Kemas kini definisi laluan dengan:
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard', init: refresh }
};
Cuba muatkan semula papan pemuka sekarang, ia akan memaparkan data akaun yang dikemas kini.
🚀 Cabaran
Setelah kita memuatkan semula data akaun setiap kali papan pemuka dimuat, adakah anda fikir kita masih perlu meneruskan semua data akaun?
Cuba bekerjasama untuk mengubah apa yang disimpan dan dimuat dari localStorage
untuk hanya memasukkan perkara yang benar-benar diperlukan agar aplikasi berfungsi.
Post-Lecture Quiz
Tugasan
Laksanakan dialog "Tambah transaksi"
Inilah hasil contoh setelah menyelesaikan tugasan: