Pergi dari jQuery ke Svelte, seolah-olah

Halo semuanya.

Ini adalah kelanjutan dari artikel " Pergi dari jQuery ke Svelte, tanpa rasa sakit ."

Di bawah ini saya akan berbicara tentang kesulitan yang saya temui, tidak banyak dari mereka, dan hanya satu yang sangat mendasar di mana saya tidak dapat mengatasi tanpa dukungan dari masyarakat .

pengantar


Saya berencana untuk menulis ulang ujung depan menjadi potongan-potongan, itu bukan sesuatu yang tidak akan berhasil sama sekali, itu tidak berhasil sepenuhnya - saya harus menulis ulang dalam potongan besar.

Pertama, karena pendekatan jQuery sangat penting, pendekatan Svelte bersifat deklaratif.

Kedua, karena menggunakan jQuery, ruang lingkup kami selalu global, kami dapat mengakses semua elemen halaman web dari setiap baris kode, kami mengaksesnya dengan ID atau pemilih CSS, sementara Svelte merekomendasikan menggunakan komponen dan di dalam komponen yang kami lihat hanya komponen itu sendiri, kami tidak memiliki elemen eksternal atau internal, dan kami tidak dapat mengaksesnya secara langsung.

Dengan Svelte, kita mendapatkan OOP nyata: kita tidak bisa membuat perubahan sendiri, kita hanya bisa memberi tahu komponen tentang perlunya perubahan. Bagaimana perubahan ini akan dilakukan, hanya tahu kode di dalam komponen.

Dan itu bagus :)

Svelte memiliki dua mekanisme untuk berkomunikasi dengan komponen.

Variabel yang mengikat (binding, mapping)


Kami mendeklarasikan variabel dan memetakannya ke atribut komponen:

<script>
    import DetailTaskView from './DetailTaskView.svelte';
    let task = {};
    let isModal = false;
    function renderTask(data) {
        const isSuccess = data.hasOwnProperty(0);
        if (isSuccess) {
            isModal = true;
            task = data[0];
        }
    }
    import {fade} from 'svelte/transition';
</script>
{#if isModal}
    <div transition:fade>
        <DetailTaskView bind:isModal="{isModal}" {...task}/>
    </div>
{/if}

Apa yang telah kita lakukan?


Kami menyatakan dua variabel lokal "tugas" dan "isModal", "tugas" adalah informasi yang akan ditampilkan dalam komponen, data hanya ditampilkan, tidak akan diubah, "isModal" adalah bendera visibilitas komponen, jika pengguna mengklik tanda silang pada komponen, maka komponen tersebut harus menghilang , tanda silang milik komponen, jadi kami tidak tahu apa-apa tentang klik, tetapi kami belajar bahwa nilai variabel "isModal" telah berubah dan berkat reaktivitasnya, kami akan mengerjakan nilai baru ini.

Jika kita membutuhkan pengikatan dua arah, maka kita menulis "bind:", perubahan nilai di dalam komponen akan dilaporkan ke komponen "induk".

Anda dapat menggunakan formulir yang disingkat jika kita hanya perlu memberi tahu komponen nilai, dan jika nama atribut komponen cocok dengan nama variabel, kita dapat menulis "{task}" atau menggunakan destruktor "{... task}".

Dengan nyaman.

Tetapi jika kita memiliki komponen lain tertanam dalam satu komponen, dan ada juga yang ketiga, maka tentu saja ada bollerplate untuk menggulirkan nilai ke atas dan ke bawah hierarki bersarang.

Gelembung acara


Saya bisa salah dengan terminologi, jangan banyak menendang.

Komponen induk dapat menangani peristiwa komponen anak, tetapi hanya peristiwa yang dilaporkan komponen anak tersebut.

<!-- App.svelte   -->
<script>
    import SearchForm from './SearchForm.svelte';
    async function applySample(event) {
        const sample = event.detail.sample;
        if(sample){
            search(sample);
        }
        if(!sample){
            renderPage();
        }
    }
</script>
<div class="container">
    <h1>  </h1>
    <SearchForm on:search={applySample}/>
</div>

<!-- SearchForm.svelte    -->
<script>
	import { createEventDispatcher } from 'svelte';
	const dispatch = createEventDispatcher();
	let sample = '';
    function search(event) {
        event.preventDefault();
        dispatch('search', {
            sample: sample
        });
    }
</script>
<form class="form-horizontal" id="search"
on:submit={search}>
    <div class="form-group">
        <label class="control-label col-sm-2" for="sample">
        
        </label>
        <div class="col-sm-10">
            <input id="sample" class="form-control" type="search"
             placeholder="  "
             autocomplete="on" bind:value={sample}
             />
        </div>
    </div>
</form>

Apa yang terjadi di sini ?


Dalam komponen induk, fungsi "applySample" dijalankan oleh peristiwa "on: search" komponen anak "SearchForm", fungsi ini menerima parameter (event.detail) dari objek acara dan memprosesnya.

Apa yang terjadi dalam suatu komponen?


Atribut “value” dari elemen input dipetakan ke variabel “sample”; oleh event “on: submit” (dari elemen “form”), fungsi “search” dijalankan, yang menciptakan event 'search' dan menulis objek {sample: sample "ke properti" detail " } - yaitu nilai dari string pencarian.

Dengan demikian, nilai string pencarian diteruskan ke komponen induk dan dialah yang memutuskan apa yang harus dilakukan dengan nilai ini.

Komponen hanya bertanggung jawab untuk menampilkan formulir input dan mentransmisikan nilai yang dimasukkan, komponen tidak melaksanakan pencarian dan menampilkan hasilnya, jadi kami berbagi tanggung jawab.

Kecantikan!

Transisi dari imperatif ke deklaratif


Di sini, sayangnya, tidak berhasil menunjukkan perbedaannya dengan jelas. Dalam kata-kata, kedengarannya seperti ini: jika, ketika menggunakan jQuery, saya membuat markup html dan kemudian memasukkannya ke tempat yang tepat, kemudian dengan Svelte saya menghasilkan array dengan atribut komponen dan kemudian dalam loop saya menambahkan komponen dengan atribut yang sudah dihitung:

<!-- Paging.svelte        -->
<script>
    import {createEventDispatcher} from 'svelte';
    import OrdinalPlace from './OrdinalPlace.svelte';
    let pagingPlaces;
    //         pagingPlaces
    function addPlace(
        paging = [], index = Number.NEGATIVE_INFINITY,
        text = "", css = "") {
        paging.push({index:index,text:text,css:css});

        return paging;
    }
    const dispatch = createEventDispatcher();
    function browsePage(event) {
        const pageIndex = event.detail.index;
        dispatch('move', {
            index: pageIndex
        });
    }
</script>

{#if pagingPlaces.length}
    <table class = "table table-hover-cells table-bordered">
        <tbody>
            <tr>
            {#each pagingPlaces as place (place.index)}
                <OrdinalPlace on:move="{browsePage}"
                {...place}>
                </OrdinalPlace>
            {/each}
            </tr>
        </tbody>
    </table>
{/if}

<!-- OrdinalPlace.svelte     ""      -->
<script>
    export let index = -1;
    export let text = "";
    export let css = "";

    let number = index +1;
    function skip() {
        return !(text === "");
    }

    let letSkip = skip();
    let noSkip = !letSkip;

    import { createEventDispatcher } from "svelte";
    const dispatch = createEventDispatcher();
    function moveTo() {
        if(noSkip){
            dispatch("move", {index:index});
        }
    }
</script>
<td class="{css}" on:click="{moveTo}">
    {#if letSkip}
        {text}
    {/if}
    {#if noSkip}
        {number}
    {/if}
</td>

Bagaimana itu bekerja ?


Saat membuat komponen Paging, kami membentuk larik "elemen" untuk menuju ke halaman tertentu - "pagingPlaces", kemudian menggilir semua elemen dan memasukkan komponen untuk menampilkan satu posisi paging - "OrdinalPlace".

Sekali lagi, pendekatan deklaratif, kita tidak membentuk setiap posisi diri kita sendiri, kita memberi tahu komponen bahwa kita perlu menampilkan posisi dengan atribut seperti itu.

Di sini kita melihat kasus yang membingungkan tentang munculnya suatu peristiwa. Untuk masuk ke halaman hasil pencarian, pengguna mengklik komponen "OrdinalPlace", komponen ini tidak dapat memuat halaman, oleh karena itu ia membuat acara "pindah" dengan parameter indeks halaman dan acara ini mengambil komponen induk - "Paging", yang juga tidak dapat memuat halaman karena itu itu memunculkan event 'move', dan komponen induk berikutnya sudah mengambilnya dan entah bagaimana memprosesnya.

Langsing dan pendekatan komponen mendorong kita untuk berbagi tanggung jawab dan mengikuti SOLID.

Penyergapan terbesar


Contoh di atas menunjukkan solusi untuk masalah mendasar yang tidak akan bisa saya tangani tanpa petunjuk. Svelte melakukan cache semua komponen dan Anda perlu membantunya melacak perubahan pada komponen ini.

Berikut ini kode yang dimaksud:

            {#each pagingPlaces as place (place.index)}
                <OrdinalPlace on:move="{browsePage}"
                {...place}>
                </OrdinalPlace>
            {/each}

Untuk menampilkan daftar halaman dalam paging, kami berlari melalui array dan Svelte menetapkan komponen indeks array untuk setiap komponen, sekarang Svelte membuat keputusan untuk menggambar ulang komponen berdasarkan indeks ini, jika Anda tidak menentukan indeks saat iterasi melalui elemen array, maka tidak mengerti apa , Aku mencoba mengerti selama sehari, lalu aku meminta bantuan dari aula dan di aula aku tidak segera menemukan seseorang yang sangat mengenal penggaruk ini, tetapi mereka membantuku, terima kasih kepada teman-teman.

Saat bekerja dengan array, ingatlah ini: setiap pass yang melewati array harus menggunakan indeks, sekali lagi:

            {#each pagingPlaces as place (place.index)}

"PagingPlaces as place (place.index)" - pastikan untuk menggunakan.

Tentu saja, jika sebelumnya Anda pernah bekerja dengan React / Vue, maka Anda mungkin sudah terbiasa dengan fitur ini.

Efek visual


Aplikasi saya menggunakan modal windows. jQuery untuk ini menetapkan persyaratan markup, tanpa itu, metode jQuery.modal () tidak akan berfungsi.

Langsing membuat ini lebih mudah:

{#if isModal}
    <div transition:fade>
        <DetailTaskView bind:isModal="{isModal}" {...task}/>
    </div>
{/if}

Secara khusus, "transisi: fade" bertanggung jawab atas hilangnya / tampilan elemen pada halaman.
Tidak ada yang memberi tahu kami markup apa yang harus kami miliki.

Ini baik.

Selain animasi ini, Svelte memiliki beberapa lagi: terbang dan tweened , contoh dari tautan dalam tutorial.

Lain


Nama variabel


Masalah dengan penamaan variabel / parameter / atribut, Anda harus menggunakan satu kata untuk memanggil kedua properti objek dan variabel yang Anda tulis di sana, aturan handset ketika Anda perlu berbicara tentang kode di telepon, sehingga Anda tidak bingung pada akhirnya dan mengerti segalanya, seperti nama yang diulang-ulang melanggar.

Ajax


Ini tidak berlaku untuk Svelte, tetapi menyangkut penolakan menggunakan jQuery, jQuery.ajax dapat diganti dengan fetch (), saya membuat penggantian seperti itu, Anda bisa melihatnya di repositori.

Kesimpulan


Pindah dari menggunakan jQuery ke menggunakan Svelte akan membutuhkan penulisan ulang logika untuk membuat markup, tetapi itu tidak sesulit dan selama mungkin terlihat, terutama jika kode Anda tidak berdosa dengan ini.

Svelte menyederhanakan markup Anda dan mempersingkat kode JS, menggunakan Svelte membuat kode Anda lebih dapat digunakan kembali dan tahan terhadap kesalahan acak.

Gunakan Svelte, itu akan baik untuk Anda dan pelanggan Anda!

Referensi


Situs resmi Svelte
Repository dengan transisi dari menggunakan jQuery ke menggunakan Svelte
Channel dari komunitas berbahasa Rusia Svelte di Telegram

Terima kasih telah membaca.

PS: Saya tidak tahu mengapa Habr mengecualikan titik dua dari tautan ke saluran komunitas, baris tautan yang benar adalah: tg: // resol? Domain = sveltejs

All Articles