You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/ms/3-terrarium/3-intro-to-DOM-and-closures/README.md

14 KiB

Projek Terrarium Bahagian 3: Manipulasi DOM dan Penutupan (Closure)

DOM dan penutupan

Sketchnote oleh Tomomi Imura

Kuiz Pra-Kuliah

Kuiz pra-kuliah

Pengenalan

Memanipulasi DOM, atau "Document Object Model", adalah aspek penting dalam pembangunan web. Menurut MDN, "Document Object Model (DOM) adalah representasi data bagi objek-objek yang membentuk struktur dan kandungan dokumen di web." Cabaran dalam manipulasi DOM di web sering menjadi sebab utama penggunaan rangka kerja JavaScript berbanding JavaScript biasa untuk menguruskan DOM, tetapi kita akan cuba melakukannya sendiri!

Selain itu, pelajaran ini akan memperkenalkan idea tentang penutupan JavaScript, yang boleh difahami sebagai fungsi yang tertutup oleh fungsi lain supaya fungsi dalaman mempunyai akses kepada skop fungsi luaran.

Penutupan JavaScript adalah topik yang luas dan kompleks. Pelajaran ini hanya menyentuh idea asas bahawa dalam kod terrarium ini, anda akan menemui penutupan: fungsi dalaman dan fungsi luaran yang dibina dengan cara yang membolehkan fungsi dalaman mengakses skop fungsi luaran. Untuk maklumat lebih lanjut tentang cara ini berfungsi, sila lawati dokumentasi yang luas.

Kita akan menggunakan penutupan untuk memanipulasi DOM.

Fikirkan DOM sebagai pokok, yang mewakili semua cara dokumen halaman web boleh dimanipulasi. Pelbagai API (Antara Muka Program Aplikasi) telah ditulis supaya pengaturcara, menggunakan bahasa pengaturcaraan pilihan mereka, boleh mengakses DOM dan mengedit, mengubah, menyusun semula, dan menguruskannya.

Representasi pokok DOM

Representasi DOM dan markup HTML yang merujuknya. Daripada Olfa Nasraoui

Dalam pelajaran ini, kita akan melengkapkan projek terrarium interaktif kita dengan mencipta JavaScript yang membolehkan pengguna memanipulasi tumbuhan di halaman.

Prasyarat

Anda seharusnya telah membina HTML dan CSS untuk terrarium anda. Pada akhir pelajaran ini, anda akan dapat memindahkan tumbuhan masuk dan keluar dari terrarium dengan menyeretnya.

Tugasan

Dalam folder terrarium anda, buat fail baru bernama script.js. Import fail tersebut dalam bahagian <head>:

	<script src="./script.js" defer></script>

Nota: gunakan defer semasa mengimport fail JavaScript luaran ke dalam fail HTML supaya JavaScript hanya dilaksanakan selepas fail HTML dimuat sepenuhnya. Anda juga boleh menggunakan atribut async, yang membolehkan skrip dilaksanakan semasa fail HTML sedang diproses, tetapi dalam kes kita, adalah penting untuk elemen HTML tersedia sepenuhnya untuk diseret sebelum kita membenarkan skrip seretan dilaksanakan.


Elemen DOM

Perkara pertama yang perlu anda lakukan ialah mencipta rujukan kepada elemen-elemen yang ingin anda manipulasi dalam DOM. Dalam kes kita, ia adalah 14 tumbuhan yang sedang menunggu di bar sisi.

Tugasan

dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
dragElement(document.getElementById('plant4'));
dragElement(document.getElementById('plant5'));
dragElement(document.getElementById('plant6'));
dragElement(document.getElementById('plant7'));
dragElement(document.getElementById('plant8'));
dragElement(document.getElementById('plant9'));
dragElement(document.getElementById('plant10'));
dragElement(document.getElementById('plant11'));
dragElement(document.getElementById('plant12'));
dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));

Apa yang sedang berlaku di sini? Anda sedang merujuk dokumen dan mencari melalui DOM untuk mencari elemen dengan Id tertentu. Ingat dalam pelajaran pertama tentang HTML bahawa anda memberikan Id individu kepada setiap imej tumbuhan (id="plant1")? Sekarang anda akan menggunakan usaha tersebut. Selepas mengenal pasti setiap elemen, anda menghantar item tersebut kepada fungsi bernama dragElement yang akan anda bina sebentar lagi. Dengan itu, elemen dalam HTML kini boleh diseret, atau akan boleh diseret tidak lama lagi.

Mengapa kita merujuk elemen berdasarkan Id? Mengapa tidak berdasarkan kelas CSS mereka? Anda mungkin merujuk pelajaran sebelumnya tentang CSS untuk menjawab soalan ini.


Penutupan (Closure)

Sekarang anda bersedia untuk mencipta penutupan dragElement, yang merupakan fungsi luaran yang menutup fungsi dalaman atau beberapa fungsi dalaman (dalam kes kita, kita akan mempunyai tiga).

Penutupan berguna apabila satu atau lebih fungsi perlu mengakses skop fungsi luaran. Berikut adalah contoh:

function displayCandy(){
	let candy = ['jellybeans'];
	function addCandy(candyType) {
		candy.push(candyType)
	}
	addCandy('gumdrops');
}
displayCandy();
console.log(candy)

Dalam contoh ini, fungsi displayCandy mengelilingi fungsi yang menolak jenis gula-gula baru ke dalam array yang sudah wujud dalam fungsi tersebut. Jika anda menjalankan kod ini, array candy akan tidak ditakrifkan, kerana ia adalah pembolehubah tempatan (tempatan kepada penutupan).

Bagaimana anda boleh membuat array candy boleh diakses? Cuba pindahkan ia ke luar penutupan. Dengan cara ini, array menjadi global, bukannya hanya tersedia dalam skop tempatan penutupan.

Tugasan

Di bawah deklarasi elemen dalam script.js, buat fungsi:

function dragElement(terrariumElement) {
	//set 4 positions for positioning on the screen
	let pos1 = 0,
		pos2 = 0,
		pos3 = 0,
		pos4 = 0;
	terrariumElement.onpointerdown = pointerDrag;
}

dragElement mendapatkan objek terrariumElement daripada deklarasi di bahagian atas skrip. Kemudian, anda menetapkan beberapa kedudukan tempatan pada 0 untuk objek yang dihantar ke fungsi. Ini adalah pembolehubah tempatan yang akan dimanipulasi untuk setiap elemen semasa anda menambah fungsi seret dan lepaskan dalam penutupan kepada setiap elemen. Terrarium akan dipenuhi oleh elemen-elemen yang diseret ini, jadi aplikasi perlu menjejaki di mana ia diletakkan.

Selain itu, terrariumElement yang dihantar kepada fungsi ini diberikan acara pointerdown, yang merupakan sebahagian daripada web APIs yang direka untuk membantu pengurusan DOM. onpointerdown dicetuskan apabila butang ditekan, atau dalam kes kita, elemen yang boleh diseret disentuh. Pengendali acara ini berfungsi pada kedua-dua pelayar web dan mudah alih, dengan beberapa pengecualian.

Pengendali acara onclick mempunyai sokongan yang lebih luas merentas pelayar; mengapa anda tidak menggunakannya di sini? Fikirkan tentang jenis interaksi skrin yang tepat yang anda cuba cipta di sini.


Fungsi Pointerdrag

terrariumElement kini sedia untuk diseret; apabila acara onpointerdown dicetuskan, fungsi pointerDrag dipanggil. Tambahkan fungsi tersebut tepat di bawah baris ini: terrariumElement.onpointerdown = pointerDrag;:

Tugasan

function pointerDrag(e) {
	e.preventDefault();
	console.log(e);
	pos3 = e.clientX;
	pos4 = e.clientY;
}

Beberapa perkara berlaku. Pertama, anda menghalang acara lalai yang biasanya berlaku pada pointerdown daripada berlaku dengan menggunakan e.preventDefault();. Dengan cara ini anda mempunyai lebih kawalan ke atas tingkah laku antara muka.

Kembali ke baris ini apabila anda telah membina fail skrip sepenuhnya dan cuba tanpa e.preventDefault() - apa yang berlaku?

Kedua, buka index.html dalam tetingkap pelayar, dan periksa antara muka. Apabila anda mengklik tumbuhan, anda boleh melihat bagaimana acara 'e' ditangkap. Selidiki acara tersebut untuk melihat berapa banyak maklumat yang dikumpulkan oleh satu acara pointerdown!

Seterusnya, perhatikan bagaimana pembolehubah tempatan pos3 dan pos4 ditetapkan kepada e.clientX. Anda boleh mencari nilai e dalam panel pemeriksaan. Nilai-nilai ini menangkap koordinat x dan y tumbuhan pada saat anda mengklik atau menyentuhnya. Anda memerlukan kawalan yang terperinci terhadap tingkah laku tumbuhan semasa anda mengklik dan menyeretnya, jadi anda menjejaki koordinat mereka.

Adakah semakin jelas mengapa keseluruhan aplikasi ini dibina dengan satu penutupan besar? Jika tidak, bagaimana anda akan mengekalkan skop untuk setiap 14 tumbuhan yang boleh diseret?

Lengkapkan fungsi awal dengan menambah dua lagi manipulasi acara penunjuk di bawah pos4 = e.clientY:

document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;

Sekarang anda menunjukkan bahawa anda mahu tumbuhan diseret bersama penunjuk semasa anda menggerakkannya, dan untuk gerakan seretan berhenti apabila anda tidak lagi memilih tumbuhan. onpointermove dan onpointerup adalah sebahagian daripada API yang sama seperti onpointerdown. Antara muka akan membuang ralat sekarang kerana anda belum lagi mentakrifkan fungsi elementDrag dan stopElementDrag, jadi bina fungsi tersebut seterusnya.

Fungsi elementDrag dan stopElementDrag

Anda akan melengkapkan penutupan anda dengan menambah dua lagi fungsi dalaman yang akan mengendalikan apa yang berlaku apabila anda menyeret tumbuhan dan berhenti menyeretnya. Tingkah laku yang anda mahukan ialah anda boleh menyeret mana-mana tumbuhan pada bila-bila masa dan meletakkannya di mana-mana sahaja di skrin. Antara muka ini agak fleksibel (tiada zon lepasan, contohnya) untuk membolehkan anda mereka bentuk terrarium anda seperti yang anda suka dengan menambah, mengalih keluar, dan menyusun semula tumbuhan.

Tugasan

Tambahkan fungsi elementDrag tepat selepas kurungan penutup pointerDrag:

function elementDrag(e) {
	pos1 = pos3 - e.clientX;
	pos2 = pos4 - e.clientY;
	pos3 = e.clientX;
	pos4 = e.clientY;
	console.log(pos1, pos2, pos3, pos4);
	terrariumElement.style.top = terrariumElement.offsetTop - pos2 + 'px';
	terrariumElement.style.left = terrariumElement.offsetLeft - pos1 + 'px';
}

Dalam fungsi ini, anda melakukan banyak pengeditan pada kedudukan awal 1-4 yang anda tetapkan sebagai pembolehubah tempatan dalam fungsi luaran. Apa yang sedang berlaku di sini?

Semasa anda menyeret, anda menetapkan semula pos1 dengan menjadikannya sama dengan pos3 (yang anda tetapkan sebelum ini sebagai e.clientX) tolak nilai e.clientX semasa. Anda melakukan operasi yang sama pada pos2. Kemudian, anda menetapkan semula pos3 dan pos4 kepada koordinat X dan Y baru elemen tersebut. Anda boleh melihat perubahan ini dalam konsol semasa anda menyeret. Kemudian, anda memanipulasi gaya CSS tumbuhan untuk menetapkan kedudukannya yang baru berdasarkan kedudukan baru pos1 dan pos2, mengira koordinat X dan Y atas dan kiri tumbuhan berdasarkan perbandingan offsetnya dengan kedudukan baru ini.

offsetTop dan offsetLeft adalah sifat CSS yang menetapkan kedudukan elemen berdasarkan kedudukan elemen induknya; elemen induknya boleh menjadi mana-mana elemen yang tidak diposisikan sebagai static.

Semua pengiraan semula kedudukan ini membolehkan anda menyesuaikan tingkah laku terrarium dan tumbuhannya.

Tugasan

Tugasan terakhir untuk melengkapkan antara muka ialah menambah fungsi stopElementDrag selepas kurungan penutup elementDrag:

function stopElementDrag() {
	document.onpointerup = null;
	document.onpointermove = null;
}

Fungsi kecil ini menetapkan semula acara onpointerup dan onpointermove supaya anda boleh sama ada memulakan semula kemajuan tumbuhan anda dengan mula menyeretnya semula, atau mula menyeret tumbuhan baru.

Apa yang berlaku jika anda tidak menetapkan acara ini kepada null?

Sekarang anda telah melengkapkan projek anda!

🥇Tahniah! Anda telah menyiapkan terrarium anda yang cantik. terrarium siap


🚀Cabaran

Tambahkan pengendali acara baru kepada penutupan anda untuk melakukan sesuatu yang lebih kepada tumbuhan; contohnya, klik dua kali pada tumbuhan untuk membawanya ke hadapan. Jadilah kreatif!

Kuiz Pasca-Kuliah

Kuiz pasca-kuliah

Kajian Semula & Kajian Kendiri

Walaupun menyeret elemen di sekitar skrin kelihatan remeh, terdapat banyak cara untuk melakukannya dan banyak perangkap, bergantung pada kesan yang anda cari. Malah, terdapat keseluruhan API seret dan lepaskan yang boleh anda cuba. Kami tidak menggunakannya dalam modul ini kerana kesan yang kami mahukan agak berbeza, tetapi cuba API ini pada projek anda sendiri dan lihat apa yang anda boleh capai.

Cari lebih banyak maklumat tentang acara penunjuk di dokumen W3C dan di dokumen web MDN.

Sentiasa periksa keupayaan pelayar menggunakan CanIUse.com.

Tugasan

Bekerja lebih lanjut dengan DOM


Penafian:
Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI Co-op Translator. Walaupun kami berusaha untuk memastikan ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat yang kritikal, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.