Saya jenis pemaju yang suka bermula dari awal dan memahami bagaimana semuanya berfungsi. Walaupun saya tahu ini membawa diri saya beban kerja (tidak perlu), ia membantu saya menghargai dan memahami mekanisme di sebalik kerangka, perpustakaan, atau modul tertentu.
React adalah perpustakaan sumber terbuka berasaskan komponen yang dicipta oleh Facebook untuk membina antara muka pengguna. Walaupun React hanyalah lapisan pandangan (
bukan rangka kerja lengkap seperti sudut atau ember
redux bebas reaksi-aplikasi dari awal
Aplikasi yang dipersoalkan adalah klon Tetris pertama mudah alih dengan beberapa pandangan yang berbeza. Logik permainan sebenar dilakukan di Redux, sementara fungsi luar talian disediakan oleh LocalStorage dan pemprosesan paparan tersuai. Repositori ini boleh didapati di GitHub, walaupun aplikasinya masih dalam perkembangan aktif dan saya menulis artikel ini semasa pembangunan.
Saya memutuskan untuk mengadopsi struktur folder yang biasa dalam projek Redux dan React. Ini adalah struktur logik yang berfungsi untuk pelbagai tetapan yang berbeza. Terdapat banyak variasi topik ini, kebanyakan projek sedikit berbeza, tetapi struktur keseluruhan adalah sama.
<code>actions/ ├── game.js ├── score.js └── ... components/ ├── router.js ├── pageControls.js ├── canvas.js └── ... constants/ ├── game.js ├── score.js └── ... reducers/ ├── game.js ├── score.js └── ... store/ ├── configureStore.js ├── connect.js └── index.js utils/ ├── serviceWorker.js ├── localStorage.js ├── dom.js └── ... index.js worker.js</code>
src/markup/
<code>layouts/ └── default.html partials/ ├── back-button.html └── meta.html pages/ ├── about.html ├── settings.html └── ... index.html</code>
lelaran pertama saya gagal. Saya tidak tahu mengapa saya fikir ini adalah idea yang baik, tetapi saya meletakkan storan dalam modulnya sendiri (skrip/kedai/indeks.js) yang kemudiannya boleh diimport oleh seluruh aplikasi. Saya akhirnya menyesal dan dengan cepat menangani kebergantungan bulat. Masalahnya ialah apabila komponen cuba mengakses storan, storan tidak dimulakan dengan betul. Saya membuat carta untuk menunjukkan aliran ketergantungan yang sedang saya jalankan:
Titik kemasukan aplikasi memulakan semua komponen dan kemudian menggunakan storan secara dalaman sama ada secara langsung atau melalui fungsi penolong (di sini dirujuk sebagai
). Walau bagaimanapun, kerana storan tidak dibuat secara eksplisit, tetapi hanya kesan sampingan dalam modulnya sendiri, komponen itu berakhir dengan menggunakan storan sebelum dibuat. Tiada kawalan ke atas masa apabila fungsi komponen atau penolong pertama kali dipanggil untuk disimpan. Ini sangat mengelirukan. modul penyimpanan adalah seperti berikut:
Skrip/Store/Index.js
(☓ Bad)Seperti yang disebutkan di atas, storan dibuat sebagai kesan sampingan dan kemudian dieksport. Fungsi penolong juga perlu disimpan.
import { createStore } from 'redux' import reducers from '../reducers' const store = createStore(reducers) export default store export { getItemList } from './connect'
Skrip/Store/Connect.js
(☓ Bad)Ini adalah tepat ketika komponen saya akhirnya berulang antara satu sama lain. Fungsi penolong memerlukan penyimpanan untuk dijalankan dan dieksport dari fail inisialisasi storan pada masa yang sama supaya mereka dapat mengakses bahagian lain aplikasi. Adakah anda melihat bagaimana keadaan ini tidak kemas?
import store from './' export function getItemList () { return store.getState().items.all }
Penyelesaian
Sekali lagi, ini sangat mirip dengan bagaimana React sebenarnya menjadikan penyimpanan boleh diakses (lihat kod sumber). Ada sebab mereka bekerja dengan baik bersama -sama, mengapa tidak mempelajari konsepnya?
mari kita lihat perubahan:
skrip/kedai/configurestore.js(✓ baik)
Saya menyimpan modul, tetapi sebaliknya mengeksport fungsi yang dipanggil ConfigureStore yang mewujudkan penyimpanan di tempat lain di pangkalan kod.
Perhatikan bahawa ini hanyalah konsep asas;<code>actions/ ├── game.js ├── score.js └── ... components/ ├── router.js ├── pageControls.js ├── canvas.js └── ... constants/ ├── game.js ├── score.js └── ... reducers/ ├── game.js ├── score.js └── ... store/ ├── configureStore.js ├── connect.js └── index.js utils/ ├── serviceWorker.js ├── localStorage.js ├── dom.js └── ... index.js worker.js</code>
Skrip/Store/Connect.js (✓ Baik)
Sambungkan fungsi penolong pada dasarnya tidak berubah, tetapi kini storan perlu diluluskan sebagai parameter. Pada mulanya saya teragak -agak untuk menggunakan penyelesaian ini kerana saya fikir "jadi apa fungsi penolong?" Sekarang saya fikir mereka cukup baik dan cukup maju untuk menjadikan semuanya lebih mudah dibaca.
<code>layouts/ └── default.html partials/ ├── back-button.html └── meta.html pages/ ├── about.html ├── settings.html └── ... index.html</code>
Ini adalah titik masuk aplikasi. Kedai dicipta dan diserahkan kepada semua komponen. PageControls menambah pendengar acara global untuk butang tindakan tertentu, dan Tetrisgame adalah komponen permainan sebenar. Ia kelihatan pada dasarnya sama sebelum memindahkan storan di sini, tetapi tidak lulus storan secara berasingan ke semua modul. Seperti yang dinyatakan sebelum ini, komponen boleh mengakses storan melalui kaedah sambungan saya yang gagal.
komponen
import { createStore } from 'redux' import reducers from '../reducers' const store = createStore(reducers) export default store export { getItemList } from './connect'
Saya memutuskan untuk menggunakan dua komponen:
Dan Abramov telah menulis artikel hebat untuk komponen React, tetapi kaedah ini juga boleh digunakan untuk mana -mana seni bina komponen lain.
Contoh di atas adalah salah satu komponen. Ia mempunyai senarai elemen (dalam kes ini semua elemen dengan atribut tindakan-tindakan) dan tindakan jadual apabila diklik berdasarkan kandungan atribut. Itu sahaja. Modul lain kemudian boleh mendengar perubahan dalam penyimpanan dan mengemas kini diri mereka dengan sewajarnya. Seperti yang dinyatakan sebelum ini, jika komponen juga mempunyai kemas kini DOM, saya akan memisahkannya.
Sekarang, izinkan saya menunjukkan kepada anda pemisahan yang jelas dari kedua -dua jenis komponen ini.
import store from './' export function getItemList () { return store.getState().items.all }
Masalah yang lebih besar yang saya ada ketika saya memulakan projek adalah bagaimana untuk mengemas kini DOM. React menggunakan perwakilan dalam memori yang cepat DOM yang dipanggil DOM maya untuk meminimumkan kemas kini DOM.
saya sebenarnya berfikir untuk melakukan perkara yang sama, jika permohonan saya semakin besar dan Dom lebih membosankan, saya mungkin beralih ke dom maya, tetapi sekarang saya sedang melakukan operat Dom Classic , yang mana Bekerja dengan baik dengan Redux.
Proses asas adalah seperti berikut:
NOTA: Saya peminat awalan simbol $ untuk apa -apa yang berkaitan dengan DOM dalam JavaScript. Seperti yang anda rasa, ia diambil dari $ JQuery's $. Oleh itu, nama fail komponen persembahan tulen diawali dengan tanda dolar.
skrip/index.js
<code>actions/ ├── game.js ├── score.js └── ... components/ ├── router.js ├── pageControls.js ├── canvas.js └── ... constants/ ├── game.js ├── score.js └── ... reducers/ ├── game.js ├── score.js └── ... store/ ├── configureStore.js ├── connect.js └── index.js utils/ ├── serviceWorker.js ├── localStorage.js ├── dom.js └── ... index.js worker.js</code>
Tidak ada yang mewah di sini. Import, Buat, dan Inisialisasi SCOREBSERVER SCOREBSERVER. Apa sebenarnya yang dilakukannya? Ia mengemas kini semua elemen paparan yang berkaitan dengan skor: Senarai skor tinggi dan maklumat skor semasa semasa permainan.
skrip/komponen/scorobserver/index.js
<code>layouts/ └── default.html partials/ ├── back-button.html └── meta.html pages/ ├── about.html ├── settings.html └── ... index.html</code>
ingat, ini adalah komponen yang mudah; Apa yang berlaku di sini? Komponen scorobserver menjimatkan rujukan dalaman ke storan dan mewujudkan dua komponen peringkat persembahan contoh baru untuk kegunaan kemudian. Kaedah INIT melanggan kemas kini penyimpanan dan mengemas kini komponen label $ setiap kali storan berubah - tetapi hanya jika permainan sebenarnya berjalan.
Kaedah Kemas kiniCorboard digunakan di tempat lain. Tidak masuk akal untuk mengemas kini senarai setiap kali perubahan berlaku, kerana pandangan itu tidak aktif pula. Terdapat juga komponen penghalaan yang mengemas kini atau menyahaktifkan komponen yang berbeza setiap kali perubahan pandangan. APInya kira -kira seperti berikut:
import { createStore } from 'redux' import reducers from '../reducers' const store = createStore(reducers) export default store export { getItemList } from './connect'
Nota: $ (dan $$) bukan rujukan jQuery, tetapi pintasan utiliti yang mudah untuk Document.QuerySelector.
skrip/komponen/scorobserver/$ board.js
import store from './' export function getItemList () { return store.getState().items.all }
Sekali lagi, ini adalah contoh asas dan komponen asas. Kaedah UpdateBoard () mengambil array, melangkah ke atasnya, dan memasukkan kandungan ke dalam senarai skor.
skrip/komponen/scorobserver/$ label.js
import { createStore } from 'redux' import reducers from '../reducers' export default function configureStore () { return createStore(reducers) }
Komponen ini hampir sama seperti papan skor di atas, tetapi hanya mengemas kini elemen tunggal.
Satu lagi perkara penting ialah melaksanakan menggunakan penyimpanan yang didorong oleh kes. Saya fikir penting untuk menyimpan kandungan yang penting untuk permohonan itu. Pada mulanya, saya hampir menyimpan segala -galanya: pandangan aktif semasa, tetapan permainan, skor, kesan hover, mod pernafasan pengguna dan sebagainya.
Walaupun ini mungkin berkaitan dengan satu aplikasi, ia tidak ada kaitan dengan yang lain. Mungkin bagus untuk menyimpan pandangan semasa dan terus di tempat yang sama apabila dimuat semula, tetapi dalam kes saya ia merasakan pengalaman pengguna yang buruk dan lebih menjengkelkan daripada berguna. Anda tidak mahu menyimpan menu atau suis modal, bukan? Mengapa pengguna perlu kembali ke keadaan tertentu itu? Dalam aplikasi web yang lebih besar, ini mungkin masuk akal. Tetapi dalam permainan fokus permainan mudah alih kecil saya, kembali ke skrin tetapan hanya kerana saya pergi dari sana, yang cukup menjengkelkan.
Saya telah melakukan projek Redux saya dengan dan tanpa bertindak balas, dan pengambilan utama saya adalah bahawa perbezaan besar dalam reka bentuk aplikasi tidak diperlukan. Kebanyakan kaedah yang digunakan dalam React sebenarnya boleh sesuai dengan mana -mana tetapan pemprosesan pandangan lain. Saya mengambil masa untuk menyedari ini kerana saya fikir pada mulanya saya terpaksa melakukan sesuatu yang berbeza, tetapi saya akhirnya mendapati ia tidak perlu.
Apa pendapat anda mengenai kaedah saya? Adakah anda menggunakan redux dan pandangan yang berbeza untuk mengendalikan tetapan sahaja? Saya suka mendengar daripada anda dan membincangkannya dalam komen.
Jika anda ingin mengetahui lebih lanjut mengenai Redux, lihat kursus kami "Menulis semula dan menguji Redux untuk menyelesaikan masalah reka bentuk" Kursus mini. Dalam kursus ini, anda akan membina aplikasi Redux yang menerima tweet yang dianjurkan oleh topik melalui sambungan WebSocket. Untuk memberi anda idea tentang apa yang akan berlaku, lihat kursus percuma di bawah.
Apakah perbezaan utama antara menggunakan Redux dan React dan tidak menggunakan React?
Redux adalah bekas keadaan yang boleh diramal untuk aplikasi JavaScript yang boleh digunakan dengan mana -mana lapisan UI. Perbezaan utama antara menggunakan Redux vs React dan tidak menggunakan React adalah bagaimana lapisan UI berinteraksi dengan penyimpanan Redux. Apabila digunakan dengan React, Redux boleh memanfaatkan seni bina berasaskan komponen React dan pendekatan kitaran hayatnya untuk mengendalikan kemas kini komponen secara automatik apabila perubahan keadaan dibuat. Tanpa React, anda perlu melanggan secara manual penyimpanan dan mengendalikan kemas kini ke UI apabila status berubah.Ya, redux devtools tidak bergantung kepada reaksi dan boleh digunakan dengan mana -mana lapisan UI yang menggunakan redux. Anda boleh mengintegrasikan Redux Devtools ke dalam aplikasi anda dengan menambahkannya sebagai middleware ketika membuat storan Redux. Ini akan membolehkan anda menyemak status dan tindakan permohonan anda dalam masa nyata, walaupun tanpa bertindak balas.
Tanpa React dan Fungsi Sambungannya, anda perlu melanggan secara manual penyimpanan Redux dan mengemas kini komponen UI apabila keadaan berubah. Anda boleh melanggan kedai menggunakan kaedah Store.Subscribe, yang mengambil fungsi pendengar yang akan dipanggil setiap kali operasi dijadualkan. Dalam fungsi pendengar ini, anda boleh menggunakan Store.getState untuk mendapatkan keadaan semasa penyimpanan dan mengemas kini komponen UI dengan sewajarnya.
Ya, Redux tidak bergantung pada React dan boleh digunakan dengan mana -mana lapisan UI. Bagi perpustakaan dan kerangka lain seperti Vue dan Angular, pengikatan disediakan yang menyediakan fungsi yang sama kepada fungsi Connect React. Pengikatan ini membolehkan anda dengan mudah menyambungkan komponen UI ke penyimpanan redux dan mengendalikan kemas kini komponen apabila keadaan berubah.
Menguji kod redux tanpa React adalah serupa dengan menguji dengan bertindak balas. Anda boleh membuat ujian unit untuk pencipta dan pengurangan tindakan anda menggunakan rangka kerja ujian JavaScript seperti Jest atau Mocha. Untuk menguji operasi asynchronous, anda boleh menggunakan penyimpanan mock untuk mensimulasikan penyimpanan redux.
Kesan sampingan di redux biasanya dikendalikan menggunakan middleware seperti Redux Thunk atau Redux Saga. Middleware ini membolehkan anda menjadualkan fungsi dengan kesan sampingan atau operasi tak segerak yang lebih kompleks, seperti membuat panggilan API. Walaupun tanpa React, anda masih boleh menggunakan middleware ini dalam penyimpanan Redux.
Ya, Redux boleh digunakan dengan JavaScript tulen. Anda boleh membuat kedai Redux, menjadualkan tindakan kepadanya, dan melanggan perubahan dalam keadaan menggunakan hanya JavaScript tulen. Walau bagaimanapun, jika tidak ada perpustakaan atau rangka kerja seperti React untuk mengendalikan kemas kini ke UI, anda perlu mengemas kini komponen UI secara manual apabila keadaan berubah.
Struktur kod redux tidak bergantung kepada sama ada anda menggunakan React. Anda masih boleh mengikuti amalan terbaik yang sama untuk membina kod Redux, seperti memisahkan operasi, pengurangan, dan pemilih ke dalam fail atau folder yang berbeza dan menganjurkan keadaan anda dengan cara yang normal dan modular.
Ya, middleware Redux tidak bergantung pada reaksi dan boleh digunakan dengan mana -mana lapisan UI yang menggunakan Redux. Middleware di Redux digunakan untuk mengendalikan kesan sampingan dan operasi tak segerak, dan sebagainya. Anda boleh menggunakan Redux memohon middleware ke storan redux anda menggunakan fungsi ApplyMidDleware Redux, sama ada anda menggunakan React atau tidak.
Atas ialah kandungan terperinci Redux tanpa bertindak balas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!