Artikel ini adalah tanggapan terhadap artikel terjemahan
“Cara mencari pengguna di GitHub menggunakan React + RxJS 6 + Komposisi Ulang” , yang baru saja kemarin mengajarkan kita bagaimana menggunakan React, RxJS, dan Komposisi Ulang bersama-sama. Baiklah, saya usulkan sekarang untuk melihat bagaimana ini dapat diimplementasikan tanpa alat-alat ini.

PenafianTampaknya banyak orang bahwa artikel ini mengandung elemen trolling, ditulis dengan tergesa-gesa dan pada penggemar ... Jadi, ini benar.
Karena ini adalah artikel kembali, saya memutuskan untuk membangunnya dalam format langkah-demi-langkah yang sama seperti aslinya. Selain itu, artikel ini juga bertujuan untuk membandingkan implementasi asli dengan yang dijelaskan di sini. Oleh karena itu, berisi banyak referensi dan kutipan dari aslinya. Mari kita mulai.
Artikel ini ditujukan untuk orang yang berpengalaman dengan Bereaksi dan RxJS. Saya hanya berbagi templat yang menurut saya berguna untuk membuat UI seperti itu.
Artikel ini ditujukan untuk orang yang berpengalaman dengan Javascript (ES6), HTML, dan CSS. Selain itu, dalam implementasi saya, saya akan menggunakan
kerangka SvelteJS "menghilang" , tetapi sangat sederhana sehingga Anda tidak perlu memiliki pengalaman menggunakannya untuk memahami kode.
Kami melakukan hal yang sama:

Tanpa kelas, bekerja dengan siklus hidup atau setState.
Ya, tanpa kelas, bekerja dengan siklus hidup atau setState. Dan juga tanpa React, ReactDOM, RxJS, Recompose. Dan selain itu, tanpa componentFromStream, buatEventHandler, kombinasikanterakhir, peta, mulaiDengan, setObservableConfig, BehaviorSubject, gabung, dari, catchError, delay, filter, map, pluck, switchMap, tap, {omong kosong lain} ... Singkatnya, Anda mengerti.
Persiapan
Yang Anda butuhkan adalah dalam
contoh REPL saya di situs web SvelteJS. Anda dapat mengendus di sana, baik secara lokal, mengunduh sumber dari sana (tombol dengan ikon karakteristik).
Pertama, buat file App.html sederhana, yang akan menjadi komponen root dari widget kami, dengan konten berikut:
<input placeholder="GitHub username"> <style> input { font-size: 20px; border: 1px solid black; border-radius: 3px; margin-bottom: 10px; padding: 10px; } </style>
Selanjutnya, saya menggunakan gaya dari artikel asli. Harap perhatikan bahwa saat ini mereka berada dalam ruang lingkup, mis. hanya berlaku untuk komponen ini dan Anda dapat menggunakan nama tag dengan aman jika relevan.
Saya akan menulis gaya langsung di komponen, karena SFC, dan juga karena REPL tidak mendukung ekspor CSS / JS / HTML ke file yang berbeda, meskipun ini mudah dilakukan dengan menggunakan
preprocessors Svelte .
Komposisikan ulang
Sedang beristirahat ...
Komponen sebaris
... berjemur ...
Konfigurasi
... minum kopi ...
Komposisi ulang + RxJS
... sementara yang lain ...
Peta
... bekerja.
Tambahkan pengendali acara
Bukan benar-benar seorang pawang tentu saja, hanya yang mengikat:
<input bind:value=username placeholder="GitHub username">
Ya, kami mendefinisikan nilai nama pengguna default:
<script> export default { data() { return { username: '' }; } }; </script>
Sekarang, jika Anda mulai mengetik sesuatu di bidang input, nilai nama pengguna akan berubah.

Masalah telur dan ayam
Tidak ada ayam, tidak ada telur, tidak ada masalah dengan hewan lain, kami tidak menggunakan RxJS.
Merajut bersama
Semuanya sudah reaktif dan terkoneksi. Jadi kita minum kopi.
Komponen Pengguna
Komponen ini akan bertanggung jawab untuk menampilkan pengguna yang namanya akan kami transfer kepadanya. Ini akan menerima nilai dari komponen App dan menerjemahkannya ke dalam permintaan AJAX.
"Wow wow wow, tenang saja" ©
Bersama kami, komponen ini akan menjadi bodoh dan hanya menampilkan kartu pengguna yang cantik sesuai dengan model yang diketahui sebelumnya. Tidak masalah dari mana data dapat berasal dan / atau di tempat antarmuka mana kami ingin menunjukkan kartu ini.
Komponen User.html akan terlihat seperti ini:
<div class="github-card user-card"> <div class="header User" /> <a class="avatar" href="https://github.com/{login}"> <img src="{avatar_url}&s=80" alt={name}> </a> <div class="content"> <h1>{name || login}</h1> <ul class="status"> <li> <a href="https://github.com/{login}?tab=repositories"> <strong>{public_repos}</strong>Repos </a> </li> <li> <a href="https://gist.github.com/{login}"> <strong>{public_gists}</strong>Gists </a> </li> <li> <a href="https://github.com/{login}/followers"> <strong>{followers}</strong>Followers </a> </li> </ul> </div> </div> <style> </style>
Jsx / css
CSS baru saja ditambahkan ke komponen. Alih-alih JSX, kami memiliki
HTMLx tertanam di Svelte.
Wadah
Wadah adalah komponen induk untuk komponen Pengguna. Dalam hal ini, itu adalah komponen dari App.
debounceTime
Input teks debug tidak masuk akal jika operasi hanya menimpa nilai dalam model data. Jadi dalam pengikatan itu sendiri kita tidak membutuhkan ini.
memetik
filter
peta
Terhubung
Mari kembali ke App.html dan mengimpor komponen Pengguna:
import User from './User.html';
Permintaan data
GitHub menyediakan API untuk mengambil informasi pengguna:
Untuk demonstrasi, kami hanya menulis file api.js kecil yang akan mengabstraksi penerimaan data dan mengekspor fungsi yang sesuai:
import axios from 'axios'; export function getUserCard(username) { return axios.get(`https://api.github.com/users/${username}`) .then(res => res.data); }
Dan seperti itu, kami mengimpor fungsi ini ke App.html.
Sekarang kita merumuskan masalah dalam bahasa yang lebih spesifik: kita perlu mengubah nilai lain ketika mengubah satu nilai dalam model data (nama pengguna). Kami akan menyebutnya pengguna, masing-masing - data pengguna yang kami dapatkan dari API. Reaktivitas dalam segala kejayaannya.
Untuk melakukan ini, tulis properti Svelte yang dihitung menggunakan konstruksi berikut di App.html:
<script> import { getUserCard } from './api.js'; ... export default { ... computed: { user: ({ username }) => username && getUserCard(username) } }; </script>
Itu saja, sekarang ketika Anda mengubah nama pengguna, permintaan akan dikirim untuk menerima data pada nilai ini. Namun, karena binder merespons setiap perubahan, yaitu input ke bidang teks, akan ada terlalu banyak permintaan dan kami akan dengan cepat melampaui semua batas yang tersedia.
Dalam artikel asli, masalah ini diselesaikan oleh fungsi debounceTime yang dibangun ke dalam RxJS, yang mencegah kita terlalu sering meminta data. Untuk implementasi kami, Anda dapat menggunakan solusi mandiri, seperti
debounce-janji atau solusi lain yang sesuai, karena ada banyak pilihan.
<script> import debounce from 'debounce-promise'; import { getUserCard } from './api.js'; ... const getUser = debounce(getUserCard, 1000); ... export default { ... computed: { user: ({ username }) => username && getUser(username) } }; </script>
Jadi, lib ini membuat versi debounce dari fungsi yang diteruskan ke sana, yang kemudian kita gunakan di properti yang dihitung.
switchMap
ajax
RxJS menyediakan implementasi ajax sendiri yang bekerja sangat baik dengan switchMap!
Karena kita tidak menggunakan RxJS dan terutama switchMap, kita bisa menggunakan pustaka apa saja untuk bekerja dengan ajax.
Saya menggunakan
aksioma karena nyaman bagi saya, tetapi Anda dapat menggunakan apa saja dan itu tidak mengubah esensi masalah ini.
Coba
Pertama, kita perlu mendaftarkan komponen Pengguna untuk menggunakannya sebagai tag templat, karena impor itu sendiri tidak menambahkan komponen ke konteks templat:
<script> import User from './User.html'; ... export default { components: { User } ... }; </script>
Terlepas dari coretan yang kelihatannya berlebihan, ini memungkinkan, antara lain, untuk memberikan nama tag yang berbeda untuk instance dari komponen yang sama, membuat templat Anda lebih dapat dipahami secara semantik.
Lebih lanjut, nilai pengguna bukanlah data itu sendiri, tetapi janji untuk data itu. Karena kami adalah pekerja lepas dan tidak ingin melakukan pekerjaan apa pun, hanya minum kopi dengan kue.
Untuk mentransfer data nyata ke komponen Pengguna, kami dapat menggunakan desain khusus untuk bekerja dengan janji:
{#await user} {:then user} {#if user} <User {...user} /> {/if} {/await}
Masuk akal untuk memeriksa keberadaan objek data sebelum meneruskannya ke komponen Pengguna. Operator Spread di sini memungkinkan Anda untuk "membagi" suatu objek menjadi alat peraga yang terpisah saat membuat instance komponen Pengguna.

Pekerjaan lebih pendek.
Menangani kesalahan
Coba masukkan nama pengguna yang tidak ada.
...
Aplikasi kami rusak.
Mungkinkah ya, tetapi milik kita pasti tidak))) Hanya tidak akan terjadi apa-apa, meskipun ini tidak terjadi.
catchError
Tambahkan blok tambahan untuk pemrosesan yang ditolak janji:
{#await user} {:then user} {#if user} <User {...user} /> {/if} {:catch error} <Error {...error} /> {/await}
Kesalahan Komponen
<div class="error"> <h2>Oops!</h2> <b>{response.status}: {response.data.message}</b> <p>Please try searching again.</p> </div>
Sekarang UI kami terlihat jauh lebih baik:
Dan jangan katakan, dan yang paling penting tidak ada upaya.

Memuat indikator
Singkatnya, bid'ah lebih lanjut mulai di sana, dengan semua jenis Subjek Perilaku dan lainnya menyukai mereka. Kami hanya menambahkan indikator memuat dan kami tidak akan memerah susu gajah:
{#await user} <h3>Loading...</h3> {:then user} {#if user} <User {...user} /> {/if} {:catch error} <Error {...error} /> {/await}
Hasil?
Dua komponen kecil tanpa logika (Pengguna dan Kesalahan) dan satu komponen kendali (Aplikasi), di mana logika bisnis yang paling rumit dijelaskan dalam satu baris - menciptakan properti yang dihitung. Tidak ada menyikat benda yang dapat diamati dari kepala hingga ujung kaki dan menghubungkan +100500 alat yang tidak Anda butuhkan.
→
Demo interaktifTulis kode sederhana dan jelas. Tulis lebih sedikit kode, yang berarti lebih sedikit pekerjaan dan lebih banyak waktu dengan keluarga Anda. Hidup!
Semua kebahagiaan dan kesehatan!
Semua :)
Fyi
Jika Anda sudah melihat contoh di REPL, maka Anda mungkin memperhatikan roti panggang dengan peringatan dari kiri bawah:
Dikompilasi, tetapi dengan 1 peringatan - periksa konsol untuk detailnya
Jika Anda tidak terlalu malas untuk membuka konsol, Anda akan melihat pesan ini:
Pemilih CSS yang tidak digunakan
.user-card .Organization {
posisi latar belakang: kanan atas;
}
Svelte Static Analyzer memberi tahu kami bahwa beberapa gaya komponen tidak digunakan. Selain itu, atas permintaan Anda atau perintah pengaturan kompiler default, gaya yang tidak digunakan akan dihapus dari bundel css terakhir tanpa partisipasi Anda.
P / s
Baca
artikel lain tentang Svelte , serta lihat saluran telegram berbahasa Rusia
SvelteJS . Kami akan senang melihat Anda!