Rumah >hujung hadapan web >tutorial js >Menyelam jauh ke redux
mata teras
Dalam artikel ini, saya akan meneroka bekas negara Redux dengan mendalam dengan membina enjin pemprosesan gaji. Aplikasi ini akan menyimpan gaji bersama -sama dengan semua tambahan seperti bonus dan pilihan saham. Saya akan menggunakan JavaScript Pure dan Typescript untuk pemeriksaan jenis untuk memastikan penyelesaiannya mudah. Oleh kerana Redux sangat mudah untuk diuji, saya juga akan menggunakan JEST untuk mengesahkan permohonan.
Dalam tutorial ini, saya menganggap anda mempunyai pemahaman tentang JavaScript, Node, dan NPM.
Pertama, anda boleh memulakan aplikasi ini dengan NPM:
<code class="language-bash">npm init</code>Apabila meminta arahan ujian, terus gunakan JEST. Ini bermakna bahawa NPM T akan memulakan jest dan menjalankan semua ujian unit. Fail utama akan menjadi index.js untuk memastikannya mudah. Jangan ragu untuk menjawab soalan NPM Init yang lain.
Saya akan menggunakan TypeScript untuk melakukan pemeriksaan jenis dan menentukan model data. Ini membantu mengkonseptualisasikan apa yang kita cuba bina.
untuk memulakan dengan TypeScript:
<code class="language-bash">npm i typescript --save-dev</code>Saya akan meletakkan beberapa kebergantungan dalam aliran kerja pembangunan dalam kebencian. Ini jelas menunjukkan kebergantungan yang disediakan untuk pemaju dan kebergantungan yang akan digunakan dalam persekitaran pengeluaran. Setelah TypeScript siap, tambahkan skrip permulaan dalam pakej.json:
<code class="language-json">"start": "tsc && node .bin/index.js"</code>Buat fail index.ts di bawah folder SRC. Ini memisahkan fail sumber dari seluruh projek. Sekiranya anda memulakan NPM, penyelesaiannya tidak akan dilaksanakan. Ini kerana anda perlu mengkonfigurasi TypeScript.
Buat fail tsconfig.json dengan konfigurasi berikut:
<code class="language-json">{ "compilerOptions": { "strict": true, "lib": ["esnext", "dom"], "outDir": ".bin", "sourceMap": true }, "files": [ "src/index" ] }</code>Saya boleh meletakkan konfigurasi ini dalam hujah baris arahan TSC. Sebagai contoh, TSC SRC/INDEX.TS -Strict .... tetapi meletakkan semua ini dalam fail berasingan jauh lebih jelas. Perhatikan bahawa skrip permulaan dalam pakej.json hanya memerlukan arahan TSC.
Berikut adalah beberapa pilihan pengkompil yang munasabah yang akan memberi kita titik permulaan yang baik dan apakah setiap pilihan bermakna:
kerana saya akan menggunakan jest untuk ujian unit, saya akan terus menambahkannya:
<code class="language-bash">npm init</code>
TS-Jest Dependency menambah pemeriksaan jenis untuk rangka kerja ujian. Satu perkara yang perlu diperhatikan adalah untuk menambah konfigurasi jest dalam pakej.json:
<code class="language-bash">npm i typescript --save-dev</code>
Ini membolehkan rangka kerja ujian untuk mengambil fail TypeScript dan mengetahui cara menukarnya. Ciri yang bagus ialah anda boleh melakukan pemeriksaan jenis semasa menjalankan ujian unit. Untuk memastikan projek ini siap, buat folder __Tests__ yang mengandungi fail index.test.ts. Kemudian, pemeriksaan sanitasi dilakukan. Contohnya:
<code class="language-json">"start": "tsc && node .bin/index.js"</code>Sekarang laksanakan permulaan NPM dan NPM T tidak akan menyebabkan sebarang kesilapan. Ini memberitahu kita bahawa kita kini boleh memulakan penyelesaian bangunan. Tetapi sebelum kita melakukan ini, mari tambahkan Redux ke projek:
<code class="language-json">{ "compilerOptions": { "strict": true, "lib": ["esnext", "dom"], "outDir": ".bin", "sourceMap": true }, "files": [ "src/index" ] }</code>Ketergantungan ini akan digunakan dalam persekitaran pengeluaran. Oleh itu, tidak perlu memasukkannya dengan--save-dev. Jika anda menyemak pakej.json anda, ia akan berada dalam kebergantungan.
enjin paystop dalam operasi sebenar
jadi ini meninggalkan jenis operasi berikut:
<code class="language-bash">npm i jest ts-jest @types/jest @types/node --save-dev</code>Jenis Operasi Pay_day boleh digunakan untuk mengeluarkan cek pada hari gaji dan trek sejarah gaji. Jenis operasi ini membimbing seluruh reka bentuk kerana kami menyempurnakan enjin gaji. Mereka menangkap peristiwa dalam kitaran hayat negeri, seperti menetapkan jumlah gaji asas. Peristiwa tindakan ini boleh dilampirkan pada sebarang kandungan, sama ada peristiwa klik atau kemas kini data. Jenis operasi Redux adalah abstrak tentang mana penjadualan datang. Bekas status boleh dijalankan pada klien dan/atau pada pelayan.
TypeScript
Sebagai contoh, masukkannya dalam src/index.ts:
<code class="language-json">"jest": { "preset": "ts-jest" }</code>Untuk status gaji, kita memerlukan atribut untuk gaji asas, bonus, dll. Kami juga akan menggunakan status ini untuk mengekalkan sejarah gaji.
Antara muka TypeScript ini harus dilakukan:
<code class="language-bash">npm init</code>
Bagi setiap harta, perhatikan bahawa TypeScript menggunakan kolon untuk menentukan jenis. Sebagai contoh,: nombor. Ini menentukan kontrak jenis dan menambah kebolehprediksi kepada pemeriksa jenis. Redux boleh dipertingkatkan menggunakan sistem jenis dengan pengisytiharan jenis eksplisit. Ini kerana bekas negara Redux dibina untuk tingkah laku yang boleh diramal.
Idea ini tidak gila atau radikal. Pembelajaran Redux Bab 1 (ahli Premium SitePoint sahaja) menerangkan ini dengan baik.
Apabila perubahan aplikasi, pemeriksaan taip menambah ramalan tambahan. Apabila aplikasi berkembang, teori jenis juga membantu memudahkan pembinaan semula segmen kod besar.
menggunakan enjin konseptualisasi jenis sekarang membantu membuat fungsi operasi berikut:
<code class="language-bash">npm i typescript --save-dev</code>
Perkara yang baik ialah jika anda cuba melakukan ProcessBasePay ('ABC'), pemeriksa jenis akan memberi amaran kepada anda. Memusnahkan kontrak jenis mengurangkan kebolehprediksi bekas negara. Saya menggunakan kontrak operasi tunggal seperti PayrollAction untuk menjadikan pemproses gaji lebih diramalkan. Ambil perhatian bahawa jumlahnya ditetapkan dalam objek Operasi melalui singkatan atribut ES6. Pendekatan yang lebih tradisional adalah jumlah: jumlah, yang lebih verbose. Fungsi anak panah, seperti () = & gt;
Contoh:
<code class="language-json">"start": "tsc && node .bin/index.js"</code>Pemeriksa jenis memastikan bahawa ini adalah nilai yang betul kepunyaan objek ini. Dengan keadaan awal, mula membuat fungsi reducer:
<code class="language-json">{ "compilerOptions": { "strict": true, "lib": ["esnext", "dom"], "outDir": ".bin", "sourceMap": true }, "files": [ "src/index" ] }</code>redux reducer mempunyai corak di mana semua jenis operasi diproses oleh penyataan suis. Tetapi sebelum meleleh melalui semua kes suis, saya akan membuat pembolehubah tempatan yang boleh diguna semula:
<code class="language-bash">npm i jest ts-jest @types/jest @types/node --save-dev</code>Perhatikan bahawa jika anda tidak mengubah keadaan global, anda boleh mengubah pembolehubah tempatan. Saya menggunakan pengendali LET untuk menyampaikan bahawa pembolehubah ini akan berubah pada masa akan datang. Mengubah keadaan global (seperti parameter negeri atau operasi) boleh menyebabkan pengurangan menjadi tidak suci. Paradigma berfungsi ini penting kerana fungsi reducer mesti disimpan murni. JavaScript dari Newbie ke Ninja Bab 11 (ahli SitePoint Premium sahaja).
Mulakan pernyataan suis pengurangan untuk mengendalikan kes penggunaan pertama:
<code class="language-json">"jest": { "preset": "ts-jest" }</code>Saya menggunakan pengendali REST ES6 untuk memastikan harta negara tidak berubah. Sebagai contoh, ... Negeri. Anda boleh menulis ganti sebarang atribut selepas pengendali lain dalam objek baru. Basepay berasal dari dekonstruksi, yang sama seperti corak yang sepadan dalam bahasa lain. Fungsi ComputeToTalPay ditetapkan seperti berikut:
<code class="language-typescript">it('is true', () => { expect(true).toBe(true); });</code>Sila ambil perhatian bahawa anda akan memotong stok stok kerana wang itu akan digunakan untuk membeli stok syarikat. Katakan anda ingin berurusan dengan pembayaran balik:
<code class="language-bash">npm init</code>
Oleh kerana jumlahnya adalah pilihan, pastikan ia mempunyai nilai lalai untuk mengurangkan kegagalan. Ini adalah kelebihan TypeScript, kerana pemeriksa jenis akan melihat perangkap ini dan memberi amaran kepada anda. Sistem jenis tahu fakta tertentu, jadi ia boleh membuat andaian yang munasabah. Katakan anda ingin berurusan dengan bonus:
<code class="language-bash">npm i typescript --save-dev</code>
Mod ini menjadikan reducer boleh dibaca kerana ia hanya mengekalkan keadaan. Anda mendapat jumlah operasi, hitung jumlah gaji, dan buat teks objek baru. Tidak ada yang berbeza ketika berurusan dengan pilihan saham:
<code class="language-json">"start": "tsc && node .bin/index.js"</code>
Untuk memproses gaji pada hari gaji, ia memerlukan pemadaman bonus dan pembayaran balik. Kedua -dua atribut ini tidak disimpan di negeri ini dalam setiap gaji. Dan, tambahkan kemasukan ke sejarah gaji. Upah asas dan pilihan saham boleh disimpan di negeri ini kerana mereka tidak sering berubah. Dengan itu, ini adalah bagaimana Pay_day dikendalikan:
<code class="language-json">{ "compilerOptions": { "strict": true, "lib": ["esnext", "dom"], "outDir": ".bin", "sourceMap": true }, "files": [ "src/index" ] }</code>
Dalam array seperti NewPayHistory, gunakan pengendali lanjutan, yang merupakan antonim untuk berehat. Tidak seperti harta benda dalam objek koleksi, ia memperluaskan projek. Sebagai contoh, [... payhistory]. Walaupun kedua -dua pengendali kelihatan sama, mereka tidak sama. Tonton dengan teliti, kerana ini mungkin muncul dalam soalan wawancara.
menggunakan pop () untuk payhistory tidak akan mengubah keadaan. Kenapa? Kerana Slice () mengembalikan array baru. Array dalam JavaScript disalin dengan rujukan. Menetapkan array ke pembolehubah baru tidak mengubah objek yang mendasari. Oleh itu, penjagaan mesti diambil semasa berurusan dengan jenis objek ini.
Kerana lastPayHistory mungkin tidak ditentukan, saya menggunakan nilai null lelaki miskin untuk memulakannya kepada sifar. Sila ambil perhatian bahawa (O && O.Property) || Mungkin ada cara yang lebih elegan untuk melakukan ini dalam versi masa depan JavaScript atau bahkan TypeScript.
Setiap pengurangan redux mesti menentukan cawangan lalai. Untuk memastikan bahawa Negeri tidak menjadi tidak jelas:
<code class="language-bash">npm i jest ts-jest @types/jest @types/node --save-dev</code>
Salah satu daripada banyak manfaat menulis fungsi tulen ialah mereka mudah diuji. Ujian unit adalah ujian di mana anda perlu mengharapkan tingkah laku yang boleh diramal, dan anda boleh mengautomasikan semua ujian sebagai sebahagian daripada binaan. Dalam __Tests __/index.test.ts, membatalkan ujian maya dan mengimport semua fungsi kepentingan:
<code class="language-json">"jest": { "preset": "ts-jest" }</code>
Perhatikan bahawa semua fungsi ditetapkan untuk dieksport, jadi anda boleh mengimportnya. Untuk gaji asas, mulakan pengurangan enjin gaji dan uji:
<code class="language-typescript">it('is true', () => { expect(true).toBe(true); });</code>
Redux menetapkan keadaan awal untuk tidak ditentukan. Oleh itu, adalah idea yang baik untuk memberikan nilai lalai dalam fungsi reducer. Bagaimana dengan pengendalian pembayaran balik?
<code class="language-bash">npm i redux --save</code>
Corak bonus pengendalian adalah sama seperti ini:
<code class="language-typescript">const BASE_PAY = 'BASE_PAY'; const REIMBURSEMENT = 'REIMBURSEMENT'; const BONUS = 'BONUS'; const STOCK_OPTIONS = 'STOCK_OPTIONS'; const PAY_DAY = 'PAY_DAY';</code>
untuk pilihan saham:
<code class="language-typescript">interface PayrollAction { type: string; amount?: number; }</code>
Perhatikan bahawa apabila stockoptions lebih besar daripada totalpay, totalpay mesti kekal tidak berubah. Oleh kerana syarikat hipotetikal ini beretika, ia tidak mahu mengambil wang dari pekerjanya. Jika anda menjalankan ujian ini, sila ambil perhatian bahawa TotalPay ditetapkan kepada -10, kerana stok akan ditolak. Inilah sebabnya kami menguji kod! Mari kita selesaikan tempat di mana jumlah gaji dikira:
<code class="language-bash">npm init</code>
Jika wang yang diperoleh oleh pekerja tidak mempunyai cukup wang untuk membeli saham syarikat, sila terus melangkau potongan. Juga, pastikan ia menetapkan semula stok ke sifar:
<code class="language-bash">npm i typescript --save-dev</code>
Pembetulan ini menentukan sama ada mereka mempunyai cukup wang dalam NewStockOptions. Dengan ini, ujian unit berlalu, kod itu adalah bunyi dan bermakna. Kami boleh menguji kes penggunaan positif di mana terdapat cukup wang untuk membuat potongan:
<code class="language-json">"start": "tsc && node .bin/index.js"</code>
untuk hari paydays, gunakan pelbagai status untuk menguji dan pastikan transaksi satu kali tidak berterusan:
<code class="language-json">{ "compilerOptions": { "strict": true, "lib": ["esnext", "dom"], "outDir": ".bin", "sourceMap": true }, "files": [ "src/index" ] }</code>
Perhatikan bagaimana saya menyesuaikan Oldstate untuk mengesahkan bonus dan menetapkan semula pembayaran balik kepada sifar.
Bagaimana dengan cawangan lalai dalam pengurangan?
<code class="language-bash">npm i jest ts-jest @types/jest @types/node --save-dev</code>
redux menetapkan jenis operasi seperti init_action pada mulanya. Kami hanya peduli sama ada pengurangan kami mempunyai beberapa set keadaan awal.
Pada ketika ini, anda mungkin mula tertanya -tanya jika Redux lebih banyak corak reka bentuk. Jika anda menjawab bahawa ia adalah corak dan perpustakaan ringan, anda betul. Dalam index.ts, import redux:
<code class="language-json">"jest": { "preset": "ts-jest" }</code>
Contoh kod seterusnya boleh dibalut ini jika pernyataan. Ini adalah stopgap jadi ujian unit tidak bocor ke ujian integrasi:
<code class="language-typescript">it('is true', () => { expect(true).toBe(true); });</code>
Saya tidak mengesyorkan melakukan ini dalam projek sebenar. Modul boleh diletakkan dalam fail berasingan untuk mengasingkan komponen. Ini menjadikannya lebih mudah dibaca dan tidak membocorkan masalah. Ujian unit juga mendapat manfaat daripada fakta bahawa modul berjalan secara bebas.
Gunakan PayrollEnginereducer untuk memulakan penyimpanan Redux:
<code class="language-bash">npm i redux --save</code>
setiap kedai.subscribe () mengembalikan fungsi berhenti berlangganan () berikutnya yang boleh digunakan untuk pembersihan. Ia berhenti melanggan panggilan balik apabila ia dijadualkan melalui storan. Di sini saya menggunakan Store.getState () untuk mengeluarkan keadaan semasa ke konsol.
Katakan pekerja memperoleh 300, mempunyai 50 pembayaran balik, 100 bonus, dan 15 untuk stok syarikat:
<code class="language-typescript">const BASE_PAY = 'BASE_PAY'; const REIMBURSEMENT = 'REIMBURSEMENT'; const BONUS = 'BONUS'; const STOCK_OPTIONS = 'STOCK_OPTIONS'; const PAY_DAY = 'PAY_DAY';</code>
untuk menjadikannya lebih menyeronokkan, membuat 50 lagi pembayaran balik dan memproses gaji lain:
<code class="language-typescript">interface PayrollAction { type: string; amount?: number; }</code>
Akhirnya, jalankan gaji lain dan berhenti berlangganan untuk penyimpanan redux:
<code class="language-typescript">interface PayStubState { basePay: number; reimbursement: number; bonus: number; stockOptions: number; totalPay: number; payHistory: Array<payhistorystate>; } interface PayHistoryState { totalPay: number; totalCompensation: number; }</payhistorystate></code>
Hasil akhir adalah seperti berikut:
<code class="language-typescript">export const processBasePay = (amount: number): PayrollAction => ({type: BASE_PAY, amount}); export const processReimbursement = (amount: number): PayrollAction => ({type: REIMBURSEMENT, amount}); export const processBonus = (amount: number): PayrollAction => ({type: BONUS, amount}); export const processStockOptions = (amount: number): PayrollAction => ({type: STOCK_OPTIONS, amount}); export const processPayDay = (): PayrollAction => ({type: PAY_DAY});</code>
Seperti yang ditunjukkan, Redux mengekalkan keadaan, mengubah keadaan dan memberitahu pelanggan dalam pakej kecil yang kemas. Fikirkan Redux sebagai mesin negara, yang merupakan sumber sebenar data negara. Semua ini mengamalkan amalan terbaik pengekodan, seperti paradigma fungsional yang baik.
Redux menyediakan penyelesaian mudah kepada masalah pengurusan negara yang kompleks. Ia bergantung kepada paradigma berfungsi untuk mengurangkan ketidakpastian. Kerana reducer adalah fungsi tulen, ujian unit sangat mudah. Saya memutuskan untuk menggunakan JEST, tetapi sebarang rangka kerja ujian yang menyokong dakwaan asas akan berfungsi.
TypeScript menggunakan teori jenis untuk menambah lapisan perlindungan tambahan. Campurkan pemeriksaan jenis dengan pengaturcaraan berfungsi dan anda mendapat kod kukuh yang hampir tidak pernah terganggu. Paling penting, TypeScript tidak mendapat cara bekerja semasa menambah nilai. Jika anda perasan, sebaik sahaja kontrak jenis disediakan, hampir tidak ada pengekodan tambahan. Pemeriksa jenis melakukan selebihnya. Seperti mana -mana alat yang baik, TypeScript mengotomatisasi disiplin pengekodan sementara masih tidak kelihatan. Typescript menyalak dengan kuat, tetapi ia menggigit ringan.
Jika anda ingin mencuba projek ini (saya harap anda melakukan ini), anda boleh mencari kod sumber untuk artikel ini di GitHub.
Atas ialah kandungan terperinci Menyelam jauh ke redux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!