Merge pull request #90 from EugeneGohh/main
Translating to Malay language (In Progress)pull/180/head
commit
7ed3219bdb
@ -0,0 +1,190 @@
|
||||
# Pengenalan Bahasa Pengaturcaraan dan Alat Perdagangan
|
||||
|
||||
Pelajaran ini merangkumi asas bahasa pengaturcaraan. Topik yang anda akan belajar di sini dapat mengaplikasikan untuk kebanyakan bahasa pengaturcaraan moden hari ini. Pada bahagian 'Alat Perdagangan', anda akan belajar bagaimana mengenai perisian berguna yang membantu anda sebagai pembangun.
|
||||
|
||||
![Intro Programming](../webdev101-programming.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra-Kuliah
|
||||
[Kuiz Pra-Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/1)
|
||||
|
||||
## Pengenalan
|
||||
|
||||
Dalam bab ini, kita akan belajar:
|
||||
|
||||
- Apa itu pengaturcaraan?
|
||||
- Jenis bahasa pengaturcaraan
|
||||
- Elemen asas program
|
||||
- Perisian dan perkakas yang berguna untuk pembangun profesional
|
||||
|
||||
## Apa itu pengaturcaraan?
|
||||
|
||||
Pengaturcaraan (juga dikenali sebagai pengekodan) adalah proses menulis arahan ke peranti, seperti komputer atau peranti mudah alih. Kami menulis arahan ini dengan bahasa pengaturcaraan, yang kemudian ditafsirkan oleh peranti. Set arahan ini dapat disebut dengan pelbagai nama, tetapi *program*, *program komputer*, *aplikasi (app)*, dan *boleh dilaksanakan* ialah beberapa nama yang popular.
|
||||
|
||||
*Program* boleh menjadi apa-apa sahaja yang ditulis dengan kod; laman web, permainan, dan aplikasi telefon adalah program. Walaupun mungkin kita boleh membuat program tanpa menulis kod, logik yang mendasari ditafsirkan ke peranti dan logik itu kemungkinan besar ditulis dengan kod. Program yang *melaksanakan kod* ialah dedefinisikan sebagai program yang sedang menjalankan arahan. Peranti yang anda sedang gunakan untuk membaca pelajaran ini sedang menjalankan program sendiri untuk mencetakkan pada skrin anda.
|
||||
|
||||
✅ Lakukan sedikit pengajian: siapakah yang dianggap sebagai pengaturcara komputer pertama di dunia?
|
||||
|
||||
## Bahasa Pengaturcaraan
|
||||
|
||||
Bahasa pengaturcaraan berfungsi untuk tujuan utama: bagi pembangun untuk membina arahan untuk menghantar ke peranti. Peranti hanya dapat memahami binari (1s dan 0s), dan *untuk kebanyakan* pembangun itu bukan kaedah yang sangat efisien untuk berkomunikasi. Bahasa pengaturcaraan adalah wahana berkomunikasi antara manusia dan komputer.
|
||||
|
||||
Bahasa pengaturcaraan terdapat dalam format-format yang berbeza dan mungkin mempunyai tujuan yang berbeza. Sebagai contoh, ('JavaScript') digunakan terutamanya untuk aplikasi web dan ('Bash') digunakan terutamanya untuk sistem operasi.
|
||||
|
||||
*Bahasa tahap rendah* biasanya memerlukan langkah yang lebih sedikit berbanding daripada *bahasa tahap tinggi* agar peranti dapat menafsirkan arahan. Walau bagaimanapun, apa yang menjadikan bahasa peringkat tinggi menjadi popular adalah kebolehbacaan dan sokongannya. ('JavaScript') dianggap bahasa tahap tinggi.
|
||||
|
||||
Kod berikut akan menggambarkan perbezaan antara bahasa tahap tinggi dengan ('JavaScript') dan bahasa tahap rendah dengan kod pemasangan ARM.
|
||||
|
||||
```javascript
|
||||
let number = 10
|
||||
let n1 = 0, n2 = 1, nextTerm;
|
||||
|
||||
for (let i = 1; i <= number; i++) {
|
||||
console.log(n1);
|
||||
nextTerm = n1 + n2;
|
||||
n1 = n2;
|
||||
n2 = nextTerm;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
area ascen,code,readonly
|
||||
entry
|
||||
code32
|
||||
adr r0,thumb+1
|
||||
bx r0
|
||||
code16
|
||||
thumb
|
||||
mov r0,#00
|
||||
sub r0,r0,#01
|
||||
mov r1,#01
|
||||
mov r4,#10
|
||||
ldr r2,=0x40000000
|
||||
back add r0,r1
|
||||
str r0,[r2]
|
||||
add r2,#04
|
||||
mov r3,r0
|
||||
mov r0,r1
|
||||
mov r1,r3
|
||||
sub r4,#01
|
||||
cmp r4,#00
|
||||
bne back
|
||||
end
|
||||
```
|
||||
|
||||
Percaya atau tidak, *mereka berdua melakukan perkara yang sama*: mencetak urutan Fibonacci hingga 10.
|
||||
|
||||
✅ Urutan Fibonacci [didefinisikan] (https://en.wikipedia.org/wiki/Fibonacci_number) sebagai satu set nombor sehingga setiap nombor adalah jumlah dari dua nombor sebelumnya, bermula dari 0 dan 1.
|
||||
|
||||
## Elemen Asas Program
|
||||
|
||||
Satu arahan dalam program dipanggil *pernyataan* dan biasanya akan mempunyai watak atau jarak baris yang menandakan di mana arahan itu berakhir, atau *diterminasikan*. Bagaimanakah program ditamatkan berbeza-beza dengan setiap bahasa.
|
||||
|
||||
Sebilangan besar program bergantung pada penggunaan data dari pengguna atau di tempat lain, di mana pernyataan mungkin bergantung pada data untuk melaksanakan arahan. Data dapat mengubah bagaimana program berperilaku, sehingga bahasa pengaturcaraan dilengkapi dengan cara untuk menyimpan data sementara yang dapat digunakan kemudian. Data ini dipanggil *pemboleh ubah* (*Variable*). Pemboleh ubah ialah pernyataan yang memerintahkan peranti menyimpan data dalam ingatannya. Pemboleh ubah dalam program serupa dengan ('algebra'), di mana mereka mempunyai nama yang unik dan nilainya mungkin berubah dari semasa ke semasa.
|
||||
|
||||
Ada kemungkinan beberapa penyataan tidak akan dilaksanakan oleh peranti. Ini biasanya berdasarkan reka bentuk apabila ditulis oleh pembangun atau secara tidak sengaja apabila berlaku kesalahan yang tidak dijangka. Jenis kawalan aplikasi ini menjadikannya lebih mantap dan dapat dikendalikan. Biasanya perubahan kawalan ini berlaku apabila keputusan tertentu dipenuhi. Pernyataan umum dalam bahasa pengaturcaraan moden untuk mengawal bagaimana program dijalankan adalah pernyataan `if..else`.
|
||||
|
||||
✅ Anda akan belajar lebih mendalam tentang jenis pernyataan ini dalam pelajaran seterusnya
|
||||
|
||||
## Alat Perdagangan
|
||||
|
||||
[![Tools of the Trade](https://img.youtube.com/vi/69WJeXGBdxg/0.jpg)](https://youtube.com/watch?v=69WJeXGBdxg "Tools of the Trade")
|
||||
|
||||
Dalam bahagian ini, anda akan belajar tentang beberapa perisian yang mungkin berguna bagi anda semasa memulakan perjalanan pengembangan profesional anda.
|
||||
|
||||
**Persekitaran pengembangan** ('development enviroment') ialah sekumpulan alat dan ciri unik yang sering digunakan oleh pembangun semasa menulis perisian. Sebilangan alat ini telah disesuaikan untuk keperluan khusus pembangun, dan mungkin berubah dari masa ke masa jika pembangun mengubah keutamaan dalam kerja atau projek peribadi, atau ketika mereka menggunakan bahasa pengaturcaraan yang berbeda. Persekitaran pembangunan sama uniknya dengan pemaju yang menggunakannya.
|
||||
|
||||
### Editor
|
||||
|
||||
Salah satu alat yang paling penting untuk pembangunan perisian adalah ('editor'). ('Editor') ialah tempat anda menulis kod anda dan kadang kala anda akan menjalankan kod anda.
|
||||
|
||||
Pembangun bergantung pada editor untuk beberapa sebab tambahan:
|
||||
|
||||
- *Debugging* Mencari bug dan kesilapan dengan melangkah ke kod, baris demi baris. Beberapa editor mempunyai kemampuan debug, atau dapat disesuaikan dan ditambahkan untuk bahasa pengaturcaraan tertentu.
|
||||
- *Penyorotan sintaks* Menambah warna dan format teks ke kod, menjadikannya lebih mudah dibaca. Sebilangan besar editor membenarkan penyorotan sintaks yang disesuaikan.
|
||||
- *Sambungan dan Integrasi* Penambahan yang dikhususkan untuk pembangun, oleh pemaju, untuk akses ke alat tambahan yang tidak terdapat dalam penyunting asas. Sebagai contoh, banyak pembangun juga memerlukan cara untuk mendokumentasikan kod mereka dan menerangkan cara kerjanya dan akan memasang pelanjutan pemeriksaan ejaan untuk memeriksa kesalahan ketik. Sebilangan besar penambahan ini dimaksudkan untuk digunakan dalam editor tertentu, dan kebanyakan editor datang dengan cara untuk mencari sambungan yang tersedia.
|
||||
- *Penyesuaian* Sebilangan besar editor sangat disesuaikan, dan setiap pembangun akan mempunyai persekitaran pembangunan unik mereka sendiri yang sesuai dengan keperluan mereka. Banyak juga yang membenarkan pembangun membuat peluasan mereka sendiri.
|
||||
|
||||
- [Visual Studio Code](https://code.visualstudio.com/)
|
||||
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
|
||||
- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack)
|
||||
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
- [Atom](https://atom.io/)
|
||||
- [spell-check](https://atom.io/packages/spell-check)
|
||||
- [teletype](https://atom.io/packages/teletype)
|
||||
- [atom-beautify](https://atom.io/packages/atom-beautify)
|
||||
|
||||
### Penyemak Imbas
|
||||
|
||||
Alat penting lain ialah penyemak imbas. Pembangun web bergantung pada penyemak imbas untuk melihat bagaimana kod mereka berjalan di web, ia juga digunakan untuk melihat elemen visual dari laman web yang ditulis dalam editor, seperti HTML.
|
||||
|
||||
Banyak penyemak imbas dilengkapi dengan *developer tools* (DevTools) yang mengandungi sekumpulan ciri dan maklumat berguna untuk membantu pembangun mengumpulkan dan menangkap pandangan penting mengenai aplikasinya. Contohnya: Sekiranya halaman web mempunyai kesilapan, kadang-kadang bermanfaat untuk mengetahui kapan halaman tersebut berlaku. DevTools dalam penyemak imbas boleh dikonfigurasi untuk menangkap maklumat ini.
|
||||
|
||||
### Penyemak Imbas Popular dan DevTools
|
||||
|
||||
- [Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium)
|
||||
- [Chrome](https://developers.google.com/web/tools/chrome-devtools/)
|
||||
- [Firefox](https://developer.mozilla.org/docs/Tools)
|
||||
|
||||
### Alat Command Line
|
||||
|
||||
Sebahagian pembangun lebih suka paparan yang kurang grafik untuk tugas harian mereka dan bergantung kepada baris perintah untuk mencapainya. Membangunkan kod memerlukan sebilangan besar menaip, dan sebilangan pembangun memilih untuk tidak mengganggu aliran mereka pada papan kekunci dan akan menggunakan pintasan papan kekunci untuk menukar antara tetingkap desktop, mengerjakan fail yang berbeza, dan menggunakan alat. Sebilangan besar tugas dapat diselesaikan dengan tetikus, tetapi satu manfaat menggunakan baris perintah adalah banyak yang dapat dilakukan dengan alat baris perintah tanpa perlu menukar antara tetikus dan papan kekunci. Manfaat yang lain daripada baris perintah ialah mereka boleh dikonfigurasi dan anda dapat menukar konfigurasi yang sesuai untuk anda, mengubahnya kemudian, dan juga mengimportnya ke mesin pengembangan baru. Kerana persekitaran pembangunan sangat unik bagi setiap pembangun, ada yang akan menghindari penggunaan baris perintah, ada yang akan bergantung sepenuhnya, dan ada yang lebih suka gabungan kedua-duanya.
|
||||
|
||||
### Pilihan Command Line Popular
|
||||
|
||||
Pilihan untuk ('command line') akan berbeza berdasarkan sistem operasi yang anda mengguna.
|
||||
|
||||
*💻 = sudah dimuat turun dalam sistem operasi.*
|
||||
|
||||
#### Windows
|
||||
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7) 💻
|
||||
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands) (Juga dikenali sebagai CMD) 💻
|
||||
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/)
|
||||
- [mintty](https://mintty.github.io/)
|
||||
|
||||
#### MacOS
|
||||
|
||||
- [Terminal](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac) 💻
|
||||
- [iTerm](https://iterm2.com/)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7)
|
||||
|
||||
#### Linux
|
||||
|
||||
- [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 💻
|
||||
- [KDE Konsole](https://docs.kde.org/trunk5/en/applications/konsole/index.html)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7)
|
||||
|
||||
#### Popular Command Line Tools
|
||||
|
||||
- [Git](https://git-scm.com/) (💻 Dimuat turun pada kebanyakkan sistem operasi)
|
||||
- [NPM](https://www.npmjs.com/)
|
||||
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
|
||||
|
||||
### Dokumentasi
|
||||
|
||||
Apabila pembangun ingin mempelajari sesuatu yang baru, kemungkinan besar mereka akan beralih ke dokumentasi untuk mengetahui cara menggunakannya. Pembangun sering bergantung pada dokumentasi untuk membimbing mereka bagaimana menggunakan alat dan bahasa dengan betul, dan juga untuk mendapatkan pengetahuan yang lebih mendalam tentang cara ia berfungsi.
|
||||
|
||||
#### Dokumentasi Popular untuk Pembangunan Web
|
||||
|
||||
- [Mozilla Developer Network](https://developer.mozilla.org/docs/Web)
|
||||
- [Frontend Masters](https://frontendmasters.com/learn/)
|
||||
|
||||
✅ Lakukan penyelidikan: Sekarang setelah anda mengetahui asas-asas persekitaran pembangun web, membandingkan dan membezakannya dengan persekitaran pereka web.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Bandingkan beberapa bahasa pengaturcaraan. Apa ciri unik JavaScript berbanding dengan Java? Bagaimanakah dengan COBOL vs. Go?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/2)
|
||||
|
||||
## Mengkaji sendiri & Belajar sendiri
|
||||
|
||||
Belajar sedikit mengenai bahasa yang disediakan untuk pengaturcara. Cuba menulis baris dalam satu bahasa pengaturcaraan, dan kemudian membuat semula dalam dua bahasa pengaturcaraan lain. Apakah yang anda pelajari?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Membaca Dokumentasi](assignment.ms.md)
|
@ -0,0 +1,10 @@
|
||||
# Membaca Docs
|
||||
|
||||
## Arahan
|
||||
Terdapat banyak alat yang mungkin diperlukan oleh pembangun web adalah di [Dokumentasi MDN untuk perkakas sisi pelanggan](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview). Pilih 3 alat yang tidak diliputi dalam pelajaran, terangkan mengapa pembangun web menggunakannya, dan mencari alat yang terdapat dalam kategori ini dan kongsikan dokumentasinya. Jangan menggunakan contoh alat yang sama pada MDN.
|
||||
|
||||
## Rubrik
|
||||
|
||||
Contoh | Mencukupi | Usaha Lagi
|
||||
--- | --- | -- |
|
||||
|Terangkan mengapa pembangun web menggunakan alat| Terangkan bagaimana dan mengapa pembangun akan menggunakan alat| Tidak menyebut bagaimana atau mengapa pembangun menggunakan alat |
|
@ -0,0 +1,318 @@
|
||||
# Pengenalan Tentang GitHub
|
||||
|
||||
Pelajaran ini merangkumi pengetahuan asas tentang GitHub, dan adalah salah satu platform untuk menjadi tuan rumah dan menguruskan perubahan pada kod anda.
|
||||
|
||||
![Intro to GitHub](../images/webdev101-github.png)
|
||||
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra-Kuliah
|
||||
[Pre-lecture quiz](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/3)
|
||||
|
||||
## Pengenalan
|
||||
|
||||
Dalam pelajaran ini, kita akan belajar tentang:
|
||||
|
||||
- mengesan kerja yang anda lakukan di mesin anda
|
||||
- membuat projek dengan orang lain
|
||||
- bagaimanakah menyumbang kepada perisian sumber terbuka
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Sebelum bermula, anda perlu memeriksa sama ada Git dipasang dalam komputer anda. Dalam terminal menaip:
|
||||
`git --version`
|
||||
|
||||
Sekiranya Git tidak dipasang, [memuat turun Git](https://git-scm.com/downloads). Kemudian, siapkan profil Git anda di terminal:
|
||||
* `git config --global user.name "your-name"`
|
||||
* `git config --global user.email "your-email"`
|
||||
|
||||
Untuk memeriksa sama ada Git sudah dikonfigurasi, anda boleh menaip:
|
||||
`git config --list`
|
||||
|
||||
Anda juga memerlukan akaun GitHub, penyunting kod (seperti Visual Studio Code), dan anda perlu membuka terminal anda (atau: command prompt).
|
||||
|
||||
Navigasi ke [github.com] (https://github.com/) dan buat akaun jika anda belum melakukannya, atau log masuk dan isi profil anda.
|
||||
|
||||
✅ GitHub bukan satu-satunya repositori kod di dunia; ada yang lain, tetapi GitHub adalah yang paling terkenal.
|
||||
|
||||
### Persediaan
|
||||
|
||||
Anda memerlukan kedua-dua folder dengan projek kod pada mesin tempatan anda (komputer riba atau PC), dan repositori awam di GitHub, yang akan menjadi contoh bagaimana menyumbang kepada projek orang lain.
|
||||
|
||||
---
|
||||
|
||||
## Pengurusan Kod
|
||||
|
||||
Katakan anda mempunyai folder secara tempatan dengan beberapa projek kod dan anda ingin mula mengesan kemajuan anda menggunakan git - sistem kawalan versi. Sebilangan orang membandingkan menggunakan git dengan menulis surat cinta untuk diri masa depan anda. Membaca mesej komit anda beberapa hari atau minggu atau bulan kemudian anda akan dapat mengingat mengapa anda membuat keputusan, atau "memutar balik (rollback)" perubahan - iaitu ketika anda menulis "pesan komit (commit messages)" yang baik.
|
||||
|
||||
### Tugasan: Buat repositori dan kod komit
|
||||
|
||||
1. **Buat satu repository di GitHub**. Di GitHub.com, pada tab repositori, atau dari bar navigasi di sebelah kanan atas, cari butang **repo baru (new repo)**.
|
||||
|
||||
1. Beri nama repositori (folder) anda
|
||||
1. Pilih **repositori kreat (create repository)**.
|
||||
|
||||
1. **Navigasi ke folder kerja anda**. Di terminal anda, beralih ke folder (juga dikenali sebagai direktori) yang ingin anda mulakan penjejakan. Jenis:
|
||||
|
||||
```bash
|
||||
cd [name of your folder]
|
||||
```
|
||||
|
||||
1. **Memulakan git repositori**. Dalam jenis projek anda:
|
||||
|
||||
```bash
|
||||
git init
|
||||
```
|
||||
|
||||
1. **Periksa status**. Untuk memeriksa status repositori anda:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
the output can look something like this:
|
||||
|
||||
```output
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git checkout -- <file>..." to discard changes in working directory)
|
||||
|
||||
modified: file.txt
|
||||
modified: file2.txt
|
||||
```
|
||||
|
||||
Biasanya perintah `git status` memberitahu anda perkara seperti fail apa yang siap disimpan_ ke repo atau mempunyai perubahan di atasnya yang mungkin anda mahu berterusan.
|
||||
|
||||
1. **Tambahkan semua fail untuk penjejakan**
|
||||
Ini juga disebut sebagai fail pementasan / menambahkan fail ke kawasan pementasan (staging area).
|
||||
|
||||
```bash
|
||||
git add .
|
||||
```
|
||||
|
||||
Argumen `git add` plus `.` menunjukkan bahawa semua fail & perubahan anda untuk dijejaki.
|
||||
|
||||
1. **Tambahkan fail terpilih untuk dijejaki**
|
||||
|
||||
```bash
|
||||
git add [file or folder name]
|
||||
```
|
||||
|
||||
Ini membantu kita untuk menambahkan fail yang dipilih hanya ke kawasan pementasan ketika kita tidak ingin melakukan semua fail sekaligus.
|
||||
|
||||
1. **Lepaskan semua fail**
|
||||
|
||||
```bash
|
||||
git reset
|
||||
```
|
||||
|
||||
Perintah ini membantu kita untuk melepaskan semua fail sekaligus.
|
||||
|
||||
1. **Lepaskan fail yang tertentu**
|
||||
|
||||
```bash
|
||||
git reset [file or folder name]
|
||||
```
|
||||
|
||||
Perintah ini membantu kita untuk melepaskan hanya fail yang tertentu sekaligus yang tidak ingin kita sertakan untuk komit berikutnya.
|
||||
|
||||
1. **Meneruskan kerja anda**. Pada masa ini anda telah menambahkan fail ke yang disebut _staging area_. Salah satu tempat di mana Git mengesan fail anda. Untuk melakukan perubahan itu kekal, anda perlu _commit_ fail itu. Untuk melakukannya anda perlu membuat _commit_ dengan perintah `git commit`. _commit_ mewakili titik simpanan dalam sejarah repo anda. Menaip perintah tersebut untuk membuat _commit_:
|
||||
|
||||
```bash
|
||||
git commit -m "first commit"
|
||||
```
|
||||
|
||||
Untuk komit semua fail anda, menaip mesej "komit pertama (first commit)". Untuk mesej komit pada masa kelak, anda ingin lebih terperinci dalam penerangan anda untuk menyampaikan jenis perubahan yang telah anda buat.
|
||||
|
||||
1. **Sambungkan repo Git tempatan anda dengan GitHub**. Repo Git adalah bagus dalam mesin anda tetapi pada satu ketika anda ingin mempunyai sandaran fail anda di suatu tempat dan juga mengundang orang lain untuk bekerja dengan anda di repo anda. Salah satu tempat yang bagus untuk melakukannya adalah di GitHub. Ingatlah bahawa kita sudah membuat repo di GitHub jadi satu-satunya perkara yang perlu kita lakukan ialah menghubungkan repo Git tempatan kita dengan GitHub. Perintah ini `git remote add` akan membuat tugasan tersebut. Menaip perintah tersebut:
|
||||
|
||||
> Perhatikan, sebelum anda mengetik perintah, pergi ke halaman repo GitHub anda untuk mencari URL repositori. Anda akan menggunakannya dalam arahan di bawah. Gantikan `repository_name` degan GitHub URL.
|
||||
|
||||
```bash
|
||||
git remote add origin https://github.com/username/repository_name.git
|
||||
```
|
||||
|
||||
Ini membuat _remote_, atau sambungan, bernama "origin" yang menunjuk ke repositori GitHub yang anda buat sebelumnya.
|
||||
|
||||
1. **Hantar fail tempatan ke GitHub**. Setakat ini anda telah membuat _connection_ antara repo tempatan dan repo GitHub. Marilah hantarkan fail-fail ini ke GitHub dengan perintah berikut `git push`, seperti di bawah:
|
||||
|
||||
```bash
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
Perintah ini menghantar komit anda di cawangan "utama" (main branch) anda ke GitHub.
|
||||
|
||||
1. **Untuk menambahkan perubahan lain**. Sekiranya anda ingin terus membuat perubahan dan menghantar ke GitHub, anda hanya perlu menggunakan tiga arahan berikut:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "type your commit message here"
|
||||
git push
|
||||
```
|
||||
|
||||
>Tip, Anda mungkin juga mahu mengadopsi fail `.gitignore` untuk mengelakkan fail yang tidak ingin anda lacak muncul di GitHub - seperti fail nota yang anda simpan di folder yang sama tetapi tidak mempunyai tempat di repositori awam. Anda boleh mencari templat untuk `.gitignore` fail pada [.gitignore templates](github.com/github/gitignore).
|
||||
|
||||
#### Mesej Komit
|
||||
|
||||
Baris subjek Git komit yang hebat melengkapkan ayat berikut:
|
||||
Sekiranya berlaku, komit ini akan <baris subjek anda di sini>
|
||||
|
||||
Untuk subjek gunakan keharusan, ketegangan sekarang: "perubahan" tidak "berubah" atau "perubahan".
|
||||
Seperti dalam subjek, dalam badan (pilihan) juga menggunakan keharusan, sekarang tegang. Tubuh harus merangkumi motivasi untuk perubahan dan membezakannya dengan tingkah laku sebelumnya. Anda menerangkan `mengapa`, bukan `bagaimana`.
|
||||
|
||||
✅ Luangkan masa beberapa minit untuk melayari GitHub. Bolehkah anda menemui mesej komit yang sangat hebat? Bolehkah anda mencari yang paling minimum? Maklumat apa yang anda fikir paling penting dan berguna untuk disampaikan dalam pesanan komited?
|
||||
|
||||
### Tugas: Kolaborasi
|
||||
|
||||
Sebab utama meletakkan perkara di GitHub adalah untuk memungkinkan untuk berkolaborasi dengan pemaju lain.
|
||||
|
||||
## Melakukan projek dengan orang lain
|
||||
|
||||
Dalam repositori anda, arahkan ke `Insights> Community` untuk melihat bagaimana projek anda dibandingkan dengan standard komuniti yang disyorkan.
|
||||
|
||||
Berikut adalah beberapa perkara yang dapat meningkatkan repo GitHub anda:
|
||||
- **Penerangan**. Adakah anda menambah keterangan untuk projek anda?
|
||||
- **README**. Adakah anda menambah README? GitHub memberikan panduan untuk menulis [README](https://docs.github.com/articles/about-readmes/).
|
||||
- **Garis panduan penyumbang**. Adakah projek anda mempunyai [cGaris panduan penyumbang](https://docs.github.com/articles/setting-guidelines-for-repository-contributors/),
|
||||
- **Tatakelakuan**. a [Tatakelakuan](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/),
|
||||
- **Lesen**. Yang paling penting, ialah [lesen](https://docs.github.com/articles/adding-a-license-to-a-repository/)?
|
||||
|
||||
|
||||
Semua sumber ini akan memberi manfaat kepada ahli pasukan baru. Dan ini biasanya merupakan jenis perkara yang dilihat oleh penyumbang baru bahkan sebelum melihat kod anda, untuk mengetahui sama ada projek anda adalah tempat yang tepat untuk mereka menghabiskan masa.
|
||||
|
||||
✅ README fail, walaupun memerlukan masa untuk disiapkan, sering diabaikan oleh penyelenggara yang sibuk. Bolehkah anda mencari contoh yang sangat deskriptif? Catatan: ada beberapa [alat untuk membantu mencipta README yang baik](https://www.makeareadme.com/) yang anda boleh cuba.
|
||||
|
||||
### Tugas: Gabungkan beberapa kod
|
||||
|
||||
Menyumbang kepada dokumen membantu orang menyumbang dalam projek tersebut. Ini menerangkan jenis sumbangan yang anda cari dan bagaimana prosesnya berjalan. Penyumbang perlu melalui beberapa langkah untuk dapat menyumbang kepada repo anda di GitHub:
|
||||
|
||||
|
||||
1. **Memalsukan repo anda** Anda mungkin mahu orang membuat projek anda. Memalsukan (_fork_) bermaksud membuat replika repositori anda di profil GitHub mereka.
|
||||
1. **Klon**. Dari sana mereka akan mengklonkan projek ke mesin tempatan mereka.
|
||||
1. **Buat branch**. Anda ingin meminta mereka membuat branch (_branch_) untuk kerja mereka.
|
||||
1. **Fokus perubahan mereka pada satu kawasan**. Minta penyumbang memusatkan sumbangan mereka pada satu perkara pada satu masa - dengan cara itu peluang yang anda dapat _merge_ dalam pekerjaan mereka adalah lebih tinggi. Bayangkan mereka menulis perbaikan pepijat, menambah ciri baru, dan mengemas kini beberapa ujian - bagaimana jika anda mahu, atau hanya dapat melaksanakan 2 dari 3, atau 1 dari 3 perubahan?
|
||||
|
||||
✅ Bayangkan keadaan di mana branch sangat penting untuk menulis dan menghantar kod yang baik. Apa kes penggunaan yang boleh anda fikirkan?
|
||||
|
||||
> Perhatikan, jadikan perubahan yang ingin anda lihat di dunia, dan buatlah cawangan untuk karya anda sendiri juga. Segala komit yang anda buat akan dibuat di cabang tempat Anda sedang "check out" gunakan `git status` untuk melihat cabang mana.
|
||||
|
||||
Mari melalui aliran kerja penyumbang. Anggaplah penyumbang telah _forked_ dan _cloned_ repo sehingga mereka mempunyai repo Git yang siap diusahakan, di mesin tempatan mereka:
|
||||
|
||||
1. **Membuat branch**. Guna perintah `git branch` untuk membuat branch baharu seperti berikut:
|
||||
|
||||
```bash
|
||||
git branch [branch-name]
|
||||
```
|
||||
|
||||
1. **Tukar ke working branch**. Tukar ke branch yang ditentukan dan kemas kini direktori kerja dengan `git checkout`:
|
||||
|
||||
```bash
|
||||
git checkout [branch-name]
|
||||
```
|
||||
|
||||
1. **Membuat kerja**. Pada ketika ini anda ingin menambahkan perubahan anda. Jangan lupa memberitahu Git mengenainya dengan arahan berikut:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "my changes"
|
||||
```
|
||||
|
||||
Pastikan anda memberikan ayat dengan baik kepada komit anda, demi anda dan juga penjaga repo yang anda bantu.
|
||||
|
||||
1. **Gabungkan kerja anda dengan `main` branch**. Pada satu ketika anda selesai bekerja dan anda ingin menggabungkan kerja anda dengan `main` branch. `main` branch mungkin telah berubah sementara itu, pastikan anda mengemas kini terlebih dahulu kepada yang terbaru dengan arahan berikut:
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
|
||||
Pada ketika ini anda ingin memastikan bahawa apa-apa _conflicts_, keadaan di mana Git tidak dapat dengan mudah _combine_ perubahan berlaku di working branch anda. Oleh itu, jalankan arahan berikut:
|
||||
|
||||
```bash
|
||||
git checkout [branch_name]
|
||||
git merge main
|
||||
```
|
||||
|
||||
Ini akan membawa semua perubahan dari `main` ke branch anda dan semoga anda dapat meneruskannya. Sekiranya tidak, VS Code akan memberitahu anda di mana Git _confused_ dan anda hanya mengubah fail yang terjejas untuk mengatakan kandungan mana yang paling tepat.
|
||||
|
||||
1. **Hantar kerja anda ke GitHub**. Menghantar karya anda ke GitHub bermaksud dua perkara. Menolak branch anda ke repo anda dan kemudian membuka PR, Tarik Permintaan (Pull Request).
|
||||
|
||||
```bash
|
||||
git push --set-upstream origin [branch-name]
|
||||
```
|
||||
|
||||
Perintah di atas membuat branch untuk forked repo.
|
||||
|
||||
1. **Buka Tarik Permintaan (Pull Request)** Seterusnya, anda mahu membuka tarik permintaan (Pull Request). Anda melakukannya dengan menavigasi ke repo bercabang di GitHub. Anda akan melihat petunjuk di GitHub di mana ia bertanya sama ada anda mahu membuat tarik permintaan (Pull Request) baru, anda mengkliknya dan anda akan dibawa ke antara muka di mana anda boleh menukar tajuk mesej komit, berikan keterangan yang lebih sesuai. Sekarang penyelenggara repo yang anda garpu akan melihat PR ini dan _fingers crossed_ mereka akan menghargai dan _merge_ tarik permintaan (Pull Request) anda. Anda telah menjadi penyumbang, yay:)
|
||||
|
||||
1. **Bersihkan**. Menjadikan amalan baik untuk _cleanup_ selepas anda. Anda mahu membersihkan local branch dan branch yang anda dorong ke GitHub. Pertama marilah hapuskannya secara tempatan dengan arahan berikut:
|
||||
|
||||
```bash
|
||||
git branch -d [branch-name]
|
||||
```
|
||||
|
||||
Pastikan anda pergi ke halaman GitHub untuk forked repo seterusnya dan keluarkan branch terpencil yang baru anda tolak.
|
||||
|
||||
`Tarik Permintaan (Pull request)` nampaknya istilah yang tidak bermoral kerana anda benar-benar mahu mendorong perubahan anda ke projek. Tetapi penyelenggara (pemilik projek) atau pasukan inti perlu mempertimbangkan perubahan anda sebelum menggabungkannya dengan "main" branch projek, jadi anda benar-benar meminta keputusan perubahan dari penyelenggara.
|
||||
|
||||
Tarik permintaan (Pull Request) adalah tempat untuk membandingkan dan membincangkan perbezaan yang diperkenalkan di cabang dengan ulasan, komen, ujian bersepadu, dan banyak lagi. Tarik permintaan (Pull Request) yang baik mengikuti kira-kira peraturan yang sama dengan pesanan pesanan. Anda dapat menambahkan rujukan ke masalah dalam pelacak masalah, ketika pekerjaan Anda misalnya menyelesaikan masalah. Ini dilakukan dengan menggunakan `#` diikuti dengan jumlah masalah (issue) anda. Contohnya `# 97`.
|
||||
|
||||
🤞 Jari memintas bahawa semua cek lulus dan pemilik projek menggabungkan perubahan anda ke dalam projek🤞
|
||||
|
||||
Kemas kini working branch tempatan anda sekarang dengan semua komit baru dari branch terpencil yang sesuai di GitHub:
|
||||
|
||||
`git pull`
|
||||
|
||||
## Bagaimanakah menyumbang kepada sumber terbuka
|
||||
|
||||
Pertama, marilah kita cari repositori - atau: repo - di GitHub yang menarik bagi anda dan yang anda ingin menyumbang perubahan. Anda mahu menyalin kandungannya ke mesin kami.
|
||||
|
||||
✅ Kaedah yang baik untuk mencari repo 'mesra pemula (beginner-friendly)' adalah dengan [cari mengikut tag 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
|
||||
|
||||
![Salin repo secara tempatan](images/clone_repo.png)
|
||||
|
||||
Terdapat beberapa cara menyalin kod. Salah satu cara adalah dengan "mengklon" kandungan repositori, menggunakan HTTPS, SSH, atau menggunakan GitHub CLI (Command Line Interface).
|
||||
|
||||
Buka terminal dan klon repo seperti di bawah:
|
||||
`git clone https://github.com/ProjectURL`
|
||||
|
||||
Untuk kerja dengan projek tersebut, tukar the fail kanan:
|
||||
`cd ProjectURL`
|
||||
|
||||
And juga boleh membuka keseluruhan projek dengan [Codespaces](https://github.com/features/codespaces), Penyunting kod terbitan GitHub / persekitaran pengembangan awan, atau [GitHub Desktop](https://desktop.github.com/).
|
||||
|
||||
Akhirnya, anda boleh memuat turun kod dalam bentuk zip.
|
||||
|
||||
### Beberapa perkara menarik mengenai GitHub
|
||||
|
||||
Anda boleh membintangi, menonton, dan / atau "fork" mana-mana repositori awam di GitHub. Anda boleh mencari repositori berbintang anda di menu lungsur kanan atas. Ia seperti penanda buku, tetapi untuk kod.
|
||||
|
||||
Projek mempunyai pelacak masalah, kebanyakannya di GitHub di tab "Isu" kecuali dinyatakan sebaliknya, di mana orang membincangkan masalah yang berkaitan dengan projek. Dan tab Tarik Permintaan adalah tempat orang membincangkan dan mengkaji perubahan yang sedang berlangsung.
|
||||
|
||||
Projek mungkin juga ada perbincangan di forum, senarai surat, atau saluran sembang seperti Slack, Discord atau IRC.
|
||||
|
||||
✅ Lihatlah repo GitHub baru anda dan cuba beberapa perkara, seperti menyunting tetapan, menambahkan maklumat ke repo anda, dan membuat projek (seperti papan Kanban). Banyak yang boleh anda lakukan!
|
||||
|
||||
---
|
||||
|
||||
### 🚀 Cabaran
|
||||
|
||||
Berpasangan dengan rakan untuk mengerjakan kod masing-masing. Buat projek secara kolaboratif, fork kod, buat branch dan gabungkan perubahan.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/4)
|
||||
|
||||
## Mengkaji dan belajar sendiri
|
||||
|
||||
Membaca tentang [menyumbang kepada sumber terbuka](https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution).
|
||||
|
||||
[Git nota](https://training.github.com/downloads/github-git-cheat-sheet/).
|
||||
|
||||
Berlatih, berlatih, berlatih. GitHub mempunyai jalan pembelajaran yang hebat yang tersedia melalui [lab.github.com](https://lab.github.com/):
|
||||
|
||||
- [Minggu pertama di GitHub](https://lab.github.com/githubtraining/first-week-on-github)
|
||||
|
||||
Anda juga akan menemui makmal yang lebih maju.
|
||||
|
||||
## Tugasan
|
||||
|
||||
Selesaikan [Minggu pertama di GitHub (training lab)](https://lab.github.com/githubtraining/first-week-on-github)
|
@ -0,0 +1,220 @@
|
||||
# Membuat Halaman Web yang Boleh Diakses
|
||||
|
||||
![Semua Tentang Kebolehcapaian](../webdev101-a11y.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/5)
|
||||
|
||||
> Kekuatan Web berada dalam kesejagatannya. Akses oleh semua orang tanpa mengira kecacatan adalah aspek penting.
|
||||
>
|
||||
> \- Sir Timothy Berners-Lee, Pengarah W3C dan penemu World Wide Web
|
||||
|
||||
Petikan ini dengan jelas menunjukkan pentingnya membuat laman web yang boleh diakses. Aplikasi yang tidak dapat diakses oleh semua orang adalah definisi pengecualian. Sebagai pembangun laman web, kita harus sentiasa mempunyai fikiran aksesibiliti. Dengan fokus ini dari awal, anda akan dapat memastikan semua orang dapat mengakses halaman yang anda buat. Dalam pelajaran ini, anda akan mengetahui tentang alat yang dapat membantu anda memastikan bahawa aset web anda dapat diakses dan bagaimana membina dengan mempertimbangkan kebolehcapaian.
|
||||
|
||||
## Alat untuk digunakan
|
||||
|
||||
### Pembaca skrin
|
||||
|
||||
Salah satu alat kebolehcapaian yang terkenal ialah pembaca skrin.
|
||||
|
||||
[Pembaca Skrin](https://en.wikipedia.org/wiki/Screen_reader) adalah pelanggan yang biasa digunakan untuk mereka yang mengalami masalah penglihatan Semasa kita menghabiskan masa untuk memastikan penyemak imbas menyampaikan maklumat yang ingin kita kongsi dengan betul, kita juga harus memastikan pembaca skrin melakukan perkara yang sama.
|
||||
|
||||
Pada asasnya, pembaca skrin akan membaca halaman dari atas ke bawah dengan didengar. Sekiranya halaman anda semua teks, pembaca akan menyampaikan maklumat dengan cara yang serupa dengan penyemak imbas. Sudah tentu, laman web jarang hanya teks; mereka akan mengandungi pautan, grafik, warna, dan komponen visual lain. Perhatian mesti diambil untuk memastikan bahawa maklumat ini dibaca dengan betul oleh pembaca skrin.
|
||||
|
||||
Setiap pembangun web harus membiasakan diri dengan pembaca skrin. Seperti yang dinyatakan di atas, ini adalah pelanggan yang akan digunakan pengguna anda Sama seperti anda mengetahui bagaimana penyemak imbas beroperasi, anda harus mengetahui cara pembaca skrin beroperasi. Nasib baik pembaca skrin dimasukkan ke dalam kebanyakan sistem operasi, dan banyak penyemak imbas mengandungi sambungan untuk meniru pembaca skrin.
|
||||
|
||||
✅ Cuba pelanjutan atau alat penyemak imbas pembaca skrin. Yang hanya berfungsi pada Windows ialah [JAWS](https://webaim.org/articles/jaws/). Penyemak imbas juga mempunyai alat bawaan yang dapat digunakan untuk tujuan ini; cuba [alat penyemak imbas Edge yang berfokus kebolehaksesan ini](https://support.microsoft.com/en-us/help/4000734/microsoft-edge-accessibility-features).
|
||||
|
||||
### Pemeriksa Kontras
|
||||
|
||||
Warna di laman web perlu dipilih dengan teliti untuk menjawab keperluan pengguna buta warna atau orang yang mengalami kesukaran untuk melihat warna kontras rendah.
|
||||
|
||||
✅ Uji laman web yang anda gemari untuk penggunaan warna dengan pelanjutan penyemak imbas seperti [WCAG's color checker](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US). Apakah anda telah belajar?
|
||||
|
||||
### Lighthouse
|
||||
|
||||
Di kawasan alat pembangun penyemak imbas (developer tool area) anda, anda akan menemui alat Lighthouse. Alat ini penting untuk mendapatkan pandangan pertama mengenai kebolehaksesan (serta analisis lain) dari laman web. Walaupun penting untuk tidak bergantung sepenuhnya pada Lighthouse, skor 100% sangat membantu sebagai asas.
|
||||
|
||||
✅ Cari Lighthouse pada panel alat pembangun penyemak imbas anda dan jalankan analisis di mana-mana laman web. Apakah yang anda telah cari?
|
||||
|
||||
## Reka bentuk untuk kebolehcapaian
|
||||
|
||||
Kebolehcapaian adalah topik yang agak besar. Untuk membantu anda, terdapat banyak sumber yang ada.
|
||||
|
||||
- [Accessible U - University of Minnesota](https://accessibility.umn.edu/your-role/web-developers)
|
||||
|
||||
Walaupun kami tidak dapat merangkumi setiap aspek dalam membuat laman web yang dapat diakses, berikut adalah beberapa prinsip utama yang ingin anda laksanakan. Merancang halaman yang dapat diakses dari awal **selalu** lebih mudah daripada kembali ke halaman yang ada untuk menjadikannya mudah diakses.
|
||||
|
||||
## Prinsip paparan yang baik
|
||||
|
||||
### Palet warna selamat
|
||||
|
||||
Orang melihat dunia dengan cara yang berbeza, dan ini termasuk warna. Semasa memilih skema warna untuk laman web anda, anda harus memastikannya dapat diakses oleh semua orang. Salah satu alat yang hebat [untuk menghasilkan palet warna ialah Warna Selamat](http://colorsafe.co/).
|
||||
|
||||
✅ Kenalpasti laman web yang sangat bermasalah dalam penggunaan warnanya. Kenapa?
|
||||
|
||||
### Sorot teks dengan betul
|
||||
|
||||
Menonjolkan teks mengikut warna, [font weight](https://developer.mozilla.org/docs/Web/CSS/font-weight), atau [text decoration](https://developer.mozilla.org/docs/Web/CSS/text-decoration) tidak memberitahu pembaca skrin mengenai kepentingannya. Sesuatu perkataan boleh dicetak tebal kerana itu adalah kata kunci, atau kerana kata pertama dan pereka memutuskan bahawa perkataan itu harus tebal.
|
||||
|
||||
Apabila frasa tertentu perlu diserlahkan, gunakan elemen `<strong>` atau `<em>`. Ini akan menunjukkan kepada pembaca skrin bahawa item tersebut penting.
|
||||
|
||||
### Guna HTML dengan betul
|
||||
|
||||
Dengan CSS dan JavaScript, elemen boleh kelihatan seperti jenis kawalan. `<span>` dapat digunakan untuk membuat `<button>`, dan `<b>` dapat menjadi hyperlink. Walaupun ini mungkin dianggap lebih mudah untuk digayakan, membingungkan pembaca skrin. Gunakan HTML yang sesuai semasa membuat kawalan pada halaman. Sekiranya anda mahukan hyperlink, gunakan `<a>`. Menggunakan HTML yang betul untuk kawalan yang tepat disebut menggunakan HTML Semantik.
|
||||
|
||||
✅ Pergi ke mana-mana laman web dan lihat apakah pereka dan pembangun menggunakan HTML dengan betul. Bolehkah anda mencari butang yang seharusnya menjadi pautan? Petunjuk: klik kanan dan pilih 'Lihat Sumber Halaman' di penyemak imbas anda untuk melihat kod yang mendasari.
|
||||
|
||||
### Gunakan petunjuk visual yang baik
|
||||
|
||||
CSS menawarkan kawalan penuh terhadap penampilan elemen apa pun pada halaman Anda boleh membuat kotak teks tanpa garis besar atau pautan hiper tanpa garis bawah. Malangnya, menghapus petunjuk itu boleh menjadikannya lebih mencabar bagi seseorang yang bergantung kepada mereka untuk dapat mengenali jenis kawalan.
|
||||
|
||||
## Kepentingan teks pautan
|
||||
|
||||
Hyperlink adalah teras untuk menavigasi web. Hasilnya, memastikan pembaca skrin dapat membaca pautan dengan betul membolehkan semua pengguna menavigasi laman web anda.
|
||||
|
||||
### Pembaca skrin dan pautan
|
||||
|
||||
Seperti yang anda harapkan, pembaca skrin membaca teks pautan dengan cara yang sama seperti mereka membaca teks lain di halaman. Dengan ini, teks yang ditunjukkan di bawah mungkin dapat diterima dengan baik.
|
||||
|
||||
> Penguin kecil, kadang-kadang dikenali sebagai penguin peri, adalah penguin terkecil di dunia. [Tekan sini](https://en.wikipedia.org/wiki/Little_penguin) untuk maklumat lanjut.
|
||||
|
||||
> Penguin kecil, kadang-kadang dikenali sebagai penguin peri, adalah penguin terkecil di dunia. Layari https://en.wikipedia.org/wiki/Little_penguin untuk maklumat lanjut.
|
||||
|
||||
> **CATATAN** Semasa hendak membaca, anda seharusnya **tidak pernah** membuat pautan yang kelihatan seperti di atas.
|
||||
|
||||
Ingat, pembaca skrin adalah antara muka yang berbeza dari penyemak imbas dengan set ciri yang berbeza.
|
||||
|
||||
### Masalah dengan menggunakan URL
|
||||
|
||||
Pembaca skrin membaca teks. Sekiranya URL muncul dalam teks, pembaca skrin akan membaca URL tersebut. Secara umum, URL tidak menyampaikan maklumat yang bermakna, dan boleh menyakitkan hati. Anda mungkin pernah mengalami ini jika telefon anda pernah membaca pesanan teks dengan URL.
|
||||
|
||||
### Masalah dengan "klik di sini"
|
||||
|
||||
Pembaca skrin juga mempunyai kemampuan untuk membaca hanya pautan hiper pada halaman, dengan cara yang sama orang yang melihat akan mengimbas halaman untuk mendapatkan pautan. Sekiranya teks pautan selalu "klik di sini", semua pengguna akan mendengar adalah "klik di sini, klik di sini, klik di sini, klik di sini, klik di sini, ..." Semua pautan kini tidak dapat dibezakan antara satu sama lain.
|
||||
|
||||
### Teks pautan yang baik
|
||||
|
||||
Teks pautan yang baik menerangkan secara ringkas apa yang terdapat di seberang pautan. Dalam contoh di atas yang membicarakan penguin kecil, pautan adalah ke halaman Wikipedia mengenai spesies tersebut. Frasa *penguin kecil* akan menghasilkan teks pautan yang sempurna kerana ia menjelaskan apa yang akan dipelajari oleh seseorang jika mereka mengklik pautan itu - penguin kecil.
|
||||
|
||||
> [penguin kecil](https://en.wikipedia.org/wiki/Little_penguin), kadang-kadang dikenali sebagai penguin peri, adalah penguin terkecil di dunia.
|
||||
|
||||
✅ Melayari laman web selama beberapa minit untuk mencari halaman yang menggunakan strategi penghubung yang tidak jelas. Bandingkan dengan laman web lain yang mempunyai hubungan lebih baik. Apa yang anda pelajari?
|
||||
|
||||
#### Nota enjin carian
|
||||
|
||||
Sebagai bonus tambahan untuk memastikan laman web anda dapat diakses oleh semua orang, anda juga akan membantu enjin carian menavigasi laman web anda. Enjin carian menggunakan teks pautan untuk mempelajari topik halaman. Oleh itu, menggunakan teks pautan yang baik membantu semua orang!
|
||||
|
||||
### ARIA
|
||||
|
||||
Bayangkan halaman berikut:
|
||||
|
||||
| Produk | Penerangan | Pesanan |
|
||||
| ------------ | ---------------- | ------------ |
|
||||
| Widget | [Penerangan]('#') | [Pesanan]('#') |
|
||||
| Super widget | [Penerangan]('#') | [Pesanan]('#') |
|
||||
|
||||
Dalam contoh ini, mendua teks keterangan dan urutan masuk akal bagi seseorang yang menggunakan penyemak imbas. Walau bagaimanapun, seseorang yang menggunakan pembaca skrin hanya akan mendengar kata-kata *Penerangan* dan *Pesanan* diulang tanpa konteks.
|
||||
|
||||
Untuk menyokong jenis senario ini, HTML menyokong sekumpulan atribut yang dikenali sebagai [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/docs/Web/Accessibility/ARIA). Atribut ini membolehkan anda memberikan maklumat tambahan kepada pembaca skrin.
|
||||
|
||||
> **CATATAN**: Seperti banyak aspek HTML, sokongan penyemak imbas dan pembaca skrin mungkin berbeza. Walau bagaimanapun, kebanyakan pelanggan utama menyokong atribut ARIA.
|
||||
|
||||
Anda boleh menggunakan `aria-label` untuk menerangkan pautan apabila format halaman tidak membenarkan anda. Keterangan untuk widget dapat ditetapkan sebagai
|
||||
|
||||
``` html
|
||||
<a href="#" aria-label="Widget description">description</a>
|
||||
```
|
||||
|
||||
✅ Secara umum, menggunakan markup Semantik seperti yang dijelaskan di atas menggantikan penggunaan ARIA, tetapi kadang-kadang tidak ada yang setara dengan semantik untuk pelbagai widget HTML. Contoh yang baik ialah Progressbar. Tidak ada setara HTML untuk bar kemajuan, jadi anda mengenal pasti generik `<div>` untuk elemen ini dengan peranan dan nilai aria yang betul. [MDN documentation on ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) mengandungi maklumat yang lebih berguna.
|
||||
|
||||
```html
|
||||
<div id="percent-loaded" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
|
||||
</div>
|
||||
```
|
||||
|
||||
## Gambar
|
||||
|
||||
Sudah tentu, pembaca skrin tidak dapat membaca secara automatik apa yang terdapat dalam gambar. Memastikan gambar dapat diakses tidak memerlukan banyak kerja - itulah atribut `alt`. Semua gambar harus mempunyai `alt` untuk menggambarkan apa itu.
|
||||
|
||||
✅ Seperti yang anda jangkakan, enjin carian juga tidak dapat memahami apa yang ada dalam gambar. Mereka juga menggunakan teks alt. Oleh itu, sekali lagi, memastikan halaman anda dapat diakses memberikan bonus tambahan!
|
||||
|
||||
## Papan Kekunci
|
||||
|
||||
Sebilangan pengguna tidak dapat menggunakan tetikus atau pad jejak, sebaliknya bergantung pada interaksi papan kekunci ke tab dari satu elemen ke elemen yang lain. Penting bagi laman web anda untuk menyajikan kandungan anda mengikut urutan logik agar papan kekunci dapat mengakses setiap elemen ketika pengguna menurunkan dokumen. Sekiranya anda membina laman web anda dengan penanda semantik dan menggunakan CSS untuk menggayakan susun atur visual mereka, laman web anda harus dilayari papan kekunci, tetapi penting untuk menguji aspek ini secara manual. Ketahui lebih lanjut mengenai [Strategi Papan Kekunci](https://webaim.org/techniques/keyboard/).
|
||||
|
||||
✅ Pergi ke mana-mana laman web dan cuba menavigasinya melalui hanya menggunakan kunci tab anda. Apa yang berfungsi, apa yang tidak berfungsi? Kenapa?
|
||||
|
||||
## Rumusan
|
||||
|
||||
Web yang boleh diakses oleh sesetengah orang bukan benar-benar 'web seluruh dunia'. Kaedah terbaik untuk memastikan laman web yang anda buat dapat diakses adalah dengan menggabungkan amalan terbaik kebolehcapaian sejak awal. Walaupun ada langkah tambahan yang diperlukan, memasukkan kemahiran ini ke dalam aliran kerja anda sekarang akan bermakna semua halaman yang anda buat akan dapat diakses.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Ambil HTML ini dan tulis semula agar dapat diakses semaksimum mungkin, mengingat strategi yang anda pelajari.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Example
|
||||
</title>
|
||||
<link href='../assets/style.css' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
<body>
|
||||
<div class="site-header">
|
||||
<p class="site-title">Turtle Ipsum</p>
|
||||
<p class="site-subtitle">The World's Premier Turtle Fan Club</p>
|
||||
</div>
|
||||
<div class="main-nav">
|
||||
<p class="nav-header">Resources</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="https://www.youtube.com/watch?v=CMNry4PE93Y">"I like turtles"</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtle">Basic Turtle Info</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtles_(chocolate)">Chocolate Turtles</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div>
|
||||
<p class="page-title">Welcome to Turtle Ipsum.
|
||||
<a href="">Click here</a> to learn more.
|
||||
</p>
|
||||
<p class="article-text">
|
||||
Turtle ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="footer-section">
|
||||
<span class="button">Sign up for turtle news</span>
|
||||
</div><div class="footer-section">
|
||||
<p class="nav-header footer-title">
|
||||
Internal Pages
|
||||
</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="../">Index</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="../semantic">Semantic Example</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="footer-copyright">© 2016 Instrument</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/6)
|
||||
|
||||
## Mengkaji dan belajar sendiri
|
||||
|
||||
Banyak kerajaan mempunyai undang-undang mengenai syarat aksesibilitas. Baca undang-undang kebolehcapaian negara asal anda. Apa yang dilindungi, dan apa yang tidak? Contohnya ialah [laman kerajaan](https://accessibility.blog.gov.uk/).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Menganalisis laman web yang tidak dapat diakses](../assignment.md)
|
||||
|
||||
Kredit: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) karya Instrument
|
@ -0,0 +1,17 @@
|
||||
# Mulai dengan Pembangunan Web
|
||||
|
||||
Dalam bahagian kurikulum ini, anda akan diperkenalkan kepada konsep bukan projek yang penting untuk menjadi pembangun profesional.
|
||||
|
||||
### Topik
|
||||
|
||||
1. [Pengenalan Bahasa Pengaturcaraan dan Alat Perdagangan](1-intro-to-programming-languages/README.md)
|
||||
2. [Pengetahuan Asas tentang GitHub](2-github-basics/README.md)
|
||||
3. [Asas Kebolehcapaian](3-accessibility/README.md)
|
||||
|
||||
### Kredit
|
||||
|
||||
Asas Kebolehcapaian ditulis dengan ♥️ karya [Christopher Harrison](https://twitter.com/geektrainer)
|
||||
|
||||
Pengetahuan Asas tentang GitHub ditulis dengan ♥️ karya [Floor Drees](https://twitter.com/floordrees)
|
||||
|
||||
Pengenalan Bahasa Pengaturcaraan dan Alat Perdagangan ditulis dengan ♥️ karya [Jasmine Greenaway](https://twitter.com/paladique)
|
@ -0,0 +1,196 @@
|
||||
# Asas JavaScript: Jenis Data
|
||||
|
||||
![Asas JavaScript: Jenis Data](../images/webdev101-js-datatypes.png)
|
||||
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/7)
|
||||
|
||||
Pelajaran ini merangkumi asas-asas JavaScript, bahasa yang menyediakan interaktiviti di web.
|
||||
|
||||
[![Jenis Data Dalam JavaScript](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Data types in JavaScript")
|
||||
|
||||
|
||||
Marilah kita mulakan dengan pemboleh ubah dan jenis data yang mengisinya!
|
||||
|
||||
## Pemboleh Ubah
|
||||
|
||||
Pemboleh ubah menyimpan nilai yang boleh digunakan dan diubah di seluruh kod anda.
|
||||
|
||||
Membuat dan **menyatakan** pemboleh ubah mempunyai sintaks berikut **[kata kunci] [nama]**. Ia terdiri daripada dua bahagian:
|
||||
|
||||
- **Kata Kunci**. Kata kunci seperti `let` atau `var`.
|
||||
|
||||
> Perhatikan, kata kunci seperti `let` diperkenalkan dalam ES6 dan memberikan pemboleh ubah anda apa yang disebut _block lingkup_. Sebaiknya gunakan `let` over` var`. Kami akan merangkumi skop blok dengan lebih mendalam di bahagian-bahagian masa depan.
|
||||
- **Nama pemboleh ubah**, ini adalah nama yang anda pilih sendiri.
|
||||
|
||||
### Tugasan - bekerja dengan pemboleh ubah
|
||||
|
||||
1. **Menyatakan pemboleh ubah**. Marilah nyatakan pemboleh ubah menggunakan kata kunci `let`:
|
||||
|
||||
```javascript
|
||||
let myVariable;
|
||||
```
|
||||
|
||||
`myVariable` kini telah dinyatakan menggunakan kata kunci` let`. Pada masa ini tidak mempunyai nilai.
|
||||
|
||||
1. **Berikan nilai**. Simpan nilai dalam pemboleh ubah dengan pengendali `=`, diikuti dengan nilai yang diharapkan.
|
||||
|
||||
```javascript
|
||||
myVariable = 123;
|
||||
```
|
||||
|
||||
> Catatan: penggunaan `=` dalam pelajaran ini berarti kita menggunakan "pengendali tugasan", yang digunakan untuk menetapkan nilai ke pemboleh ubah. Itu tidak menunjukkan persamaan.
|
||||
|
||||
`myVariable` kini telah *diinisialisasi* dengan nilai 123.
|
||||
|
||||
1. **Pemfaktor**. Gantikan kod anda dengan pernyataan berikut.
|
||||
|
||||
```javascript
|
||||
let myVariable = 123;
|
||||
```
|
||||
Perkara di atas dipanggil _inisialisasi eksplisit_ apabila pemboleh ubah diisytiharkan dan diberikan nilai pada masa yang sama.
|
||||
|
||||
1. **Tukar nilai pemboleh ubah**. Tukar nilai pemboleh ubah dengan cara berikut:
|
||||
|
||||
```javascript
|
||||
myVariable = 321;
|
||||
```
|
||||
|
||||
Setelah pemboleh ubah diisytiharkan, anda boleh mengubah nilainya pada bila-bila masa dalam kod anda dengan pengedali `=` dan nilai baru.
|
||||
|
||||
✅ Cubalah! Anda boleh menulis JavaScript di penyemak imbas anda. Buka tetingkap penyemak imbas dan arahkan ke Alat Pembangun. Dalam konsol, anda akan menemui arahan; taip `let myVariable = 123`, tekan return, kemudian taip `myVariable`. Apa yang berlaku? Perhatikan, anda akan mengetahui lebih lanjut mengenai konsep ini dalam pelajaran seterusnya.
|
||||
|
||||
## Pemalar
|
||||
|
||||
Pengisytiharan dan permulaan pemalar mengikuti konsep yang sama dengan pemboleh ubah, dengan menggunakan `const`. Pemalar biasanya dinyatakan dengan semua huruf besar.
|
||||
|
||||
```javascript
|
||||
const MY_VARIABLE = 123;
|
||||
```
|
||||
|
||||
Pemalar serupa dengan pemboleh ubah, dengan dua pengecualian:
|
||||
|
||||
- **Mesti ada nilai**. Pemalar mesti diinisialisasi, atau kesalahan akan berlaku semasa menjalankan kod.
|
||||
- **Rujukan tidak boleh diubah**. Rujukan pemalar tidak dapat diubah setelah diinisialisasi, atau kesalahan akan terjadi ketika menjalankan kod. Marilah kita lihat dua contoh:
|
||||
- **Menyimpan nilai**. Perkara berikut TIDAK dibenarkan:
|
||||
|
||||
```javascript
|
||||
const PI = 3;
|
||||
PI = 4; // tidak dibenarkan
|
||||
```
|
||||
|
||||
- **Rujukan objek dilindungi**. Perkara berikut TIDAK dibenarkan:
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj = { b: 5 } // tidak dibenarkan
|
||||
```
|
||||
|
||||
|
||||
- **Rujukan objek tidak dilindungi**. Perkara berikut dibenakan:
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj.a = 5; // allowed
|
||||
```
|
||||
|
||||
Di atas anda mengubah nilai objek tetapi bukan rujukan itu sendiri, yang membuatnya dibenarkan.
|
||||
|
||||
> Perhatikan, `const` bermaksud rujukan dilindungi dari penugasan semula. Nilainya tidak _tidak berubah_ dan ia juga boleh berubah, terutamanya jika konstruk kompleks seperti objek.
|
||||
|
||||
## Jenis Data
|
||||
|
||||
Pemboleh ubah boleh menyimpan pelbagai jenis nilai, seperti nombor dan teks. Pelbagai jenis nilai ini dikenali sebagai **jenis data**. Jenis data adalah bahagian penting dalam pembangunan perisian kerana ia membantu pembangun membuat keputusan mengenai bagaimana kod itu harus ditulis dan bagaimana perisian itu harus dijalankan. Tambahan pula, beberapa jenis data mempunyai ciri unik yang membantu mengubah atau mengekstrak maklumat tambahan dalam suatu nilai.
|
||||
|
||||
✅ Jenis Data juga disebut sebagai primitif data JavaScript, kerana ia adalah jenis data tahap terendah yang disediakan oleh bahasa. Terdapat 6 jenis data primitif: rentetan, nombor, bigint, boolean, tidak ditentukan, dan simbol. Luangkan masa sebentar untuk menggambarkan apa yang diwakili oleh setiap primitif ini. Apa itu `zebra`? Bagaimana dengan `0`? `benar`?
|
||||
|
||||
### Nombor
|
||||
|
||||
Pada bahagian sebelumnya, nilai `myVariable` adalah jenis data nombor.
|
||||
|
||||
`let myVariable = 123;`
|
||||
|
||||
Pemboleh ubah boleh menyimpan semua jenis nombor, termasuk nombor perpuluhan atau nombor negatif. Nombor juga boleh digunakan dengan pengendali aritmetik, yang terdapat dalam [bahagian seterusnya](#pengendali).
|
||||
|
||||
### Pengendali Aritmetik
|
||||
|
||||
Terdapat beberapa jenis operator yang boleh digunakan semasa menjalankan fungsi aritmetik, dan ada yang disenaraikan di sini:
|
||||
|
||||
| Simbol | Penerangan | Contoh |
|
||||
| ------ | ------------------------------------------------------------------------ | -------------------------------- |
|
||||
| `+` | **Penambahan**: Mengira jumlah dua nombor | `1 + 2 // jawapan ialah 3` |
|
||||
| `-` | **Penolakan**: Mengira perbezaan dua nombor | `1 - 2 // jawapan ialah -1` |
|
||||
| `*` | **Pendaraban**: Mengira hasil dua nombor | `1 * 2 // jawapan ialah 2` |
|
||||
| `/` | **Pembahagian**: Mengira hasil bagi dua nombor | `1 / 2 //jawapan ialah 0.5` |
|
||||
| `%` | **Baki**: Mengira baki dari pembahagian dua nombor | `1 % 2 //jawapan ialah 1` |
|
||||
|
||||
✅ Cubalah! Cuba operasi aritmetik di konsol penyemak imbas anda. Adakah hasilnya mengejutkan anda?
|
||||
|
||||
### String
|
||||
|
||||
String adalah kumpulan watak yang berada di antara tanda petik tunggal atau ganda.
|
||||
|
||||
- `'Ini adalah string'`
|
||||
- `"Ini pun juga string"`
|
||||
- `let myString = 'Ini adalah nilai string yang disimpan dalam pemboleh ubah';`
|
||||
|
||||
Ingatlah untuk menggunakan tanda kutip semasa menulis string, jika tidak, JavaScript akan menganggapnya adalah nama yang berubah-ubah.
|
||||
|
||||
### Memformat String
|
||||
|
||||
String bersifat teks, dan memerlukan format dari semasa ke semasa.
|
||||
|
||||
Untuk **menggabungkan** dua atau lebih string, gunakan pengendali `+`.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
myString1 + myString2 + "!"; //HelloWorld!
|
||||
myString1 + " " + myString2 + "!"; //Hello World!
|
||||
myString1 + ", " + myString2 + "!"; //Hello, World!
|
||||
|
||||
```
|
||||
|
||||
✅ Mengapakah `1 + 1 = 2` dalam JavaScript, tetapi `'1' + '1' = 11?` Cuba fikirkan. Bagaimanakah dengan `'1' + 1`?
|
||||
|
||||
**Literal templat** adalah cara lain untuk memformat rentetan, kecuali tanda petik, tanda belakang digunakan. Apa-apa yang bukan teks biasa mesti diletakkan di dalam pemegang tempat `$ {}`. Ini merangkumi sebarang pemboleh ubah yang mungkin adalah string.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
`${myString1} ${myString2}!` //Hello World!
|
||||
`${myString1}, ${myString2}!` //Hello, World!
|
||||
```
|
||||
|
||||
Anda boleh mencapai matlamat pemformatan anda dengan mana-mana kaedah, tetapi templat literal akan menghormati ruang dan jeda baris.
|
||||
|
||||
✅ Bilakah anda menggunakan templat literal berbanding string biasa?
|
||||
|
||||
### Booleans
|
||||
|
||||
Booleans boleh hanya dua nilai: `benar` atau `salah`. Booleans dapat membantu membuat keputusan mengenai garis kod mana yang harus dijalankan apabila syarat tertentu dipenuhi. Dalam banyak kes, [pengendali](#pengendali) membantu menetapkan nilai Boolean dan anda sering akan melihat dan menulis pemboleh ubah yang dimulakan atau nilainya dikemas kini dengan operator.
|
||||
|
||||
- `let myTrueBool = betul`
|
||||
- `let myFalseBool = salah`
|
||||
|
||||
✅ Pemboleh ubah boleh dianggap 'benar' jika dinilai menjadi `benar` boolean. Menariknya, dalam JavaScript, [semua nilai adalah benar kecuali ditakrifkan sebagai palsu](https://developer.mozilla.org/en-US/docs/Glossary/Truthy).
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
JavaScript terkenal kerana kaedahnya yang mengagumkan dalam mengendalikan jenis data sesekali. Lakukan sedikit kajian mengenai 'gotchas' ini. Contohnya: kepekaan kes boleh menggigit! Cubalah ini di konsol anda: `let age = 1; biarkan Umur = 2; age == Age` (menyelesaikan `false` - mengapa?). Apa lagi gotchas yang anda dapati?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/8)
|
||||
|
||||
## Mengkaji dan belajar sendiri
|
||||
|
||||
Lihat [latihan JavaScript](https://css-tricks.com/snippets/javascript/) dan cubalah. Apa yang anda telah belajar?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Latihan Jenis Data](../assignment.md)
|
@ -0,0 +1,11 @@
|
||||
# Latihan Jenis Data
|
||||
|
||||
## Arahan
|
||||
|
||||
Bayangkan anda sedang membina keranjang belanja. Tulis beberapa dokumentasi mengenai jenis data yang anda perlukan untuk melengkapkan pengalaman membeli-belah anda. Bagaimana anda sampai pada pilihan anda?
|
||||
|
||||
## Rubrik
|
||||
|
||||
Kriteria | Contoh | Mencukupi | Usaha Lagi
|
||||
--- | --- | --- | -- |
|
||||
||Enam jenis data disenaraikan dan diterokai secara terperinci, mendokumentasikan penggunaannya|Empat jenis data diterokai|Duo jenis data diterokai|
|
@ -0,0 +1,195 @@
|
||||
# Asas JavaScript: Kaedah dan Fungsi
|
||||
|
||||
![Asas JavaScript - Fungsi](../images/webdev101-js-functions.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/9)
|
||||
|
||||
Apabila kita berfikir tentang menulis kod, kita selalu ingin memastikan kod kita dapat dibaca. Walaupun ini terdengar berlawanan dengan intuisi, kod dibaca lebih banyak kali daripada yang ditulis. Satu alat inti dalam kotak alat pemaju untuk memastikan kod yang dapat dikendalikan adalah **fungsi**.
|
||||
|
||||
[![Kaedah dan Fungsi](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Methods and Functions")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai kaedah dan fungsi.
|
||||
|
||||
## Fungsi
|
||||
|
||||
Pada intinya, fungsi adalah sekumpulan kod yang dapat kita laksanakan berdasarkan permintaan. Ini sesuai untuk senario di mana kita perlu melakukan tugas yang sama berkali-kali; daripada menggandakan logik di beberapa lokasi (yang akan menjadikannya sukar untuk dikemas kini apabila tiba masanya), kita dapat memusatkannya di satu lokasi, dan memanggilnya setiap kali kita memerlukan operasi yang dilakukan - anda bahkan dapat memanggil fungsi dari fungsi lain !.
|
||||
|
||||
Sama pentingnya ialah kemampuan menamakan fungsi. Walaupun ini kelihatan remeh, namanya memberikan cara cepat untuk mendokumentasikan bahagian kod. Anda boleh menganggap ini sebagai label pada butang. Sekiranya saya mengklik pada butang yang berbunyi "Batalkan pemasa", saya tahu ia akan berhenti menjalankan jam.
|
||||
|
||||
## Membuat dan memanggil fungsi
|
||||
|
||||
Sintaks untuk fungsi kelihatan seperti berikut:
|
||||
|
||||
```javascript
|
||||
function nameOfFunction() { // definisi fungsi
|
||||
// definisi fungsi dan badannya
|
||||
}
|
||||
```
|
||||
|
||||
Sekiranya saya ingin membuat fungsi untuk memaparkan ucapan, mungkin seperti ini:
|
||||
|
||||
```javascript
|
||||
function displayGreeting() {
|
||||
console.log('Hello, world!');
|
||||
}
|
||||
```
|
||||
|
||||
Setiap kali kita mahu memanggil (atau memanggil) fungsi kita, kita menggunakan nama fungsi diikuti oleh `()`. Perlu diperhatikan bahawa fungsi kita dapat ditentukan sebelum atau selepas kita memutuskan untuk menyebutnya; penyusun JavaScript akan mencarinya untuk anda.
|
||||
|
||||
```javascript
|
||||
// memanggil fungsi
|
||||
displayGreeting();
|
||||
```
|
||||
|
||||
> **CATATAN:** Terdapat jenis fungsi khas yang dikenali sebagai
|
||||
**kaedah**, yang sudah anda gunakan! Sebenarnya, kami melihat ini dalam demo kami di atas semasa kami menggunakan `console.log`. Apa yang membuat kaedah berbeza dari fungsi adalah metode yang dilampirkan ke objek (`console` dalam contoh kami), sementara fungsi bebas mengambang. Anda akan mendengar banyak pembangun menggunakan istilah ini secara bergantian.
|
||||
|
||||
### Amalan terbaik untuk fungsi
|
||||
|
||||
Terdapat sebilangan kecil amalan terbaik yang perlu diingat semasa membuat fungsi
|
||||
|
||||
- Seperti biasa, gunakan nama deskriptif sehingga anda tahu fungsi apa yang akan dilakukan
|
||||
- Gunakan **camelCasing** untuk menggabungkan perkataan
|
||||
- Pastikan fungsi anda tertumpu pada tugas tertentu
|
||||
|
||||
## Menyampaikan maklumat ke fungsi
|
||||
|
||||
Untuk menjadikan fungsi lebih boleh digunakan semula, anda selalunya ingin menyampaikan maklumat ke dalamnya. Sekiranya kita mempertimbangkan contoh `displayGreeting` di atas, ia hanya akan memaparkan **Hello, world!**. Bukan fungsi paling berguna yang dapat dibuat oleh seseorang. Sekiranya kita ingin menjadikannya sedikit lebih fleksibel, seperti membiarkan seseorang menentukan nama orang yang disambut, kita dapat menambahkan **parameter**. Parameter (kadang-kadang disebut **argumen**), adalah maklumat tambahan yang dikirim ke fungsi.
|
||||
|
||||
Parameter disenaraikan di bahagian definisi dalam kurungan dan dipisahkan koma seperti:
|
||||
|
||||
```javascript
|
||||
function name(param, param2, param3) {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Kami boleh mengemas kini `displayGreeting` kami untuk menerima nama dan memaparkannya.
|
||||
|
||||
```javascript
|
||||
function displayGreeting(name) {
|
||||
const message = `Hello, ${name}!`;
|
||||
console.log(message);
|
||||
}
|
||||
```
|
||||
|
||||
Apabila kita mahu memanggil fungsi kita dan meneruskan parameter, kita menentukannya dalam kurungan.
|
||||
|
||||
```javascript
|
||||
displayGreeting('Christopher');
|
||||
// memapar "Hello, Christopher!" apabila memproseskannya
|
||||
```
|
||||
|
||||
## Nilai lalai
|
||||
|
||||
Kita dapat menjadikan fungsi kita lebih fleksibel dengan menambahkan lebih banyak parameter. Tetapi bagaimana jika kita tidak mahu setiap nilai ditentukan? Sesuai dengan contoh ucapan kami, kami dapat meninggalkan nama seperti yang diperlukan (kami harus tahu siapa yang kami sapa), tetapi kami ingin membiarkan ucapan itu disesuaikan sesuai keinginan. Sekiranya seseorang tidak mahu menyesuaikannya, kami memberikan nilai lalai. Untuk memberikan nilai lalai ke parameter, kami menetapkannya dengan cara yang sama dengan menetapkan nilai untuk pemboleh ubah - `parameterName = 'defaultValue' `. Untuk melihat contoh penuh:
|
||||
|
||||
```javascript
|
||||
function displayGreeting(name, salutation='Hello') {
|
||||
console.log(`${salutation}, ${name}`);
|
||||
}
|
||||
```
|
||||
|
||||
Apabila kita memanggil fungsi tersebut, kita kemudian dapat memutuskan apakah kita ingin menetapkan nilai untuk `salam `.
|
||||
|
||||
```javascript
|
||||
displayGreeting('Christopher');
|
||||
// memapar "Hello, Christopher"
|
||||
|
||||
displayGreeting('Christopher', 'Hi');
|
||||
// memapar "Hi, Christopher"
|
||||
```
|
||||
|
||||
## Nilai Pulangan
|
||||
|
||||
Sehingga kini fungsi yang kami bina akan selalu dikeluarkan ke [console](https://developer.mozilla.org/en-US/docs/Web/API/console). Kadang kala inilah yang sebenarnya kita cari, terutamanya ketika kita membuat fungsi yang akan memanggil perkhidmatan lain. Tetapi bagaimana jika saya ingin membuat fungsi pembantu untuk melakukan pengiraan dan memberikan nilai kembali supaya saya dapat menggunakannya di tempat lain?
|
||||
|
||||
Kita boleh melakukan ini dengan menggunakan **nilai kembali**. Nilai kembali akan dikembalikan oleh fungsi, dan dapat disimpan dalam pemboleh ubah sama seperti kita dapat menyimpan nilai literal seperti rentetan atau angka.
|
||||
|
||||
Sekiranya fungsi mengembalikan sesuatu maka kata kunci `return` digunakan. Kata kunci `return` menjangkakan nilai atau rujukan tentang apa yang dikembalikan seperti itu:
|
||||
|
||||
```javascript
|
||||
return myVariable;
|
||||
```
|
||||
|
||||
Kami dapat membuat fungsi untuk membuat pesan ucapan dan mengembalikan nilainya kembali ke pemanggil
|
||||
|
||||
```javascript
|
||||
function createGreetingMessage(name) {
|
||||
const message = `Hello, ${name}`;
|
||||
return message;
|
||||
}
|
||||
```
|
||||
|
||||
Apabila memanggil fungsi ini, kita akan menyimpan nilainya dalam pemboleh ubah. Ini sama dengan cara kita menetapkan pemboleh ubah ke nilai statik (seperti `const name = 'Christopher' `).
|
||||
|
||||
```javascript
|
||||
const greetingMessage = createGreetingMessage('Christopher');
|
||||
```
|
||||
|
||||
## Berfungsi sebagai parameter untuk fungsi
|
||||
|
||||
Semasa anda maju dalam kerjaya pengaturcaraan anda, anda akan menemui fungsi yang menerima fungsi sebagai parameter. Trik rapi ini biasanya digunakan ketika kita tidak tahu kapan sesuatu akan terjadi atau selesai, tetapi kita tahu kita perlu melakukan operasi sebagai tindak balas.
|
||||
|
||||
Sebagai contoh, pertimbangkan [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout), yang memulakan pemasa dan akan melaksanakan kod apabila selesai. Kita perlu memberitahu apa kod yang ingin kita laksanakan. Kedengarannya pekerjaan yang sempurna untuk fungsi!
|
||||
|
||||
Sekiranya anda menjalankan kod di bawah ini, setelah 3 saat anda akan melihat mesej **3 saat telah berlalu**.
|
||||
|
||||
```javascript
|
||||
function displayDone() {
|
||||
console.log('3 seconds has elapsed');
|
||||
}
|
||||
// timer value is in milliseconds
|
||||
setTimeout(displayDone, 3000);
|
||||
```
|
||||
|
||||
### Fungsi tanpa nama
|
||||
|
||||
Mari kita lihat lagi apa yang telah kita bina. Kami membuat fungsi dengan nama yang akan digunakan sekali sahaja. Oleh kerana aplikasi kita semakin rumit, kita dapat melihat diri kita membuat banyak fungsi yang hanya akan dipanggil sekali. Ini tidak sesuai. Ternyata, kita tidak selalu perlu memberikan nama!
|
||||
|
||||
Ketika kita meneruskan fungsi sebagai parameter, kita dapat memotong membuatnya terlebih dahulu dan sebaliknya membangunnya sebagai bagian dari parameter. Kami menggunakan kata kunci `function` yang sama, tetapi sebaliknya kami membuatnya sebagai parameter.
|
||||
|
||||
Marilah tulis semula kod di atas untuk menggunakan fungsi tanpa nama:
|
||||
|
||||
```javascript
|
||||
setTimeout(function() {
|
||||
console.log('3 seconds has elapsed');
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
Sekiranya anda menjalankan kod baru kami, anda akan melihat bahawa kami mendapat hasil yang sama. Kami telah membuat fungsi, tetapi tidak perlu memberikan nama!
|
||||
|
||||
### Fungsi panah gemuk
|
||||
|
||||
Salah satu jalan pintas yang biasa digunakan dalam banyak bahasa pengaturcaraan (termasuk JavaScript) adalah kemampuan untuk menggunakan apa yang disebut fungsi **panah** atau **panah lemak**. Ia menggunakan penunjuk khas `=>`, yang kelihatan seperti anak panah - dengan demikian namanya! Dengan menggunakan `=>`, kita dapat melangkau kata kunci `function`.
|
||||
|
||||
Mari tulis semula kod kami sekali lagi untuk menggunakan fungsi anak panah lemak:
|
||||
|
||||
```javascript
|
||||
setTimeout(() => {
|
||||
console.log('3 saat telah berlalu');
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
### Bila menggunakan strategi masing-masing
|
||||
|
||||
Anda sekarang telah melihat kita mempunyai tiga cara untuk meneruskan fungsi sebagai parameter dan mungkin tertanya-tanya kapan menggunakannya. Sekiranya anda tahu anda akan menggunakan fungsi lebih dari sekali, buat seperti biasa. Sekiranya anda menggunakannya hanya untuk satu lokasi, biasanya lebih baik menggunakan fungsi tanpa nama. Sama ada anda menggunakan fungsi anak panah lemak atau sintaks `function` yang lebih tradisional bergantung kepada anda, tetapi anda akan perhatikan bahawa kebanyakan pembangun moden lebih suka `=>`.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Bolehkah anda menyatakan dalam satu ayat perbezaan antara fungsi dan kaedah? Mencubanya!
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/10)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Perlu [membaca sedikit lebih banyak mengenai fungsi anak panah](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), kerana ia semakin banyak digunakan dalam pangkalan kod. Berlatih menulis fungsi, dan kemudian menulis semula dengan sintaks ini.
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Seronok dengan Fungsi](assignment.ms.md)
|
@ -0,0 +1,13 @@
|
||||
# Seronok dengan Fungsi
|
||||
|
||||
## Arahan
|
||||
|
||||
Buat fungsi yang berbeza, kedua fungsi yang mengembalikan sesuatu dan fungsi yang tidak mengembalikan apa-apa.
|
||||
|
||||
Lihat apakah anda dapat membuat fungsi yang memiliki gabungan parameter dan parameter dengan nilai lalai.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------- |
|
||||
| | Penyelesaian ditawarkan dengan dua atau lebih fungsi yang berfungsi dengan baik dengan pelbagai parameter | Penyelesaian kerja ditawarkan dengan satu fungsi dan beberapa parameter | Penyelesaian mempunyai pepijat |
|
@ -0,0 +1,175 @@
|
||||
# Asas JavaScript: Membuat Keputusan
|
||||
|
||||
![Asas JavaScript - Membuat Keputusan](../images/webdev101-js-decisions.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/11)
|
||||
|
||||
Membuat keputusan dan mengawal urutan kod anda berjalan menjadikan kod anda boleh digunakan semula dan kukuh. Bahagian ini merangkumi sintaks untuk mengawal aliran data dalam JavaScript dan kepentingannya apabila digunakan dengan jenis data Boolean
|
||||
|
||||
[![Membuat Keputusan](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "Membuat Keputusan")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai membuat keputusan.
|
||||
## Secara rumus untuk mengenai Booleans
|
||||
|
||||
Booleans boleh hanya dua nilai: `true` atau` false`. Booleans membantu membuat keputusan mengenai garis kod mana yang harus dijalankan apabila syarat tertentu dipenuhi.
|
||||
|
||||
Tetapkan boolean anda menjadi benar atau salah seperti ini:
|
||||
|
||||
`let myTrueBool = true`
|
||||
`let myFalseBool = false`
|
||||
|
||||
✅ Booleans dinamai oleh ahli matematik Inggeris, ahli falsafah dan ahli logik George Boole (1815-1864).
|
||||
|
||||
## Pengendali Perbandingan dan Booleans
|
||||
|
||||
Pengendali digunakan untuk menilai keadaan dengan membuat perbandingan yang akan menghasilkan nilai Boolean. Berikut adalah senarai pengendali yang sering digunakan.
|
||||
|
||||
| Simbol | Penerangan | Contoh |
|
||||
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
|
||||
| `<` | **Kurang daripada**: Membandingkan dua nilai dan mengembalikan jenis data Boolean `true` jika nilai di sebelah kiri kurang dari kanan | `5 < 6 // true` |
|
||||
| `<=` | **Kurang daripada atau sama dengan**: Membandingkan dua nilai dan mengembalikan jenis data Boolean `true` jika nilai di sebelah kiri kurang dari atau sama dengan kanan | `5 <= 6 // true` |
|
||||
| `>` | **Lebih daripada**: Membandingkan dua nilai dan mengembalikan jenis data Boolean `true` jika nilai di sebelah kiri lebih besar daripada kanan | `5 > 6 // false` |
|
||||
| `>=` | **Lebih daripada atau sama dengan**: Membandingkan dua nilai dan mengembalikan jenis data Boolean `true` jika nilai di sebelah kiri lebih besar daripada atau sama dengan kanan| `5 >= 6 // false` |
|
||||
| `===` | **Persamaan yang ketat**: Membandingkan dua nilai dan mengembalikan jenis data Boolean `true` jika nilai di kanan dan kiri sama DAN adalah jenis data yang sama. | `5 === 6 // false` |
|
||||
| `!==` | **Ketidaksamaan**: Membandingkan dua nilai dan mengembalikan nilai Boolean yang bertentangan dengan apa yang akan dikembalikan oleh operator persamaan yang ketat | `5 !== 6 // true` |
|
||||
|
||||
✅ Periksa pengetahuan anda dengan menulis beberapa perbandingan di konsol penyemak imbas anda. Adakah data yang dikembalikan mengejutkan anda?
|
||||
|
||||
## Penyata sekiranya (if)
|
||||
|
||||
Pernyataan _if_ akan menjalankan kod di antara bloknya jika keadaannya benar.
|
||||
|
||||
```javascript
|
||||
if (condition){
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
}
|
||||
```
|
||||
|
||||
Pengendali logik sering digunakan untuk membentuk keadaan.
|
||||
|
||||
```javascript
|
||||
let currentMoney;
|
||||
let laptopPrice;
|
||||
|
||||
if (currentMoney >= laptopPrice){
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
console.log("Getting a new laptop!");
|
||||
}
|
||||
```
|
||||
|
||||
## Penyata (IF.. Else)
|
||||
|
||||
Pernyataan `else` akan menjalankan kod di antara bloknya apabila keadaannya salah. Ia pilihan dengan pernyataan `if`.
|
||||
|
||||
```javascript
|
||||
let currentMoney;
|
||||
let laptopPrice;
|
||||
|
||||
if (currentMoney >= laptopPrice){
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
console.log("Getting a new laptop!");
|
||||
}
|
||||
else{
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
console.log("Can't afford a new laptop, yet!");
|
||||
}
|
||||
```
|
||||
|
||||
✅ Uji pemahaman anda mengenai kod ini dan kod berikut dengan menjalankannya di konsol penyemak imbas. Tukar nilai pemboleh ubahMoney dan laptopPrice semasa untuk menukar `console.log ()` yang dikembalikan.
|
||||
|
||||
## Pengendali Logik dan Booleans
|
||||
|
||||
Keputusan mungkin memerlukan lebih dari satu perbandingan, dan dapat disatukan dengan operator logik untuk menghasilkan nilai Boolean.
|
||||
|
||||
| Simbol | Penerangan | Contoh |
|
||||
| ------ | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `&&` | **Logik AND**: Membandingkan dua ungkapan Boolean. Mengembalikan benar **hanya** jika kedua-dua sisi benar | `(5 > 6) && (5 < 6 ) //Satu pihak salah, yang lain benar. Mengembalikan palsu` |
|
||||
| `\|\|` | **Logik OR**: Membandingkan dua ungkapan Boolean. Mengembalikan benar jika sekurang-kurangnya satu sisi benar | `(5 > 6) \|\| (5 < 6) //Satu pihak salah, yang lain benar. Kembali benar` |
|
||||
| `!` | **Logik NOT**: Mengembalikan nilai bertentangan ungkapan Boolean | `!(5 > 6) // 5 tidak lebih besar daripada 6, tetapi "!" akan kembali benar` |
|
||||
|
||||
## Syarat dan Keputusan dengan Pengendali Logik
|
||||
|
||||
Pengendali logik boleh digunakan untuk membentuk keadaan dalam pernyataan (if..else).
|
||||
|
||||
```javascript
|
||||
let currentMoney;
|
||||
let laptopPrice;
|
||||
let laptopDiscountPrice = laptopPrice - (laptopPrice * .20) //Harga komputer riba diskaun 20 peratus
|
||||
|
||||
if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice){
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
console.log("Getting a new laptop!");
|
||||
}
|
||||
else {
|
||||
//Keadaan itu benar. Kod di blok ini akan dijalankan.
|
||||
console.log("Can't afford a new laptop, yet!");
|
||||
}
|
||||
```
|
||||
|
||||
### Pengendali negasi
|
||||
|
||||
Anda telah melihat sejauh mana bagaimana anda boleh menggunakan pernyataan `if ... else` untuk membuat logik bersyarat. Apa-apa yang masuk ke `if` perlu dinilai menjadi benar / salah. Dengan menggunakan operator `!` Anda boleh _negate_ ungkapan itu. Ia kelihatan seperti:
|
||||
|
||||
```javascript
|
||||
if (!condition) {
|
||||
// kod ini akan berjalan sekiranya keadaan salah
|
||||
} else {
|
||||
// kod ini akan berjalan sekiranya keadaan benar
|
||||
}
|
||||
```
|
||||
|
||||
### Ungkapan Ternary
|
||||
|
||||
`if ... else` bukan satu-satunya cara untuk menyatakan logik keputusan. Anda juga boleh menggunakan sesuatu yang disebut pengendali ternary. Sintaks untuknya kelihatan seperti ini:
|
||||
|
||||
```javascript
|
||||
let variable = condition ? <return this if true> : <return this if false>
|
||||
```
|
||||
|
||||
Berikut adalah contoh yang lebih nyata:
|
||||
|
||||
```javascript
|
||||
let firstNumber = 20;
|
||||
let secondNumber = 10
|
||||
let biggestNumber = firstNumber > secondNumber ? firstNumber: secondNumber;
|
||||
```
|
||||
|
||||
✅ Luangkan masa sebentar untuk membaca kod ini beberapa kali. Adakah anda faham bagaimana pengendali ini berfungsi?
|
||||
|
||||
Perkara di atas menyatakan bahawa
|
||||
- jika `firstNumber` lebih besar daripada` secondNumber`
|
||||
- kemudian tetapkan `firstNumber` ke` largeNumber`
|
||||
- lain tetapkan `secondNumber`.
|
||||
|
||||
Ungkapan terner hanyalah cara ringkas untuk menulis kod di bawah:
|
||||
|
||||
```javascript
|
||||
let biggestNumber;
|
||||
if (firstNumber > secondNumber) {
|
||||
biggestNumber = firstNumber;
|
||||
} else {
|
||||
biggestNumber = secondNumber;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Buat program yang ditulis terlebih dahulu dengan operator logik, dan kemudian tulis semula menggunakan ungkapan terary. Apakah sintaks pilihan anda?
|
||||
|
||||
---
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/12)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Baca lebih lanjut mengenai banyak pengendali yang ada pada pengguna[pada laman MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators).
|
||||
|
||||
Lalui laman Josh Comeau tentang [pengendali](https://joshwcomeau.com/operator-lookup/)!
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Pengendali](./assignment.ms.md)
|
@ -0,0 +1,40 @@
|
||||
# Pengendali
|
||||
|
||||
## Arahan
|
||||
|
||||
Main dengan pengendali. Berikut adalah cadangan untuk program yang boleh anda laksanakan:
|
||||
|
||||
Anda mempunyai sekumpulan pelajar dari dua sistem penggredan yang berbeza.
|
||||
|
||||
### Sistem penggredan pertama
|
||||
|
||||
Sistem penggredan pertama ditakrifkan sebagai gred dari 1-5 di mana 3 dan ke atas bermaksud anda lulus kursus.
|
||||
|
||||
### Sistem penggredan kedua
|
||||
|
||||
Sistem gred lain mempunyai gred berikut `A, A-, B, B-, C, C-` di mana `A` adalah gred teratas dan` C` adalah gred lulus terendah.
|
||||
|
||||
### Tugasan
|
||||
|
||||
Memandangkan susunan berikut `allStudents` yang mewakili semua pelajar dan gred mereka, bina array baru` studentsWhoPass` yang mengandungi semua pelajar yang lulus.
|
||||
|
||||
> TIP, gunakan (for-loop) dan (if...else) dan perbandingan pengendali:
|
||||
|
||||
```javascript
|
||||
let allStudents = [
|
||||
'A',
|
||||
'B-',
|
||||
1,
|
||||
4,
|
||||
5,
|
||||
2
|
||||
]
|
||||
|
||||
let studentsWhoPass = [];
|
||||
```
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------ | ----------------------------- | ------------------------------- |
|
||||
| | Penyelesaian lengkap dikemukakan | Penyelesaian separuh dikemukakan | Penyelesaian dengan pepijat dikemukakan |
|
@ -0,0 +1,124 @@
|
||||
# Asas JavaScript: Array dan Loop
|
||||
|
||||
![Asas JavaScript - Array](../images/webdev101-js-arrays.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/13)
|
||||
|
||||
Pelajaran ini merangkumi asas-asas JavaScript, bahasa yang menyediakan interaktiviti di web. Dalam pelajaran ini, anda akan belajar tentang array dan loop, yang digunakan untuk memanipulasi data.
|
||||
|
||||
[![Array dan Loop](https://img.youtube.com/vi/Q_CRM2lXXBg/0.jpg)](https://youtube.com/watch?v=Q_CRM2lXXBg "Array dan Loop")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai tatasusunan dan gelung.
|
||||
## Array
|
||||
|
||||
Bekerja dengan data adalah tugas biasa untuk bahasa apa pun, dan ini adalah tugas yang lebih mudah apabila data disusun dalam format struktur, seperti array. Dengan array, data disimpan dalam struktur yang serupa dengan senarai. Satu faedah utama array ialah anda dapat menyimpan pelbagai jenis data dalam satu array.
|
||||
|
||||
✅ Array ada di sekeliling kita! Bolehkah anda memikirkan contoh array sebenar, seperti susunan panel solar?
|
||||
|
||||
Sintaks untuk array adalah sepasang tanda kurung persegi.
|
||||
|
||||
`let myArray = [];`
|
||||
|
||||
Ini adalah array kosong, tetapi tatasusunan dapat dinyatakan sudah diisi dengan data. Pelbagai nilai dalam array dipisahkan dengan koma.
|
||||
|
||||
`let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];`
|
||||
|
||||
Nilai array diberikan nilai unik yang disebut **indeks**, nombor bulat yang diberikan berdasarkan jaraknya dari awal array. Dalam contoh di atas, nilai rentetan "Chocolate" mempunyai indeks 0, dan indeks "Rocky Road" adalah 4. Gunakan indeks dengan tanda kurung persegi untuk mengambil, mengubah, atau memasukkan nilai array.
|
||||
|
||||
✅ Adakah mengejutkan anda bahawa tatasusunan bermula dari indeks sifar? Dalam beberapa bahasa pengaturcaraan, indeks bermula pada 1. Ada sejarah menarik di sekitar ini, yang boleh anda [baca di Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors[2]; //"Vanilla"
|
||||
```
|
||||
|
||||
Anda boleh memanfaatkan indeks untuk mengubah nilai, seperti ini:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[4] = "Butter Pecan"; //Tukar "Rocky Road" menjadi "Butter Pecan"
|
||||
```
|
||||
|
||||
Dan anda boleh memasukkan nilai baru pada indeks tertentu seperti ini:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[5] = "Cookie Dough"; //Tambah "Cookie Dough"
|
||||
```
|
||||
|
||||
✅ Cara yang lebih biasa untuk mendorong nilai ke array adalah dengan menggunakan pengendali array seperti array.push()
|
||||
|
||||
Untuk mengetahui berapa banyak item dalam array, gunakan sifat `length`.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors.length; //5
|
||||
```
|
||||
|
||||
✅ Cubalah sendiri! Gunakan konsol penyemak imbas anda untuk membuat dan memanipulasi pelbagai ciptaan anda sendiri.
|
||||
|
||||
## Loop
|
||||
|
||||
Loop membolehkan tugas berulang atau tugasan **interaktif**, dan dapat menjimatkan banyak masa dan kod. Setiap lelaran boleh berbeza-beza dalam pemboleh ubah, nilai, dan keadaannya. Terdapat pelbagai jenis loop dalam JavaScript, dan mereka mempunyai perbezaan kecil, tetapi pada dasarnya melakukan perkara yang sama: loop over data.
|
||||
|
||||
### For Loop
|
||||
|
||||
Gelung `for` memerlukan 3 bahagian untuk berulang:
|
||||
- `counter` Pemboleh ubah yang biasanya diinisialisasi dengan nombor yang mengira bilangan lelaran.
|
||||
- Ungkapan `condition` yang menggunakan operator perbandingan untuk menyebabkan gelung berhenti ketika` true`
|
||||
- `iterasi-ekspresi` Berjalan pada akhir setiap lelaran, biasanya digunakan untuk mengubah nilai pembilang
|
||||
|
||||
```javascript
|
||||
//Menggira hingga 10
|
||||
for (let i = 0; i < 10; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
✅ Jalankan kod ini di konsol penyemak imbas. Apa yang berlaku apabila anda membuat perubahan kecil pada ungkapan pembilang, keadaan, atau lelaran? Bolehkah anda membuatnya berjalan ke belakang, membuat undur?
|
||||
|
||||
### While loop
|
||||
|
||||
Tidak seperti sintaks untuk `for` loop, `while` loop hanya memerlukan keadaan yang akan menghentikan loop ketika `true`. Keadaan dalam loop biasanya bergantung pada nilai lain seperti pembilang, dan mesti dikendalikan semasa gelung. Nilai permulaan untuk pembilang mesti dibuat di loop luar, dan sebarang ungkapan untuk memenuhi syarat, termasuk menukar pembilang mesti dipertahankan di dalam loop.
|
||||
|
||||
```javascript
|
||||
//Menggira hingga 10
|
||||
let i = 0;
|
||||
while (i < 10) {
|
||||
console.log(i);
|
||||
i++;
|
||||
}
|
||||
```
|
||||
|
||||
✅ Mengapakah anda memilih gelung untuk gelung berbanding sebentar? Penonton 17K mempunyai soalan yang sama mengenai StackOverflow, dan beberapa pendapat [mungkin menarik bagi anda](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
|
||||
|
||||
## Loop dan Array
|
||||
|
||||
Array sering digunakan dengan loop kerana kebanyakan keadaan memerlukan panjang larik untuk menghentikan loop, dan indeks juga boleh menjadi nilai pembilang.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
|
||||
for (let i = 0; i < iceCreamFlavors.length; i++) {
|
||||
console.log(iceCreamFlavors[i]);
|
||||
} //Berakhir apabila semua perisa dicetak
|
||||
```
|
||||
|
||||
✅ Bereksperimen dengan melengkapkan pelbagai pembuatan anda sendiri di konsol penyemak imbas anda.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Terdapat cara lain untuk mengulangi tatasusunan selain untuk dan semasa gelung. Terdapat [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), dan [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Tulis semula array loop anda menggunakan salah satu teknik ini.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/14)
|
||||
|
||||
## Mengkaji and Belajar Sendiri
|
||||
|
||||
Array dalam JavaScript mempunyai banyak kaedah yang melekat padanya, sangat berguna untuk manipulasi data. [Baca kaedah ini](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) dan cuba beberapa di antaranya (seperti push, pop, slice dan splice) pada pelbagai ciptaan anda.
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Loop an Array](./assignment.ms.md)
|
@ -0,0 +1,13 @@
|
||||
# Loop an Array
|
||||
|
||||
## Arahan
|
||||
|
||||
Buat program yang menyenaraikan setiap nombor ke-3 antara 1-20 dan mencetaknya ke konsol.
|
||||
|
||||
> TIP: gunakan for-loop dan ubah ekspresi iterasi
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | --------------------------------------- | ------------------------ | ------------------------------ |
|
||||
| | Program berjalan dengan betul dan dikomentari | Program tidak dikomentari | Program tidak lengkap atau kereta |
|
@ -0,0 +1,14 @@
|
||||
# Pengenalan kepada JavaScript
|
||||
|
||||
JavaScript adalah bahasa web. Dalam empat pelajaran ini, anda akan mengetahui asasnya.
|
||||
|
||||
### Topik
|
||||
|
||||
1. [Pemboleh ubah dan Jenis Data](1-data-types/README.md)
|
||||
2. [Fungsi dan Kaedah](2-functions-methods/README.md)
|
||||
3. [Membuat Keputusan dengan JavaScript](3-making-decisions/README.md)
|
||||
4. [Susunan dan Gelung](4-arrays-loops/README.md)
|
||||
|
||||
### Kredit
|
||||
|
||||
Pelajaran ini ditulis dengan ♥️ oleh [Jasmine Greenaway](https://twitter.com/paladique), [Christopher Harrison](https://twitter.com/geektrainer) dan [Chris Noring](https://twitter.com/chris_noring)
|
@ -0,0 +1,230 @@
|
||||
# Projek Terrarium Bahagian 1: Pengenalan Kepada HTML
|
||||
|
||||
![Pengenalan Kepada HTML](images/webdev101-html.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/15)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
HTML, atau HyperText Markup Language, adalah 'kerangka' web. Sekiranya CSS 'mendandan' HTML dan JavaScript anda menghidupkannya, HTML adalah badan aplikasi web anda. Sintaks HTML bahkan menggambarkan idea itu, kerana ia merangkumi tag "kepala", "badan", dan "footer".
|
||||
|
||||
Dalam pelajaran ini, kita akan menggunakan HTML untuk menyusun 'kerangka' antara muka terarium maya kita. Ini akan mempunyai tajuk dan tiga lajur: lajur kanan dan kiri di mana tumbuhan yang boleh diseret hidup, dan kawasan tengah yang akan menjadi terarium yang kelihatan kaca. Pada akhir pelajaran ini, anda akan dapat melihat tanaman di lajur, tetapi antara muka akan kelihatan sedikit pelik; jangan risau, di bahagian seterusnya anda akan menambahkan gaya CSS ke antara muka untuk menjadikannya lebih baik.
|
||||
|
||||
### Tugas
|
||||
|
||||
Pada komputer anda, buat folder bernama 'terrarium' dan di dalamnya, fail yang bernama 'index.html' Anda boleh melakukannya dalam Visual Studio Code setelah membuat folder terarium anda dengan membuka tetingkap VS Code baru, mengklik 'buka folder', dan menavigasi ke folder baru anda. Klik butang 'fail' kecil di panel Explorer dan buat fail baru:
|
||||
|
||||
![explorer dalam VS Code](../images/vs-code-index.png)
|
||||
|
||||
Atau
|
||||
|
||||
Gunakan arahan ini dalam git bash anda:
|
||||
* `mkdir terrarium`
|
||||
* `cd terrarium`
|
||||
* `touch index.html`
|
||||
* `code index.html` atau `nano index.html`
|
||||
|
||||
> index.html fail menunjukkan kepada penyemak imbas bahawa ia adalah fail lalai dalam folder; URL seperti `https: // anysite.com / test` mungkin dibina menggunakan struktur folder termasuk folder yang disebut `test` dengan `index.html` di dalamnya; `index.html` tidak perlu dipaparkan dalam URL.
|
||||
|
||||
---
|
||||
|
||||
## Tag DocType dan html
|
||||
|
||||
Baris pertama fail HTML adalah doctype. Agak mengejutkan bahawa anda perlu mempunyai baris ini di bahagian paling atas fail, tetapi ia memberitahu penyemak imbas lama bahawa penyemak imbas perlu membuat halaman dalam mod standard, mengikuti spesifikasi html semasa.
|
||||
|
||||
> Tip: dalam Kod VS, anda boleh mengarahkan kursor ke atas teg dan mendapatkan maklumat mengenai penggunaannya dari panduan Rujukan MDN.
|
||||
|
||||
Baris kedua harus berupa tag pembuka tag `<html>`, diikuti sekarang oleh tag penutupnya `</html>`. Tag ini adalah elemen asas antara interface anda.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan baris ini di bahagian atas fail `index.html` anda:
|
||||
|
||||
```HTML
|
||||
<!DOCTYPE html>
|
||||
<html></html>
|
||||
```
|
||||
|
||||
✅ Terdapat beberapa mod berbeza yang dapat ditentukan dengan menetapkan Jenis Dokumen dengan rentetan pertanyaan: [Mod Quirks dan Mod Piawai](https://developer.mozilla.org/en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode) . Mod ini digunakan untuk menyokong penyemak imbas lama yang tidak biasa digunakan pada masa ini (Netscape Navigator 4 dan Internet Explorer 5). Anda boleh berpegang pada pernyataan standard documentype.
|
||||
|
||||
---
|
||||
|
||||
## Dokumen 'head'
|
||||
|
||||
Kawasan 'head' dokumen HTML merangkumi maklumat penting mengenai laman web anda, juga dikenali sebagai [metadata](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta). Dalam kes kami, kami memberitahu pelayan web tempat halaman ini akan dihantar untuk diberikan, empat perkara berikut:
|
||||
|
||||
- tajuk halaman
|
||||
- metadata halaman termasuk:
|
||||
- 'set watak', menceritakan tentang pengekodan watak apa yang digunakan di halaman
|
||||
- maklumat penyemak imbas, termasuk `x-ua-compatible` yang menunjukkan bahawa penyemak imbas tepi IE = disokong
|
||||
- maklumat tentang bagaimana tingkah laku pandangan harus berkelakuan ketika dimuat. Menetapkan viewport untuk mempunyai skala awal 1 mengawal tahap zoom ketika halaman pertama kali dimuat.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan blok 'head' ke dokumen anda di antara tag pembuka dan penutup `<html>`.
|
||||
|
||||
```html
|
||||
<head>
|
||||
<title>Welcome to my Virtual Terrarium</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
```
|
||||
|
||||
✅ Apa yang akan berlaku jika anda menetapkan tag meta viewport seperti ini: `<meta name =" viewport "content =" width = 600 ">`? Baca lebih lanjut mengenai [viewport](https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag).
|
||||
|
||||
---
|
||||
|
||||
## Dokumen 'body'
|
||||
|
||||
### Tag HTML
|
||||
|
||||
Dalam HTML, anda menambahkan tag ke fail .html anda untuk membuat elemen halaman web. Setiap tag biasanya memiliki tag pembuka dan penutup, seperti ini: `<p>hello</p>` untuk menunjukkan perenggan. Buat badan antara muka anda dengan menambahkan satu set tag `<body>` di dalam pasangan tag `<html>`; markup anda sekarang kelihatan seperti ini:
|
||||
|
||||
### Tugas
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to my Virtual Terrarium</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Sekarang, anda boleh mula membina halaman anda. Biasanya, anda menggunakan tag `<div>` untuk membuat elemen yang terpisah dalam halaman. Kami akan membuat rangkaian elemen `<div>` yang akan mengandungi gambar.
|
||||
|
||||
### Gambar
|
||||
|
||||
Satu tag html yang tidak memerlukan tag penutup adalah tag `<img>`, kerana ia memiliki elemen `src` yang berisi semua informasi yang diperlukan halaman untuk membuat item.
|
||||
|
||||
Buat folder di aplikasi anda yang disebut `gambar` dan di dalamnya, tambahkan semua gambar di [folder kod sumber](../solution/images); (terdapat 14 gambar tumbuhan).
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan gambar tanaman tersebut ke dalam dua lajur di antara tag `<body></body>`:
|
||||
|
||||
```html
|
||||
<div id="page">
|
||||
<div id="left-container" class="container">
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant1" src="./images/plant1.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant2" src="./images/plant2.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant3" src="./images/plant3.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant4" src="./images/plant4.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant5" src="./images/plant5.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant6" src="./images/plant6.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant7" src="./images/plant7.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="right-container" class="container">
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant8" src="./images/plant8.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant9" src="./images/plant9.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant10" src="./images/plant10.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant11" src="./images/plant11.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant12" src="./images/plant12.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant13" src="./images/plant13.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant14" src="./images/plant14.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
> Catatan: Spans vs Divs. Divs dianggap sebagai elemen 'blok', dan Spans adalah 'sebaris'. Apa yang akan berlaku sekiranya anda mengubah div ini menjadi spans?
|
||||
|
||||
Dengan penanda ini, tanaman kini muncul di skrin. Ia kelihatan sangat buruk, kerana mereka belum digayakan menggunakan CSS, dan kami akan melakukannya pada pelajaran seterusnya.
|
||||
|
||||
Setiap gambar mempunyai teks alt yang akan muncul walaupun Anda tidak dapat melihat atau membuat gambar. Ini adalah sifat penting untuk disertakan untuk aksesibilitas. Ketahui lebih lanjut mengenai kebolehcapaian dalam pelajaran akan datang; buat masa ini, ingat bahawa atribut alt memberikan maklumat alternatif untuk gambar jika pengguna untuk beberapa sebab tidak dapat melihatnya (kerana sambungan lambat, kesalahan pada atribut src, atau jika pengguna menggunakan pembaca layar).
|
||||
|
||||
✅ Adakah anda perhatikan bahawa setiap gambar mempunyai tag alt yang sama? Adakah ini amalan yang baik? Mengapa atau mengapa tidak? Bolehkah anda memperbaiki kod ini?
|
||||
|
||||
---
|
||||
|
||||
## Markup semantik
|
||||
|
||||
Secara amnya, lebih baik menggunakan 'semantik' yang bermakna semasa menulis HTML. Apa maksudnya? Ini bermaksud bahawa anda menggunakan tag HTML untuk mewakili jenis data atau interaksi yang dirancang untuknya. Sebagai contoh, teks tajuk utama pada halaman harus menggunakan tag `<h1>`.
|
||||
|
||||
Tambahkan baris berikut tepat di bawah tag `<body>` pembuka anda:
|
||||
|
||||
```html
|
||||
<h1>My Terrarium</h1>
|
||||
```
|
||||
|
||||
Menggunakan markup semantik seperti header menjadi `<h1>` dan senarai yang tidak disusun akan diberikan sebagai `<ul>` membantu pembaca skrin menavigasi halaman. Secara umum, butang harus ditulis sebagai `<button>` dan senarai harus `<li>`. Walaupun _mungkin_ menggunakan elemen `<span>` yang digayakan khas dengan pengendali klik untuk mengekang butang, lebih baik pengguna kurang upaya menggunakan teknologi untuk menentukan di mana halaman terdapat butang, dan berinteraksi dengannya, jika elemen tersebut muncul sebagai butang. Atas sebab ini, cuba gunakan penanda semantik sebanyak mungkin.
|
||||
|
||||
✅ Lihatlah pembaca skrin dan [bagaimanakah ia berinteraksi dengan laman web](https://www.youtube.com/watch?v=OUDV1gqs9GA). Bolehkah anda melihat mengapa mempunyai penanda bukan semantik boleh membuat pengguna kecewa?
|
||||
|
||||
## Terrarium
|
||||
|
||||
Bahagian terakhir antara muka ini melibatkan membuat markup yang akan digayakan untuk membuat terarium.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan markup ini di atas tag `</div>` terakhir:
|
||||
|
||||
```html
|
||||
<div id="terrarium">
|
||||
<div class="jar-top"></div>
|
||||
<div class="jar-walls">
|
||||
<div class="jar-glossy-long"></div>
|
||||
<div class="jar-glossy-short"></div>
|
||||
</div>
|
||||
<div class="dirt"></div>
|
||||
<div class="jar-bottom"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
✅ Walaupun anda menambahkan markup ini ke skrin, anda tidak dapat melihat apa-apa. Kenapa?
|
||||
|
||||
---
|
||||
|
||||
## 🚀Cabaran
|
||||
|
||||
Terdapat beberapa tag 'lawas' liar dalam HTML yang masih menyeronokkan untuk dimainkan, walaupun anda tidak boleh menggunakan tag yang tidak digunakan seperti [tag ini](https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) dalam markup anda. Masih bolehkah anda menggunakan tag `<marquee>` lama untuk menjadikan tajuk h1 menatal secara mendatar? (jika anda melakukannya, jangan lupa membuangnya selepas itu)
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/16)
|
||||
|
||||
## Mengkaji dan Belajar Sendiri
|
||||
|
||||
HTML adalah sistem blok bangunan 'cuba dan benar' yang telah membantu membina web menjadi seperti sekarang. Ketahui sedikit mengenai sejarahnya dengan mempelajari beberapa tanda lama dan baru. Bolehkah anda mengetahui mengapa beberapa teg tidak digunakan lagi dan ada yang ditambahkan? Tag apa yang mungkin diperkenalkan pada masa akan datang?
|
||||
|
||||
Ketahui lebih lanjut mengenai membina laman web dan peranti mudah alih di [Microsoft Learn](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=cxaall-4621-cxall).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Berlatih HTML anda: Bina mockup blog](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Berlatih HTML anda: Bina mockup blog
|
||||
|
||||
## Arahan
|
||||
|
||||
Bayangkan anda merancang, atau merancang semula, laman web peribadi anda. Buat markup grafik laman web anda, dan kemudian tuliskan markup HTML yang akan anda gunakan untuk membina pelbagai elemen laman web ini. Anda boleh melakukannya di atas kertas, dan mengimbasnya, atau menggunakan perisian pilihan anda, pastikan anda memasukkan kod HTML dengan tangan.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| | Susun atur blog ditunjukkan secara visual dengan sekurang-kurangnya 10 elemen markup dipaparkan | Susun atur blog ditunjukkan secara visual dengan sekitar 5 elemen markup ditampilkan | Susun atur blog ditunjukkan secara visual dengan paling banyak 3 elemen markup dipaparkan |
|
@ -0,0 +1,263 @@
|
||||
# Projek Terrarium Bahagian 2: Pengenalan Kepada CSS
|
||||
|
||||
![Pengenalan Kepada CSS](../images/webdev101-css.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/17)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
CSS, atau Cascading Style Sheets, menyelesaikan masalah penting dalam pembangunan web: bagaimana menjadikan laman web anda kelihatan cantik. Menggayakan aplikasi anda menjadikannya lebih berguna dan kelihatan lebih baik; anda juga boleh menggunakan CSS untuk membuat Reka Bentuk Web Responsif (RWD) - membolehkan apl anda kelihatan baik tidak kira ukuran skrin yang dipaparkan. CSS bukan hanya menjadikan aplikasi anda kelihatan bagus; spesifikasinya merangkumi animasi dan transformasi yang membolehkan interaksi yang canggih untuk aplikasi anda. Kumpulan Kerja CSS membantu mengekalkan spesifikasi CSS semasa; anda boleh mengikuti karya mereka di [laman web World Wide Web Consortium](https://www.w3.org/Style/CSS/members) .
|
||||
|
||||
> Perhatikan, CSS adalah bahasa yang berkembang, seperti semua yang ada di web, dan tidak semua penyemak imbas menyokong bahagian spesifikasi yang lebih baru. Sentiasa periksa pelaksanaan anda dengan merujuk [CanIUse.com](https://caniuse.com).
|
||||
|
||||
Dalam pelajaran ini, kami akan menambahkan gaya ke terarium dalam talian kami dan mengetahui lebih lanjut mengenai beberapa konsep CSS: lata, pewarisan, dan penggunaan pemilih, penentuan kedudukan, dan menggunakan CSS untuk membina susun atur. Dalam prosesnya kita akan menyusun terarium dan membuat terarium itu sendiri.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda harus mempunyai pengetahuan HTML untuk terarium anda dan siap digayakan.
|
||||
|
||||
### Tugas
|
||||
|
||||
Dalam folder terarium anda, buat fail baru yang disebut `style.css`. Import fail itu di bahagian `<head>`:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## The Cascade
|
||||
|
||||
Cascading Style Sheets menggabungkan idea bahawa gaya 'cascade' sehingga penerapan gaya dipandu oleh keutamaannya. Gaya yang ditetapkan oleh pengarang laman web lebih diutamakan daripada yang ditetapkan oleh penyemak imbas. Gaya yang ditetapkan 'sebaris' lebih diutamakan daripada yang ditetapkan dalam helaian gaya luaran.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan gaya sebaris "color: red" ke tag `<h1>` anda:
|
||||
|
||||
```HTML
|
||||
<h1 style="color: red">My Terrarium</h1>
|
||||
```
|
||||
|
||||
Kemudian, tambahkan kod berikut ke fail `style.css` anda:
|
||||
|
||||
```CSS
|
||||
h1 {
|
||||
color: blue;
|
||||
}
|
||||
```
|
||||
|
||||
✅ Warna mana yang dipaparkan di aplikasi web anda? Kenapa? Bolehkah anda mencari cara untuk mengganti gaya? Bilakah anda mahu melakukan ini, atau mengapa tidak?
|
||||
|
||||
---
|
||||
|
||||
## Warisan
|
||||
|
||||
Gaya diwarisi dari gaya nenek moyang hingga keturunan, sehingga elemen bersarang mewarisi gaya ibu bapa mereka.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tetapkan fon badan ke fon tertentu, dan periksa untuk melihat fon elemen bersarang:
|
||||
|
||||
```
|
||||
body {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
Buka konsol penyemak imbas anda ke tab 'Elements' dan perhatikan fon H1. Ini mewarisi fonnya dari badan, seperti yang dinyatakan dalam penyemak imbas:
|
||||
|
||||
![inherited font](../images/1.png)
|
||||
|
||||
✅ Bolehkah anda menjadikan gaya bersarang mewarisi harta yang berbeza?
|
||||
|
||||
---
|
||||
|
||||
## CSS Selector
|
||||
|
||||
### Tag
|
||||
|
||||
Setakat ini, fail `style.css` anda hanya mempunyai beberapa tag yang digayakan, dan aplikasinya kelihatan sangat pelik:
|
||||
|
||||
```
|
||||
body {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #3a241d;
|
||||
text-align: center;
|
||||
}
|
||||
```
|
||||
|
||||
Cara menggayakan tag ini memberi anda kawalan terhadap elemen unik, tetapi anda perlu mengawal gaya banyak tanaman di terarium anda. Untuk melakukan itu, anda perlu memanfaatkan CSS selector.
|
||||
|
||||
### Id
|
||||
|
||||
Tambahkan beberapa gaya untuk mengatur bekas kiri dan kanan. Oleh kerana hanya ada satu bekas kiri dan hanya satu bekas kanan, mereka diberi id dalam markup. Untuk menggayakannya, gunakan `#`:
|
||||
|
||||
```
|
||||
#left-container {
|
||||
background-color: #eee;
|
||||
width: 15%;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#right-container {
|
||||
background-color: #eee;
|
||||
width: 15%;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
```
|
||||
|
||||
Di sini, anda telah meletakkan bekas ini dengan kedudukan mutlak di paling kiri dan kanan skrin, dan menggunakan peratusan untuk lebarnya sehingga dapat menskalakan untuk skrin mudah alih kecil.
|
||||
|
||||
✅ Kod ini agak berulang, oleh itu tidak "DRY" (Don't Repeat Yourself); bolehkah anda mencari cara yang lebih baik untuk menggayakan id ini, mungkin dengan id dan kelas? Anda perlu mengubah markup dan memfaktorkan semula CSS:
|
||||
|
||||
```html
|
||||
<div id="left-container" class="container"></div>
|
||||
```
|
||||
|
||||
### Kelas
|
||||
|
||||
Dalam contoh di atas, anda menggayakan dua elemen unik di skrin. Sekiranya anda mahu gaya diterapkan pada banyak elemen di layar, anda boleh menggunakan kelas CSS. Lakukan ini untuk menyusun tanaman di bekas kiri dan kanan.
|
||||
|
||||
Perhatikan bahawa setiap tanaman dalam markup HTML mempunyai kombinasi id dan kelas. Id di sini digunakan oleh JavaScript yang akan anda tambahkan kemudian untuk memanipulasi penempatan tanaman terarium. Walau bagaimanapun, kelas-kelasnya memberi gaya kepada semua tanaman.
|
||||
|
||||
```html
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant1" src="./images/plant1.png" />
|
||||
</div>
|
||||
```
|
||||
|
||||
Tambahkan yang berikut ke fail `style.css` anda:
|
||||
|
||||
```css
|
||||
.plant-holder {
|
||||
position: relative;
|
||||
height: 13%;
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
.plant {
|
||||
position: absolute;
|
||||
max-width: 150%;
|
||||
max-height: 150%;
|
||||
z-index: 2;
|
||||
}
|
||||
```
|
||||
|
||||
Dalam coretan ini adalah gabungan kedudukan relatif dan mutlak, yang akan kita bahas di bahagian seterusnya. Lihat cara ketinggian dikendalikan oleh peratusan:
|
||||
|
||||
Anda menetapkan ketinggian pemegang kilang kepada 13%, jumlah yang baik untuk memastikan bahawa semua tanaman dipaparkan di setiap bekas menegak tanpa perlu menatal.
|
||||
|
||||
Anda menetapkan pemegang kilang bergerak ke kiri untuk membiarkan tanaman lebih berpusat di dalam bekasnya. Gambar mempunyai sejumlah besar latar belakang lutsinar sehingga membuatnya lebih mudah diseret, jadi perlu didorong ke kiri agar lebih pas di layar.
|
||||
|
||||
Kemudian, kilang itu sendiri diberi lebar maksimum 150%. Ini memungkinkan untuk mengecil ketika penyemak imbas turun. Cuba ubah saiz penyemak imbas anda; tanaman tinggal di dalam bekasnya tetapi dikecilkan agar sesuai.
|
||||
|
||||
Juga dapat diperhatikan adalah penggunaan z-index, yang mengendalikan ketinggian relatif suatu elemen (sehingga tanaman duduk di atas wadah dan tampak duduk di dalam terarium).
|
||||
|
||||
✅ Mengapakah anda memerlukan pemegang tanaman dan CSS Selector?
|
||||
|
||||
## Kedudukan CSS
|
||||
|
||||
Sifat pencampuran kedudukan (terdapat kedudukan statik, relatif, tetap, mutlak, dan melekit) boleh menjadi agak rumit, tetapi apabila dilakukan dengan betul, ia memberi anda kawalan yang baik terhadap unsur-unsur di halaman anda.
|
||||
|
||||
Unsur-unsur yang diposisikan secara mutlak diposisikan berbanding dengan nenek moyang mereka yang terdekat, dan jika tidak ada, ia diposisikan sesuai dengan badan dokumen.
|
||||
|
||||
Elemen kedudukan relatif diletakkan berdasarkan arahan CSS untuk menyesuaikan penempatannya dari kedudukan awalnya.
|
||||
|
||||
Dalam sampel kami, `pemegang tumbuhan` adalah elemen kedudukan relatif yang diposisikan dalam wadah kedudukan mutlak. Tingkah laku yang dihasilkan adalah bahawa wadah bar sisi disematkan ke kiri dan kanan, dan pemegang tanaman bersarang, menyesuaikan diri di dalam bar sisi, memberi ruang untuk tanaman ditempatkan dalam barisan menegak.
|
||||
|
||||
> `Tumbuhan` itu sendiri juga mempunyai kedudukan mutlak, yang diperlukan untuk membuatnya dapat diseret, seperti yang akan anda ketahui dalam pelajaran seterusnya.
|
||||
|
||||
✅ Eksperimen dengan menukar jenis penempatan bekas sampingan dan pemegang tumbuhan. Apa yang berlaku?
|
||||
|
||||
## Susun atur CSS
|
||||
|
||||
Sekarang anda akan menggunakan apa yang anda pelajari untuk membina terarium itu sendiri, semuanya menggunakan CSS!
|
||||
|
||||
Pertama, gayakan anak-anak `.terrarium` sebagai segi empat bulat menggunakan CSS:
|
||||
|
||||
```css
|
||||
.jar-walls {
|
||||
height: 80%;
|
||||
width: 60%;
|
||||
background: #d1e1df;
|
||||
border-radius: 10%;
|
||||
position: absolute;
|
||||
bottom: 0.5%;
|
||||
left: 20%;
|
||||
opacity: 0.5;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.jar-top {
|
||||
width: 50%;
|
||||
height: 5%;
|
||||
background: #d1e1df;
|
||||
position: absolute;
|
||||
bottom: 80.5%;
|
||||
left: 25%;
|
||||
opacity: 0.7;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.jar-bottom {
|
||||
width: 50%;
|
||||
height: 1%;
|
||||
background: #d1e1df;
|
||||
position: absolute;
|
||||
bottom: 0%;
|
||||
left: 25%;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.dirt {
|
||||
width: 58%;
|
||||
height: 5%;
|
||||
background: #3a241d;
|
||||
position: absolute;
|
||||
border-radius: 0 0 4rem 4rem;
|
||||
bottom: 1%;
|
||||
left: 21%;
|
||||
opacity: 0.7;
|
||||
z-index: -1;
|
||||
}
|
||||
```
|
||||
|
||||
Perhatikan penggunaan peratusan di sini, walaupun untuk `radius sempadan (border-radius)`. Sekiranya anda menurunkan penyemak imbas anda, anda dapat melihat bagaimana skala sudut jar juga. Perhatikan juga peratusan lebar dan tinggi untuk elemen balang dan bagaimana setiap elemen benar-benar diposisikan di tengah, disematkan ke bahagian bawah pandang.
|
||||
|
||||
✅ Cubalah ubah warna balang dan kelegapan berbanding kotoran. Apa yang berlaku? Kenapa?
|
||||
|
||||
---
|
||||
|
||||
## 🚀Cabaran
|
||||
|
||||
Tambahkan kilauan 'bubble' ke bahagian bawah kiri balang agar kelihatan lebih menyerupai kaca. Anda akan menggayakan `.jar-glossy-long` dan` .jar-glossy-short` agar kelihatan seperti kilauan yang dipantulkan. Ini rupanya:
|
||||
|
||||
![finished terrarium](../images/terrarium-final.png)
|
||||
|
||||
Untuk menyelesaikan kuiz pasca kuliah, baca modul Belajar ini: [Gaya aplikasi HTML anda dengan CSS](https://docs.microsoft.com/en-us/learn/modules/build-simple-website/4-css-basics)
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/18)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
CSS nampaknya sangat mudah, tetapi ada banyak cabaran ketika mencuba gaya aplikasi dengan sempurna untuk semua penyemak imbas dan semua saiz skrin. CSS-Grid dan Flexbox adalah alat yang telah dikembangkan untuk menjadikan pekerjaan itu sedikit lebih tersusun dan lebih dipercayai. Ketahui mengenai alat ini dengan bermain [Flexbox Froggy](https://flexboxfroggy.com/) dan [Grid Garden](https://codepip.com/games/grid-garden/).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Pemfaktoran Semula CSS](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Pemfaktoran Semula CSS
|
||||
|
||||
## Arahan
|
||||
|
||||
Nyalakan semula terarium menggunakan Flexbox atau CSS Grid, dan ambil tangkapan skrin untuk menunjukkan bahawa anda telah mengujinya di beberapa penyemak imbas. Anda mungkin perlu mengubah markup jadi buat versi aplikasi baharu dengan seni yang ada untuk anda memfaktorkan. Jangan bimbang menjadikan unsur-unsur itu boleh diseret; hanya memfaktorkan HTML dan CSS buat masa ini.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ----------------------------------------------------------------- | ----------------------------- | ------------------------------------ |
|
||||
| | Bentangkan terarium yang diperbaiki sepenuhnya menggunakan Flexbox atau CSS Grid | Susun semula beberapa elemen | Gagal menyusun semula terarium sama sekali |
|
@ -0,0 +1,216 @@
|
||||
# Projek Terrarium Bahagian 3: Memanipulasi DOM dan Penutupan
|
||||
|
||||
![DOM dan penutupan](../images/webdev101-js.png)
|
||||
> Sketchnote karya [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/19)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Memanipulasi DOM, atau "Document Object Model", adalah aspek penting dalam pengembangan web. Menurut [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction), "Document Object Model (DOM) adalah representasi data dari objek yang terdiri dari struktur dan kandungan dokumen di web. " Cabaran di sekitar manipulasi DOM di web sering menjadi dorongan di belakang menggunakan kerangka kerja JavaScript dan bukannya JavaScript vanila untuk menguruskan DOM, tetapi kami akan menguruskannya sendiri!
|
||||
|
||||
Selain itu, pelajaran ini akan memperkenalkan idea [Penutupan JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures), yang dapat anda fikirkan sebagai fungsi yang dilampirkan oleh yang lain berfungsi sehingga fungsi dalaman mempunyai akses ke ruang fungsi scope luar.
|
||||
|
||||
> Penutupan JavaScript adalah topik yang luas dan kompleks. Pelajaran ini menyentuh idea paling asas bahawa dalam kod terarium ini, anda akan menemui penutup: fungsi dalaman dan fungsi luar yang dibina dengan cara yang membolehkan fungsi dalaman mengakses ke ruang lingkup fungsi luar. Untuk lebih banyak maklumat mengenai cara ini berfungsi, sila lawati [dokumentasi yang luas](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures).
|
||||
|
||||
Kami akan menggunakan penutup untuk memanipulasi DOM.
|
||||
|
||||
Fikirkan DOM sebagai pokok, mewakili semua cara dokumen laman web dapat dimanipulasi. Berbagai API (Interface Program Aplikasi) telah ditulis sehingga pengaturcara, menggunakan bahasa pilihan program mereka, dapat mengakses DOM dan mengedit, mengubah, menyusun semula, dan sebaliknya mengaturnya.
|
||||
|
||||
![Perwakilan pokok DOM](../images/dom-tree.png)
|
||||
|
||||
> Perwakilan DOM dan markup HTML yang merujuknya. Oleh [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
|
||||
|
||||
Dalam pelajaran ini, kami akan menyelesaikan projek terarium interaktif kami dengan membuat JavaScript yang akan membolehkan pengguna memanipulasi tanaman di halaman.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda harus mempunyai HTML dan CSS untuk terarium anda. Pada akhir pelajaran ini, anda akan dapat memindahkan tanaman ke dalam dan keluar dari terarium dengan menyeretnya.
|
||||
|
||||
### Tugas
|
||||
|
||||
Dalam folder terarium anda, buat fail baru yang disebut `script.js`. Import fail itu di bahagian `<head>`:
|
||||
|
||||
```html
|
||||
<script src="./script.js" defer></script>
|
||||
```
|
||||
|
||||
> Catatan: gunakan `defer` ketika mengimpor file JavaScript eksternal ke dalam file html sehingga memungkinkan JavaScript dijalankan hanya setelah file HTML dimuat sepenuhnya. Anda juga boleh menggunakan atribut `async`, yang membolehkan skrip dijalankan semasa fail HTML dihuraikan, tetapi dalam kes kami, penting untuk memiliki elemen HTML sepenuhnya tersedia untuk menyeret sebelum kami membiarkan skrip seret dijalankan.
|
||||
---
|
||||
|
||||
## Elemen DOM
|
||||
|
||||
Perkara pertama yang perlu anda lakukan ialah membuat rujukan pada elemen yang ingin anda manipulasi dalam DOM. Dalam kes kami, mereka adalah 14 tanaman yang sedang menunggu di bar sisi.
|
||||
|
||||
### Tugas
|
||||
|
||||
```html
|
||||
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 berlaku di sini? Anda merujuk dokumen dan mencari melalui DOM untuk mencari elemen dengan Id tertentu. Masih ingat pada pelajaran pertama mengenai HTML bahawa anda memberikan Id individu untuk setiap gambar tumbuhan (`id=" plant1"`)? Sekarang anda akan menggunakan usaha itu. Setelah mengenal pasti setiap elemen, anda meneruskan item tersebut ke fungsi yang disebut `dragElement` yang akan anda bina dalam satu minit. Oleh itu, elemen dalam HTML kini diaktifkan seret, atau tidak lama lagi.
|
||||
|
||||
✅ Mengapakah kita merujuk elemen dengan Id? Mengapa tidak oleh kelas CSS mereka? Anda mungkin merujuk kepada pelajaran CSS sebelumnya untuk menjawab soalan ini.
|
||||
|
||||
---
|
||||
|
||||
## Penutupan
|
||||
|
||||
Sekarang anda sudah bersedia untuk membuat penutupan dragElement, yang merupakan fungsi luar yang merangkumi fungsi atau fungsi dalaman (dalam kes kita, kita akan mempunyai tiga).
|
||||
|
||||
Penutupan berguna apabila satu atau lebih fungsi perlu memasuki ruang lingkup fungsi luar. Inilah contohnya:
|
||||
|
||||
```javascript
|
||||
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 mendorong jenis permen baru ke dalam array yang sudah ada dalam fungsi tersebut. Sekiranya anda menjalankan kod ini, array `candy` tidak akan ditentukan, kerana ini adalah pemboleh ubah tempatan (tempatan hingga penutupan).
|
||||
|
||||
✅ Bagaimanakah anda boleh membuat array `candy` dapat diakses? Cuba gerakkannya di luar penutup. Dengan cara ini, susunan menjadi global, dan bukannya hanya tersedia untuk skop tempatan penutupan.
|
||||
|
||||
### Tugas
|
||||
|
||||
Di bawah deklarasi elemen dalam `script.js`, buat fungsi:
|
||||
|
||||
```javascript
|
||||
function dragElement(terrariumElement) {
|
||||
//tetapkan 4 kedudukan untuk penentuan kedudukan di skrin
|
||||
let pos1 = 0,
|
||||
pos2 = 0,
|
||||
pos3 = 0,
|
||||
pos4 = 0;
|
||||
terrariumElement.onpointerdown = pointerDrag;
|
||||
}
|
||||
```
|
||||
|
||||
`dragElement` dapatkan objek` terrariumElement` dari pernyataan di bahagian atas skrip. Kemudian, anda menetapkan beberapa kedudukan tempatan pada `0` untuk objek yang dilewatkan ke dalam fungsi. Ini adalah pemboleh ubah tempatan yang akan dimanipulasi untuk setiap elemen semasa anda menambahkan fungsi seret dan lepas dalam penutupan ke setiap elemen. Terarium akan dihuni oleh unsur-unsur yang diseret ini, jadi aplikasinya perlu memantau lokasi mereka ditempatkan.
|
||||
|
||||
Selain itu, elemen terarium yang diteruskan ke fungsi ini diberikan acara `pointerdown`, yang merupakan sebahagian dari [web API](https://developer.mozilla.org/en-US/docs/Web/API) yang dirancang untuk membantu pengurusan DOM. `onpointerdown` menyala apabila butang ditekan, atau dalam kes kita, elemen yang boleh diseret disentuh. Pengendali acara ini berfungsi pada [penyemak imbas web dan mudah alih](https://caniuse.com/?search=onpointerdown), dengan beberapa pengecualian.
|
||||
|
||||
✅ [Pengendali acara (event handler) `onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) mempunyai sokongan penyemak imbas yang lebih banyak; mengapa anda tidak menggunakannya di sini? Fikirkan jenis interaksi skrin yang tepat yang ingin anda buat di sini.
|
||||
|
||||
---
|
||||
|
||||
## Fungsi Pointerdrag
|
||||
|
||||
TerariumElement siap diseret; apabila peristiwa `onpointerdown` dipecat, fungsi pointerDrag dipanggil. Tambahkan fungsi itu tepat di bawah baris ini: `terrariumElement.onpointerdown = pointerDrag;`:
|
||||
|
||||
### Tugas
|
||||
|
||||
```javascript
|
||||
function pointerDrag(e) {
|
||||
e.preventDefault();
|
||||
console.log(e);
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
}
|
||||
```
|
||||
|
||||
Beberapa perkara berlaku. Pertama, anda mencegah kejadian lalai yang biasanya berlaku pada pointerdown tidak berlaku dengan menggunakan `e.preventDefault ();`. Dengan cara ini anda mempunyai lebih banyak kawalan terhadap tingkah laku antara muka.
|
||||
|
||||
> Kembali ke baris ini apabila anda telah membina fail skrip sepenuhnya dan mencubanya tanpa `e.preventDefault ()` - apa yang berlaku?
|
||||
|
||||
Kedua, buka `index.html` di tetingkap penyemak imbas, dan periksa antara muka. Apabila anda mengklik kilang, anda dapat melihat bagaimana peristiwa 'e' ditangkap. Gali acara untuk melihat berapa banyak maklumat yang dikumpulkan oleh satu acara penunjuk ke bawah!
|
||||
|
||||
Seterusnya, perhatikan bagaimana pemboleh ubah tempatan `pos3` dan` pos4` ditetapkan ke e.clientX. Anda boleh mendapatkan nilai `e` di panel pemeriksaan. Nilai-nilai ini menangkap koordinat x dan y loji pada saat anda mengklik atau menyentuhnya. Anda memerlukan kawalan yang terperinci terhadap tingkah laku tanaman semasa anda mengklik dan menyeretnya, jadi anda terus mengawasi koordinatnya.
|
||||
|
||||
✅ Adakah semakin jelas mengapa keseluruhan aplikasi ini dibina dengan satu penutupan besar? Sekiranya tidak, bagaimana anda mengekalkan ruang lingkup bagi setiap 14 tumbuhan yang boleh diseret?
|
||||
|
||||
Selesaikan fungsi awal dengan menambahkan dua lagi manipulasi peristiwa penunjuk di bawah `pos4 = e.clientY`:
|
||||
|
||||
```html
|
||||
document.onpointermove = elementDrag;
|
||||
document.onpointerup = stopElementDrag;
|
||||
```
|
||||
Sekarang anda menunjukkan bahawa anda mahu kilang diseret bersama-sama dengan penunjuk semasa anda menggerakkannya, dan agar gerakan seret berhenti ketika anda membatalkan pilihan kilang. `onpointermove` dan` onpointerup` adalah semua bahagian dari API yang sama dengan `onpointerdown`. Antaramuka akan membuang ralat sekarang kerana anda belum menentukan fungsi `elementDrag` dan` stopElementDrag`, jadi bina yang seterusnya.
|
||||
|
||||
## Fungsi elementDrag dan stopElementDrag
|
||||
|
||||
Anda akan menyelesaikan penutupan anda dengan menambahkan dua fungsi dalaman yang akan menangani apa yang berlaku semasa anda menyeret kilang dan berhenti menyeretnya. Tingkah laku yang anda mahukan ialah anda boleh menyeret mana-mana tanaman pada bila-bila masa dan meletakkannya di mana sahaja di skrin. Antaramuka ini agak tidak diingini (tidak ada zon penurunan) untuk membolehkan anda merancang terarium anda dengan tepat seperti yang anda suka dengan menambah, membuang, dan memasang semula tanaman.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan fungsi `elementDrag` tepat setelah pendakap keriting penutup` pointerDrag`:
|
||||
|
||||
```javascript
|
||||
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 posisi awal 1-4 yang anda tetapkan sebagai pemboleh ubah tempatan dalam fungsi luar. Apa yang berlaku di sini?
|
||||
|
||||
Semasa anda menyeret, anda menetapkan semula `pos1` dengan menjadikannya sama dengan` pos3` (yang anda tetapkan lebih awal sebagai `e.clientX`) tolak nilai `e.clientX` semasa. Anda melakukan operasi yang serupa dengan `pos2`. Kemudian, anda menetapkan semula `pos3` dan `pos4` ke koordinat X dan Y elemen yang baru. Anda boleh melihat perubahan ini di konsol semasa anda menyeret. Kemudian, anda memanipulasi gaya css kilang untuk menetapkan kedudukan barunya berdasarkan kedudukan baru `pos1` dan` pos2`, mengira koordinat X dan Y bahagian atas dan kiri kilang berdasarkan membandingkan ofsetnya dengan kedudukan baru ini.
|
||||
|
||||
> `offsetTop` dan` offsetLeft` adalah sifat CSS yang menetapkan kedudukan elemen berdasarkan kedudukan induknya; induknya boleh menjadi unsur apa pun yang tidak diposisikan sebagai `statik`.
|
||||
|
||||
Semua pengiraan semula kedudukan ini membolehkan anda menyesuaikan tingkah laku terarium dan tanamannya.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tugas terakhir untuk melengkapkan antara muka adalah dengan menambahkan fungsi `stopElementDrag` setelah pendakap keriting` elementDrag`:
|
||||
|
||||
```javascript
|
||||
function stopElementDrag() {
|
||||
document.onpointerup = null;
|
||||
document.onpointermove = null;
|
||||
}
|
||||
```
|
||||
|
||||
Fungsi kecil ini menetapkan semula peristiwa `onpointerup` dan `onpointermove` sehingga anda dapat memulakan semula kemajuan tanaman anda dengan mula menyeretnya lagi, atau mula menyeret loji baru.
|
||||
|
||||
✅ Apakah yang berlaku jika anda tidak menetapkan peristiwa ini menjadi null?
|
||||
|
||||
Sekarang anda telah menyelesaikan projek anda!
|
||||
|
||||
🥇 Tahniah! Anda telah menyelesaikan terarium yang indah. ![terarium selesai](../images/terrarium-final.png)
|
||||
|
||||
---
|
||||
|
||||
## 🚀Cabaran
|
||||
|
||||
Tambahkan pengendali acara (event handler) baharu ke penutupan anda untuk melakukan sesuatu yang lebih banyak pada tanaman; contohnya, klik dua kali loji untuk membawanya ke hadapan. Dapatkan kreatif!
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/20)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Walaupun menyeret elemen di sekitar skrin kelihatan remeh, ada banyak cara untuk melakukan ini dan banyak perangkap, bergantung pada kesan yang anda cari. Sebenarnya, terdapat keseluruhan [drag and drop API] (https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) 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 boleh anda capai.
|
||||
|
||||
Dapatkan lebih banyak maklumat mengenai peristiwa penunjuk pada [dokumen W3C](https://www.w3.org/TR/pointerevents1/) dan di [dokumen web MDN](https://developer.mozilla.org/en-US/ dokumen / Web / API / Pointer_events).
|
||||
|
||||
Sentiasa periksa keupayaan penyemak imbas menggunakan [CanIUse.com](https://caniuse.com/).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Bekerja sedikit dengan DOM](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Bekerja sedikit dengan DOM
|
||||
|
||||
## Arahan
|
||||
|
||||
Mengkaji DOM sedikit dengan 'menerapkan' elemen DOM. Lawati laman MSDN [senarai antara muka DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) dan pilih satu. Cari ia digunakan di laman web di web, dan tulis penjelasan bagaimana ia digunakan.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | --------------------------------------------- | ------------------------------------------------ | ----------------------- |
|
||||
| | Penulisan perenggan dibentangkan, dengan contoh | Penulisan perenggan dibentangkan, tanpa contoh | Tiada penulisan perenggan dibentangkan |
|
@ -0,0 +1,31 @@
|
||||
# My Terrarium: Projek untuk belajar mengenai HTML, CSS, dan memanipulasikan DOM menggunakan JavaScript 🌵🌱
|
||||
|
||||
Meditasi kod seret dan lepas kecil. Dengan sedikit HTML, JS dan CSS, anda boleh membina antara muka web, menggayakannya, dan menambahkan interaksi.
|
||||
|
||||
![my terrarium](../images/screenshot_gray.png)
|
||||
|
||||
# Pengajaran
|
||||
|
||||
1. [Pengenalan HTML](../1-intro-to-html/README.md)
|
||||
2. [Pengenalan CSS](../2-intro-to-css/README.md)
|
||||
3. [Pengenalan DOM dan Penutupan JS](../3-intro-to-DOM-and-closures/README.md)
|
||||
|
||||
## Kredit
|
||||
|
||||
Ditulis dengan ♥️ oleh [Jen Looper](https://www.twitter.com/jenlooper)
|
||||
|
||||
Terarium yang dibuat melalui CSS diilhamkan oleh balang kaca Jakub Mandra [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY).
|
||||
|
||||
Karya seni inu dilukis oleh [Jen Looper](http://jenlooper.com) dengan menggunakan Procreate.
|
||||
|
||||
## Sebarkan Terrarium anda
|
||||
|
||||
Anda boleh menggunakan, atau menerbitkan terarium anda ke web menggunakan Aplikasi Web Azure Static (Azure Static Web Apps).
|
||||
|
||||
1. Fork repo ini
|
||||
|
||||
2. Tekan butang ini
|
||||
|
||||
[![Sebarkan ke butang Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/?feature.customportal=false&WT.mc_id=cxaall-4621-cxall#create/Microsoft.StaticApp)
|
||||
|
||||
3. Berjalan melalui wizard membuat aplikasi anda. Pastikan anda menetapkan root aplikasi menjadi `/solution` atau root basis pangkalan data anda. Tidak ada API dalam aplikasi ini, jadi jangan risau untuk menambahkannya. Folder .github akan dibuat di repo bercabang anda yang akan membantu membina perkhidmatan Aplikasi Azure Static Web membina dan menerbitkan aplikasi anda ke URL baru.
|
@ -0,0 +1,30 @@
|
||||
# Pengaturcaraan Berdasarkan Acara - Bina Permainan Menaip
|
||||
|
||||
## Pengenalan
|
||||
|
||||
Menaip adalah salah satu kemahiran yang paling diremehkan oleh pemaju. Keupayaan untuk memindahkan pemikiran dari kepala ke editor anda dengan cepat membolehkan kreativiti mengalir dengan bebas. Salah satu kaedah terbaik untuk belajar adalah bermain permainan!
|
||||
|
||||
> Oleh itu, mari kita membina permainan menaip!
|
||||
|
||||
Anda akan menggunakan kemahiran JavaScript, HTML dan CSS yang telah anda buat selama ini untuk membuat permainan menaip. Permainan akan memberikan petikan secara rawak kepada pemain (kami menggunakan petikan [Sherlock Holmes](https://en.wikipedia.org/wiki/Sherlock_Holmes)) dan masa yang diperlukan pemain untuk mengetiknya dengan tepat. Anda akan menggunakan kemahiran JavaScript, HTML dan CSS yang telah anda buat selama ini untuk membuat permainan menaip.
|
||||
|
||||
![demo](../images/demo.gif)
|
||||
|
||||
## Prasyarat
|
||||
|
||||
Pelajaran ini menganggap anda sudah biasa dengan konsep berikut:
|
||||
|
||||
- Membuat input teks dan kawalan butang
|
||||
- CSS dan gaya penetapan menggunakan kelas
|
||||
- Asas JavaScript
|
||||
- Membuat susunan
|
||||
- Membuat nombor rawak
|
||||
- Mendapatkan masa sekarang
|
||||
|
||||
## Pelajaran
|
||||
|
||||
[Membuat permainan menaip dengan menggunakan pengaturcaraan berdasarkan acara](../typing-game/README.ms.md)
|
||||
|
||||
## Kredit
|
||||
|
||||
Ditulisa dengan ♥️ oleh [Christopher Harrison](http://www.twitter.com/geektrainer)
|
@ -0,0 +1,339 @@
|
||||
# Membuat permainan menggunakan acara (events)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/21)
|
||||
|
||||
## Pengaturcaraan berdasarkan acara
|
||||
|
||||
Semasa membuat aplikasi berasaskan penyemak imbas, kami menyediakan antara muka pengguna grafik (GUI) untuk pengguna gunakan ketika berinteraksi dengan apa yang telah kami buat. Cara paling biasa untuk berinteraksi dengan penyemak imbas adalah dengan mengklik dan menaip pelbagai elemen. Cabaran yang kita hadapi sebagai pembangun adalah kita tidak tahu kapan mereka akan melakukan operasi ini!
|
||||
|
||||
[Pengaturcaraan berdasarkan acara](https://en.wikipedia.org/wiki/Event-driven_programming) adalah nama untuk jenis pengaturcaraan yang perlu kita lakukan untuk membuat GUI kita. Sekiranya kita memecahkan frasa ini sedikit, kita akan melihat kata intinya di sini adalah **event**. [Event](https://www.merriam-webster.com/dictionary/event), menurut Merriam-Webster, didefinisikan sebagai "sesuatu yang berlaku". Ini menggambarkan keadaan kita dengan sempurna. Kami tahu ada sesuatu yang akan berlaku dan kami ingin melaksanakan beberapa kod sebagai tindak balas, tetapi kami tidak tahu kapan ia akan berlaku.
|
||||
|
||||
Cara kita menandakan bahagian kod yang ingin kita laksanakan adalah dengan membuat fungsi. Apabila kita memikirkan [pengaturcaraan prosedural](https://en.wikipedia.org/wiki/Procedural_programming), fungsi dipanggil dalam urutan tertentu. Perkara yang sama akan berlaku dengan pengaturcaraan berdasarkan acara. Perbezaannya adalah **bagaimana** fungsi akan dipanggil.
|
||||
|
||||
Untuk menangani acara (klik butang, menaip, dll.), Kami mendaftarkan **pendengar acara**. Pendengar peristiwa adalah fungsi yang mendengarkan peristiwa yang berlaku dan dilaksanakan sebagai tindak balas. Pendengar acara boleh mengemas kini UI, membuat panggilan ke pelayan, atau apa sahaja yang perlu dilakukan sebagai tindak balas terhadap tindakan pengguna. Kami menambahkan pendengar acara dengan menggunakan [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener), dan menyediakan fungsi untuk dilaksanakan.
|
||||
|
||||
> **CATATAN:** Perlu dinyatakan bahawa terdapat banyak cara untuk membuat pendengar acara. Anda boleh menggunakan fungsi tanpa nama, atau membuat fungsi yang dinamakan. Anda boleh menggunakan pelbagai jalan pintas, seperti menetapkan sifat `klik`, atau menggunakan` addEventListener`. Dalam latihan kami, kami akan menumpukan pada fungsi `addEventLister` dan anonim, kerana mungkin teknik yang paling biasa digunakan oleh pembangun web. Ini juga paling fleksibel, kerana `addEventListener` berfungsi untuk semua acara, dan nama acara dapat diberikan sebagai parameter.
|
||||
|
||||
### Acara biasa
|
||||
|
||||
Terdapat [puluhan acara](https://developer.mozilla.org/docs/Web/Events) yang tersedia untuk anda dengarkan semasa membuat aplikasi. Pada asasnya apa sahaja yang dilakukan pengguna pada halaman menimbulkan peristiwa, yang memberi anda banyak kekuatan untuk memastikan mereka mendapat pengalaman yang anda inginkan. Nasib baik, anda biasanya hanya memerlukan sebilangan kecil acara. Berikut adalah beberapa perkara biasa (termasuk dua yang akan kami gunakan semasa membuat permainan kami):
|
||||
|
||||
- [click](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event): Pengguna mengklik sesuatu, biasanya butang atau hyperlink
|
||||
- [contextmenu](https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event): Pengguna mengklik butang tetikus kanan
|
||||
- [select](https://developer.mozilla.org/en-US/docs/Web/API/Element/select_event): Pengguna menyoroti beberapa teks
|
||||
- [input](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event): Pengguna memasukkan beberapa teks
|
||||
|
||||
## Membuat permainan
|
||||
|
||||
Kami akan membuat permainan untuk meneroka bagaimana acara berfungsi dalam JavaScript. Permainan kami akan menguji kemahiran menaip pemain, yang merupakan salah satu kemahiran paling rendah yang harus dimiliki oleh pemaju. Kita semua mesti berlatih menaip kita! Aliran umum permainan akan kelihatan seperti ini:
|
||||
|
||||
- Pemain mengklik butang mula dan disertakan dengan petikan untuk menaip
|
||||
- Pemain menaip petikan secepat mungkin di kotak teks
|
||||
- Apabila setiap perkataan selesai, yang berikutnya diserlahkan
|
||||
- Sekiranya pemain mempunyai kesalahan ketik, kotak teks dikemas kini menjadi merah
|
||||
- Apabila pemain menyelesaikan petikan, mesej kejayaan akan dipaparkan dengan masa yang berlalu
|
||||
|
||||
Mari membina permainan kami, dan belajar tentang acara!
|
||||
|
||||
### Struktur fail
|
||||
|
||||
Kami memerlukan tiga jumlah fail: **index.html**, **script.js** dan **style.css**. Mari mulakan dengan menetapkannya untuk menjadikan hidup lebih mudah bagi kita.
|
||||
|
||||
- Buat folder baru untuk kerja anda dengan membuka tetingkap konsol atau terminal dan mengeluarkan perintah berikut:
|
||||
|
||||
```bash
|
||||
# Linux or macOS
|
||||
mkdir typing-game && cd typing-game
|
||||
|
||||
# Windows
|
||||
md typing-game && cd typing-game
|
||||
```
|
||||
|
||||
- Buka Visual Studio Code
|
||||
|
||||
```bash
|
||||
code .
|
||||
```
|
||||
|
||||
- Tambahkan tiga fail ke folder dalam Visual Studio Code dengan nama berikut:
|
||||
- index.html
|
||||
- skrip.js
|
||||
- style.css
|
||||
|
||||
## Buat antara muka pengguna (user interface)
|
||||
|
||||
Sekiranya kita meneliti syarat-syaratnya, kita tahu kita akan memerlukan segelintir elemen di halaman HTML kita. Ini seperti resipi, di mana kita memerlukan beberapa ramuan:
|
||||
|
||||
- Di suatu tempat untuk memaparkan petikan untuk pengguna menaip
|
||||
- Di suatu tempat untuk memaparkan sebarang mesej, seperti mesej kejayaan
|
||||
- Kotak teks untuk menaip
|
||||
- Butang mula
|
||||
|
||||
Masing-masing memerlukan ID supaya kita dapat bekerja dengannya dalam JavaScript kita. Kami juga akan menambahkan rujukan ke fail CSS dan JavaScript yang akan kami buat.
|
||||
|
||||
Buat fail baru bernama **index.html**. Tambahkan HTML berikut:
|
||||
|
||||
```html
|
||||
<!-- inside index.html -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Typing game</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Typing game!</h1>
|
||||
<p>Practice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!</p>
|
||||
<p id="quote"></p> <!-- This will display our quote -->
|
||||
<p id="message"></p> <!-- This will display any status messages -->
|
||||
<div>
|
||||
<input type="text" aria-label="current word" id="typed-value" /> <!-- The textbox for typing -->
|
||||
<button type="button" id="start">Start</button> <!-- To start the game -->
|
||||
</div>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Lancarkan aplikasi
|
||||
|
||||
Adalah lebih baik untuk mengembangkannya secara berulang untuk melihat bagaimana keadaannya. Mari melancarkan aplikasi kami. Terdapat peluasan hebat untuk Visual Studio Code yang disebut [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) yang akan menghoskan aplikasi anda secara tempatan dan menyegarkan penyemak imbas setiap kali anda menyimpan.
|
||||
|
||||
- Pasang [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) dengan mengikuti pautan dan mengklik **Install**
|
||||
- Anda akan diminta oleh penyemak imbas untuk membuka Kod Visual Studio, dan kemudian oleh Kod Visual Studio untuk melakukan pemasangan
|
||||
- Mulakan semula Kod Visual Studio jika diminta
|
||||
- Setelah dipasang, dalam Visual Studio Code, klik Ctrl-Shift-P (atau Cmd-Shift-P) untuk membuka perintah pallate
|
||||
- Taip **Pelayan Langsung: Buka dengan Pelayan Langsung**
|
||||
- Live Server akan mula menghoskan aplikasi anda
|
||||
- Buka penyemak imbas dan arahkan ke **https: // localhost: 5500**
|
||||
- Anda kini harus melihat halaman yang anda buat!
|
||||
|
||||
Mari tambahkan beberapa fungsi.
|
||||
|
||||
## Tambah CSS
|
||||
|
||||
Dengan HTML kami dibuat, mari tambahkan CSS untuk gaya inti. Kita perlu mengetengahkan perkataan yang harus ditaip oleh pemain, dan mewarnakan kotak teks jika apa yang mereka taipkan tidak betul. Kami akan melakukan ini dengan dua kelas.
|
||||
|
||||
Buat fail baru bernama **style.css** dan tambahkan sintaks berikut.
|
||||
|
||||
```css
|
||||
/* dalam style.css */
|
||||
.highlight {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: lightcoral;
|
||||
border: red;
|
||||
}
|
||||
```
|
||||
|
||||
✅ Ketika datang ke CSS, anda boleh mengatur halaman anda sesuka hati. Luangkan sedikit masa dan buat halaman kelihatan lebih menarik:
|
||||
|
||||
- Pilih fon yang berbeza
|
||||
- Warnakan tajuk
|
||||
- Ubah saiz item
|
||||
|
||||
## JavaScript
|
||||
|
||||
Dengan UI kami dibuat, inilah masanya untuk menumpukan perhatian kami pada JavaScript yang akan memberikan logik. Kami akan membahagikannya kepada beberapa langkah:
|
||||
|
||||
- [Buat pemalar](#tambah-pemalar)
|
||||
- [Pendengar acara untuk memulakan permainan](#add-start-logic)
|
||||
- [Pendengar acara untuk menaip](#add-typing-logic)
|
||||
|
||||
Tetapi pertama, buat fail baru bernama **script.js**.
|
||||
|
||||
### Tambahkan pemalar
|
||||
|
||||
Kita akan memerlukan beberapa item untuk menjadikan kehidupan kita lebih mudah untuk pengaturcaraan. Sekali lagi, serupa dengan resipi, inilah yang kita perlukan:
|
||||
|
||||
- Susun dengan senarai semua petikan
|
||||
- Susunan kosong untuk menyimpan semua perkataan untuk petikan semasa
|
||||
- Ruang untuk menyimpan indeks kata pemain sedang menaip
|
||||
- Masa pemain mengklik permulaan
|
||||
|
||||
Kami juga mahu rujukan ke elemen UI:
|
||||
|
||||
- Kotak teks (**nilai taip**)
|
||||
- Paparan petikan (**petikan**)
|
||||
- Mesej (**mesej**)
|
||||
|
||||
```javascript
|
||||
// dalam script.js
|
||||
// semua quotes
|
||||
const quotes = [
|
||||
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
|
||||
'There is nothing more deceptive than an obvious fact.',
|
||||
'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.',
|
||||
'I never make exceptions. An exception disproves the rule.',
|
||||
'What one man can invent another can discover.',
|
||||
'Nothing clears up a case so much as stating it to another person.',
|
||||
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
|
||||
];
|
||||
// simpan senarai perkataan dan indeks perkataan yang sedang ditaip pemain
|
||||
let words = [];
|
||||
let wordIndex = 0;
|
||||
// masa permulaan
|
||||
let startTime = Date.now();
|
||||
// elemen halaman
|
||||
const quoteElement = document.getElementById('quote');
|
||||
const messageElement = document.getElementById('message');
|
||||
const typedValueElement = document.getElementById('typed-value');
|
||||
```
|
||||
|
||||
✅ Teruskan dan tambahkan lebih banyak petikan ke permainan anda
|
||||
|
||||
> ** CATATAN: ** Kami dapat mengambil elemen bila-bila masa yang kami mahukan dalam kod dengan menggunakan `document.getElementById`. Oleh kerana hakikatnya kita akan merujuk unsur-unsur ini secara berkala, kita akan mengelakkan kesalahan ketik dengan literal string dengan menggunakan pemalar. Rangka kerja seperti [Vue.js](https://vuejs.org/) atau [React](https://reactjs.org/) dapat membantu anda menguruskan pemusatan kod anda dengan lebih baik.
|
||||
|
||||
Luangkan masa sebentar untuk menonton video menggunakan `const`,` let` dan `var`
|
||||
|
||||
[![Jenis pemboleh ubah](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Jenis pemboleh ubah")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai pemboleh ubah.
|
||||
|
||||
### Tambahkan Logik
|
||||
|
||||
Untuk memulakan permainan, pemain akan mengklik pada permulaan. Sudah tentu, kita tidak tahu kapan mereka akan mula klik. Di sinilah seorang [pendengar acara](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) mula bermain. Pendengar acara akan membolehkan kita mendengar sesuatu yang berlaku (suatu peristiwa) dan melaksanakan kod sebagai tindak balas. Dalam kes kami, kami ingin melaksanakan kod ketika pengguna mengklik pada permulaan.
|
||||
|
||||
Apabila pengguna mengklik **start**, kita harus memilih sebut harga, menyiapkan antarmuka pengguna, dan penyiapan pelacakan untuk kata dan waktu semasa. Berikut adalah JavaScript yang perlu anda tambahkan; kita membincangkannya selepas blok skrip.
|
||||
|
||||
```javascript
|
||||
// pada akhir script.js
|
||||
document.getElementById('start').addEventListener('click', () => {
|
||||
// dapatkan quote
|
||||
const quoteIndex = Math.floor(Math.random() * quotes.length);
|
||||
const quote = quotes[quoteIndex];
|
||||
// Masukkan petikan ke dalam susunan kata
|
||||
words = quote.split(' ');
|
||||
// tetapkan semula indeks kata untuk penjejakan
|
||||
wordIndex = 0;
|
||||
|
||||
// Kemas kini UI
|
||||
// Buat susunan elemen span supaya kita dapat mengatur kelas
|
||||
const spanWords = words.map(function(word) { return `<span>${word} </span>`});
|
||||
// Tukar menjadi rentetan dan tetapkan sebagai innerHTML pada paparan petikan
|
||||
quoteElement.innerHTML = spanWords.join('');
|
||||
// Serlahkan perkataan pertama
|
||||
quoteElement.childNodes[0].className = 'highlight';
|
||||
// Kosongkan sebarang mesej sebelumnya
|
||||
messageElement.innerText = '';
|
||||
|
||||
// Sediakan kotak teks
|
||||
// Kosongkan kotak teks
|
||||
typedValueElement.value = '';
|
||||
// Sediakan fokus
|
||||
typedValueElement.focus();
|
||||
// tetapkan pengendali acara
|
||||
|
||||
// Mulakan pemasa
|
||||
startTime = new Date().getTime();
|
||||
});
|
||||
```
|
||||
|
||||
Mari pecahkan kodnya!
|
||||
|
||||
- Siapkan penjejakan perkataan
|
||||
- Menggunakan [Math.floor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) dan [Math.random](https://developer.mozilla.org/docs / Web / JavaScript / Rujukan / Global_Objects / Matematik / rawak) membolehkan kita memilih petikan secara rawak dari array `quotes`
|
||||
- Kami menukar `quote 'menjadi array` kata` sehingga kami dapat mengesan perkataan yang sedang ditaip pemain
|
||||
- `wordIndex` ditetapkan ke 0, kerana pemain akan bermula pada kata pertama
|
||||
- Sediakan UI
|
||||
- Buat array `spanWords`, yang berisi setiap kata di dalam elemen` span`
|
||||
- Ini akan membolehkan kita menonjolkan perkataan di paparan
|
||||
- `join` array untuk membuat rentetan yang dapat kita gunakan untuk mengemas kini` innerHTML` pada `quoteElement`
|
||||
- Ini akan memaparkan petikan kepada pemain
|
||||
- Tetapkan `className` elemen` span` pertama ke highlight untuk menyerlahkannya sebagai kuning
|
||||
- Bersihkan `messageElement` dengan menetapkan "innerText" ke `''`
|
||||
- Sediakan kotak teks
|
||||
- Kosongkan `nilai` semasa di` typedValueElement`
|
||||
- Tetapkan `fokus` ke` typedValueElement`
|
||||
- Mulakan pemasa dengan memanggil `getTime`
|
||||
|
||||
### Tambahkan logik menaip
|
||||
|
||||
Semasa pemain menaip, acara `input` akan dinaikkan. Pendengar acara ini akan memeriksa untuk memastikan pemain menaip perkataan dengan betul, dan mengendalikan status permainan semasa. Kembali ke **script.js**, tambahkan kod berikut hingga akhir. Kami akan memecahkannya selepas itu.
|
||||
|
||||
```javascript
|
||||
// pada akhir skrip.js
|
||||
typedValueElement.addEventListener('input', () => {
|
||||
// Dapatkan perkataan semasa
|
||||
const currentWord = words[wordIndex];
|
||||
// dapatkan nilai semasa
|
||||
const typedValue = typedValueElement.value;
|
||||
|
||||
if (typedValue === currentWord && wordIndex === words.length - 1) {
|
||||
// akhir ayat
|
||||
// Paparkan kejayaan
|
||||
const elapsedTime = new Date().getTime() - startTime;
|
||||
const message = `CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.`;
|
||||
messageElement.innerText = message;
|
||||
} else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) {
|
||||
// akhir kata
|
||||
// kosongkan typedValueElement untuk perkataan baru
|
||||
typedValueElement.value = '';
|
||||
// beralih ke perkataan seterusnya
|
||||
wordIndex++;
|
||||
// tetapkan semula nama kelas untuk semua elemen dalam petikan
|
||||
for (const wordElement of quoteElement.childNodes) {
|
||||
wordElement.className = '';
|
||||
}
|
||||
// serlahkan perkataan baru
|
||||
quoteElement.childNodes[wordIndex].className = 'highlight';
|
||||
} else if (currentWord.startsWith(typedValue)) {
|
||||
// betul sekarang
|
||||
// serlahkan perkataan seterusnya
|
||||
typedValueElement.className = '';
|
||||
} else {
|
||||
// keadaan ralat
|
||||
typedValueElement.className = 'error';
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Mari pecahkan kodnya! Kami mulakan dengan merebut perkataan semasa dan nilai yang ditaip pemain sejauh ini. Kemudian kita mempunyai logik air terjun, di mana kita memeriksa apakah petikannya lengkap, kata itu lengkap, kata itu betul, atau (akhirnya), jika ada kesalahan.
|
||||
|
||||
- Kutipan selesai, ditunjukkan oleh `typedValue` sama dengan` currentWord`, dan `wordIndex` sama dengan satu yang kurang dari` panjang 'kata-kata `
|
||||
- Hitung `elapsedTime` dengan mengurangkan` startTime` dari waktu semasa
|
||||
- Bahagikan `elapsedTime` dengan 1,000 untuk menukar dari milisaat hingga saat
|
||||
- Paparkan mesej kejayaan
|
||||
- Kata lengkap, ditunjukkan oleh `typedValue` yang diakhiri dengan spasi (akhir kata) dan` typedValue` sama dengan `currentWord`
|
||||
- Tetapkan "nilai" pada "typedElement" menjadi "" untuk membolehkan kata berikutnya ditaip
|
||||
- Kenaikan `wordIndex` untuk beralih ke kata seterusnya
|
||||
- Gelung semua "childNodes" "quoteElement" untuk menetapkan "className" ke "" untuk kembali ke paparan lalai
|
||||
- Tetapkan `className` dari kata semasa ke` highlight 'untuk menandakannya sebagai kata seterusnya untuk menaip
|
||||
- Word saat ini ditaip dengan betul (tetapi tidak lengkap), ditunjukkan oleh `currentWord` yang dimulakan dengan` typedValue`
|
||||
- Pastikan `typedValueElement` dipaparkan sebagai lalai dengan membersihkan` className`
|
||||
- Sekiranya kita berjaya sejauh ini, kita mempunyai ralat
|
||||
- Tetapkan `className` pada` typedValueElement` ke `error`
|
||||
|
||||
## Uji aplikasi anda
|
||||
|
||||
Anda berjaya sampai akhir! Langkah terakhir adalah memastikan aplikasi kita berfungsi. Cubalah! Jangan risau sekiranya terdapat kesilapan; **semua pembangun** mempunyai kesilapan. Teliti mesej dan debug mengikut keperluan.
|
||||
|
||||
Klik **start**, dan mula menaip! Ia semestinya kelihatan seperti animasi yang kita lihat sebelumnya.
|
||||
|
||||
![Animasi permainan beraksi](/4-typing-game/images/demo.gif)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Tambahkan lebih banyak fungsi
|
||||
|
||||
- Lumpuhkan pendengar acara `input` setelah selesai, dan aktifkan semula apabila butang diklik
|
||||
- Lumpuhkan kotak teks semasa pemain menyelesaikan petikan
|
||||
- Paparkan kotak dialog mod dengan mesej kejayaan
|
||||
- Simpan skor tinggi menggunakan [localStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage)
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/22)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Bacalah [semua acara yang ada](https://developer.mozilla.org/en-US/docs/Web/Events) kepada pembangun melalui penyemak imbas web, dan pertimbangkan senario di mana anda akan menggunakannya.
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Buat permainan papan kekunci baru](assignment.ms.md)
|
@ -0,0 +1,12 @@
|
||||
# Buat permainan papan kekunci baharu
|
||||
|
||||
## Arahan
|
||||
|
||||
Buat permainan kecil yang menggunakan acara papan kekunci untuk melakukan tugas. Ini boleh menjadi jenis permainan menaip yang berbeza, atau permainan jenis seni yang melukis piksel ke layar pada penekanan tombol. Dapatkan kreatif!
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------ | ------------------------ | ----------------- |
|
||||
| | Permainan penuh dipersembahkan | Permainan ini sangat minimum | Permainan ini mempunyai pepijat |
|
||||
| |
|
@ -0,0 +1,168 @@
|
||||
# Projek Pelanjutan Penyemak Imbas Bahagian 1: Semua mengenai Penyemak Imbas
|
||||
|
||||
![Sketchnote penyemak imbas](../images/sketchnote.jpg)
|
||||
> Sketchnote karya [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/23)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Sambungan penyemak imbas menambah fungsi tambahan pada penyemak imbas. Tetapi sebelum anda membuatnya, anda harus mengetahui sedikit tentang bagaimana penyemak imbas melakukan kerja mereka.
|
||||
|
||||
### Mengenai penyemak imbas
|
||||
|
||||
Dalam siri pelajaran ini, anda akan belajar bagaimana membina pelanjutan penyemak imbas yang akan berfungsi pada penyemak imbas Chrome, Firefox dan Edge. Di bahagian ini, anda akan mengetahui cara penyemak imbas berfungsi dan memaparkan elemen pelanjutan penyemak imbas.
|
||||
|
||||
Tetapi apakah sebenarnya penyemak imbas itu? Ini adalah aplikasi perisian yang memungkinkan pengguna akhir mengakses kandungan dari pelayan dan memaparkannya di laman web.
|
||||
|
||||
✅ Sejarah sedikit: penyemak imbas pertama dipanggil 'WorldWideWeb' dan dicipta oleh Sir Timothy Berners-Lee pada tahun 1990.
|
||||
|
||||
![penyemak imbas awal](../images/earlybrowsers.jpg)
|
||||
> Beberapa penyemak imbas awal, melalui [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
|
||||
|
||||
Apabila pengguna tersambung ke internet menggunakan alamat URL (Uniform Resource Locator), biasanya menggunakan Hypertext Transfer Protocol melalui alamat `http` atau `https`, penyemak imbas berkomunikasi dengan pelayan web dan mengambil halaman web.
|
||||
|
||||
Pada titik ini, mesin rendering penyemak imbas memaparkannya pada perangkat pengguna, yang mungkin merupakan telefon bimbit, desktop, atau komputer riba.
|
||||
|
||||
Penyemak imbas juga memiliki kemampuan untuk menyimpan konten sehingga tidak perlu diambil dari pelayan setiap masa. Mereka dapat mencatat sejarah aktiviti menyemak imbas pengguna, menyimpan 'kuki', yang merupakan sekumpulan kecil data yang mengandungi maklumat yang digunakan untuk menyimpan aktiviti pengguna, dan banyak lagi.
|
||||
|
||||
Perkara yang sangat penting untuk diingat mengenai penyemak imbas ialah semuanya tidak sama! Setiap penyemak imbas mempunyai kelebihan dan kekurangannya, dan pembangun web profesional perlu memahami cara membuat laman web berfungsi dengan baik di antara penyemak imbas. Ini merangkumi pengendalian ruang pandang kecil seperti telefon bimbit, dan juga pengguna yang berada di luar talian.
|
||||
|
||||
Laman web yang sangat berguna yang mungkin anda tandakan dalam penyemak imbas apa pun yang anda mahu gunakan ialah [caniuse.com](https://www.caniuse.com). Semasa anda membina laman web, sangat berguna untuk menggunakan senarai teknologi yang disokong oleh caniuse sehingga anda dapat menyokong pengguna anda dengan sebaik-baiknya.
|
||||
|
||||
✅ Bagaimanakah anda dapat mengetahui penyemak imbas apa yang paling popular dengan pangkalan pengguna laman web anda? Periksa analisis anda - anda boleh memasang pelbagai pakej analitik sebagai sebahagian daripada proses pengembangan web anda, dan mereka akan memberitahu anda penyemak imbas apa yang paling banyak digunakan oleh pelbagai penyemak imbas yang popular.
|
||||
|
||||
## Pelanjutan Penyemak Imbas
|
||||
|
||||
Mengapakah anda mahu membina pelanjutan penyemak imbas? Adalah berguna untuk melampirkan pada penyemak imbas anda apabila anda memerlukan akses cepat ke tugas yang cenderung anda ulang. Contohnya, jika anda perlu memeriksa warna di pelbagai laman web yang anda berinteraksi, anda mungkin memasang pelanjutan penyemak imbas pemilih warna. Sekiranya anda menghadapi masalah mengingat kata laluan, anda mungkin menggunakan pelanjutan penyemak imbas pengurusan kata laluan.
|
||||
|
||||
Pelanjutan penyemak imbas juga senang dikembangkan. Mereka cenderung menguruskan sejumlah tugas yang mereka laksanakan dengan baik.
|
||||
|
||||
✅ Apakah pelanjutan penyemak imbas kegemaran anda? Tugas apa yang mereka laksanakan?
|
||||
|
||||
### Memuat turun pelanjutan penyemak imbas
|
||||
|
||||
Sebelum anda mula membina, lihatlah proses membina dan menggunakan pelanjutan penyemak imbas. Walaupun setiap penyemak imbas sedikit berbeza dalam cara mereka menguruskan tugas ini, prosesnya serupa di Chrome dan Firefox dengan contoh ini di Edge:
|
||||
|
||||
![tangkapan skrin penyemak imbas Edge menunjukkan tepi terbuka://halaman peluasan dan menu tetapan terbuka](../images/install-on-edge.png)
|
||||
|
||||
Pada dasarnya, prosesnya adalah:
|
||||
|
||||
- buat pelanjutan anda menggunakan `npm build`
|
||||
- arahkan di penyemak imbas ke panel pelanjutan menggunakan butang "Tetapan dan lain-lain" (ikon `...`) di kanan atas
|
||||
- jika ia adalah pemasangan baru, pilih `load unpacked` untuk memuat naik ekstensi baru dari folder buildnya (dalam kes kami adalah `/ dist`)
|
||||
- atau, klik `reload` jika anda memuat semula pelanjutan yang sudah dipasang
|
||||
|
||||
✅ Arahan ini berkaitan dengan sambungan yang anda buat sendiri; untuk memasang pelanjutan yang telah dilepaskan ke kedai pelanjutan penyemak imbas yang berkaitan dengan setiap penyemak imbas, anda harus menavigasi ke [kedai](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home) dan pasang pelanjutan pilihan anda.
|
||||
|
||||
### Bermula Di Sini
|
||||
|
||||
Anda akan membina pelanjutan penyemak imbas yang memaparkan jejak karbon wilayah anda, menunjukkan penggunaan tenaga wilayah anda dan sumber tenaga. Pelanjutan penyemak imbas tersebut akan mempunyai bentuk yang mengumpulkan kunci API sehingga anda dapat mengaksesnya
|
||||
CO2 Signal's API.
|
||||
|
||||
**Keperluan:**
|
||||
|
||||
- [kunci API](https://www.co2signal.com/); masukkan e-mel anda di dalam kotak di halaman ini dan satu akan dihantar kepada anda
|
||||
- [kod untuk wilayah anda](http://api.electricitymap.org/v3/zones) yang sesuai dengan [Peta Elektrik](https://www.electricitymap.org/map) (di Boston, misalnya, Saya menggunakan 'US-NEISO').
|
||||
- [kod pemula](../start). Muat turun folder `start`; anda akan melengkapkan kod dalam folder ini.
|
||||
- [NPM](https://www.npmjs.com) - NPM adalah alat pengurusan pakej; memasangnya secara tempatan dan pakej yang disenaraikan dalam fail `package.json` anda akan dipasang untuk digunakan oleh aset web anda
|
||||
|
||||
✅ Ketahui lebih lanjut mengenai pengurusan pakej dalam [modul pembelajaran yang sangat baik](https://docs.microsoft.com/en-us/learn/modules/create-nodejs-project-dependencies/)
|
||||
|
||||
Luangkan masa sebentar untuk melihat pangkalan kode:
|
||||
|
||||
dist
|
||||
-|manifest.json (lalai ditetapkan di sini)
|
||||
-|index.html (front-end HTML markup di sini)
|
||||
-|background.js (latar belakang JS di sini)
|
||||
-|main.js (membina JS)
|
||||
src
|
||||
-|index.js (kod JS anda ada di sini)
|
||||
|
||||
✅ Setelah anda mempunyai kunci API dan kod Wilayah yang berguna, simpan di suatu tempat dalam nota untuk penggunaan masa depan.
|
||||
|
||||
### Bina HTML untuk pelanjutan penyemak imbas
|
||||
|
||||
Pelanjutan penyemak imbas ini mempunyai dua pandangan. Satu untuk mengumpulkan kunci API dan kod wilayah:
|
||||
|
||||
![tangkapan skrin pelanjutan selesai dibuka di penyemak imbas, menampilkan borang dengan input untuk nama wilayah dan kunci API.](../images/1.png)
|
||||
|
||||
Dan yang kedua untuk memaparkan penggunaan karbon di rantau ini:
|
||||
|
||||
![tangkapan skrin pelanjutan lengkap yang menunjukkan nilai untuk penggunaan karbon dan peratusan bahan bakar fosil untuk wilayah AS-NEISO.](images/2.png)
|
||||
|
||||
Mari mulakan dengan membina HTML untuk borang dan menggayakannya dengan CSS.
|
||||
|
||||
Dalam folder `/ dist`, anda akan membina borang dan kawasan hasil. Dalam fail `index.html`, isikan kawasan borang yang digambarkan:
|
||||
|
||||
```HTML
|
||||
<form class="form-data" autocomplete="on">
|
||||
<div>
|
||||
<h2>Baru? Tambahkan Maklumat anda</h2>
|
||||
</div>
|
||||
<div>
|
||||
<label for="region">Nama Wilayah</label>
|
||||
<input type="text" id="region" required class="region-name" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="api">Kunci API anda dari tmrow</label>
|
||||
<input type="text" id="api" required class="api-key" />
|
||||
</div>
|
||||
<button class="search-btn">Hantar</button>
|
||||
</form>
|
||||
```
|
||||
Ini adalah bentuk di mana maklumat yang anda simpan akan dimasukkan dan disimpan ke simpanan tempatan.
|
||||
|
||||
Seterusnya, buat kawasan hasil; di bawah tag borang akhir, tambahkan beberapa divs:
|
||||
|
||||
```HTML
|
||||
<div class="result">
|
||||
<div class="loading">loading...</div>
|
||||
<div class="errors"></div>
|
||||
<div class="data"></div>
|
||||
<div class="result-container">
|
||||
<p><strong>Wilayah: </strong><span class="my-region"></span></p>
|
||||
<p><strong>Penggunaan Karbon: </strong><span class="carbon-usage"></span></p>
|
||||
<p><strong>Peratusan Bahan Bakar Fosil: </strong><span class="fossil-fuel"></span></p>
|
||||
</div>
|
||||
<button class="clear-btn">Tukar wilayah</button>
|
||||
</div>
|
||||
```
|
||||
Pada ketika ini, anda boleh mencuba binaan. Pastikan memasang pergantungan pakej pelanjutan ini:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Perintah ini akan menggunakan npm, Pengurus Pakej Node, untuk memasang paket web untuk proses pembuatan pelanjutan anda. Webpack adalah bundler yang mengendalikan menyusun kod. Anda dapat melihat output proses ini dengan melihat di `/dist/main.js` - anda melihat kodnya telah digabungkan.
|
||||
|
||||
Buat masa ini, pelanjutan penyemak imbas perlu dibina dan, jika anda menyebarkannya ke Edge sebagai pelanjutan, anda akan melihat borang yang dipaparkan dengan kemas.
|
||||
|
||||
Tahniah, anda telah mengambil langkah pertama untuk membina pelanjutan penyemak imbas. Dalam pelajaran seterusnya, anda akan menjadikannya lebih berfungsi dan berguna.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Lihatlah kedai pelanjutan penyemak imbas dan pasang satu di penyemak imbas anda. Anda boleh memeriksa failnya dengan cara yang menarik. Apa yang anda dapati?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/24)
|
||||
|
||||
## Mengkaji dan Belajar Sendiri
|
||||
|
||||
Dalam pelajaran ini anda belajar sedikit mengenai sejarah penyemak imbas web; ambil kesempatan ini untuk mengetahui bagaimana pencipta World Wide Web membayangkan penggunaannya dengan membaca lebih banyak mengenai sejarahnya. Beberapa laman web yang berguna termasuk:
|
||||
|
||||
[Sejarah Penyemak Imbas Web](https://www.mozilla.org/en-US/firefox/browsers/browser-history/)
|
||||
|
||||
[Sejarah Tentang Web](https://webfoundation.org/about/vision/history-of-the-web/)
|
||||
|
||||
[Temu ramah dengan Tim Berners-Lee](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Mengayakan semula penlanjut penyemak imbas](assignment.ms.md)
|
||||
|
@ -0,0 +1,11 @@
|
||||
# Mengayakan semula penlanjut penyemak imbas
|
||||
|
||||
## Arahan
|
||||
|
||||
Pangkalan kode untuk peluasan ini dilengkapi dengan gaya, tetapi anda tidak perlu menggunakannya; jadikan peluasan anda sendiri dengan menyusun semula dengan mengedit fail cssnya.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | -------------------------------------------- | --------------------- | ----------------- |
|
||||
| | Kod dihantar dengan gaya baharu yang berfungsi | Gaya tidak lengkap | Gaya mempunyai pepijat |
|
@ -0,0 +1,222 @@
|
||||
# Projek Pelanjutan Penyemak Imbas Bahagian 2: Panggil API, gunakan Penyimpanan Tempatan
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/25)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Dalam pelajaran ini, anda akan memanggil API dengan menyerahkan borang pelanjutan penyemak imbas anda dan memaparkan hasilnya dalam pelanjutan penyemak imbas anda. Di samping itu, anda akan belajar bagaimana anda boleh menyimpan data di storan tempatan penyemak imbas anda untuk rujukan dan penggunaan di masa hadapan.
|
||||
|
||||
✅ Ikuti segmen bernombor dalam fail yang sesuai untuk mengetahui di mana meletakkan kod anda
|
||||
|
||||
### Sediakan elemen untuk dimanipulasi dalam pelanjutan:
|
||||
|
||||
Pada masa ini anda telah membina HTML untuk bentuk dan hasilnya `<div>` untuk pelanjutan penyemak imbas anda. Mulai sekarang, anda perlu bekerja dalam fail `/src/index.js` dan membina pelanjutan anda sedikit demi sedikit. Rujuk [pelajaran sebelumnya](../../about-browser/README.md) untuk menyiapkan projek anda dan pada proses pembinaan.
|
||||
|
||||
Bekerja dalam fail `index.js` anda, mulakan dengan membuat beberapa pemboleh ubah `const` untuk menahan nilai yang berkaitan dengan pelbagai bidang:
|
||||
|
||||
```JavaScript
|
||||
// form fields
|
||||
const form = document.querySelector('.form-data');
|
||||
const region = document.querySelector('.region-name');
|
||||
const apiKey = document.querySelector('.api-key');
|
||||
|
||||
// results
|
||||
const errors = document.querySelector('.errors');
|
||||
const loading = document.querySelector('.loading');
|
||||
const results = document.querySelector('.result-container');
|
||||
const usage = document.querySelector('.carbon-usage');
|
||||
const fossilfuel = document.querySelector('.fossil-fuel');
|
||||
const myregion = document.querySelector('.my-region');
|
||||
const clearBtn = document.querySelector('.clear-btn');
|
||||
```
|
||||
|
||||
Semua bidang ini dirujuk oleh kelas css mereka, semasa anda memasangnya dalam HTML pada pelajaran sebelumnya.
|
||||
|
||||
### Tambah pendengar
|
||||
|
||||
Seterusnya, tambahkan pendengar acara ke formulir dan butang kosong yang mengatur ulang borang, sehingga jika pengguna menyerahkan borang atau mengklik butang set semula itu, sesuatu akan terjadi, dan tambahkan panggilan untuk menginisialisasi aplikasi di bahagian bawah fail:
|
||||
|
||||
```JavaScript
|
||||
form.addEventListener('submit', (e) => handleSubmit(e));
|
||||
clearBtn.addEventListener('click', (e) => reset(e));
|
||||
init();
|
||||
```
|
||||
|
||||
✅ Perhatikan singkatan yang digunakan untuk mendengarkan acara kirim atau klik, dan bagaimana peristiwa itu diteruskan ke pemegang Fungsi hantar atau set semula. Bolehkah anda menulis setara dengan singkatan ini dalam format yang lebih panjang? Yang mana satu pilihan anda?
|
||||
|
||||
### Bangun fungsi init() dan fungsi reset():
|
||||
|
||||
Sekarang anda akan membina fungsi yang menginisialisasi pelanjutan, yang dipanggil init():
|
||||
|
||||
```JavaScript
|
||||
function init() {
|
||||
//jika ada di localStorage
|
||||
const storedApiKey = localStorage.getItem('apiKey');
|
||||
const storedRegion = localStorage.getItem('regionName');
|
||||
|
||||
//tetapkan ikon menjadi hijau generik
|
||||
//todo
|
||||
|
||||
if (storedApiKey === null || storedRegion === null) {
|
||||
//jika kami tidak mempunyai kunci, tunjukkan borangnya
|
||||
form.style.display = 'block';
|
||||
results.style.display = 'none';
|
||||
loading.style.display = 'none';
|
||||
clearBtn.style.display = 'none';
|
||||
errors.textContent = '';
|
||||
} else {
|
||||
//jika kita telah menyimpan kunci / kawasan di localStorage, tunjukkan hasilnya ketika dimuat
|
||||
displayCarbonUsage(storedApiKey, storedRegion);
|
||||
results.style.display = 'none';
|
||||
form.style.display = 'none';
|
||||
clearBtn.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
function reset(e) {
|
||||
e.preventDefault();
|
||||
//kosongkan simpanan tempatan untuk wilayah sahaja
|
||||
localStorage.removeItem('regionName');
|
||||
init();
|
||||
}
|
||||
|
||||
```
|
||||
Dalam fungsi ini, terdapat beberapa logik yang menarik. Bacalah, anda dapat melihat apa yang berlaku?
|
||||
|
||||
- dua `const` disiapkan untuk memeriksa sama ada pengguna telah menyimpan kod APIKey dan wilayah di storan tempatan.
|
||||
- jika salah satu daripadanya adalah nol, tunjukkan borang dengan mengubah gaya untuk ditampilkan sebagai 'blok'
|
||||
- sembunyikan hasilnya, muat, dan clearBtn dan tetapkan teks ralat ke rentetan kosong
|
||||
- jika ada kunci dan wilayah, mulailah rutin untuk:
|
||||
- hubungi API untuk mendapatkan data penggunaan karbon
|
||||
- menyembunyikan kawasan hasil
|
||||
- sembunyikan borang
|
||||
- tunjukkan butang set semula
|
||||
|
||||
Sebelum meneruskan, berguna untuk mengetahui konsep yang sangat penting yang terdapat dalam penyemak imbas: [LocalStorage] https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). LocalStorage adalah cara yang berguna untuk menyimpan rentetan dalam penyemak imbas sebagai pasangan `kunci-nilai` . Jenis storan web ini dapat dimanipulasi oleh JavaScript untuk menguruskan data di penyemak imbas. LocalStorage tidak akan habis masa berlakunya, sementara SessionStorage, jenis penyimpanan web lain, akan dihapus apabila penyemak imbas ditutup. Pelbagai jenis storan mempunyai kebaikan dan keburukan terhadap penggunaannya.
|
||||
|
||||
> Catatan - pelanjutan penyemak imbas anda mempunyai storan tempatan sendiri; tetingkap penyemak imbas utama adalah contoh yang berbeza dan berkelakuan secara berasingan.
|
||||
|
||||
Anda menetapkan APIKey anda agar mempunyai nilai rentetan, misalnya, dan anda dapat melihatnya diatur di Edge dengan "memeriksa" laman web (anda boleh mengklik kanan penyemak imbas untuk memeriksa) dan pergi ke tab Aplikasi untuk melihat penyimpanan.
|
||||
|
||||
![Local sotrage pane](../images/localstorage.png)
|
||||
|
||||
✅ Fikirkan situasi di mana anda TIDAK mahu menyimpan beberapa data di LocalStorage. Secara umum, meletakkan Kunci API di LocalStorage adalah idea yang tidak baik! Bolehkah anda melihat mengapa? Dalam kes kami, kerana aplikasi kami adalah semata-mata untuk belajar dan tidak akan digunakan ke kedai aplikasi, kami akan menggunakan kaedah ini.
|
||||
|
||||
Perhatikan bahawa anda menggunakan Web API untuk memanipulasi LocalStorage, baik dengan menggunakan `getItem()`, `setItem()` atau `removeItem()`. Ia disokong secara meluas di penyemak imbas.
|
||||
|
||||
Sebelum membina fungsi `displayCarbonUsage()` yang dipanggil di `init()`, mari kita bina fungsi untuk menangani penyerahan borang awal.
|
||||
|
||||
### Mengendalikan penghantaran borang
|
||||
|
||||
Buat fungsi yang disebut `handleSubmit` yang menerima argumen peristiwa `(e)`. Hentikan peristiwa daripada menyebarkan (dalam hal ini, kami ingin menghentikan penyemak imbas menyegarkan) dan panggil fungsi baru, `setUpUser`, meneruskan argumen `apiKey.value` dan `region.value`. Dengan cara ini, anda menggunakan dua nilai yang dibawa melalui bentuk awal apabila medan yang sesuai diisi.
|
||||
|
||||
```JavaScript
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
setUpUser(apiKey.value, region.value);
|
||||
}
|
||||
```
|
||||
✅ Refresh memori anda - HTML yang anda tetapkan dalam pelajaran terakhir mempunyai dua medan input yang `value` nya ditangkap melalui `const` yang anda tetapkan di bahagian atas fail, dan keduanya `required` sehingga penyemak imbas berhenti pengguna daripada memasukkan nilai nol.
|
||||
|
||||
### Sediakan pengguna
|
||||
|
||||
Beralih ke fungsi `setUpUser`, di sinilah anda menetapkan nilai penyimpanan tempatan untuk apiKey dan regionName. Tambahkan fungsi baru:
|
||||
|
||||
```JavaScript
|
||||
function setUpUser(apiKey, regionName) {
|
||||
localStorage.setItem('apiKey', apiKey);
|
||||
localStorage.setItem('regionName', regionName);
|
||||
loading.style.display = 'block';
|
||||
errors.textContent = '';
|
||||
clearBtn.style.display = 'block';
|
||||
//buat panggilan awal
|
||||
displayCarbonUsage(apiKey, regionName);
|
||||
}
|
||||
```
|
||||
Fungsi ini menetapkan mesej memuat untuk ditunjukkan semasa API dipanggil. Pada ketika ini, anda telah berjaya membuat fungsi terpenting pelanjutan penyemak imbas ini!
|
||||
|
||||
### Paparkan Penggunaan Karbon
|
||||
|
||||
Sebelum melangkah lebih jauh, kita harus membincangkan API. API, atau [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html), adalah elemen penting dari kotak alat pembangun web. Mereka menyediakan cara standard untuk program berinteraksi dan saling berinteraksi antara satu sama lain. Sebagai contoh, jika anda membuat laman web yang perlu membuat pertanyaan pada pangkalan data, seseorang mungkin telah membuat API untuk anda gunakan. Walaupun terdapat banyak jenis API, salah satu yang paling popular adalah [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
|
||||
|
||||
✅ Istilah 'REST' adalah singkatan dari 'Representational State Transfer' dan ciri menggunakan URL yang dikonfigurasikan dengan pelbagai untuk mengambil data. Lakukan sedikit kajian mengenai pelbagai jenis API yang tersedia untuk pembangun. Format apa yang menarik bagi anda?
|
||||
|
||||
Terdapat perkara penting yang perlu diperhatikan mengenai fungsi ini. Perhatikan dahulu kata kunci [`async` kata kunci](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). Menulis fungsi anda supaya mereka berjalan secara tidak segerak bermakna mereka menunggu tindakan, seperti data yang dikembalikan, diselesaikan sebelum meneruskan.
|
||||
|
||||
Inilah video ringkas mengenai `async`:
|
||||
|
||||
[![Async dan Await untuk menguruskan promises](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async dan Await untuk menguruskan promises")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai async/await.
|
||||
|
||||
Buat fungsi baru untuk meminta API C02Signal:
|
||||
|
||||
```JavaScript
|
||||
import axios from '../node_modules/axios';
|
||||
|
||||
async function displayCarbonUsage(apiKey, region) {
|
||||
try {
|
||||
await axios
|
||||
.get('https://api.co2signal.com/v1/latest', {
|
||||
params: {
|
||||
countryCode: region,
|
||||
},
|
||||
headers: {
|
||||
'auth-token': apiKey,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
let CO2 = Math.floor(response.data.data.carbonIntensity);
|
||||
|
||||
//calculateColor(CO2);
|
||||
|
||||
loading.style.display = 'none';
|
||||
form.style.display = 'none';
|
||||
myregion.textContent = region;
|
||||
usage.textContent =
|
||||
Math.round(response.data.data.carbonIntensity) + ' grams (grams C02 emitted per kilowatt hour)';
|
||||
fossilfuel.textContent =
|
||||
response.data.data.fossilFuelPercentage.toFixed(2) +
|
||||
'% (percentage of fossil fuels used to generate electricity)';
|
||||
results.style.display = 'block';
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
loading.style.display = 'none';
|
||||
results.style.display = 'none';
|
||||
errors.textContent = 'Sorry, we have no data for the region you have requested.';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ini adalah fungsi besar. Apa yang berlaku di sini?
|
||||
|
||||
- mengikuti amalan terbaik, anda menggunakan kata kunci `async` untuk menjadikan fungsi ini berkelakuan tidak segerak. Fungsi tersebut mengandungi blok `try/catch` kerana akan mengembalikan janji ketika API mengembalikan data. Oleh kerana anda tidak mempunyai kawalan terhadap kelajuan yang akan ditanggapi oleh API (ia sama sekali tidak bertindak balas!), Anda perlu mengatasi ketidakpastian ini dengan memanggilnya secara tidak segerak.
|
||||
- anda meminta API co2signal untuk mendapatkan data wilayah anda, menggunakan Kunci API anda. Untuk menggunakan kunci itu, anda mesti menggunakan jenis pengesahan dalam parameter tajuk anda.
|
||||
- setelah API bertindak balas, anda menetapkan pelbagai elemen data responsnya ke bahagian-bahagian skrin yang anda siapkan untuk menunjukkan data ini.
|
||||
- jika ada ralat, atau jika tidak ada hasil, anda akan menunjukkan mesej ralat.
|
||||
|
||||
✅ Menggunakan corak pengaturcaraan tak segerak adalah alat lain yang sangat berguna dalam kotak alat anda. Baca untuk[mengenai pelbagai cara](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) anda boleh mengkonfigurasi jenis kod ini.
|
||||
|
||||
Tahniah! Sekiranya anda membina pelanjutan anda (`npm run build`) dan menyegarkannya di panel pelanjutan anda, anda mempunyai sambungan yang berfungsi! Satu-satunya perkara yang tidak berfungsi ialah ikon, dan anda akan memperbaikinya pada pelajaran seterusnya.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Kami telah membincangkan beberapa jenis API setakat ini dalam pelajaran ini. Pilih API web dan teliti secara mendalam apa yang ditawarkannya. Sebagai contoh, perhatikan API yang tersedia dalam penyemak imbas seperti [HTML Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API). Apa yang menjadikan API hebat pada pendapat anda?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/26)
|
||||
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Anda belajar mengenai LocalStorage dan API dalam pelajaran ini, keduanya sangat berguna untuk pembangun web profesional. Bolehkah anda berfikir bagaimana kedua-dua perkara ini berfungsi bersama? Fikirkan bagaimana anda akan membina laman web yang akan menyimpan item yang akan digunakan oleh API.
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Menggunakan API](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Menggunakan API
|
||||
|
||||
## Arahan
|
||||
|
||||
API sangat menyeronokkan untuk dimainkan. Berikut adalah [senarai banyak percuma](https://github.com/public-apis/public-apis). Pilih dan API, dan buat pelanjutan penyemak imbas yang menyelesaikan masalah. Masalah kecil mungkin kerana tidak mempunyai gambar haiwan peliharaan yang cukup (jadi, cubalah [API CEO anjing](https://dog.ceo/dog-api/)) atau sesuatu yang lebih besar - bersenang-senang!
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | -------------------------------------------------------------------------- | ---------------------------------------- | ----------------------- |
|
||||
| | Pelanjutan penyemak imbas yang lengkap dihantar menggunakan API dari senarai di atas | Pelanjutan penyemak imbas separuh dihantar | Penyerahan mempunyai pepijat |
|
@ -0,0 +1,160 @@
|
||||
# Projek Pelanjutan Penyemak Imbas Bahagian 3: Ketahui mengenai Tugas dan Prestasi Latar Belakang
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/27)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Dalam dua pelajaran terakhir modul ini, anda belajar bagaimana membuat borang dan kawasan paparan untuk data yang diambil dari API. Ini adalah kaedah yang sangat standard untuk membuat kehadiran web di web. Anda juga belajar bagaimana menangani pengambilan data secara tidak serentak. Sambungan penyemak imbas anda hampir selesai.
|
||||
|
||||
Masih perlu untuk menguruskan beberapa tugas latar belakang, termasuk menyegarkan warna ikon pelanjutan, jadi ini adalah masa yang tepat untuk membincangkan bagaimana penyemak imbas menguruskan tugas seperti ini. Mari fikirkan tugas penyemak imbas ini dalam konteks prestasi aset web anda semasa anda membuatnya.
|
||||
|
||||
## Asas Prestasi Web
|
||||
|
||||
> "Prestasi laman web adalah mengenai dua perkara: seberapa pantas halaman dimuat, dan seberapa pantas kod di dalamnya berjalan." - [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
|
||||
|
||||
Topik bagaimana membuat laman web anda sangat cepat di semua jenis peranti, untuk semua jenis pengguna, dalam semua jenis situasi, sangat mengejutkan. Berikut adalah beberapa perkara yang perlu diingat semasa anda membina projek web standard atau pelanjutan penyemak imbas.
|
||||
|
||||
Perkara pertama yang perlu anda lakukan untuk memastikan laman web anda berjalan dengan cekap adalah mengumpulkan data mengenai prestasinya. Tempat pertama untuk melakukan ini adalah dengan alat pembangun penyemak imbas web anda. Di Edge, anda boleh memilih butang "Tetapan dan lain-lain" (ikon tiga titik di kanan atas penyemak imbas), kemudian arahkan ke Lebih Banyak Alat> Alat Pembangun dan buka tab Prestasi. Anda juga boleh menggunakan pintasan papan kekunci `Ctrl` + `Shift` + `I` pada Windows, atau `Option` + `Command` + `I` di Mac untuk membuka alat pembangun.
|
||||
|
||||
Tab Prestasi mengandungi alat Profil. Buka laman web (cuba, misalnya, https://www.microsoft.com) dan klik butang 'Rakam', kemudian muat semula laman web tersebut. Hentikan rakaman pada bila-bila masa, dan anda akan dapat melihat rutin yang dihasilkan untuk 'script', 'render', dan 'cat' laman web ini:
|
||||
|
||||
![Edge profiler](../images/profiler.png)
|
||||
|
||||
✅ Lawati [Microsoft Documentation](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/performance) pada panel Performance di Edge
|
||||
|
||||
> Petua: untuk mendapatkan bacaan sebenar mengenai masa permulaan laman web anda, kosongkan cache penyemak imbas anda
|
||||
|
||||
Pilih elemen garis masa profil untuk memperbesar peristiwa yang berlaku semasa halaman anda dimuat.
|
||||
|
||||
Dapatkan gambaran prestasi halaman anda dengan memilih bahagian garis masa profil dan melihat panel ringkasan:
|
||||
|
||||
![Tangkapan Edge profiler](../images/snapshot.png)
|
||||
|
||||
Periksa panel Log Peristiwa untuk melihat apakah ada acara yang mengambil masa lebih dari 15 ms
|
||||
|
||||
![Edge event log](../images/log.png)
|
||||
|
||||
✅ Kenali profiler anda! Buka alat pembangun di laman web ini dan lihat apakah ada kesulitan. Apakah aset pemuatan paling lambat? Paling pantas?
|
||||
|
||||
## Pemeriksaan profil
|
||||
|
||||
Secara umum ada beberapa "masalah" yang harus diperhatikan oleh setiap pembangun web ketika membangun laman web, untuk mengelakkan kejutan buruk ketika tiba waktunya untuk digunakan.
|
||||
|
||||
**Saiz aset**: Web menjadi 'lebih berat', dan dengan itu lebih perlahan, sejak beberapa tahun kebelakangan. Sebilangan berat ini ada kaitannya dengan penggunaan gambar.
|
||||
|
||||
✅ Lihat melalui [Arkib Internet](https://httparchive.org/reports/page-weight) untuk melihat sejarah berat halaman dan banyak lagi.
|
||||
|
||||
Amalan yang baik adalah memastikan gambar anda dioptimumkan, disampaikan pada ukuran dan resolusi yang tepat untuk pengguna anda.
|
||||
|
||||
**DOM traversals**: Penyemak imbas harus membina Model Objek Dokumennya berdasarkan kod yang anda tulis, jadi demi prestasi halaman yang baik untuk memastikan tag anda minimum, hanya menggunakan dan menggayakan apa yang diperlukan oleh halaman. Hingga saat ini, lebihan CSS yang dikaitkan dengan halaman dapat dioptimumkan; gaya yang hanya perlu digunakan pada satu halaman tidak perlu disertakan dalam helaian gaya utama, misalnya.
|
||||
|
||||
**JavaScript**: Setiap pengembang JavaScript harus menonton skrip 'render-blocking' yang mesti dimuat sebelum sisa DOM dapat dilalui dan dicat ke penyemak imbas. Pertimbangkan untuk menggunakan `defer` dengan skrip sebaris anda (seperti yang dilakukan dalam modul Terrarium).
|
||||
|
||||
✅ Cubalah beberapa laman web di [laman web Uji Kelajuan Web](https://www.webpagetest.org/) untuk mengetahui lebih lanjut mengenai pemeriksaan biasa yang dilakukan untuk menentukan prestasi laman web.
|
||||
|
||||
Setelah anda mempunyai idea tentang bagaimana penyemak imbas memberikan aset yang anda hantar kepadanya, mari kita lihat beberapa perkara terakhir yang perlu anda lakukan untuk menyelesaikan peluasan anda:
|
||||
|
||||
### Buat fungsi untuk mengira warna
|
||||
|
||||
Bekerja di `/src/index.js`, tambahkan fungsi yang disebut `calculColor ()` setelah rangkaian pemboleh ubah `const` yang anda tetapkan untuk mendapatkan akses ke DOM:
|
||||
|
||||
```JavaScript
|
||||
function calculateColor(value) {
|
||||
let co2Scale = [0, 150, 600, 750, 800];
|
||||
let colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02'];
|
||||
|
||||
let closestNum = co2Scale.sort((a, b) => {
|
||||
return Math.abs(a - value) - Math.abs(b - value);
|
||||
})[0];
|
||||
console.log(value + ' is closest to ' + closestNum);
|
||||
let num = (element) => element > closestNum;
|
||||
let scaleIndex = co2Scale.findIndex(num);
|
||||
|
||||
let closestColor = colors[scaleIndex];
|
||||
console.log(scaleIndex, closestColor);
|
||||
|
||||
chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } });
|
||||
}
|
||||
```
|
||||
|
||||
Apa yang berlaku di sini? Anda memasukkan nilai (intensiti karbon) dari panggilan API yang anda selesaikan pada pelajaran terakhir, dan kemudian anda mengira seberapa dekat nilainya dengan indeks yang disajikan dalam array warna. Kemudian anda menghantar nilai warna yang paling hampir ke masa krom.
|
||||
|
||||
The chrome.runtime mempunyai [API](https://developer.chrome.com/extensions/runtime) yang menangani semua jenis tugas latar belakang, dan pelanjutan anda memanfaatkan:
|
||||
|
||||
> "Gunakan API chrome.runtime untuk mengambil halaman latar belakang, mengembalikan butiran tentang manifes, dan mendengarkan dan menanggapi peristiwa dalam aplikasi atau kitaran hayat pelanjutan. Anda juga dapat menggunakan API ini untuk menukar jalur relatif URL menjadi sepenuhnya- URL yang berkelayakan."
|
||||
|
||||
✅ Sekiranya anda mengembangkan pelanjutan penyemak imbas ini untuk Edge, mungkin mengejutkan anda bahawa anda menggunakan API krom. Versi penyemak imbas Edge yang lebih baru dijalankan pada enjin penyemak imbas Chromium, jadi anda dapat memanfaatkan alat ini.
|
||||
|
||||
> Perhatikan, jika anda ingin membuat profil pelanjutan penyemak imbas, lancarkan alat dev dari dalam pelanjutan itu sendiri, kerana ia adalah contoh penyemak imbas tersendiri.
|
||||
|
||||
### Tetapkan warna ikon lalai
|
||||
|
||||
Sekarang, dalam fungsi `init()`, tetapkan ikon menjadi hijau generik untuk dimulakan dengan memanggil sekali lagi tindakan `updateIcon` chrome:
|
||||
|
||||
```JavaScript
|
||||
chrome.runtime.sendMessage({
|
||||
action: 'updateIcon',
|
||||
value: {
|
||||
color: 'green',
|
||||
},
|
||||
});
|
||||
```
|
||||
### Panggil fungsi, laksanakan panggilan
|
||||
|
||||
Seterusnya, panggil fungsi yang baru anda buat dengan menambahkannya pada janji yang dikembalikan oleh C02Signal API:
|
||||
|
||||
```JavaScript
|
||||
//let CO2...
|
||||
calculateColor(CO2);
|
||||
```
|
||||
|
||||
Dan akhirnya, di `/dist/background.js`, tambahkan pendengar untuk panggilan tindakan latar ini:
|
||||
|
||||
```JavaScript
|
||||
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
|
||||
if (msg.action === 'updateIcon') {
|
||||
chrome.browserAction.setIcon({ imageData: drawIcon(msg.value) });
|
||||
}
|
||||
});
|
||||
//dipinjam dari pelanjutan lollipop, ciri menarik
|
||||
function drawIcon(value) {
|
||||
let canvas = document.createElement('canvas');
|
||||
let context = canvas.getContext('2d');
|
||||
|
||||
context.beginPath();
|
||||
context.fillStyle = value.color;
|
||||
context.arc(100, 100, 50, 0, 2 * Math.PI);
|
||||
context.fill();
|
||||
|
||||
return context.getImageData(50, 50, 100, 100);
|
||||
}
|
||||
```
|
||||
Dalam kod ini, anda menambahkan pendengar untuk sebarang mesej yang datang ke pengurus tugas backend. Sekiranya disebut 'updateIcon', maka kod seterusnya dijalankan, untuk menggambar ikon warna yang tepat menggunakan Canvas API.
|
||||
|
||||
✅ Anda akan mengetahui lebih lanjut mengenai Canvas API dalam [pelajaran Space Game](../../space-game/drawing-to-canvas/README.md).
|
||||
|
||||
Sekarang, buat semula pelanjutan anda (`npm run build`), muat semula dan lancarkan peluasan anda, dan perhatikan perubahan warnanya. Adakah masa yang sesuai untuk menjalankan tugas atau mencuci pinggan? Sekarang anda tahu!
|
||||
|
||||
Tahniah, anda telah membina pelanjutan penyemak imbas yang berguna dan mengetahui lebih lanjut mengenai cara penyemak imbas berfungsi dan bagaimana profil prestasinya.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Selidiki beberapa laman web sumber terbuka telah lama wujud, dan, berdasarkan sejarah GitHub mereka, lihat apakah anda dapat menentukan bagaimana mereka dioptimumkan selama bertahun-tahun untuk prestasi, jika tidak. Apakah titik kesakitan yang paling biasa?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/28)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Pertimbangkan untuk mendaftar ke [buletin prestasi](https://perf.email/)
|
||||
|
||||
Selidiki beberapa cara penyemak imbas mengukur prestasi web dengan melihat tab prestasi di alat web mereka. Adakah anda menemui perbezaan besar?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Menganalisis laman web untuk prestasi](assignment.ms.md)
|
@ -0,0 +1,9 @@
|
||||
# Menganalisis laman web untuk prestasi
|
||||
|
||||
Berikan laporan terperinci dari laman web, menunjukkan kawasan di mana prestasi bermasalah. Analisis mengapa laman web ini perlahan dan apa yang anda boleh lakukan untuk mempercepatnya. Jangan hanya bergantung pada alat penyemak imbas, tetapi lakukan kajian mengenai alat lain yang dapat membantu laporan anda
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------- | --------------------------- | ----------------------------- |
|
||||
| | Laporan disajikan dengan perincian yang diambil bukan hanya dari alat penyemak imbas tetapi dari alat pihak ketiga jika ada | Laporan asas dibentangkan | Laporan minimum dibentangkan |
|
@ -0,0 +1,27 @@
|
||||
# Sambungan Penyemak Imbas Carbon Trigger: Kod Lengkap
|
||||
|
||||
Menggunakan API Isyarat C02 tmrow untuk mengesan penggunaan elektrik, bina pelanjutan penyemak imbas sehingga anda dapat memperoleh peringatan di penyemak imbas anda tentang betapa berat penggunaan elektrik wilayah anda. Menggunakan pelanjutan ini secara khusus akan membantu anda membuat pertimbangan mengenai aktiviti anda berdasarkan maklumat ini.
|
||||
|
||||
![tangkapan pelanjutan penyemak imbas](../../extension-screenshot.png)
|
||||
|
||||
## Bermula Dari Sini
|
||||
|
||||
Anda perlu memasang [npm] (https://npmjs.com). Muat turun salinan kod ini ke folder di komputer anda.
|
||||
|
||||
Pasang semua pakej yang diperlukan:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Bina pelanjutan dari webpack
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Untuk memasang di Edge, gunakan menu 'tiga titik' di sudut kanan atas penyemak imbas untuk mencari panel Sambungan. Dari sana, pilih 'Load Unpacked' untuk memuat sambungan baru. Buka folder 'dist' pada permintaan dan pelanjutan akan dimuat. Untuk menggunakannya, anda memerlukan kunci API untuk API Isyarat CO2 ([dapatkan satu di sini melalui e-mel](https://www.co2signal.com/) - masukkan e-mel anda di dalam kotak di halaman ini) dan [kod untuk wilayah anda](http://api.electricitymap.org/v3/zones) yang sesuai dengan [Peta Elektrik](https://www.electricitymap.org/map) (di Boston, misalnya, saya menggunakan 'US- NEISO').
|
||||
|
||||
![sedang memuat turun](../../install-on-edge.png)
|
||||
|
||||
Setelah kunci API dan wilayah dimasukkan ke antara muka peluasan, titik berwarna di bar pelanjutan penyemak imbas akan berubah untuk mencerminkan penggunaan tenaga wilayah anda dan memberi anda petunjuk mengenai aktiviti berat yang sesuai untuk anda lakukan. Konsep di sebalik sistem 'dot' ini diberikan kepada saya oleh [pelanjutan penyemak imbas Lollipop Tenaga](https://energylollipop.com/) untuk pelepasan California.
|
@ -0,0 +1,27 @@
|
||||
# Pelanjutan Penyemak Imbas Carbon Trigger: Starter Code
|
||||
|
||||
Menggunakan API Isyarat C02 tmrow untuk mengesan penggunaan elektrik, bina pelanjutan penyemak imbas sehingga anda dapat memperoleh peringatan di penyemak imbas anda tentang betapa berat penggunaan elektrik wilayah anda. Menggunakan pelanjutan ini secara khusus akan membantu anda membuat pertimbangan mengenai aktiviti anda berdasarkan maklumat ini.
|
||||
|
||||
![tangkapan penyemak imbas](../../extension-screenshot.png)
|
||||
|
||||
## Bermula Dari Sini
|
||||
|
||||
Anda perlu memasang [npm](https://npmjs.com). Muat turun salinan kod ini ke folder di komputer anda.
|
||||
|
||||
Pasang semua pakej yang diperlukan:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Bina pelanjutan dari webpack
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Untuk memasang di Edge, gunakan menu 'tiga titik' di sudut kanan atas penyemak imbas untuk mencari panel Sambungan. Dari sana, pilih 'Load Unpacked' untuk memuat sambungan baru. Buka folder 'dist' pada permintaan dan pelanjutan akan dimuat. Untuk menggunakannya, anda memerlukan kunci API untuk API Isyarat CO2 ([dapatkan satu di sini melalui e-mel](https://www.co2signal.com/) - masukkan e-mel anda di dalam kotak di halaman ini) dan [kod untuk wilayah anda](http://api.electricitymap.org/v3/zones) yang sesuai dengan [Peta Elektrik](https://www.electricitymap.org/map) (di Boston, misalnya, saya menggunakan 'US- NEISO').
|
||||
|
||||
![sedang memuat turun](../../install-on-edge.png)
|
||||
|
||||
Setelah kunci API dan wilayah dimasukkan ke antara muka peluasan, titik berwarna di bar pelanjutan penyemak imbas akan berubah untuk mencerminkan penggunaan tenaga wilayah anda dan memberi anda petunjuk mengenai aktiviti berat yang sesuai untuk anda lakukan. Konsep di sebalik sistem 'dot' ini diberikan kepada saya oleh [pelanjutan penyemak imbas Lollipop Tenaga](https://energylollipop.com/) untuk pelepasan California.
|
@ -0,0 +1,224 @@
|
||||
# Membina Permainan Angkasa Bahagian 1: Pengenalan
|
||||
|
||||
![video](../../images/pewpew.gif)
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/29)
|
||||
|
||||
### Warisan dan Komposisi dalam pembangunan permainan
|
||||
|
||||
Dalam pelajaran sebelumnya, tidak banyak yang perlu dikhawatirkan mengenai reka bentuk reka bentuk aplikasi yang anda buat, kerana skop projeknya sangat kecil. Namun, apabila aplikasi anda bertambah besar dan luas, keputusan seni bina menjadi perhatian yang lebih besar. Terdapat dua pendekatan utama untuk membuat aplikasi yang lebih besar dalam JavaScript: *komposisi* atau *pewarisan*. Terdapat kebaikan dan keburukan untuk kedua-duanya tetapi mari kita jelaskan dari dalam konteks permainan.
|
||||
|
||||
✅ Salah satu buku pengaturcaraan paling terkenal yang pernah ditulis ada kaitannya dengan [corak reka bentuk](https://en.wikipedia.org/wiki/Design_Patterns).
|
||||
|
||||
Dalam permainan, anda mempunyai `objek permainan` yang merupakan objek yang ada di layar. Ini bermakna mereka mempunyai lokasi pada sistem koordinat kartesian, yang dicirikan oleh mempunyai koordinat `x` dan `y`. Semasa anda mengembangkan permainan, anda akan melihat bahawa semua objek permainan anda mempunyai harta benda yang biasa, biasa untuk setiap permainan yang anda buat, iaitu elemen yang:
|
||||
|
||||
- **berdasarkan lokasi** Sebilangan besar, jika tidak semua, elemen permainan berdasarkan lokasi. Ini bermaksud bahawa mereka mempunyai lokasi, `x` dan` y`.
|
||||
- **bergerak** Ini adalah objek yang boleh berpindah ke lokasi baru. Ini biasanya pahlawan, raksasa atau NPC (watak bukan pemain), tetapi tidak misalnya, objek statik seperti pokok.
|
||||
- **merosakkan diri** Objek-objek ini hanya wujud untuk jangka masa yang ditetapkan sebelum mereka disiapkan untuk dihapus. Biasanya ini diwakili oleh boolean `mati` atau `dimusnahkan` yang memberi isyarat kepada mesin permainan bahawa objek ini tidak lagi boleh diberikan.
|
||||
- **cool-down** 'Cool-down' adalah sifat khas di antara objek yang berumur pendek. Contoh biasa ialah sekeping teks atau kesan grafik seperti letupan yang hanya dapat dilihat selama beberapa milisaat.
|
||||
|
||||
✅ Fikirkan permainan seperti Pac-Man. Bolehkah anda mengenal pasti empat jenis objek yang disenaraikan di atas dalam permainan ini?
|
||||
|
||||
### Menyatakan tingkah laku
|
||||
|
||||
Yang kami terangkan di atas adalah tingkah laku yang boleh dimiliki oleh objek permainan. Jadi bagaimana kita mengekodkannya? Kita boleh menyatakan tingkah laku ini sebagai kaedah yang berkaitan dengan kelas atau objek.
|
||||
|
||||
**Kelas**
|
||||
|
||||
Ideanya adalah untuk menggunakan `kelas` bersama dengan `pewarisan` untuk menyelesaikan penambahan tingkah laku tertentu ke kelas.
|
||||
|
||||
✅ Warisan adalah konsep penting untuk difahami. Ketahui lebih lanjut mengenai [artikel MDN mengenai pewarisan](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
|
||||
|
||||
Diekspresikan melalui kod, objek permainan biasanya dapat terlihat seperti ini:
|
||||
|
||||
```javascript
|
||||
|
||||
//menubuhkan kelas GameObject
|
||||
class GameObject {
|
||||
constructor(x, y, type) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
//kelas ini akan memperluaskan sifat kelas yang ada pada GameObject
|
||||
class Movable extends GameObject {
|
||||
constructor(x,y, type) {
|
||||
super(x,y, type)
|
||||
}
|
||||
|
||||
//objek bergerak ini dapat dipindahkan di skrin
|
||||
moveTo(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
//ini adalah kelas khusus yang meluaskan kelas Bergerak, sehingga dapat memanfaatkan semua sifat yang diwarisi
|
||||
class Hero extends Movable {
|
||||
constructor(x,y) {
|
||||
super(x,y, 'Hero')
|
||||
}
|
||||
}
|
||||
|
||||
//kelas ini, sebaliknya, hanya mewarisi sifat GameObject
|
||||
class Tree extends GameObject {
|
||||
constructor(x,y) {
|
||||
super(x,y, 'Tree')
|
||||
}
|
||||
}
|
||||
|
||||
//hero dapat bergerak...
|
||||
const hero = new Hero();
|
||||
hero.moveTo(5,5);
|
||||
|
||||
//tetapi pokok tidak boleh
|
||||
const tree = new Tree();
|
||||
```
|
||||
|
||||
✅ Luangkan masa beberapa minit untuk membayangkan semula pahlawan Pac-Man (misalnya Inky, Pinky atau Blinky) dan bagaimana ia ditulis dalam JavaScript.
|
||||
|
||||
**Komposisi**
|
||||
|
||||
Cara yang berbeza untuk menangani pewarisan objek adalah dengan menggunakan *Komposisi*. Kemudian, objek menyatakan tingkah laku mereka seperti ini:
|
||||
|
||||
```javascript
|
||||
//buat pemalar untuk gameObject
|
||||
const gameObject = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
type: ''
|
||||
};
|
||||
|
||||
//...dan satu constant untuk bergerak
|
||||
const movable = {
|
||||
moveTo(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
//buat pemalar movableObject terdiri daripada pemalar gameObject dan bergerak
|
||||
const movableObject = {...gameObject, ...movable};
|
||||
|
||||
//kemudian buat fungsi untuk membuat Hero baru yang mewarisi sifat movableObject
|
||||
function createHero(x, y) {
|
||||
return {
|
||||
...movableObject,
|
||||
x,
|
||||
y,
|
||||
type: 'Hero'
|
||||
}
|
||||
}
|
||||
//...dan objek statik yang hanya mewarisi sifat gameObject
|
||||
function createStatic(x, y, type) {
|
||||
return {
|
||||
...gameObject
|
||||
x,
|
||||
y,
|
||||
type
|
||||
}
|
||||
}
|
||||
//buat hero dan gerakkannya
|
||||
const hero = createHero(10,10);
|
||||
hero.moveTo(5,5);
|
||||
//dan buat pokok statik yang hanya berdiri
|
||||
const tree = createStatic(0,0, 'Tree');
|
||||
```
|
||||
|
||||
**Corak mana yang harus saya gunakan?**
|
||||
|
||||
Terpulang kepada anda corak yang anda pilih. JavaScript menyokong kedua-dua paradigma ini.
|
||||
|
||||
--
|
||||
|
||||
Pola lain yang biasa dalam pengembangan permainan menangani masalah menangani pengalaman dan prestasi pengguna permainan.
|
||||
|
||||
## Corak pub / sub
|
||||
|
||||
✅ Pub / Sub bermaksud 'publish-subscribe'
|
||||
|
||||
Corak ini mengemukakan idea bahawa bahagian aplikasi anda yang berbeza tidak boleh saling mengenali. Kenapa begitu? Ini menjadikannya lebih mudah untuk melihat apa yang berlaku secara umum jika pelbagai bahagian dipisahkan. Ini juga menjadikannya lebih mudah untuk mengubah tingkah laku secara tiba-tiba jika anda perlu Bagaimana kita mencapainya? Kami melakukan ini dengan mewujudkan beberapa konsep:
|
||||
|
||||
- **mesej**: Mesej biasanya merupakan rentetan teks yang disertai dengan muatan pilihan (sekeping data yang menjelaskan tentang mesej itu) Mesej biasa dalam permainan boleh menjadi `KEY_PRESSED_ENTER`.
|
||||
- **publish**: Elemen ini *menerbitkan* mesej dan mengirimkannya kepada semua pelanggan.
|
||||
- **subscriber**: Elemen ini *mendengar* mesej tertentu dan menjalankan beberapa tugas sebagai hasil daripada menerima mesej ini, seperti menembakkan laser.
|
||||
|
||||
Pelaksanaannya cukup kecil tetapi coraknya sangat kuat. Inilah cara ia dapat dilaksanakan:
|
||||
|
||||
```javascript
|
||||
//sediakan kelas EventEmitter yang mengandungi pendengar
|
||||
class EventEmitter {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
//apabila mesej diterima, biarkan pendengar menangani muatannya
|
||||
on(message, listener) {
|
||||
if (!this.listeners[message]) {
|
||||
this.listeners[message] = [];
|
||||
}
|
||||
this.listeners[message].push(listener);
|
||||
}
|
||||
//semasa mesej dihantar, hantarkannya kepada pendengar dengan muatan
|
||||
emit(message, payload = null) {
|
||||
if (this.listeners[message]) {
|
||||
this.listeners[message].forEach(l => l(message, payload))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Untuk menggunakan kod di atas, kita dapat membuat implementasi yang sangat kecil:
|
||||
|
||||
```javascript
|
||||
//sediakan struktur mesej
|
||||
const Messages = {
|
||||
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT'
|
||||
};
|
||||
//memanggil eventEmitter yang anda tetapkan di atas
|
||||
const eventEmitter = new EventEmitter();
|
||||
//sediakan hero
|
||||
const hero = createHero(0,0);
|
||||
//biarkan eventEmitter tahu untuk menonton mesej yang berkaitan dengan pahlawan yang bergerak ke kiri, dan bertindak di atasnya
|
||||
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
|
||||
hero.move(5,0);
|
||||
});
|
||||
|
||||
//sediakan tetingkap untuk mendengarkan acara keyup, khususnya jika anak panah kiri dipukul, mengirimkan pesan untuk menggerakkan pahlawan ke kiri
|
||||
window.addEventListener('keyup', (evt) => {
|
||||
if (evt.key === 'ArrowLeft') {
|
||||
eventEmitter.emit(Messages.HERO_MOVE_LEFT)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Di atas kami menyambungkan acara papan kekunci, `ArrowLeft` dan menghantar mesej `HERO_MOVE_LEFT`. Kami mendengar mesej itu dan memindahkan `hero` sebagai hasilnya. Kekuatan dengan corak ini ialah pendengar acara dan wira tidak saling mengenali antara satu sama lain. Anda boleh memetakan semula `ArrowLeft` ke kekunci `A`. Selain itu mungkin untuk melakukan sesuatu yang sama sekali berbeza pada `ArrowLeft` dengan membuat beberapa pengeditan pada fungsi `on` eventEmitter:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
|
||||
hero.move(5,0);
|
||||
});
|
||||
```
|
||||
|
||||
Oleh kerana keadaan menjadi lebih rumit semasa permainan anda berkembang, corak ini tetap sama dalam kerumitan dan kod anda tetap bersih. Sangat digalakkan untuk menggunakan corak ini.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Fikirkan bagaimana corak pub-sub dapat meningkatkan permainan. Bahagian mana yang harus memancarkan acara, dan bagaimana reaksi permainan terhadapnya? Inilah peluang anda untuk menjadi kreatif, memikirkan permainan baru dan bagaimana bahagiannya berkelakuan.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/30)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Ketahui lebih lanjut mengenai Pub/Sub dengan [membaca mengenainya](https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Mockup permainan](assignment.ms.md)
|
@ -0,0 +1,12 @@
|
||||
# Mock up permainan
|
||||
|
||||
## Arahan
|
||||
|
||||
Dengan menggunakan contoh kod dalam pelajaran, tulis representasi permainan yang anda nikmati. Ini mestilah permainan yang sederhana, tetapi tujuannya adalah menggunakan kelas atau corak komposisi dan corak pub / sub untuk menunjukkan bagaimana permainan dapat dilancarkan. Dapatkan kreatif!
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria |
|
||||
Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------- |
|
||||
| | Tiga elemen diletakkan di skrin dan dimanipulasi | Dua elemen diletakkan di skrin dan dimanipulasi | Satu elemen diletakkan di skrin dan dimanipulasi |
|
@ -0,0 +1,216 @@
|
||||
# Bina Permainan Angkasa Bahagian 2: Menarik Wira dan Monster ke Kanvas
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/31)
|
||||
|
||||
## Kanvas
|
||||
|
||||
Kanvas adalah elemen HTML yang secara lalai tidak mempunyai isi; itu batu tulis kosong. Anda perlu menambahkannya dengan melukisnya.
|
||||
|
||||
✅ Baca [lebih lanjut mengenai Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) di MDN.
|
||||
|
||||
Inilah cara ia dinyatakan secara umum, sebagai bahagian badan halaman:
|
||||
|
||||
```html
|
||||
<canvas id="myCanvas" width="200" height="100"></canvas>
|
||||
```
|
||||
|
||||
Di atas kita menetapkan `id`, `lebar` dan `tinggi`.
|
||||
|
||||
- `id`: tetapkan ini supaya anda dapat memperoleh rujukan apabila anda perlu berinteraksi dengannya.
|
||||
- `lebar`: ini adalah lebar elemen.
|
||||
- `tinggi`: ini adalah ketinggian elemen.
|
||||
|
||||
## Melukis geometri ringkas
|
||||
|
||||
Canvas menggunakan sistem koordinat kartesian untuk menarik sesuatu. Oleh itu ia menggunakan paksi-x dan paksi-y untuk menyatakan di mana sesuatu berada. Lokasi `0,0` adalah kedudukan kiri atas dan kanan bawah adalah yang anda katakan sebagai Luas dan TINGGI kanvas.
|
||||
|
||||
![grid kanvas](../canvas_grid.png)
|
||||
> Imej dari [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
|
||||
|
||||
Untuk menggunakan elemen kanvas, anda perlu melalui langkah-langkah berikut:
|
||||
|
||||
1. **Dapatkan rujukan** ke elemen Kanvas.
|
||||
1. **Dapatkan rujukan** pada elemen Konteks yang terletak di elemen kanvas.
|
||||
1. **Lakukan operasi menggambar** menggunakan elemen konteks.
|
||||
|
||||
Kod untuk langkah di atas biasanya kelihatan seperti:
|
||||
|
||||
```javascript
|
||||
// melukis sebuah segi empat tepat berwarna merah
|
||||
// 1. dapatkan rujukan kanvas
|
||||
canvas = document.getElementById("myCanvas");
|
||||
|
||||
//2. tetapkan konteks ke 2D untuk melukis bentuk asas
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
//3. isi dengan warna merah
|
||||
ctx.fillStyle = 'red';
|
||||
|
||||
//4. dan lukis sebuah segi empat tepat dengan parameter ini, tetapkan lokasi dan ukuran
|
||||
ctx.fillRect(0,0, 200, 200) // x,y,luas,tinggi
|
||||
```
|
||||
|
||||
✅ Canvas API kebanyakannya memfokuskan pada bentuk 2D, tetapi anda juga dapat menarik elemen 3D ke laman web; untuk ini, anda mungkin menggunakan [WebGL API](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API).
|
||||
|
||||
Anda boleh menarik pelbagai perkara dengan Canvas API seperti:
|
||||
|
||||
- **Bentuk geometri**, kami sudah menunjukkan cara melukis segi empat tepat, tetapi masih banyak lagi yang dapat anda lukis.
|
||||
- **Teks**, anda boleh menggambar teks dengan fon dan warna yang anda inginkan.
|
||||
- **Imej**, anda boleh melukis gambar berdasarkan aset gambar seperti .jpg atau .png misalnya.
|
||||
|
||||
✅ Cubalah! Anda tahu melukis segi empat, bolehkah anda melukis bulatan ke halaman? Lihatlah beberapa lukisan Kanvas yang menarik di CodePen. Berikut adalah [contoh yang sangat mengagumkan](https://codepen.io/dissimulate/pen/KrAwx).
|
||||
|
||||
## Muat dan lukiskan aset gambar
|
||||
|
||||
Anda memuat aset gambar dengan membuat objek `Imej` dan menetapkan sifat `src`nya. Kemudian anda mendengar acara `load` untuk mengetahui kapan ia siap digunakan. Kodnya seperti ini:
|
||||
|
||||
### Muatkan aset
|
||||
|
||||
```javascript
|
||||
const img = new Image();
|
||||
img.src = 'path/to/my/image.png';
|
||||
img.onload = () => {
|
||||
// gambar dimuat dan siap digunakan
|
||||
}
|
||||
```
|
||||
|
||||
### Muatkan corak aset
|
||||
|
||||
Sebaiknya bungkus perkara di atas dengan konstruk seperti itu, jadi lebih mudah digunakan dan anda hanya mencuba memanipulasinya apabila dimuat sepenuhnya:
|
||||
|
||||
```javascript
|
||||
function loadAsset(path) {
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image();
|
||||
img.src = path;
|
||||
img.onload = () => {
|
||||
// gambar dimuat dan siap digunakan
|
||||
resolve(img);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// use like so
|
||||
|
||||
async function run() {
|
||||
const heroImg = await loadAsset('hero.png')
|
||||
const monsterImg = await loadAsset('monster.png')
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Untuk menarik aset permainan ke skrin, kod anda akan kelihatan seperti ini:
|
||||
|
||||
```javascript
|
||||
async function run() {
|
||||
const heroImg = await loadAsset('hero.png')
|
||||
const monsterImg = await loadAsset('monster.png')
|
||||
|
||||
canvas = document.getElementById("myCanvas");
|
||||
ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(heroImg, canvas.width/2,canvas.height/2);
|
||||
ctx.drawImage(monsterImg, 0,0);
|
||||
}
|
||||
```
|
||||
|
||||
## Kini tiba masanya untuk mula membina permainan anda
|
||||
|
||||
### Apa yang hendak dibina
|
||||
|
||||
Anda akan membina laman web dengan elemen Canvas. Ia harus menjadikan skrin hitam `1024*768` . Kami telah memberi anda dua gambar:
|
||||
|
||||
- Kapal wira
|
||||
|
||||
![Kapal wira](../solution/assets/player.png)
|
||||
|
||||
- 5 * 5 raksasa
|
||||
|
||||
![Monster ship](solution/assets/enemyShip.png)
|
||||
|
||||
### Langkah-langkah yang disarankan untuk memulakan pembangunan
|
||||
|
||||
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Buka salinan folder ini dalam Visual Studio Code. Anda perlu membuat persediaan persekitaran pembangunan tempatan, lebih baik dengan Visual Studio Code dengan NPM dan Node dipasang. Sekiranya anda tidak memasang `npm` di komputer anda, [berikut cara melakukannya](https://www.npmjs.com/get-npm).
|
||||
|
||||
Mulakan projek anda dengan menavigasi ke folder `your_work`:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamat itu. Ini adalah halaman kosong sekarang, tetapi itu akan berubah
|
||||
|
||||
> Catatan: untuk melihat perubahan pada layar anda, muat semula penyemak imbas anda.
|
||||
|
||||
### Tambah Kod
|
||||
|
||||
Tambahkan kod yang diperlukan ke `your-work / app.js` untuk menyelesaikan perkara di bawah
|
||||
|
||||
1. ** Lukiskan kanvas dengan latar belakang hitam
|
||||
> tip: tambahkan dua baris di bawah TODO yang sesuai di `/ app.js`, tetapkan elemen` ctx` menjadi hitam dan koordinat atas / kiri berada pada 0,0 dan tinggi dan lebarnya sama dengan kanvas .
|
||||
2. ** Muatkan tekstur **
|
||||
> tip: tambahkan gambar pemain dan musuh dengan menggunakan `menunggu loadTexture` dan melewati jalan gambar. Anda belum akan melihatnya di skrin!
|
||||
3. ** Draw ** wira di tengah skrin di bahagian bawah
|
||||
> tip: gunakan API `drawImage` untuk menarik heroImg ke skrin, tetapkan` canvas.width / 2 - 45` dan `canvas.height - canvas.height / 4)`;
|
||||
4. ** Draw ** 5 * 5 monster
|
||||
> tip: Sekarang anda boleh melepaskan kod untuk menarik musuh di layar. Seterusnya, pergi ke fungsi `createEnemies` dan bangunkan.
|
||||
|
||||
Pertama, sediakan beberapa pemalar:
|
||||
|
||||
```javascript
|
||||
const MONSTER_TOTAL = 5;
|
||||
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
|
||||
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
|
||||
const STOP_X = START_X + MONSTER_WIDTH;
|
||||
```
|
||||
|
||||
kemudian, buat gelung untuk menarik susunan monster ke skrin:
|
||||
|
||||
```javascript
|
||||
for (let x = START_X; x < STOP_X; x += 98) {
|
||||
for (let y = 0; y < 50 * 5; y += 50) {
|
||||
ctx.drawImage(enemyImg, x, y);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Keputusan
|
||||
|
||||
Hasil akhirnya akan kelihatan seperti:
|
||||
|
||||
![Skrin hitam dengan wira dan 5 * 5 monster](../partI-solution.png)
|
||||
|
||||
## Penyelesaian
|
||||
|
||||
Cuba selesaikannya sendiri terlebih dahulu tetapi jika anda buntu, lihatlah [solution](../solution/app.js)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Anda telah belajar melukis dengan Canvas API 2D; lihatlah [WebGL API](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API), dan cuba lukis objek 3D.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/32)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Ketahui lebih lanjut mengenai Canvas API dengan [membaca mengenainya](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Main dengan Canvas API](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Main dengan Canvas API
|
||||
|
||||
## Arahan
|
||||
|
||||
Pilih satu elemen API Canvas dan buat sesuatu yang menarik di sekitarnya. Bolehkah anda membuat galaksi kecil bintang berulang? Bolehkah anda membuat tekstur garis berwarna yang menarik? Anda boleh melihat CodePen untuk mendapatkan inspirasi (tetapi jangan menyalin)
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | --------------------------------------------------------- | ----------------------------------- | --------------------- |
|
||||
| | Kod dihantar menunjukkan tekstur atau bentuk yang menarik | Kod dihantar, tetapi tidak dijalankan | Kod tidak dihantar |
|
@ -0,0 +1,388 @@
|
||||
# Bina Permainan Angkasa Bahagian 3: Menambah Gerakan
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/33)
|
||||
|
||||
Permainan tidak begitu menyeronokkan sehingga anda mempunyai makhluk asing di layar! Dalam permainan ini, kami akan menggunakan dua jenis pergerakan:
|
||||
|
||||
- **Pergerakan papan kekunci / Tetikus**: ketika pengguna berinteraksi dengan papan kekunci atau tetikus untuk menggerakkan objek di layar.
|
||||
- **Pergerakan yang disebabkan oleh permainan**: ketika permainan menggerakkan objek dengan selang waktu tertentu.
|
||||
|
||||
Jadi bagaimana kita memindahkan sesuatu di skrin? Ini semua mengenai koordinat kartesian: kami menukar lokasi (x, y) objek dan kemudian melukis semula skrin.
|
||||
|
||||
Biasanya anda memerlukan langkah-langkah berikut untuk menyelesaikan *pergerakan* di skrin:
|
||||
|
||||
1. **Tetapkan lokasi baru** untuk objek; ini diperlukan untuk melihat objek sebagai bergerak.
|
||||
2. **Kosongkan skrin**, skrin perlu dibersihkan di antara undian. Kita dapat membersihkannya dengan melukis sebuah segi empat tepat yang kita isi dengan warna latar belakang.
|
||||
3. **Lukis semula objek** di lokasi baru. Dengan melakukan ini kita akhirnya dapat memindahkan objek dari satu lokasi ke lokasi lain.
|
||||
|
||||
Inilah rupa bentuknya dalam kod:
|
||||
|
||||
```javascript
|
||||
//set the hero's location
|
||||
hero.x += 5;
|
||||
// clear the rectangle that hosts the hero
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// redraw the game background and hero
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.fillStyle = "black";
|
||||
ctx.drawImage(heroImg, hero.x, hero.y);
|
||||
```
|
||||
|
||||
✅ Bolehkah anda memikirkan sebab mengapa menggambar semula pahlawan anda dengan banyak bingkai sesaat mungkin menambah kos prestasi? Baca mengenai [alternatif untuk corak ini](https://www.html5rocks.com/en/tutorials/canvas/performance/).
|
||||
|
||||
## Mengendalikan acara papan kekunci
|
||||
|
||||
Anda mengendalikan acara dengan melampirkan acara tertentu ke kod. Peristiwa papan kekunci dipicu di seluruh tetingkap sedangkan peristiwa tetikus seperti `click` dapat dihubungkan dengan mengklik elemen tertentu. Kami akan menggunakan acara papan kekunci sepanjang projek ini.
|
||||
|
||||
Untuk menangani suatu peristiwa, anda perlu menggunakan kaedah ``addEventListener()` tetingkap dan memberikannya dua parameter input. Parameter pertama adalah nama acara, misalnya `keyup`. Parameter kedua adalah fungsi yang harus dipanggil sebagai akibat dari peristiwa yang berlaku.
|
||||
|
||||
Inilah contohnya:
|
||||
|
||||
```javascript
|
||||
window.addEventListener('keyup', (evt) => {
|
||||
// `evt.key` = string representation of the key
|
||||
if (evt.key === 'ArrowUp') {
|
||||
// do something
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Untuk acara utama terdapat dua sifat pada acara yang boleh anda gunakan untuk melihat kunci apa yang ditekan:
|
||||
|
||||
- `key`, ini adalah representasi rentetan dari kekunci yang ditekan, misalnya `ArrowUp`
|
||||
- `keyCode`, ini adalah representasi angka, misalnya `37`, sesuai dengan `ArrowLeft`.
|
||||
|
||||
✅ Manipulasi acara utama berguna di luar pengembangan permainan. Apa kegunaan lain yang dapat anda fikirkan untuk teknik ini?
|
||||
|
||||
### Kekunci khas: peringatan
|
||||
|
||||
Terdapat beberapa *kunci* khas yang mempengaruhi tetingkap. Ini bermaksud bahawa jika anda sedang mendengar acara `keyup` dan anda menggunakan kekunci khas ini untuk menggerakkan wira anda, ia juga akan melakukan tatal mendatar. Untuk itu anda mungkin mahu *mematikan* tingkah laku penyemak imbas terbina dalam ini semasa anda membina permainan anda. Anda memerlukan kod seperti ini:
|
||||
|
||||
```javascript
|
||||
let onKeyDown = function (e) {
|
||||
console.log(e.keyCode);
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
case 39:
|
||||
case 38:
|
||||
case 40: // Arrow keys
|
||||
case 32:
|
||||
e.preventDefault();
|
||||
break; // Space
|
||||
default:
|
||||
break; // do not block other keys
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
```
|
||||
|
||||
Kod di atas akan memastikan bahawa anak panah dan kekunci spasi mempunyai tingkah laku *lalai* mereka. Mekanisme *shut-off* berlaku apabila kita memanggil `e.preventDefault()`.
|
||||
|
||||
## Pergerakan yang disebabkan oleh permainan
|
||||
|
||||
Kita dapat membuat sesuatu bergerak dengan menggunakan pemasa seperti fungsi `setTimeout()` atau `setInterval()` yang mengemas kini lokasi objek pada setiap centang, atau selang waktu. Begini rupa:
|
||||
|
||||
```javascript
|
||||
let id = setInterval(() => {
|
||||
//move the enemy on the y axis
|
||||
enemy.y += 10;
|
||||
})
|
||||
```
|
||||
|
||||
## Gelung permainan
|
||||
|
||||
Gelung permainan adalah konsep yang pada dasarnya adalah fungsi yang dipanggil pada selang waktu yang tetap. Ia dipanggil gelung permainan kerana segala sesuatu yang dapat dilihat oleh pengguna ditarik ke dalam gelung. Gelung permainan menggunakan semua objek permainan yang menjadi bagian dari permainan, menggambar semuanya kecuali untuk beberapa alasan tidak seharusnya menjadi bagian dari permainan lagi. Contohnya jika objek adalah musuh yang terkena laser dan meletup, ia bukan lagi bahagian dari gelung permainan semasa (anda akan mengetahui lebih lanjut mengenai perkara ini dalam pelajaran berikutnya).
|
||||
|
||||
Inilah rupa gelung permainan, yang dinyatakan dalam kod:
|
||||
|
||||
```javascript
|
||||
let gameLoopId = setInterval(() =>
|
||||
function gameLoop() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawHero();
|
||||
drawEnemies();
|
||||
drawStaticObjects();
|
||||
}, 200);
|
||||
```
|
||||
|
||||
Gelung di atas dipanggil setiap `200` milisaat untuk menggambar semula kanvas. Anda mempunyai kemampuan untuk memilih selang terbaik yang sesuai untuk permainan anda.
|
||||
|
||||
## Meneruskan Permainan Angkasa
|
||||
|
||||
Anda akan mengambil kod yang ada dan memanjangkannya. Mulakan dengan kod yang anda lengkapkan semasa bahagian I atau gunakan kod di [Bahagian II- starter] (karya anda).
|
||||
|
||||
- **Memindahkan pahlawan**: anda akan menambah kod untuk memastikan anda dapat memindahkan pahlawan menggunakan kekunci anak panah.
|
||||
- **Pindahkan musuh**: anda juga perlu menambahkan kod untuk memastikan musuh bergerak dari atas ke bawah pada kadar tertentu.
|
||||
|
||||
## Langkah yang disyorkan
|
||||
|
||||
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Anda memulakan projek anda folder `your_work` dengan mengetik:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamat itu, sekarang ia harus menjadikan pahlawan dan semua musuh; tidak ada yang bergerak - namun!
|
||||
|
||||
### Tambah kod
|
||||
|
||||
1. **Tambahkan objek khusus** untuk `hero` dan `musuh` dan `objek permainan`, mereka harus mempunyai sifat `x` dan `y`. ( Ingat bahagian pada [Warisan atau komposisi](../../translations/README.ms.md) ).
|
||||
|
||||
*HINT* `objek permainan` harus menjadi objek dengan `x` dan `y` dan kemampuan untuk menarik dirinya ke kanvas.
|
||||
|
||||
> tip: mulakan dengan menambahkan kelas GameObject baru dengan konstruktornya digambarkan seperti di bawah, dan kemudian lukiskannya ke kanvas:
|
||||
|
||||
```javascript
|
||||
|
||||
class GameObject {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.dead = false;
|
||||
this.type = "";
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.img = undefined;
|
||||
}
|
||||
|
||||
draw(ctx) {
|
||||
ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Sekarang, panjangkan GameObject ini untuk membuat Wira dan Musuh.
|
||||
|
||||
```javascript
|
||||
class Hero extends GameObject {
|
||||
constructor(x, y) {
|
||||
...it needs an x, y, type, and speed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
class Enemy extends GameObject {
|
||||
constructor(x, y) {
|
||||
super(x, y);
|
||||
(this.width = 98), (this.height = 50);
|
||||
this.type = "Enemy";
|
||||
let id = setInterval(() => {
|
||||
if (this.y < canvas.height - this.height) {
|
||||
this.y += 5;
|
||||
} else {
|
||||
console.log('Stopped at', this.y)
|
||||
clearInterval(id);
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Tambahkan pengendali acara utama** untuk mengendalikan navigasi utama (pusing pahlawan ke atas / bawah kiri / kanan)
|
||||
|
||||
*INGAT* ini adalah sistem kartesian, kiri atas adalah `0,0`. Juga ingat untuk menambah kod untuk menghentikan *tingkah laku lalai*
|
||||
|
||||
> tip: buat fungsi onKeyDown anda dan pasangkannya ke tetingkap:
|
||||
|
||||
```javascript
|
||||
let onKeyDown = function (e) {
|
||||
console.log(e.keyCode);
|
||||
...add the code from the lesson above to stop default behavior
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", onKeyDown);
|
||||
```
|
||||
|
||||
Periksa konsol penyemak imbas anda pada ketika ini, dan perhatikan penekanan kekunci dicatat.
|
||||
|
||||
3. **Terapkan** the [Pub sub pattern](../../translations/README.ms.md), ini akan memastikan kod anda tetap bersih semasa anda mengikuti bahagian yang tinggal.
|
||||
|
||||
Untuk melakukan bahagian terakhir ini, anda boleh:
|
||||
|
||||
1. **Tambahkan pendengar acara** di tetingkap:
|
||||
|
||||
```javascript
|
||||
window.addEventListener("keyup", (evt) => {
|
||||
if (evt.key === "ArrowUp") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_UP);
|
||||
} else if (evt.key === "ArrowDown") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_DOWN);
|
||||
} else if (evt.key === "ArrowLeft") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_LEFT);
|
||||
} else if (evt.key === "ArrowRight") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_RIGHT);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
1. **Buat kelas EventEmitter** untuk menerbitkan dan melanggan mesej:
|
||||
|
||||
```javascript
|
||||
class EventEmitter {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
|
||||
on(message, listener) {
|
||||
if (!this.listeners[message]) {
|
||||
this.listeners[message] = [];
|
||||
}
|
||||
this.listeners[message].push(listener);
|
||||
}
|
||||
|
||||
emit(message, payload = null) {
|
||||
if (this.listeners[message]) {
|
||||
this.listeners[message].forEach((l) => l(message, payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. **Tambah pemalar** dan sediakan EventEmitter:
|
||||
|
||||
```javascript
|
||||
const Messages = {
|
||||
KEY_EVENT_UP: "KEY_EVENT_UP",
|
||||
KEY_EVENT_DOWN: "KEY_EVENT_DOWN",
|
||||
KEY_EVENT_LEFT: "KEY_EVENT_LEFT",
|
||||
KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT",
|
||||
};
|
||||
|
||||
let heroImg,
|
||||
enemyImg,
|
||||
laserImg,
|
||||
canvas, ctx,
|
||||
gameObjects = [],
|
||||
hero,
|
||||
eventEmitter = new EventEmitter();
|
||||
```
|
||||
|
||||
1. **Memulakan permainan**
|
||||
|
||||
```javascript
|
||||
function initGame() {
|
||||
gameObjects = [];
|
||||
createEnemies();
|
||||
createHero();
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_UP, () => {
|
||||
hero.y -=5 ;
|
||||
})
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
|
||||
hero.y += 5;
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
|
||||
hero.x -= 5;
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => {
|
||||
hero.x += 5;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
1. **Siapkan gelung permainan**
|
||||
|
||||
Memfaktorkan semula fungsi window.onload untuk memulakan permainan dan mengatur gelung permainan pada selang waktu yang baik. Anda juga akan menambah sinar laser:
|
||||
|
||||
```javascript
|
||||
window.onload = async () => {
|
||||
canvas = document.getElementById("canvas");
|
||||
ctx = canvas.getContext("2d");
|
||||
heroImg = await loadTexture("assets/player.png");
|
||||
enemyImg = await loadTexture("assets/enemyShip.png");
|
||||
laserImg = await loadTexture("assets/laserRed.png");
|
||||
|
||||
initGame();
|
||||
let gameLoopId = setInterval(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawGameObjects(ctx);
|
||||
}, 100)
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
5. **Tambahkan kod** untuk memindahkan musuh pada selang waktu tertentu
|
||||
|
||||
Refactor fungsi `createEnemies()` untuk membuat musuh dan mendorong mereka ke kelas gameObjects yang baru:
|
||||
|
||||
```javascript
|
||||
function createEnemies() {
|
||||
const MONSTER_TOTAL = 5;
|
||||
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
|
||||
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
|
||||
const STOP_X = START_X + MONSTER_WIDTH;
|
||||
|
||||
for (let x = START_X; x < STOP_X; x += 98) {
|
||||
for (let y = 0; y < 50 * 5; y += 50) {
|
||||
const enemy = new Enemy(x, y);
|
||||
enemy.img = enemyImg;
|
||||
gameObjects.push(enemy);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
dan tambahkan fungsi `createHero()` untuk melakukan proses yang serupa untuk wira.
|
||||
|
||||
```javascript
|
||||
function createHero() {
|
||||
hero = new Hero(
|
||||
canvas.width / 2 - 45,
|
||||
canvas.height - canvas.height / 4
|
||||
);
|
||||
hero.img = heroImg;
|
||||
gameObjects.push(hero);
|
||||
}
|
||||
```
|
||||
|
||||
dan akhirnya, tambahkan fungsi `drawGameObjects()` untuk memulakan lukisan:
|
||||
|
||||
```javascript
|
||||
function drawGameObjects(ctx) {
|
||||
gameObjects.forEach(go => go.draw(ctx));
|
||||
}
|
||||
```
|
||||
|
||||
Musuh anda harus mula maju di kapal angkasa wira anda!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Seperti yang anda lihat, kod anda boleh berubah menjadi 'spaghetti code' apabila anda mula menambahkan fungsi dan pemboleh ubah dan kelas. Bagaimana anda dapat mengatur kod anda dengan lebih baik agar lebih mudah dibaca? Lakarkan sistem untuk mengatur kod anda, walaupun masih terdapat dalam satu fail.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/34)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Semasa kami menulis permainan kami tanpa menggunakan kerangka kerja, ada banyak kerangka kanvas berdasarkan JavaScript untuk pengembangan permainan. Luangkan sedikit masa untuk melakukan [membaca mengenai perkara ini](https://github.com/collections/javascript-game-engines).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Komen kod anda](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Komen Kod Anda
|
||||
|
||||
## Arahan
|
||||
|
||||
Periksa fail /app.js semasa anda di folder permainan anda, dan cari cara untuk mengomentarinya dan rapi. Sangat mudah bagi kod untuk tidak terkawal, dan sekarang adalah peluang yang baik untuk menambahkan komen untuk memastikan bahawa anda mempunyai kod yang dapat dibaca sehingga anda dapat menggunakannya kemudian.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------------------------------------------ | ------------------------------------- | -------------------------------------------------------------- |
|
||||
| | Kod `app.js` dikomentari sepenuhnya dan disusun menjadi blok logik | Kod `app.js` diberi komen yang mencukupi | Kod `app.js` agak tidak teratur dan tidak mempunyai komen yang baik |
|
@ -0,0 +1,297 @@
|
||||
# Bina Permainan Angkasa Bahagian 4: Menambah Laser dan Mengesan Perlanggaran
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/35)
|
||||
|
||||
Dalam pelajaran ini, anda akan belajar bagaimana menembak laser dengan JavaScript! Kami akan menambah dua perkara pada permainan kami:
|
||||
|
||||
- **Laser**: laser ini ditembak dari kapal wira anda dan menegak ke atas
|
||||
- **Pengesanan perlanggaran**, sebagai bagian dari menerapkan kemampuan untuk *menembak* kami juga akan menambahkan beberapa peraturan permainan yang bagus:
|
||||
- **Laser menyerang musuh**: Musuh mati jika terkena laser
|
||||
- **Laser mencecah skrin atas**: Laser hancur jika memukul bahagian atas skrin
|
||||
- **Pertempuran musuh dan pahlawan**: Musuh dan pahlawan musnah jika saling memukul
|
||||
- **Musuh memukul bahagian bawah layar**: Musuh dan pahlawan hancur jika musuh memukul bahagian bawah layar
|
||||
|
||||
Pendek kata, anda - *pahlawan* - perlu memukul semua musuh dengan laser sebelum mereka berjaya bergerak ke bahagian bawah skrin.
|
||||
|
||||
✅ Lakukan sedikit kajian mengenai permainan komputer pertama yang pernah ditulis. Apa fungsinya?
|
||||
|
||||
Mari sama-sama menjadi wira!
|
||||
|
||||
## Pengesanan perlanggaran
|
||||
|
||||
Bagaimanakah kita melakukan pengesanan perlanggaran? Kita perlu memikirkan objek permainan kita sebagai segi empat tepat bergerak. Mengapa anda bertanya? Nah, gambar yang digunakan untuk menggambar objek permainan adalah persegi panjang: ia memiliki `x`, `y`, `width` dan` height`.
|
||||
|
||||
Sekiranya dua segi empat tepat, iaitu pahlawan dan musuh *berpotongan*, anda akan bertembung. Apa yang harus berlaku adalah mengikut peraturan permainan. Oleh itu, untuk melaksanakan pengesanan perlanggaran anda memerlukan perkara berikut:
|
||||
|
||||
1. Cara untuk mendapatkan representasi segi empat tepat dari objek permainan, seperti ini:
|
||||
|
||||
```javascript
|
||||
rectFromGameObject() {
|
||||
return {
|
||||
top: this.y,
|
||||
left: this.x,
|
||||
bottom: this.y + this.height,
|
||||
right: this.x + this.width
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Fungsi perbandingan, fungsi ini boleh kelihatan seperti ini:
|
||||
|
||||
```javascript
|
||||
function intersectRect(r1, r2) {
|
||||
return !(r2.left > r1.right ||
|
||||
r2.right < r1.left ||
|
||||
r2.top > r1.bottom ||
|
||||
r2.bottom < r1.top);
|
||||
}
|
||||
```
|
||||
|
||||
## Bagaimanakah kita memusnahkan perkara
|
||||
|
||||
Untuk menghancurkan sesuatu dalam permainan, anda perlu memberitahu permainan bahawa permainan ini tidak lagi harus melukis item ini dalam gelung permainan yang mencetuskan pada selang waktu tertentu. Cara untuk melakukannya adalah dengan menandakan objek permainan sebagai *mati* apabila sesuatu berlaku, seperti:
|
||||
|
||||
```javascript
|
||||
// collision happened
|
||||
enemy.dead = true
|
||||
```
|
||||
|
||||
Kemudian anda meneruskan untuk menyusun *mati* objek sebelum mengecat semula skrin, seperti:
|
||||
|
||||
```javascript
|
||||
gameObjects = gameObject.filter(go => !go.dead);
|
||||
```
|
||||
|
||||
## Bagaimanakah kita menghidupkan laser
|
||||
|
||||
Menyalakan laser diterjemahkan untuk bertindak balas terhadap peristiwa penting dan membuat objek yang bergerak ke arah tertentu. Oleh itu, kita perlu melakukan langkah-langkah berikut:
|
||||
|
||||
1. **Buat objek laser**: dari bahagian atas kapal pahlawan kita, bahawa setelah penciptaan mula bergerak ke atas menuju bahagian atas layar.
|
||||
2. **Lampirkan kod ke acara utama**: kita perlu memilih kunci pada papan kekunci yang mewakili pemain yang menembak laser.
|
||||
3. **Buat objek permainan yang kelihatan seperti laser** apabila kekunci ditekan.
|
||||
|
||||
## Cooldown menggunakan laser kami
|
||||
|
||||
Laser perlu menyala setiap kali anda menekan kekunci, seperti *ruang* misalnya. Untuk mengelakkan permainan menghasilkan terlalu banyak laser dalam masa yang singkat, kita perlu memperbaikinya. Penyelesaiannya adalah dengan menerapkan *cooldown*, pemasa, yang memastikan bahawa laser hanya dapat dipecat begitu kerap. Anda boleh melaksanakannya dengan cara berikut:
|
||||
|
||||
```javascript
|
||||
class Cooldown {
|
||||
constructor(time) {
|
||||
this.cool = false;
|
||||
setTimeout(() => {
|
||||
this.cool = true;
|
||||
}, time)
|
||||
}
|
||||
}
|
||||
|
||||
class Weapon {
|
||||
constructor {
|
||||
}
|
||||
fire() {
|
||||
if (!this.cooldown || this.cooldown.cool) {
|
||||
// menghasilkan laser
|
||||
this.cooldown = new Cooldown(500);
|
||||
} else {
|
||||
// buat apa-apa - ia belum cooldown.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ Rujuk pelajaran 1 dalam siri permainan ruang untuk mengingatkan diri anda mengenai *cooldowns*.
|
||||
|
||||
## Apakah yang hendak dibina
|
||||
|
||||
Anda akan mengambil kod yang ada (yang seharusnya anda bersihkan dan refactored) dari pelajaran sebelumnya, dan memperpanjangnya. Mulakan dengan kod dari bahagian II atau gunakan kod di [Bahagian III-starter](/your-work)
|
||||
|
||||
> tip: laser yang akan anda gunakan sudah ada di folder aset anda dan dirujuk oleh kod anda
|
||||
|
||||
- **Tambahkan pengesanan perlanggaran**, apabila laser bertabrakan dengan sesuatu peraturan berikut harus berlaku:
|
||||
1. **Laser memukul musuh**: musuh mati jika terkena laser
|
||||
2. **Laser mencecah skrin atas**: Laser hancur jika menyentuh bahagian atas skrin kita
|
||||
3. **Pertembungan musuh dan pahlawan**: musuh dan pahlawan musnah jika saling memukul
|
||||
4. **Musuh memukul bahagian bawah skrin**: Musuh dan pahlawan hancur jika musuh memukul bahagian bawah skrin
|
||||
|
||||
## Langkah-langkah yang disyorkan
|
||||
|
||||
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| laserRed.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Anda memulakan projek anda folder `your_work` dengan mengetik:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http: // localhost: 5000`. Buka penyemak imbas dan masukkan alamatnya, sekarang ia harus menjadikan pahlawan dan semua musuh, tidak ada yang bergerak - namun :).
|
||||
|
||||
### Tambah kod
|
||||
|
||||
1. **Siapkan representasi segi empat tepat dari objek permainan anda, untuk menangani perlanggaran** Kod di bawah ini membolehkan anda mendapatkan representasi segi empat tepat dari `GameObject`. Edit kelas GameObject anda untuk memperluasnya:
|
||||
|
||||
```javascript
|
||||
rectFromGameObject() {
|
||||
return {
|
||||
top: this.y,
|
||||
left: this.x,
|
||||
bottom: this.y + this.height,
|
||||
right: this.x + this.width,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
2. **Tambahkan kod yang memeriksa perlanggaran** Ini akan menjadi fungsi baru yang menguji sama ada dua segi empat tepat bersilang:
|
||||
|
||||
```javascript
|
||||
function intersectRect(r1, r2) {
|
||||
return !(
|
||||
r2.left > r1.right ||
|
||||
r2.right < r1.left ||
|
||||
r2.top > r1.bottom ||
|
||||
r2.bottom < r1.top
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
3. **Tambahkan keupayaan menembak laser**
|
||||
1. **Tambah mesej peristiwa penting**. Kekunci *ruang* harus membuat laser tepat di atas kapal wira. Tambahkan tiga pemalar dalam objek Mesej:
|
||||
|
||||
```javascript
|
||||
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
|
||||
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
|
||||
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
|
||||
```
|
||||
|
||||
1. **Kendalikan kekunci ruang**. Edit fungsi kekunci `window.addEventListener` untuk menangani ruang:
|
||||
|
||||
```javascript
|
||||
} else if(evt.keyCode === 32) {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
|
||||
}
|
||||
```
|
||||
|
||||
1. **Tambah pendengar**. Edit fungsi `initGame ()` untuk memastikan bahawa pahlawan dapat melepaskan tembakan ketika spasi terkena:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
|
||||
if (hero.canFire()) {
|
||||
hero.fire();
|
||||
}
|
||||
```
|
||||
|
||||
and add a new `eventEmitter.on()` function to ensure behavior when an enemy collides with a laser:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
||||
first.dead = true;
|
||||
second.dead = true;
|
||||
})
|
||||
```
|
||||
|
||||
1. **Pindahkan objek**, Pastikan laser bergerak ke bahagian atas skrin secara beransur-ansur. Anda akan membuat kelas Laser baru yang meluaskan `GameObject`, seperti yang telah anda lakukan sebelumnya:
|
||||
|
||||
```javascript
|
||||
class Laser extends GameObject {
|
||||
constructor(x, y) {
|
||||
super(x,y);
|
||||
(this.width = 9), (this.height = 33);
|
||||
this.type = 'Laser';
|
||||
this.img = laserImg;
|
||||
let id = setInterval(() => {
|
||||
if (this.y > 0) {
|
||||
this.y -= 15;
|
||||
} else {
|
||||
this.dead = true;
|
||||
clearInterval(id);
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. ** Tangani perlanggaran **, Terapkan peraturan perlanggaran untuk laser. Tambahkan fungsi `updateGameObjects ()` yang menguji objek bertembung untuk hits
|
||||
|
||||
```javascript
|
||||
function updateGameObjects() {
|
||||
const enemies = gameObjects.filter(go => go.type === 'Enemy');
|
||||
const lasers = gameObjects.filter((go) => go.type === "Laser");
|
||||
// laser hit something
|
||||
lasers.forEach((l) => {
|
||||
enemies.forEach((m) => {
|
||||
if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) {
|
||||
eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, {
|
||||
first: l,
|
||||
second: m,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
gameObjects = gameObjects.filter(go => !go.dead);
|
||||
}
|
||||
```
|
||||
|
||||
Pastikan untuk menambah `updateGameObjects ()` ke gelung permainan anda di `window.onload`.
|
||||
|
||||
4. ** Terapkan cooldown ** pada laser, sehingga hanya dapat dipecat begitu kerap.
|
||||
|
||||
Akhir sekali, edit kelas Wira sehingga dapat dikembalikan:
|
||||
|
||||
```javascript
|
||||
class Hero extends GameObject {
|
||||
constructor(x, y) {
|
||||
super(x, y);
|
||||
(this.width = 99), (this.height = 75);
|
||||
this.type = "Hero";
|
||||
this.speed = { x: 0, y: 0 };
|
||||
this.cooldown = 0;
|
||||
}
|
||||
fire() {
|
||||
gameObjects.push(new Laser(this.x + 45, this.y - 10));
|
||||
this.cooldown = 500;
|
||||
|
||||
let id = setInterval(() => {
|
||||
if (this.cooldown > 0) {
|
||||
this.cooldown -= 100;
|
||||
} else {
|
||||
clearInterval(id);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
canFire() {
|
||||
return this.cooldown === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Pada ketika ini, permainan anda mempunyai beberapa fungsi! Anda boleh menavigasi dengan kekunci anak panah anda, menembak laser dengan bar ruang anda, dan musuh hilang ketika anda memukulnya. Bagus!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Tambah letupan! Lihat aset permainan di [Space Art repo](../../solution/spaceArt/readme.txt) dan cuba tambahkan letupan ketika laser memukul makhluk asing
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/36)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Percubaan dengan selang permainan anda setakat ini. Apa yang berlaku apabila anda menukarnya? Baca lebih lanjut mengenai [acara pemasaan JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Menerokai Perlanggaran](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Menorokai Perlanggaran
|
||||
|
||||
## Arahan
|
||||
|
||||
## Rubrik
|
||||
|
||||
Untuk lebih memahami bagaimana perlanggaran berfungsi, bina permainan yang sangat kecil dengan beberapa item yang bertembung. Buat mereka bergerak melalui menekan kekunci atau klik tetikus, dan membuat sesuatu berlaku pada salah satu item ketika dipukul. Ini mungkin seperti meteor yang menghantam bumi, atau kereta bumper. Dapatkan kreatif!
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------ | ----------------- |
|
||||
| | Sampel kod kerja lengkap dihasilkan, dengan item dilukis ke kanvas, perlanggaran asas berlaku, dan reaksi berlaku | Kod tidak lengkap dalam beberapa cara | Kod Tidak Berfungsi |
|
@ -0,0 +1,189 @@
|
||||
# Membina Permainan Angkasa Bahagian 5: Pemarkahan dan Kehidupan
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/37)
|
||||
|
||||
Dalam pelajaran ini, anda akan belajar bagaimana menambahkan skor pada permainan dan mengira kehidupan.
|
||||
|
||||
## Lukis teks di skrin
|
||||
|
||||
Untuk dapat memaparkan skor permainan di layar, Anda harus tahu cara meletakkan teks di layar. Jawapannya adalah menggunakan kaedah `fillText()` pada objek kanvas. Anda juga dapat mengawal aspek lain seperti fon apa yang hendak digunakan, warna teks dan juga penjajarannya (kiri, kanan, tengah). Di bawah ini terdapat beberapa kod yang melukis beberapa teks di skrin.
|
||||
|
||||
```javascript
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = "red";
|
||||
ctx.textAlign = "right";
|
||||
ctx.fillText("show this on the screen", 0, 0);
|
||||
```
|
||||
|
||||
✅ Baca lebih lanjut mengenai [cara menambahkan teks ke kanvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text), dan jangan ragu untuk menjadikan teks anda kelihatan lebih menarik!
|
||||
|
||||
## Hidup, sebagai konsep permainan
|
||||
|
||||
Konsep mempunyai kehidupan dalam permainan hanya bilangan. Dalam konteks permainan ruang angkasa adalah biasa untuk menetapkan satu set nyawa yang dipotong satu demi satu ketika kapal anda mengalami kerosakan. Senang jika anda dapat menunjukkan gambaran grafik seperti miniships atau hati dan bukannya angka.
|
||||
|
||||
## Apakah yang anda perlu bina
|
||||
|
||||
Mari tambahkan yang berikut ke permainan anda:
|
||||
|
||||
- **Skor permainan**: Untuk setiap kapal musuh yang musnah, pahlawan harus diberikan beberapa mata, kami mencadangkan 100 mata setiap kapal. Skor permainan harus ditunjukkan di kiri bawah.
|
||||
- **Kehidupan**: Kapal anda mempunyai tiga nyawa. Anda kehilangan nyawa setiap kali kapal musuh bertembung dengan anda. Skor hidup mesti dipaparkan di kanan bawah dan dibuat berdasarkan grafik berikut! [Gambar hidup](../solution/assets/life.png).
|
||||
|
||||
## Langkah yang disyorkan
|
||||
|
||||
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| laserRed.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Anda memulakan projek anda folder `your_work` dengan mengetik:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http://localhost:5000`. Buka penyemak imbas dan masukkan alamatnya, sekarang ia akan menjadikan pahlawan dan semua musuh, dan ketika anda menekan anak panah kiri dan kanan, pahlawan bergerak dan dapat menembak musuh.
|
||||
|
||||
### Tambahkan Kod
|
||||
|
||||
1. **Salin atas aset yang diperlukan** dari folder `solution/aset/` ke folder `your-work`; anda akan menambah aset `life.png`. Tambahkan lifeImg ke fungsi window.onload:
|
||||
|
||||
```javascript
|
||||
lifeImg = await loadTexture("assets/life.png");
|
||||
```
|
||||
|
||||
1. Tambahkan `lifeImg` ke senarai aset:
|
||||
|
||||
```javascript
|
||||
let heroImg,
|
||||
...
|
||||
lifeImg,
|
||||
...
|
||||
eventEmitter = new EventEmitter();
|
||||
```
|
||||
|
||||
2. **Tambah pemboleh ubah**. Tambahkan kod yang mewakili jumlah skor anda (0) dan tinggal (3), paparkan skor ini di skrin.
|
||||
|
||||
3. **Panjangkan fungsi `updateGameObjects ()`**. Panjangkan fungsi `updateGameObjects ()` untuk menangani perlanggaran musuh:
|
||||
|
||||
```javascript
|
||||
enemies.forEach(enemy => {
|
||||
const heroRect = hero.rectFromGameObject();
|
||||
if (intersectRect(heroRect, enemy.rectFromGameObject())) {
|
||||
eventEmitter.emit(Messages.COLLISION_ENEMY_HERO, { enemy });
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
4. **Tambahkan `life` dan` point`**.
|
||||
1. **Memulakan pemboleh ubah**. Di bawah `this.cooldown = 0` di kelas `Hero`, tetapkan hidup dan mata:
|
||||
|
||||
```javascript
|
||||
this.life = 3;
|
||||
this.points = 0;
|
||||
```
|
||||
|
||||
1. **Lukis pemboleh ubah pada skrin**. Lukiskan nilai-nilai ini ke skrin:
|
||||
|
||||
```javascript
|
||||
function drawLife() {
|
||||
// TODO, 35, 27
|
||||
const START_POS = canvas.width - 180;
|
||||
for(let i=0; i < hero.life; i++ ) {
|
||||
ctx.drawImage(
|
||||
lifeImg,
|
||||
START_POS + (45 * (i+1) ),
|
||||
canvas.height - 37);
|
||||
}
|
||||
}
|
||||
|
||||
function drawPoints() {
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = "red";
|
||||
ctx.textAlign = "left";
|
||||
drawText("Points: " + hero.points, 10, canvas.height-20);
|
||||
}
|
||||
|
||||
function drawText(message, x, y) {
|
||||
ctx.fillText(message, x, y);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
1. ** Tambahkan kaedah ke gelung Permainan **. Pastikan anda menambahkan fungsi ini ke fungsi window.onload anda di bawah `updateGameObjects()`:
|
||||
|
||||
```javascript
|
||||
drawPoints();
|
||||
drawLife();
|
||||
```
|
||||
|
||||
1. **Melaksanakan peraturan permainan**. Laksanakan peraturan permainan berikut:
|
||||
|
||||
1. **Untuk setiap pertembungan pahlawan dan musuh**, tolaklah nyawa.
|
||||
|
||||
Lanjutkan kelas `Hero` untuk melakukan pemotongan ini:
|
||||
|
||||
```javascript
|
||||
decrementLife() {
|
||||
this.life--;
|
||||
if (this.life === 0) {
|
||||
this.dead = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Untuk setiap laser yang menyerang musu**, tingkatkan skor permainan dengan 100 mata.
|
||||
|
||||
Panjangkan kelas Wira untuk melakukan kenaikan ini:
|
||||
|
||||
```javascript
|
||||
incrementPoints() {
|
||||
this.points += 100;
|
||||
}
|
||||
```
|
||||
|
||||
Tambahkan fungsi ini ke Collision Event Emitter anda:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
||||
first.dead = true;
|
||||
second.dead = true;
|
||||
hero.incrementPoints();
|
||||
})
|
||||
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
|
||||
enemy.dead = true;
|
||||
hero.decrementLife();
|
||||
});
|
||||
```
|
||||
|
||||
✅ Lakukan sedikit penyelidikan untuk mengetahui permainan lain yang dibuat menggunakan JavaScript/Canvas. Apakah sifat umum mereka?
|
||||
|
||||
Menjelang akhir kerja ini, anda akan melihat kapal-kapal kecil 'kehidupan' di kanan bawah, titik di kiri bawah, dan anda akan melihat pengurangan jumlah hayat anda semasa anda bertembung dengan musuh dan kenaikan mata anda ketika anda menembak musuh. Bagus! Permainan anda hampir selesai.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Kod anda hampir lengkap. Bolehkah anda membayangkan langkah seterusnya?
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/38)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Teliti beberapa cara yang boleh anda tambah dan mengurangkan skor dan kehidupan permainan. Terdapat beberapa enjin permainan yang menarik seperti [PlayFab](https://playfab.com). Bagaimana penggunaan salah satu daripadanya dapat meningkatkan permainan anda?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Bina Permainan Pemarkahan](assignment.ms.md)
|
@ -0,0 +1,11 @@
|
||||
# Bina Permainan Pemarkahan
|
||||
|
||||
## Arahan
|
||||
|
||||
Buat permainan di mana anda menampilkan kehidupan dan mata dengan cara yang kreatif. Satu cadangan adalah untuk menunjukkan kehidupan sebagai hati dan poin sebagai angka yang besar di bahagian tengah bawah skrin. Lihat di sini [Sumber permainan percuma](https://www.kenney.nl/)
|
||||
|
||||
# Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ---------------------- | --------------------------- | -------------------------- |
|
||||
| | permainan penuh dipersembahkan | permainan dipersembahkan sebahagiannya | permainan separa mengandungi pepijat |
|
@ -0,0 +1,222 @@
|
||||
# Bina Permainan Angkasa Bahagian 6: Tamat dan Mulakan Semula
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/39)
|
||||
|
||||
Terdapat pelbagai cara untuk menyatakan dan *keadaan akhir* dalam permainan. Terserah anda sebagai pencipta permainan untuk mengatakan mengapa permainan ini berakhir. Berikut adalah beberapa sebab, jika kita menganggap bahawa kita sedang membincangkan permainan ruang angkasa yang anda buat sejauh ini:
|
||||
|
||||
- **Kapal musuh `N` telah hancur**: Sangat biasa jika anda membahagikan permainan ke dalam tahap yang berbeza yang anda perlukan untuk menghancurkan kapal `N` Musuh untuk menyelesaikan level
|
||||
- **Kapal anda hancur**: Pasti ada permainan di mana anda kehilangan permainan jika kapal anda musnah. Pendekatan umum lain ialah anda mempunyai konsep kehidupan. Setiap kali kapal anda musnah, ia akan meragut nyawa. Setelah semua nyawa telah hilang maka anda akan kehilangan permainan.
|
||||
- **Anda telah mengumpulkan mata `N`**: Syarat akhir yang umum ialah anda mengumpulkan mata. Cara anda memperoleh mata adalah bergantung kepada anda tetapi agak biasa untuk memberikan mata kepada pelbagai aktiviti seperti memusnahkan kapal musuh atau mungkin mengumpulkan barang-barang yang item *turun* ketika mereka musnah.
|
||||
- **Lengkapkan tahap**: Ini mungkin melibatkan beberapa syarat seperti kapal musuh `X` musnah, mata `Y` dikumpulkan atau mungkin item tertentu telah dikumpulkan.
|
||||
|
||||
## Memulakan semula
|
||||
|
||||
Sekiranya orang menikmati permainan anda, mereka mungkin ingin memainkannya semula. Setelah permainan berakhir dengan alasan apa pun, anda harus menawarkan alternatif untuk dimulakan semula.
|
||||
|
||||
✅ Fikirkan sedikit dalam keadaan apa permainan anda berakhir, dan kemudian bagaimana anda diminta untuk memulakan semula
|
||||
|
||||
## Apakah yang anda perlu bina
|
||||
|
||||
Anda akan menambahkan peraturan ini ke permainan anda:
|
||||
|
||||
1. **Memenangi permainan**. Setelah semua kapal musuh musnah, anda memenangi permainan. Selain itu memaparkan semacam mesej kemenangan.
|
||||
1. **Mulakan semula**. Setelah semua nyawa anda hilang atau permainan dimenangi, anda harus menawarkan cara untuk memulakan semula permainan. Ingat! Anda perlu memulakan semula permainan dan keadaan permainan sebelumnya harus dibersihkan.
|
||||
|
||||
## Langkah-langkah yang disyorkan
|
||||
|
||||
Cari fail yang telah dibuat untuk anda dalam sub folder `your-work`. Ia harus mengandungi yang berikut:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| laserRed.png
|
||||
-| life.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Anda memulakan projek anda folder `your_work` dengan mengetik:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Perkara di atas akan memulakan Pelayan HTTP pada alamat `http://localhost:5000`. Buka penyemak imbas dan masukkan alamat itu. Permainan anda mestilah dalam keadaan boleh dimainkan.
|
||||
|
||||
> tip: untuk mengelakkan amaran dalam Visual Studio Code, edit fungsi `window.onload` untuk memanggil `gameLoopId` sebagaimana adanya (tanpa `let`), dan nyatakan gameLoopId di bahagian atas fail, secara bebas: `let gameLoopId;`
|
||||
|
||||
### Tambahkan kod
|
||||
|
||||
1. **Keadaan hujung trek**. Tambahkan kod yang memantau jumlah musuh, atau jika kapal pahlawan telah musnah dengan menambahkan dua fungsi ini:
|
||||
|
||||
```javascript
|
||||
function isHeroDead() {
|
||||
return hero.life <= 0;
|
||||
}
|
||||
|
||||
function isEnemiesDead() {
|
||||
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
|
||||
return enemies.length === 0;
|
||||
}
|
||||
```
|
||||
|
||||
1. **Tambahkan logik ke pengendali mesej**. Edit `eventEmitter` untuk menangani keadaan berikut:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
||||
first.dead = true;
|
||||
second.dead = true;
|
||||
hero.incrementPoints();
|
||||
|
||||
if (isEnemiesDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_WIN);
|
||||
}
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
|
||||
enemy.dead = true;
|
||||
hero.decrementLife();
|
||||
if (isHeroDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_LOSS);
|
||||
return; // loss before victory
|
||||
}
|
||||
if (isEnemiesDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_WIN);
|
||||
}
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.GAME_END_WIN, () => {
|
||||
endGame(true);
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.GAME_END_LOSS, () => {
|
||||
endGame(false);
|
||||
});
|
||||
```
|
||||
|
||||
1. **Tambahkan jenis mesej baru**. Tambahkan Mesej ini ke objek pemalar:
|
||||
|
||||
```javascript
|
||||
GAME_END_LOSS: "GAME_END_LOSS",
|
||||
GAME_END_WIN: "GAME_END_WIN",
|
||||
```
|
||||
|
||||
2. **Tambah kod restart** kod yang memulakan semula permainan dengan menekan butang yang dipilih.
|
||||
|
||||
1. **Dengarkan kekunci tekan `Enter`**. Edit eventListener tetingkap anda untuk mendengar akhbar ini:
|
||||
|
||||
```javascript
|
||||
else if(evt.key === "Enter") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
|
||||
}
|
||||
```
|
||||
|
||||
1. **Tambah semula mesej**. Tambahkan Mesej ini ke pemalar Mesej anda:
|
||||
|
||||
```javascript
|
||||
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
|
||||
```
|
||||
|
||||
1. **Melaksanakan peraturan permainan**. Laksanakan peraturan permainan berikut:
|
||||
|
||||
1. **Syarat kemenangan pemain**. Apabila semua kapal musuh hancur, tunjukkan mesej kemenangan.
|
||||
|
||||
1. Pertama, buat fungsi `displayMessage()`:
|
||||
|
||||
```javascript
|
||||
function displayMessage(message, color = "red") {
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = color;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
|
||||
}
|
||||
```
|
||||
|
||||
1. Buat fungsi `endGame()`:
|
||||
|
||||
```javascript
|
||||
function endGame(win) {
|
||||
clearInterval(gameLoopId);
|
||||
|
||||
// atur kelewatan supaya kami yakin sebarang cat telah selesai
|
||||
setTimeout(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
if (win) {
|
||||
displayMessage(
|
||||
"Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew",
|
||||
"green"
|
||||
);
|
||||
} else {
|
||||
displayMessage(
|
||||
"You died !!! Press [Enter] to start a new game Captain Pew Pew"
|
||||
);
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
```
|
||||
|
||||
1. **Mulakan semula logik**. Apabila semua nyawa hilang atau pemain memenangi permainan, tunjukkan bahawa permainan dapat dimulakan semula. Selain itu mulakan semula permainan apabila butang * restart * dipukul (anda boleh menentukan kunci apa yang harus dipetakan untuk dimulakan semula).
|
||||
|
||||
1. Buat fungsi `resetGame ()`:
|
||||
|
||||
```javascript
|
||||
function resetGame() {
|
||||
if (gameLoopId) {
|
||||
clearInterval(gameLoopId);
|
||||
eventEmitter.clear();
|
||||
initGame();
|
||||
gameLoopId = setInterval(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawPoints();
|
||||
drawLife();
|
||||
updateGameObjects();
|
||||
drawGameObjects(ctx);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Tambahkan panggilan ke `eventEmitter` untuk menetapkan semula permainan di `initGame()`:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
|
||||
resetGame();
|
||||
});
|
||||
```
|
||||
|
||||
1. Tambahkan fungsi `clear()` ke EventEmitter:
|
||||
|
||||
```javascript
|
||||
clear() {
|
||||
this.listeners = {};
|
||||
}
|
||||
```
|
||||
|
||||
👽 💥 🚀 Tahniah, Kapten! Permainan anda selesai! Bagus! 🚀 💥 👽
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Tambahkan suara! Bolehkah anda menambahkan suara untuk meningkatkan permainan anda, mungkin ketika ada pancaran laser, atau wira mati atau menang? Lihatlah [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) untuk belajar bagaimana memainkan suara menggunakan JavaScript
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/40)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Tugas anda adalah membuat permainan contoh baru, jadi terokai beberapa permainan menarik di luar sana untuk melihat jenis permainan yang mungkin anda bina.
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Bina Contoh Permainan](assignment.ms.md)
|
@ -0,0 +1,19 @@
|
||||
# Bina Contoh Permainan
|
||||
|
||||
## Arahan
|
||||
|
||||
Cuba buat permainan kecil di mana anda berlatih dengan keadaan akhir yang berbeza. Berbeza antara mendapatkan sejumlah mata, wira kehilangan semua nyawa atau semua raksasa dikalahkan. Bina sesuatu yang mudah seperti permainan pengembaraan berasaskan konsol. Gunakan aliran permainan di bawah sebagai inspirasi:
|
||||
|
||||
```
|
||||
Wira> Serangan dengan pedang lebar - orc mengalami kerosakan 3p
|
||||
Orc> Hits with club - wira mengalami kerosakan 2p
|
||||
Wira> Tendangan - orc mengalami kerosakan 1p
|
||||
Permainan> Orc dikalahkan - Hero mengumpulkan 2 syiling
|
||||
Permainan> ****Tidak ada lagi raksasa, anda telah menakluki kubu jahat****
|
||||
```
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ---------------------- | --------------------------- | -------------------------- |
|
||||
| | permainan penuh dipersembahkan| permainan dipersembahkan sebahagiannya | permainan separa mengandungi pepijat |
|
@ -0,0 +1,31 @@
|
||||
# Bina Permainan Angkasa
|
||||
|
||||
Permainan ruang untuk mengajar asas-asas JavaScript yang lebih mendalam
|
||||
|
||||
Dalam pelajaran ini, anda akan belajar bagaimana membuat permainan ruang angkasa anda sendiri. Sekiranya anda pernah memainkan permainan "Space Invaders", permainan ini mempunyai idea yang sama: untuk mengarahkan kapal angkasa dan menembak monster yang turun dari atas. Beginilah rupa permainan yang sudah siap:
|
||||
|
||||
![Permainan selesai](../images/pewpew.gif)
|
||||
|
||||
Dalam enam pelajaran ini anda akan mempelajari perkara berikut:
|
||||
|
||||
- **Berinteraksi** dengan elemen Canvas untuk menarik sesuatu di skrin
|
||||
- **Memahami** sistem koordinat kartesian
|
||||
- **Pelajari** corak Pub-Sub untuk membuat seni bina permainan suara yang lebih mudah dijaga dan diperluas
|
||||
- **Leverage** Async / Tunggu untuk memuatkan sumber permainan
|
||||
- **Mengendalikan** acara papan kekunci
|
||||
|
||||
## Gambaran keseluruhan
|
||||
|
||||
- Theori
|
||||
- [Pengenalan membina permainan dengan JavaScript](../1-introduction/README.md)
|
||||
- Practice
|
||||
- [Melukis ke kanvas](../2-drawing-to-canvas/README.md)
|
||||
- [Menggerakkan elemen di sekitar skrin](../3-moving-elements-around/README.md)
|
||||
- [Pengesanan perlanggaran](../4-collision-detection/README.md)
|
||||
- [Menjaga skor](../5-keeping-score/README.md)
|
||||
- [Menamatkan dan memulakan semula permainan](../6-end-condition/README.md)
|
||||
|
||||
## Kredit
|
||||
|
||||
Aset yang digunakan untuk ini berasal dari https://www.kenney.nl/.
|
||||
Sekiranya anda suka membina permainan, ini adalah beberapa aset yang sangat baik, banyak percuma dan ada juga yang dibayar.
|
@ -0,0 +1,306 @@
|
||||
# Bina Aplikasi Perbankan Bahagian 1: Templat dan Laluan HTML dalam Aplikasi Web
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/41)
|
||||
|
||||
### Arahan
|
||||
|
||||
Sejak munculnya JavaScript di penyemak imbas, laman web menjadi lebih interaktif dan kompleks daripada sebelumnya. Teknologi web kini biasa digunakan untuk membuat aplikasi berfungsi sepenuhnya yang langsung masuk ke penyemak imbas yang kita panggil [aplikasi web](https://en.wikipedia.org/wiki/Web_application). Oleh kerana aplikasi Web sangat interaktif, pengguna tidak mahu menunggu muat semula halaman penuh setiap kali tindakan dilakukan. Itulah sebabnya JavaScript digunakan untuk mengemas kini HTML secara langsung menggunakan DOM, untuk memberikan pengalaman pengguna yang lebih lancar.
|
||||
|
||||
Dalam pelajaran ini, kita akan meletakkan dasar untuk membuat aplikasi web bank, menggunakan templat HTML untuk membuat banyak layar yang dapat ditampilkan dan diperbarui tanpa harus memuat ulang seluruh halaman HTML.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda memerlukan pelayan web tempatan untuk menguji aplikasi web yang akan kami bina dalam pelajaran ini. Sekiranya tidak memilikinya, anda boleh memasang [Node.js](https://nodejs.org) dan menggunakan arahan `npx lite-server` dari folder projek anda. Ini akan membuat pelayan web tempatan dan membuka aplikasi anda di penyemak imbas.
|
||||
|
||||
### Penyediaan
|
||||
|
||||
Di komputer anda, buat folder bernama `bank` dengan fail bernama `index.html` di dalamnya. Kami akan bermula dari HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code):
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bank App</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- This is where you'll work -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Templat HTML
|
||||
|
||||
Jika anda ingin membuat beberapa layar untuk halaman web, satu penyelesaiannya adalah dengan membuat satu file HTML untuk setiap layar yang ingin anda tampilkan. Walau bagaimanapun, penyelesaian ini disertakan dengan beberapa kesulitan:
|
||||
|
||||
- Anda harus memuat semula keseluruhan HTML ketika menukar skrin, yang boleh menjadi lambat.
|
||||
- Sukar untuk berkongsi data antara skrin yang berbeza.
|
||||
|
||||
Pendekatan lain hanya mempunyai satu fail HTML, dan menentukan beberapa [templat HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) menggunakan elemen `<template>`. Templat adalah blok HTML yang dapat digunakan kembali yang tidak ditampilkan oleh penyemak imbas, dan perlu dibuat pada waktu berjalan menggunakan JavaScript.
|
||||
|
||||
### Tugas
|
||||
|
||||
Kami akan membuat aplikasi bank dengan dua skrin: halaman log masuk dan papan pemuka. Pertama, mari kita tambahkan elemen penanda tempat pada badan HTML yang akan kita gunakan untuk menunjukkan pelbagai skrin aplikasi kita:
|
||||
|
||||
```html
|
||||
<div id="app">Loading...</div>
|
||||
```
|
||||
|
||||
Kami memberikannya `id` untuk memudahkan pencarian dengan JavaScript kemudian.
|
||||
|
||||
> Petua: kerana kandungan elemen ini akan diganti, kita dapat memasukkan pesan pemuatan atau penunjuk yang akan ditunjukkan semasa aplikasi dimuat.
|
||||
|
||||
Seterusnya, mari kita tambahkan di bawah templat HTML untuk halaman log masuk. Buat masa ini kami hanya akan memasukkan tajuk dan bahagian yang mengandungi pautan yang akan kami gunakan untuk melakukan navigasi.
|
||||
|
||||
```html
|
||||
<template id="login">
|
||||
<h1>Bank App</h1>
|
||||
<section>
|
||||
<a href="/dashboard">Login</a>
|
||||
</section>
|
||||
</template>
|
||||
```
|
||||
|
||||
Kemudian kami akan menambahkan templat HTML lain untuk halaman papan pemuka. Halaman ini akan mengandungi bahagian yang berbeza:
|
||||
|
||||
- Tajuk dengan tajuk dan pautan log keluar
|
||||
- Baki semasa akaun bank
|
||||
- Senarai urus niaga, ditunjukkan dalam jadual
|
||||
|
||||
```html
|
||||
<template id="dashboard">
|
||||
<header>
|
||||
<h1>Bank App</h1>
|
||||
<a href="/login">Logout</a>
|
||||
</header>
|
||||
<section>
|
||||
Balance: 100$
|
||||
</section>
|
||||
<section>
|
||||
<h2>Transactions</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Object</th>
|
||||
<th>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</section>
|
||||
</template>
|
||||
```
|
||||
|
||||
> Petua: semasa membuat templat HTML, jika anda ingin melihat seperti apa, anda boleh memberi komen baris `<template>` `dan` `</template>` dengan melampirkannya dengan `<! - -> ` .
|
||||
|
||||
✅ Menurut anda mengapa kami menggunakan atribut `id` pada templat? Bolehkah kita menggunakan sesuatu yang lain seperti kelas?
|
||||
|
||||
## Memaparkan templat dengan JavaScript
|
||||
|
||||
Sekiranya anda mencuba fail HTML semasa anda dalam penyemak imbas, anda akan melihat fail tersebut macet memaparkan `Memuat ... '. Itu kerana kita perlu menambahkan beberapa kod JavaScript untuk memberi contoh dan memaparkan templat HTML.
|
||||
|
||||
Membuat templat biasanya dilakukan dalam 3 langkah:
|
||||
|
||||
1. Dapatkan semula elemen templat di DOM, misalnya menggunakan [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById).
|
||||
2. Klon elemen templat, menggunakan [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode).
|
||||
3. Lampirkan ke DOM di bawah elemen yang kelihatan, misalnya menggunakan [`appendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild).
|
||||
|
||||
✅ Mengapa kita perlu mengklon templat sebelum melampirkannya ke DOM? Apa yang anda fikir akan berlaku sekiranya kita melangkau langkah ini?
|
||||
|
||||
### Tugas
|
||||
|
||||
Buat fail baru bernama `app.js` di folder projek anda dan import fail itu di bahagian `<head>` HTML anda:
|
||||
|
||||
```html
|
||||
<script src="app.js" defer></script>
|
||||
```
|
||||
|
||||
Sekarang di `app.js`, kami akan membuat fungsi baru `updateRoute`:
|
||||
|
||||
```js
|
||||
function updateRoute(templateId) {
|
||||
const template = document.getElementById(templateId);
|
||||
const view = template.content.cloneNode(true);
|
||||
const app = document.getElementById('app');
|
||||
app.innerHTML = '';
|
||||
app.appendChild(view);
|
||||
}
|
||||
```
|
||||
|
||||
Apa yang kami lakukan di sini adalah tepat 3 langkah yang dinyatakan di atas. Kami membuat templat dengan id `templateId`, dan memasukkan kandungan klonnya ke dalam ruang letak aplikasi kami. Perhatikan bahawa kita perlu menggunakan `cloneNode(true)` untuk menyalin keseluruhan subtree templat.
|
||||
|
||||
Sekarang panggil fungsi ini dengan salah satu templat dan lihat hasilnya.
|
||||
|
||||
```js
|
||||
updateRoute('login');
|
||||
```
|
||||
|
||||
✅ Apa tujuan kod ini `app.innerHTML = '';`? Apa yang berlaku tanpanya?
|
||||
|
||||
## Membuat laluan
|
||||
|
||||
Ketika berbicara tentang aplikasi web, kami memanggil *Routing* niat untuk memetakan **URL** ke layar tertentu yang harus ditampilkan. Di laman web dengan banyak fail HTML, ini dilakukan secara automatik kerana jalur fail ditunjukkan pada URL. Contohnya, dengan fail ini dalam folder projek anda:
|
||||
|
||||
```
|
||||
mywebsite/index.html
|
||||
mywebsite/login.html
|
||||
mywebsite/admin/index.html
|
||||
```
|
||||
|
||||
Sekiranya anda membuat pelayan web dengan `mywebsite` sebagai root, pemetaan URL akan:
|
||||
|
||||
```
|
||||
https://site.com --> mywebsite/index.html
|
||||
https://site.com/login.html --> mywebsite/login.html
|
||||
https://site.com/admin/ --> mywebsite/admin/index.html
|
||||
```
|
||||
|
||||
Walau bagaimanapun, untuk aplikasi web kami menggunakan satu fail HTML yang mengandungi semua skrin sehingga tingkah laku lalai ini tidak akan membantu kami. Kita harus membuat peta ini secara manual dan melakukan kemas kini templat yang dipaparkan menggunakan JavaScript.
|
||||
|
||||
### Tugas
|
||||
|
||||
Kami akan menggunakan objek sederhana untuk melaksanakan [peta](https://en.wikipedia.org/wiki/Associative_array) antara jalur URL dan templat kami. Tambahkan objek ini di bahagian atas fail `app.js` anda.
|
||||
|
||||
```js
|
||||
const routes = {
|
||||
'/login': { templateId: 'login' },
|
||||
'/dashboard': { templateId: 'dashboard' },
|
||||
};
|
||||
```
|
||||
|
||||
Sekarang mari kita ubah sedikit fungsi `updateRoute`. Daripada meneruskan secara langsung `templateId` sebagai argumen, kami ingin mendapatkannya dengan terlebih dahulu melihat URL semasa, dan kemudian menggunakan peta kami untuk mendapatkan nilai ID templat yang sesuai. Kita boleh menggunakan [`window.location.pathname`](https://developer.mozilla.org/en-US/docs/Web/API/Location/pathname) untuk mendapatkan hanya bahagian jalan dari URL.
|
||||
|
||||
```js
|
||||
function updateRoute() {
|
||||
const path = window.location.pathname;
|
||||
const route = routes[path];
|
||||
|
||||
const template = document.getElementById(route.templateId);
|
||||
const view = template.content.cloneNode(true);
|
||||
const app = document.getElementById('app');
|
||||
app.innerHTML = '';
|
||||
app.appendChild(view);
|
||||
}
|
||||
```
|
||||
|
||||
Di sini kami memetakan laluan yang kami nyatakan ke templat yang sesuai. Anda boleh mencubanya agar berfungsi dengan betul dengan menukar URL secara manual di penyemak imbas anda.
|
||||
|
||||
✅ Apa yang berlaku jika anda memasukkan jalan yang tidak diketahui dalam URL? Bagaimana kita dapat menyelesaikannya?
|
||||
|
||||
## Tambahkan navigasi
|
||||
|
||||
Langkah seterusnya untuk aplikasi kita adalah menambahkan kemungkinan untuk menavigasi antara halaman tanpa perlu mengubah URL secara manual. Ini menunjukkan dua perkara:
|
||||
|
||||
1. Mengemas kini URL semasa
|
||||
2. Mengemas kini templat yang dipaparkan berdasarkan URL baru
|
||||
|
||||
Kami sudah mengurus bahagian kedua dengan fungsi `updateRoute`, jadi kami harus memikirkan cara mengemas kini URL semasa.
|
||||
|
||||
Kita mesti menggunakan JavaScript dan lebih khusus lagi [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) yang memungkinkan untuk mengemas kini URL dan buat entri baru dalam sejarah penyemakan imbas, tanpa memuatkan semula HTML.
|
||||
|
||||
> Catatan: Walaupun elemen anchor HTML [`<a href>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) dapat digunakan sendiri untuk membuat hyperlink ke URL yang berbeza, ini akan menjadikan penyemak imbas memuat semula HTML secara lalai. Adalah perlu untuk mencegah tingkah laku ini ketika menangani routing dengan javascript khusus, menggunakan fungsi preventDefault () pada peristiwa klik.
|
||||
|
||||
### Tugas
|
||||
|
||||
Mari buat fungsi baru yang dapat kita gunakan untuk menavigasi di aplikasi kita:
|
||||
|
||||
```js
|
||||
function navigate(path) {
|
||||
window.history.pushState({}, path, window.location.origin + path);
|
||||
updateRoute();
|
||||
}
|
||||
```
|
||||
|
||||
Kaedah ini terlebih dahulu mengemas kini URL semasa berdasarkan jalan yang diberikan, kemudian mengemas kini templat. Properti `window.location.origin` mengembalikan akar URL, yang membolehkan kami membina semula URL lengkap dari jalan yang ditentukan.
|
||||
|
||||
Sekarang kita mempunyai fungsi ini, kita dapat mengatasi masalah yang kita ada jika jalan tidak sesuai dengan rute yang ditentukan. Kami akan mengubah fungsi `updateRoute` dengan menambahkan fallback ke salah satu laluan yang ada jika kami tidak dapat mencari yang sesuai.
|
||||
|
||||
```js
|
||||
function updateRoute() {
|
||||
const path = window.location.pathname;
|
||||
const route = routes[path];
|
||||
|
||||
if (!route) {
|
||||
return navigate('/login');
|
||||
}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Sekiranya laluan tidak dapat dijumpai, kami sekarang akan mengalihkan ke halaman `login`.
|
||||
|
||||
Sekarang mari kita buat fungsi untuk mendapatkan URL apabila pautan diklik, dan untuk mengelakkan tingkah laku pautan lalai penyemak imbas:
|
||||
|
||||
```js
|
||||
function onLinkClick(event) {
|
||||
event.preventDefault();
|
||||
navigate(event.target.href);
|
||||
}
|
||||
```
|
||||
|
||||
Mari lengkapkan sistem navigasi dengan menambahkan pengikatan pada pautan *Login* dan *Logout* kami dalam HTML.
|
||||
|
||||
```html
|
||||
<a href="/dashboard" onclick="onLinkClick()">Login</a>
|
||||
...
|
||||
<a href="/login" onclick="onLinkClick()">Logout</a>
|
||||
```
|
||||
|
||||
Menggunakan atribut [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) mengikat peristiwa`klik` ke kod JavaScript, di sini panggilan ke `navigasi() `fungsi.
|
||||
|
||||
Cuba klik pada pautan-pautan ini, kini anda seharusnya dapat menavigasi antara pelbagai skrin aplikasi anda.
|
||||
|
||||
✅ Kaedah `history.pushState` adalah sebahagian daripada standard HTML5 dan dilaksanakan di [semua penyemak imbas moden](https://caniuse.com/?search=pushState). Sekiranya anda membuat aplikasi web untuk penyemak imbas yang lebih lama, ada helah yang dapat Anda gunakan sebagai ganti API ini: menggunakan [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) sebelum jalan yang dapat anda laksanakan perutean yang berfungsi dengan navigasi jangkar biasa dan tidak memuat semula halaman, kerana tujuannya adalah untuk membuat pautan dalaman dalam halaman.
|
||||
|
||||
## Mengendalikan butang belakang dan hadapan penyemak imbas
|
||||
|
||||
Menggunakan `history.pushState` membuat entri baru dalam sejarah navigasi penyemak imbas. Anda boleh memastikan bahawa dengan menahan * butang belakang * penyemak imbas anda, ia akan memaparkan sesuatu seperti ini:
|
||||
|
||||
![Tangkapan skrin sejarah navigasi](../history.png)
|
||||
|
||||
Sekiranya anda cuba mengklik butang kembali beberapa kali, anda akan melihat bahawa URL semasa berubah dan sejarahnya dikemas kini, tetapi templat yang sama terus dipaparkan.
|
||||
|
||||
Ini kerana tidak tahu bahawa kita perlu memanggil `updateRoute()` setiap kali sejarah berubah. Sekiranya anda melihat dokumentasi [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState), anda dapat melihat bahawa jika keadaan berubah - yang bermaksud bahawa kami berpindah ke URL yang berbeza - peristiwa [`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event) dicetuskan. Kami akan menggunakannya untuk menyelesaikan masalah itu.
|
||||
|
||||
### Tugas
|
||||
|
||||
Untuk memastikan templat yang ditampilkan diperbaharui ketika sejarah penyemak imbas berubah, kami akan melampirkan fungsi baru yang memanggil `updateRoute ()`. Kami akan melakukannya di bahagian bawah fail `app.js` kami:
|
||||
|
||||
```js
|
||||
window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Catatan: kami menggunakan [fungsi panah](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) di sini untuk menyatakan pengendali acara `popstate` kami untuk kesimpulan, fungsi biasa akan berfungsi sama.
|
||||
|
||||
Berikut adalah video penyegaran mengenai fungsi anak panah:
|
||||
|
||||
[![Fungsi Anak Panah](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Fungsi Anak Panah")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai fungsi anak panah.
|
||||
|
||||
Sekarang cuba gunakan butang belakang dan depan penyemak imbas anda, dan periksa bahawa laluan yang dipaparkan dikemas kini dengan betul kali ini.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Tambahkan templat dan laluan baru untuk halaman ketiga yang menunjukkan kredit untuk aplikasi ini.
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/42)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Perutean adalah salah satu bahagian pengembangan web yang sangat mengejutkan, terutama ketika web beralih dari tingkah laku penyegaran halaman ke penyegaran halaman Aplikasi Halaman Tunggal. Baca sedikit mengenai [bagaimana perkhidmatan Aplikasi Web Statik Azure](https://docs.microsoft.com/en-us/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa) menangani penghalaan . Bolehkah anda menjelaskan mengapa beberapa keputusan yang dijelaskan pada dokumen itu diperlukan?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Tingkatkan penghalaan](assignment.ms.md)
|
@ -0,0 +1,14 @@
|
||||
# Tingkatkan penghalaan
|
||||
|
||||
## Arahan
|
||||
|
||||
Deklarasi laluan hanya mengandungi ID templat yang akan digunakan. Tetapi ketika memaparkan halaman baru, kadang-kadang diperlukan lebih banyak lagi. Mari tingkatkan pelaksanaan penghalaan kami dengan dua ciri tambahan:
|
||||
|
||||
- Berikan tajuk untuk setiap templat dan kemas kini tajuk tetingkap dengan tajuk baru ini apabila templat berubah.
|
||||
- Tambahkan pilihan untuk menjalankan beberapa kod setelah templat berubah. Kami ingin mencetak `"Papan Pemuka ditunjukkan"` di konsol pembangun setiap kali halaman papan pemuka dipaparkan.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| | Kedua-dua ciri tersebut dilaksanakan dan berfungsi. Penambahan tajuk dan kod juga berfungsi untuk laluan baru yang ditambahkan dalam deklarasi `route` | Kedua-dua ciri berfungsi, tetapi tingkah laku itu dikodkan keras dan tidak dapat dikonfigurasi melalui deklarasi `route`. Menambah laluan ketiga dengan penambahan tajuk dan kod tidak berfungsi atau berfungsi secara separa. | Salah satu ciri hilang atau tidak berfungsi dengan baik. |
|
@ -0,0 +1,294 @@
|
||||
# Bina Aplikasi Perbankan Bahagian 2: Bina Log Masuk dan Borang Pendaftaran
|
||||
|
||||
# Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/43)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Di hampir semua aplikasi web moden, anda boleh membuat akaun untuk mempunyai ruang peribadi anda sendiri. Oleh kerana banyak pengguna dapat mengakses aplikasi web pada masa yang sama, anda memerlukan mekanisme untuk menyimpan data peribadi setiap pengguna secara berasingan dan memilih maklumat yang akan ditampilkan. Kami tidak akan membahas bagaimana menguruskan [identiti pengguna dengan selamat](https://en.wikipedia.org/wiki/Authentication) kerana ia adalah topik yang luas sendiri, tetapi kami akan memastikan setiap pengguna dapat membuatnya (atau lebih) akaun bank di aplikasi kami.
|
||||
|
||||
Di bahagian ini kami akan menggunakan borang HTML untuk menambahkan log masuk dan pendaftaran ke aplikasi web kami. Kami akan melihat cara mengirim data ke API pelayan secara terprogram, dan akhirnya bagaimana menentukan peraturan pengesahan asas untuk input pengguna.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda perlu melengkapkan [templat HTML dan perutean](../../1-template-rute/README.md) aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [jalankan API pelayan](../../api/README.md) secara tempatan supaya anda dapat menghantar data untuk membuat akaun.
|
||||
|
||||
Anda boleh menguji bahawa pelayan berjalan dengan betul dengan menjalankan perintah ini di terminal:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> harus mengembalikan "Bank API v1.0.0" sebagai hasilnya
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bentuk dan kawalan
|
||||
|
||||
Elemen `<form>` merangkumi bahagian dokumen HTML di mana pengguna dapat memasukkan dan menyerahkan data dengan kawalan interaktif. Terdapat pelbagai jenis kawalan antara muka pengguna (UI) yang dapat digunakan dalam bentuk, yang paling umum adalah elemen `<input>` dan elemen `<button>`.
|
||||
|
||||
Terdapat banyak [jenis yang berbeza](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) dari `<input>`, misalnya untuk membuat bidang di mana pengguna boleh memasukkan nama penggunanya yang boleh anda gunakan:
|
||||
|
||||
```html
|
||||
<input id="username" name="username" type="text">
|
||||
```
|
||||
|
||||
Atribut `name` akan digunakan sebagai nama harta ketika data borang akan dihantar. Atribut `id` digunakan untuk mengaitkan` <label>` dengan kawalan bentuk.
|
||||
|
||||
> Lihat keseluruhan senarai [`<input>` types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) dan [kawalan bentuk lain](https://developer.mozilla.org/en-US/docs/Learn/Forms/Other_form_controls) untuk mendapatkan idea tentang semua elemen UI asli yang boleh anda gunakan semasa membina UI anda.
|
||||
|
||||
✅ Perhatikan bahawa `<input>` adalah [elemen kosong](https://developer.mozilla.org/en-US/docs/Glossary/Empty_element) di mana anda seharusnya *tidak* menambahkan tag penutup yang sepadan. Anda bagaimanapun boleh menggunakan notasi `<input/>` tutup sendiri, tetapi tidak diperlukan.
|
||||
|
||||
Elemen `<button>` dalam bentuk agak istimewa. Sekiranya anda tidak menentukan atribut `type`, ia akan secara automatik mengirimkan data borang ke pelayan ketika ditekan. Berikut adalah nilai `type` yang mungkin:
|
||||
|
||||
- `submit`: Lalai dalam `<form>`, butang memicu tindakan pengiriman borang.
|
||||
- `reset`: Butang menetapkan semula semua kawalan bentuk ke nilai awalnya.
|
||||
- `button`: Jangan berikan tingkah laku lalai semasa butang ditekan. Anda kemudian dapat menetapkan tindakan khusus untuknya menggunakan JavaScript.
|
||||
|
||||
### Tugas
|
||||
|
||||
Mari mulakan dengan menambahkan borang ke templat `login`. Kami memerlukan medan *nama pengguna* dan butang *Log masuk*.
|
||||
|
||||
```html
|
||||
<template id="login">
|
||||
<h1>Bank App</h1>
|
||||
<section>
|
||||
<h2>Login</h2>
|
||||
<form id="loginForm">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="user" type="text">
|
||||
<button>Login</button>
|
||||
</form>
|
||||
</section>
|
||||
</template>
|
||||
```
|
||||
|
||||
Sekiranya anda melihat lebih dekat, anda dapat melihat bahawa kami juga menambahkan elemen `<label>` di sini. Elemen `<label>` digunakan untuk menambahkan nama ke kawalan UI, seperti bidang nama pengguna kami. Label penting untuk keterbacaan borang anda, tetapi juga dilengkapi dengan faedah tambahan:
|
||||
|
||||
- Dengan mengaitkan label dengan kawalan bentuk, ia membantu pengguna menggunakan teknologi bantu (seperti pembaca skrin) untuk memahami data apa yang diharapkan dapat mereka berikan.
|
||||
- Anda dapat mengklik label untuk memberi fokus langsung pada input yang berkaitan, sehingga lebih mudah dijangkau pada peranti berdasarkan layar sentuh.
|
||||
|
||||
> [Kebolehcapaian](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility) di web adalah topik yang sangat penting yang sering diabaikan. Terima kasih kepada [elemen HTML semantik](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML) tidak sukar untuk membuat kandungan yang boleh diakses jika anda menggunakannya dengan betul. Anda boleh [baca lebih lanjut mengenai kebolehaksesan](https://developer.mozilla.org/en-US/docs/Web/Accessibility) untuk mengelakkan kesilapan biasa dan menjadi pembangun yang bertanggungjawab.
|
||||
|
||||
Sekarang kita akan menambah borang kedua untuk pendaftaran, tepat di bawah yang sebelumnya:
|
||||
|
||||
```html
|
||||
<hr/>
|
||||
<h2>Register</h2>
|
||||
<form id="registerForm">
|
||||
<label for="user">Username</label>
|
||||
<input id="user" name="user" type="text">
|
||||
<label for="currency">Currency</label>
|
||||
<input id="currency" name="currency" type="text" value="$">
|
||||
<label for="description">Description</label>
|
||||
<input id="description" name="description" type="text">
|
||||
<label for="balance">Current balance</label>
|
||||
<input id="balance" name="balance" type="number" value="0">
|
||||
<button>Register</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
Dengan menggunakan atribut `value` kita dapat menentukan nilai lalai untuk input yang diberikan.
|
||||
Perhatikan juga bahawa input untuk `balance` mempunyai jenis `number`. Adakah ia kelihatan berbeza daripada input lain? Cuba berinteraksi dengannya.
|
||||
|
||||
✅ Bolehkah anda menavigasi dan berinteraksi dengan borang hanya menggunakan papan kekunci? Bagaimana anda akan melakukannya?
|
||||
|
||||
## Menyerahkan data ke pelayan
|
||||
|
||||
Sekarang kita mempunyai UI yang berfungsi, langkah seterusnya adalah mengirim data ke pelayan kita. Mari buat ujian cepat menggunakan kod kami sekarang: apa yang berlaku jika anda mengklik butang *Login* atau *Register*?
|
||||
|
||||
Adakah anda melihat perubahan pada bahagian URL penyemak imbas anda?
|
||||
|
||||
![Tangkapan skrin perubahan URL penyemak imbas setelah mengklik butang Daftar](../images/click-register.png)
|
||||
|
||||
Tindakan lalai untuk `<form>` adalah menyerahkan borang ke URL pelayan semasa menggunakan [kaedah GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3 ), menambahkan data borang terus ke URL. Kaedah ini mempunyai beberapa kekurangan walaupun:
|
||||
|
||||
- Ukuran data yang dikirim sangat terhad (sekitar 2000 aksara)
|
||||
- Data dapat dilihat secara langsung di URL (tidak bagus untuk kata laluan)
|
||||
- Ia tidak berfungsi dengan muat naik fail
|
||||
|
||||
Itulah sebabnya anda boleh mengubahnya untuk menggunakan [kaedah POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) yang menghantar data borang ke pelayan di badan permintaan HTTP, tanpa batasan sebelumnya.
|
||||
|
||||
> Walaupun POST adalah kaedah yang paling sering digunakan untuk mengirim data, [dalam beberapa senario tertentu](https://www.w3.org/2001/tag/doc/whenToUseGet.html) lebih baik menggunakan kaedah GET, semasa melaksanakan bidang carian misalnya.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan sifat `action` dan `method` ke borang pendaftaran:
|
||||
|
||||
```html
|
||||
<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">
|
||||
```
|
||||
|
||||
Sekarang cuba daftarkan akaun baru dengan nama anda. Setelah mengklik butang * Daftar * anda akan melihat sesuatu seperti ini:
|
||||
|
||||
![Tetingkap penyemak imbas di alamat localhost:5000/api/akaun, menunjukkan rentetan JSON dengan data pengguna](../images/form-post.png)
|
||||
|
||||
Sekiranya semuanya berjalan lancar, pelayan harus menjawab permintaan anda dengan respons [JSON](https://www.json.org/json-en.html) yang mengandungi data akaun yang telah dibuat.
|
||||
|
||||
✅ Cuba daftar sekali lagi dengan nama yang sama. Apa yang berlaku?
|
||||
|
||||
## Mengirim data tanpa memuatkan semula halaman
|
||||
|
||||
Seperti yang anda perhatikan, ada sedikit masalah dengan pendekatan yang baru kami gunakan: semasa menghantar borang, kami keluar dari aplikasi kami dan penyemak imbas mengalihkan ke URL pelayan. Kami berusaha untuk mengelakkan semua muat semula halaman dengan aplikasi web kami, kerana kami sedang membuat [Aplikasi satu halaman (SPA)](https://en.wikipedia.org/wiki/Single-page_application).
|
||||
|
||||
Untuk mengirim data formulir ke pelayan tanpa memaksa muat ulang halaman, kita harus menggunakan kod JavaScript. Daripada meletakkan URL di properti `action` elemen `<form>`, Anda dapat menggunakan kod JavaScript apa pun yang disiapkan oleh string `javascript:` untuk melakukan tindakan khusus. Menggunakan ini juga bermaksud bahawa anda harus melaksanakan beberapa tugas yang sebelumnya dilakukan secara automatik oleh penyemak imbas:
|
||||
|
||||
- Dapatkan semula data borang
|
||||
- Tukar dan kodkan data bentuk ke format yang sesuai
|
||||
- Buat permintaan HTTP dan kirimkan ke pelayan
|
||||
|
||||
### Tugas
|
||||
|
||||
Ganti borang tindakan `action` dengan:
|
||||
|
||||
```html
|
||||
<form id="registerForm" action="javascript:register()">
|
||||
```
|
||||
|
||||
Buka `app.js` tambahkan fungsi baru bernama `register`:
|
||||
|
||||
```js
|
||||
function register() {
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
const formData = new FormData(registerForm);
|
||||
const data = Object.fromEntries(formData);
|
||||
const jsonData = JSON.stringify(data);
|
||||
}
|
||||
```
|
||||
|
||||
Di sini kita mengambil elemen borang menggunakan `getElementById()` dan menggunakan pembantu [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) untuk mengekstrak nilai dari borang kawalan sebagai satu set pasangan kunci / nilai. Kemudian kami menukar data ke objek biasa menggunakan [`Object.fromEntries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) dan akhirnya bersiri data ke [JSON](https://www.json.org/json-en.html), format yang biasa digunakan untuk pertukaran data di web.
|
||||
|
||||
Data kini siap dihantar ke pelayan. Buat fungsi baru bernama `createAccount`:
|
||||
|
||||
```js
|
||||
async function createAccount(account) {
|
||||
try {
|
||||
const response = await fetch('//localhost:5000/api/accounts', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: account
|
||||
});
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
return { error: error.message || 'Unknown error' };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Apakah fungsi ini? Pertama, perhatikan kata kunci `async` di sini. Ini bermaksud bahawa fungsi tersebut mengandungi kod yang akan menjalankan [**asynchronously**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). Apabila digunakan di sepanjang kata kunci `await`, ia membolehkan menunggu kod tak segerak untuk dilaksanakan - seperti menunggu tindak balas pelayan di sini - sebelum meneruskan.
|
||||
|
||||
Berikut adalah video ringkas mengenai penggunaan `async/await`:
|
||||
|
||||
[![Async dan Tunggu untuk menguruskan janji](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async dan Tunggu untuk mengurus janji")
|
||||
|
||||
> Klik gambar di atas untuk video mengenai async / waiting.
|
||||
|
||||
Kami menggunakan API `fetch()` untuk mengirim data JSON ke pelayan. Kaedah ini mengambil 2 parameter:
|
||||
|
||||
- URL pelayan, jadi kami meletakkan kembali `//localhost5000/api/akaun` di sini.
|
||||
- Tetapan permintaan. Di situlah kami menetapkan kaedah untuk `POST` dan memberikan `body` untuk permintaan tersebut. Semasa kami menghantar data JSON ke pelayan, kami juga perlu menetapkan tajuk `Content-Type` ke` application/json` sehingga pelayan tahu bagaimana menafsirkan isi.
|
||||
|
||||
Oleh kerana pelayan akan menjawab permintaan dengan JSON, kita dapat menggunakan `tunggu tunggu.json()` untuk mengurai kandungan JSON dan mengembalikan objek yang dihasilkan. Perhatikan bahawa kaedah ini tidak segerak, jadi kami menggunakan kata kunci `tunggu 'di sini sebelum kembali untuk memastikan sebarang ralat semasa penghuraian juga terperangkap.
|
||||
|
||||
Sekarang tambahkan beberapa kod ke fungsi `register` untuk memanggil `createAccount()`:
|
||||
|
||||
```js
|
||||
const result = await createAccount(jsonData);
|
||||
```
|
||||
|
||||
Kerana kita menggunakan kata kunci `await` di sini, kita perlu menambahkan kata kunci `async` sebelum fungsi daftar:
|
||||
|
||||
```js
|
||||
async function register() {
|
||||
```
|
||||
|
||||
Akhirnya, mari kita tambahkan beberapa log untuk memeriksa hasilnya. Fungsi terakhir kelihatan seperti ini:
|
||||
|
||||
```js
|
||||
async function register() {
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
const formData = new FormData(registerForm);
|
||||
const jsonData = JSON.stringify(Object.fromEntries(formData));
|
||||
const result = await createAccount(jsonData);
|
||||
|
||||
if (result.error) {
|
||||
return console.log('An error occured:', result.error);
|
||||
}
|
||||
|
||||
console.log('Account created!', result);
|
||||
}
|
||||
```
|
||||
|
||||
Itu agak lama tetapi kami sampai di sana! Sekiranya anda membuka [alat pembangun penyemak imbas](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), dan cuba mendaftarkan akaun baru, anda tidak akan melihat perubahan di laman web tetapi mesej akan muncul di konsol yang mengesahkan bahawa semuanya berfungsi.
|
||||
|
||||
![Tangkapan skrin yang menunjukkan mesej log di konsol penyemak imbas](../images/browser-console.png)
|
||||
|
||||
✅ Anda fikir data dihantar ke pelayan dengan selamat? Bagaimana jika seseorang yang dapat memintas permintaan itu? Anda boleh membaca mengenai [HTTPS](https://en.wikipedia.org/wiki/HTTPS) untuk mengetahui lebih lanjut mengenai komunikasi data yang selamat.
|
||||
|
||||
## Pengesahan data
|
||||
|
||||
Sekiranya anda cuba mendaftarkan akaun baru tanpa menetapkan nama pengguna terlebih dahulu, anda dapat melihat bahawa pelayan mengembalikan ralat dengan kod status [400 (Bad Request)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,%2C%20or%20deceptive%20request%20routing).).
|
||||
|
||||
Sebelum menghantar data ke pelayan, adalah amalan yang baik untuk [mengesahkan data borang](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) terlebih dahulu apabila mungkin, untuk memastikan anda menghantar permintaan yang sah. Kawalan borang HTML5 memberikan pengesahan terbina dalam menggunakan pelbagai atribut:
|
||||
|
||||
- `diperlukan`: bidang perlu diisi jika tidak, borang tidak dapat dihantar.
|
||||
- `minlength` dan` maxlength`: menentukan bilangan aksara minimum dan maksimum dalam bidang teks.
|
||||
- `min` dan `max`: menentukan nilai minimum dan maksimum medan angka.
|
||||
- `type`: mentakrifkan jenis data yang diharapkan, seperti `number`, `email`, `file` atau [other built-in types](https://developer.mozilla.org/en-US/docs/Web/HTML/Elemen/input). Atribut ini juga dapat mengubah rendering visual kawalan bentuk.
|
||||
- `pattern`: memungkinkan untuk menentukan [ungkapan biasa](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) untuk menguji sama ada data yang dimasukkan sah atau tidak.
|
||||
|
||||
> Petua: anda boleh menyesuaikan rupa kawalan borang anda bergantung pada apakah itu sah atau tidak menggunakan kelas pseudo CSS `:invalid` dan`:valid`.
|
||||
|
||||
### Tugas
|
||||
|
||||
Terdapat 2 medan yang diperlukan untuk membuat akaun baru yang sah, nama pengguna dan mata wang, medan lain menjadi pilihan. Kemas kini HTML borang, menggunakan atribut `required` dan teks di label medan untuk itu:
|
||||
|
||||
```html
|
||||
<label for="user">Username (required)</label>
|
||||
<input id="user" name="user" type="text" required>
|
||||
...
|
||||
<label for="currency">Currency (required)</label>
|
||||
<input id="currency" name="currency" type="text" value="$" required>
|
||||
```
|
||||
|
||||
Walaupun pelaksanaan pelayan tertentu ini tidak memaksakan had khusus pada panjang maksimum medan, selalu menjadi amalan yang baik untuk menentukan had yang munasabah untuk setiap entri teks pengguna.
|
||||
|
||||
Tambahkan atribut `maxlength` ke medan teks:
|
||||
|
||||
```html
|
||||
<input id="user" name="user" type="text" maxlength="20" required>
|
||||
...
|
||||
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
|
||||
...
|
||||
<input id="description" name="description" type="text" maxlength="100">
|
||||
```
|
||||
|
||||
Sekarang jika anda menekan butang *Daftar* dan medan tidak mematuhi peraturan pengesahan yang kami tetapkan, anda akan melihat sesuatu seperti ini:
|
||||
|
||||
![Tangkapan skrin menunjukkan ralat pengesahan semasa cuba menghantar borang](../images/validation-error.png)
|
||||
|
||||
Pengesahan seperti ini dilakukan *sebelum* menghantar sebarang data ke pelayan dipanggil pengesahan **client-side**. Tetapi perhatikan bahawa tidak semestinya melakukan semua pemeriksaan tanpa menghantar data. Sebagai contoh, kami tidak dapat memeriksa di sini jika akaun sudah ada dengan nama pengguna yang sama tanpa menghantar permintaan ke pelayan. Pengesahan tambahan yang dilakukan di pelayan dipanggil pengesahan **server-side**.
|
||||
|
||||
Biasanya kedua-duanya perlu dilaksanakan, dan semasa menggunakan pengesahan sisi klien meningkatkan pengalaman pengguna dengan memberikan maklum balas segera kepada pengguna, pengesahan sisi pelayan sangat penting untuk memastikan data pengguna yang anda manipulasi adalah baik dan selamat.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Tunjukkan mesej ralat dalam HTML jika pengguna sudah ada.
|
||||
|
||||
Berikut adalah contoh bagaimana rupa halaman log masuk akhir setelah sedikit gaya:
|
||||
|
||||
![Tangkapan skrin halaman log masuk setelah menambahkan gaya CSS](../images/result.png)
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/44)
|
||||
|
||||
## Mengkaji & Belajar Sendiri
|
||||
|
||||
Pembangun menjadi sangat kreatif mengenai usaha membina bentuk mereka, terutama mengenai strategi pengesahan. Ketahui mengenai aliran bentuk yang berbeza dengan melihat melalui [CodePen](https://codepen.com); bolehkah anda mencari beberapa bentuk yang menarik dan memberi inspirasi?
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Gayakan bank app anda](assignment.ms.md)
|
@ -0,0 +1,13 @@
|
||||
# Gaya aplikasi bank anda
|
||||
|
||||
## Arahan
|
||||
|
||||
Buat fail `styles.css` baru dan tambahkan pautan ke dalam fail `index.html` semasa anda. Dalam fail CSS yang baru anda buat, tambahkan beberapa gaya untuk menjadikan halaman *Login* dan *Dashboard* kelihatan baik dan kemas. Cuba buat tema warna untuk memberikan jenama sendiri pada aplikasi anda.
|
||||
|
||||
> Petua: anda boleh mengubah HTML dan menambahkan elemen dan kelas baru jika diperlukan.
|
||||
|
||||
## Rubrik
|
||||
|
||||
| kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| | Semua halaman kelihatan bersih dan mudah dibaca, dengan tema warna yang konsisten dan bahagian yang berbeza menonjol dengan betul. | Halaman digayakan tetapi tanpa tema atau bahagian yang tidak dibatasi dengan jelas. | Halaman kurang digayakan, bahagiannya kelihatan tidak teratur dan maklumatnya sukar dibaca. |
|
@ -0,0 +1,334 @@
|
||||
# Bina Aplikasi Perbankan Bahagian 3: Kaedah Mengambil dan Menggunakan Data
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/45)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Inti setiap aplikasi web ada *data*. Data boleh dilakukan dalam pelbagai bentuk, tetapi tujuan utamanya adalah untuk menunjukkan maklumat kepada pengguna. Dengan aplikasi web menjadi semakin interaktif dan kompleks, bagaimana pengguna mengakses dan berinteraksi dengan maklumat kini menjadi bahagian penting dalam pembangunan web.
|
||||
|
||||
Dalam pelajaran ini, kita akan melihat cara mengambil data dari pelayan secara asinkron, dan menggunakan data ini untuk memaparkan maklumat di laman web tanpa memuatkan semula HTML.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda perlu membina bahagian [Borang Log Masuk dan Pendaftaran](../2-forms/README.md) dari aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [jalankan API pelayan](../api/README.md) secara tempatan supaya anda mendapat data akaun.
|
||||
|
||||
Anda boleh menguji bahawa pelayan berjalan dengan betul dengan menjalankan perintah ini di terminal:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> harus mengembalikan "Bank API v1.0.0" sebagai hasilnya
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AJAX dan pengambilan data
|
||||
|
||||
Laman web tradisional mengemas kini kandungan yang dipaparkan ketika pengguna memilih pautan atau mengirimkan data menggunakan borang, dengan memuatkan semula halaman HTML penuh. Setiap kali data baru dimuat, pelayan web mengembalikan halaman HTML baru yang perlu diproses oleh penyemak imbas, mengganggu tindakan pengguna semasa dan membatasi interaksi semasa muat semula. Alur kerja ini juga disebut *Aplikasi Multi-Halaman* atau *MPA*.
|
||||
|
||||
![Kemas kini aliran kerja dalam aplikasi berbilang halaman](./images/mpa.png)
|
||||
|
||||
Ketika aplikasi web mula menjadi lebih kompleks dan interaktif, teknik baru yang disebut [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)) muncul. Teknik ini membolehkan aplikasi web mengirim dan mengambil data dari pelayan secara asinkron menggunakan JavaScript, tanpa harus memuat semula halaman HTML, menghasilkan kemas kini yang lebih cepat dan interaksi pengguna yang lebih lancar. Apabila data baru diterima dari pelayan, halaman HTML semasa juga dapat diperbarui dengan JavaScript menggunakan API [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model). Dari masa ke masa, pendekatan ini telah berkembang menjadi apa yang sekarang disebut [*Aplikasi Halaman Tunggal* atau *SPA*](https://en.wikipedia.org/wiki/Single-page_application).
|
||||
|
||||
![Kemas kini alur kerja dalam aplikasi satu halaman](./images/spa.png)
|
||||
|
||||
Semasa AJAX pertama kali diperkenalkan, satu-satunya API yang tersedia untuk mengambil data secara asinkron adalah [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Tetapi penyemak imbas moden kini juga melaksanakan [`Fetch` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), yang menggunakan janji dan lebih sesuai untuk dimanipulasi Data JSON.
|
||||
|
||||
> Walaupun semua penyemak imbas moden menyokong `Fetch API`, jika anda mahu aplikasi web anda berfungsi pada penyemak imbas lama atau penyemak imbas lama, sebaiknya periksa [jadual keserasian di caniuse.com](https://caniuse.com/fetch) pertama.
|
||||
|
||||
### Tugas
|
||||
|
||||
Dalam [pelajaran sebelumnya](../2-form/README.md) kami melaksanakan borang pendaftaran untuk membuat akaun. Kami sekarang akan menambahkan kod untuk log masuk menggunakan akaun yang ada, dan mengambil datanya. Buka fail `app.js` dan tambahkan fungsi `login` baru:
|
||||
|
||||
```js
|
||||
async function login() {
|
||||
const loginForm = document.getElementById('loginForm')
|
||||
const user = loginForm.user.value;
|
||||
}
|
||||
```
|
||||
|
||||
Di sini kita mulakan dengan mengambil elemen borang dengan `getElementById()`, dan kemudian kita mendapat nama pengguna dari input dengan `loginForm.user.value`. Setiap kawalan borang dapat diakses dengan namanya (diatur dalam HTML menggunakan atribut `name`) sebagai harta bentuk.
|
||||
|
||||
Dengan cara yang serupa dengan apa yang kami lakukan untuk pendaftaran, kami akan membuat fungsi lain untuk melakukan permintaan pelayan, tetapi kali ini untuk mengambil data akaun:
|
||||
|
||||
```js
|
||||
async function getAccount(user) {
|
||||
try {
|
||||
const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
return { error: error.message || 'Unknown error' };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Kami menggunakan API `fetch` untuk meminta data secara tidak serentak dari pelayan, tetapi kali ini kami tidak memerlukan parameter tambahan selain URL untuk dipanggil, kerana kami hanya meminta data. Secara lalai, `fetch` membuat permintaan HTTP [`GET`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET), itulah yang kami cari di sini.
|
||||
|
||||
✅ `encodeURIComponent()` adalah fungsi yang melarikan diri daripada watak khas untuk URL. Masalah apa yang mungkin kita hadapi jika kita tidak memanggil fungsi ini dan menggunakan nilai `pengguna` secara langsung di URL?
|
||||
|
||||
Sekarang mari kita kemas kini fungsi `login` kami untuk menggunakan `getAccount`:
|
||||
|
||||
```js
|
||||
async function login() {
|
||||
const loginForm = document.getElementById('loginForm')
|
||||
const user = loginForm.user.value;
|
||||
const data = await getAccount(user);
|
||||
|
||||
if (data.error) {
|
||||
return console.log('loginError', data.error);
|
||||
}
|
||||
|
||||
account = data;
|
||||
navigate('/dashboard');
|
||||
}
|
||||
```
|
||||
|
||||
Pertama, kerana `getAccount` adalah fungsi tak segerak, kita perlu memadankannya dengan kata kunci `await` untuk menunggu hasil pelayan. Seperti permintaan pelayan, kami juga harus menangani kes ralat. Buat masa ini kami hanya akan menambahkan mesej log untuk memaparkan ralat, dan kembali kepadanya kemudian.
|
||||
|
||||
Kemudian kita harus menyimpan data di suatu tempat sehingga nanti kita dapat menggunakannya untuk memaparkan maklumat papan pemuka. Oleh kerana pemboleh ubah `account` belum ada, kami akan membuat pemboleh ubah global untuknya di bahagian atas fail kami:
|
||||
|
||||
```js
|
||||
let account = null;
|
||||
```
|
||||
|
||||
Setelah data pengguna disimpan ke dalam variabel kita dapat menavigasi dari halaman *login* ke papan pemuka * menggunakan fungsi `navigate()` yang sudah kita miliki.
|
||||
|
||||
Akhirnya, kita perlu memanggil fungsi `login` kita semasa borang log masuk dihantar, dengan mengubah HTML:
|
||||
|
||||
```html
|
||||
<form id="loginForm" action="javascript:login()">
|
||||
```
|
||||
|
||||
Uji bahawa semuanya berfungsi dengan betul dengan mendaftarkan akaun baru dan cuba log masuk menggunakan akaun yang sama.
|
||||
|
||||
Sebelum beralih ke bahagian seterusnya, kita juga dapat menyelesaikan fungsi `register` dengan menambahkan ini di bahagian bawah fungsi:
|
||||
|
||||
```js
|
||||
account = result;
|
||||
navigate('/dashboard');
|
||||
```
|
||||
|
||||
✅ Tahukah anda bahawa secara lalai, anda hanya dapat memanggil API pelayan dari *domain dan port yang sama* daripada halaman web yang anda lihat? Ini adalah mekanisme keselamatan yang dikuatkuasakan oleh penyemak imbas. Tetapi tunggu, aplikasi web kami berjalan di `localhost: 3000` sedangkan API pelayan berjalan di `localhost: 5000`, mengapa ia berfungsi? Dengan menggunakan teknik yang disebut [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), adalah mungkin untuk melakukan permintaan HTTP bersilang asal jika pelayan menambah tajuk khas untuk respons, yang memungkinkan pengecualian untuk domain tertentu.
|
||||
|
||||
> Ketahui lebih lanjut mengenai API dengan mengambil [pelajaran](https://docs.microsoft.com/en-us/learn/modules/use-apis-discover-museum-art?WT.mc_id=academic-13441-cxa)
|
||||
|
||||
## Kemas kini HTML untuk memaparkan data
|
||||
|
||||
Sekarang kita mempunyai data pengguna, kita harus mengemas kini HTML yang ada untuk memaparkannya. Kami sudah tahu cara mendapatkan elemen dari DOM menggunakan contohnya `document.getElementById()`. Setelah anda mempunyai elemen asas, berikut adalah beberapa API yang boleh anda gunakan untuk mengubahnya atau menambahkan elemen anak padanya:
|
||||
|
||||
- Dengan menggunakan sifat [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent), anda boleh mengubah teks elemen. Perhatikan bahawa mengubah nilai ini akan membuang semua anak elemen (jika ada) dan menggantinya dengan teks yang disediakan. Oleh itu, ini juga kaedah yang berkesan untuk membuang semua anak dari elemen tertentu dengan memberikan string kosong "" kepadanya.
|
||||
|
||||
- Menggunakan [`document.createElement()`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentcreateElement) bersama dengan [`append()`](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append) kaedah anda boleh membuat dan melampirkan satu atau lebih elemen anak baru.
|
||||
|
||||
✅ Menggunakan sifat [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) elemen juga mungkin untuk mengubah kandungan HTMLnya, tetapi yang ini harus dielakkan kerana terdedah kepada serangan [cross-site scripting (XSS)](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting) serangan.
|
||||
|
||||
### Tugas
|
||||
|
||||
Sebelum beralih ke skrin papan pemuka, ada satu perkara lagi yang harus kita lakukan di halaman *log masuk*. Pada masa ini, jika anda cuba log masuk dengan nama pengguna yang tidak ada, mesej ditunjukkan di konsol tetapi untuk pengguna biasa tidak ada yang berubah dan anda tidak tahu apa yang berlaku.
|
||||
|
||||
Mari tambahkan elemen placeholder dalam borang log masuk di mana kita dapat memaparkan mesej ralat jika diperlukan. Tempat yang bagus adalah tepat sebelum log masuk `<button>`:
|
||||
|
||||
```html
|
||||
...
|
||||
<div id="loginError"></div>
|
||||
<button>Login</button>
|
||||
...
|
||||
```
|
||||
|
||||
Elemen `<div>` ini kosong, yang bermaksud bahawa tidak ada yang akan dipaparkan di layar sehingga kami menambahkan beberapa kandungan ke dalamnya. Kami juga memberikannya `id` sehingga kami dapat mengambilnya dengan mudah dengan JavaScript.
|
||||
|
||||
Kembali ke fail `app.js` dan buat fungsi pembantu baru `updateElement`:
|
||||
|
||||
```js
|
||||
function updateElement(id, text) {
|
||||
const element = document.getElementById(id);
|
||||
element.textContent = text;
|
||||
}
|
||||
```
|
||||
|
||||
Yang ini cukup mudah: diberi elemen *id* dan *teks*, ia akan mengemas kini kandungan teks elemen DOM dengan `id` yang sepadan. Mari gunakan kaedah ini sebagai ganti mesej ralat sebelumnya dalam fungsi `login`:
|
||||
|
||||
```js
|
||||
if (data.error) {
|
||||
return updateElement('loginError', data.error);
|
||||
}
|
||||
```
|
||||
|
||||
Sekiranya anda cuba log masuk dengan akaun yang tidak sah, anda akan melihat seperti ini:
|
||||
|
||||
![Tangkapan skrin yang menunjukkan mesej ralat yang ditunjukkan semasa log masuk](../images/login-error.png)
|
||||
|
||||
Sekarang kita mempunyai teks ralat yang muncul secara visual, tetapi jika anda mencubanya dengan pembaca skrin, anda akan melihat bahawa tidak ada yang diumumkan. Agar teks yang ditambahkan secara dinamis ke halaman diumumkan oleh pembaca skrin, ia perlu menggunakan sesuatu yang disebut [Live Region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions). Di sini kita akan menggunakan jenis kawasan langsung yang disebut amaran:
|
||||
|
||||
```html
|
||||
<div id="loginError" role="alert"></div>
|
||||
```
|
||||
|
||||
Terapkan tingkah laku yang sama untuk kesalahan fungsi `register` (jangan lupa untuk mengemas kini HTML).
|
||||
|
||||
## Paparkan maklumat di papan pemuka
|
||||
|
||||
Dengan menggunakan teknik yang sama seperti yang baru kita lihat, kita juga akan menjaga memaparkan maklumat akaun di halaman papan pemuka.
|
||||
|
||||
Seperti inilah objek akaun yang diterima dari pelayan:
|
||||
|
||||
```json
|
||||
{
|
||||
"user": "test",
|
||||
"currency": "$",
|
||||
"description": "Test account",
|
||||
"balance": 75,
|
||||
"transactions": [
|
||||
{ "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
|
||||
{ "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
|
||||
{ "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
> Catatan: untuk menjadikan hidup anda lebih mudah, anda boleh menggunakan akaun `test` yang sudah ada yang sudah diisi dengan data.
|
||||
|
||||
### Tugas
|
||||
|
||||
Mari mulakan dengan mengganti bahagian "Baki" dalam HTML untuk menambahkan elemen ruang letak:
|
||||
|
||||
```html
|
||||
<section>
|
||||
Balance: <span id="balance"></span><span id="currency"></span>
|
||||
</section>
|
||||
```
|
||||
|
||||
Kami juga akan menambah bahagian baru di bawah untuk memaparkan keterangan akaun:
|
||||
|
||||
```html
|
||||
<h2 id="description"></h2>
|
||||
```
|
||||
|
||||
✅ Oleh kerana perihalan akaun berfungsi sebagai tajuk untuk kandungan di bawahnya, ia ditandakan secara semantik sebagai tajuk. Ketahui lebih lanjut mengenai bagaimana [struktur tajuk](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) penting untuk dilayari, dan lihat halaman secara kritis untuk menentukan apa lagi boleh menjadi tajuk.
|
||||
|
||||
Seterusnya, kami akan membuat fungsi baru di `app.js` untuk mengisi ruang letak:
|
||||
|
||||
```js
|
||||
function updateDashboard() {
|
||||
if (!account) {
|
||||
return navigate('/login');
|
||||
}
|
||||
|
||||
updateElement('description', account.description);
|
||||
updateElement('balance', account.balance.toFixed(2));
|
||||
updateElement('currency', account.currency);
|
||||
}
|
||||
```
|
||||
|
||||
Pertama, kami memeriksa bahawa kami mempunyai data akaun yang kami perlukan sebelum melangkah lebih jauh. Kemudian kami menggunakan fungsi `updateElement()` yang kami buat sebelumnya untuk mengemas kini HTML.
|
||||
|
||||
> Untuk menjadikan paparan keseimbangan lebih cantik, kami menggunakan kaedah [`toFixed(2)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) untuk daya memaparkan nilai dengan 2 digit selepas titik perpuluhan.
|
||||
|
||||
Sekarang kita perlu memanggil fungsi `updateDashboard()` setiap kali papan pemuka dimuat. Sekiranya anda sudah menyelesaikan [tugasan 1](../1-template-route/assignment.md) ini harus dilakukan dengan mudah, jika tidak, anda boleh menggunakan pelaksanaan berikut.
|
||||
|
||||
Tambahkan kod ini ke akhir fungsi `updateRoute()`:
|
||||
|
||||
```js
|
||||
if (typeof route.init === 'function') {
|
||||
route.init();
|
||||
}
|
||||
```
|
||||
|
||||
And update the routes definition with:
|
||||
|
||||
```js
|
||||
const routes = {
|
||||
'/login': { templateId: 'login' },
|
||||
'/dashboard': { templateId: 'dashboard', init: updateDashboard }
|
||||
};
|
||||
```
|
||||
|
||||
Dengan perubahan ini, setiap kali halaman dashboard ditampilkan, fungsi `updateDashboard()` dipanggil. Selepas log masuk, anda seharusnya dapat melihat baki akaun, mata wang dan keterangan.
|
||||
|
||||
## Buat baris jadual secara dinamik dengan templat HTML
|
||||
|
||||
Dalam [first lesson](../1-template-route/README.md) kami menggunakan templat HTML bersama dengan [`appendChild()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild) kaedah untuk melaksanakan navigasi di aplikasi kami. Templat juga dapat lebih kecil dan digunakan untuk mengisi bahagian halaman yang berulang secara dinamis.
|
||||
|
||||
Kami akan menggunakan pendekatan yang serupa untuk memaparkan senarai transaksi dalam jadual HTML.
|
||||
|
||||
### Tugas
|
||||
|
||||
Tambahkan templat baru dalam HTML `<body>`:
|
||||
|
||||
```html
|
||||
<template id="transaction">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</template>
|
||||
```
|
||||
|
||||
Templat ini mewakili satu baris jadual, dengan 3 lajur yang ingin kita isi: *tarikh*, *objek* dan *jumlah* transaksi.
|
||||
|
||||
Kemudian, tambahkan sifat `id` ini ke elemen` <tbody> `di dalam templat papan pemuka untuk memudahkan pencarian menggunakan JavaScript:
|
||||
|
||||
```html
|
||||
<tbody id="transactions"></tbody>
|
||||
```
|
||||
|
||||
HTML kami sudah siap, mari beralih ke kod JavaScript dan buat fungsi baru `createTransactionRow`:
|
||||
|
||||
```js
|
||||
function createTransactionRow(transaction) {
|
||||
const template = document.getElementById('transaction');
|
||||
const transactionRow = template.content.cloneNode(true);
|
||||
const tr = transactionRow.querySelector('tr');
|
||||
tr.children[0].textContent = transaction.date;
|
||||
tr.children[1].textContent = transaction.object;
|
||||
tr.children[2].textContent = transaction.amount.toFixed(2);
|
||||
return transactionRow;
|
||||
}
|
||||
```
|
||||
|
||||
Fungsi ini melakukan apa yang disiratkan namanya: menggunakan templat yang kita buat sebelumnya, ia membuat baris jadual baru dan mengisi isinya menggunakan data transaksi. Kami akan menggunakannya dalam fungsi `updateDashboard()` kami untuk mengisi jadual:
|
||||
|
||||
```js
|
||||
const transactionsRows = document.createDocumentFragment();
|
||||
for (const transaction of account.transactions) {
|
||||
const transactionRow = createTransactionRow(transaction);
|
||||
transactionsRows.appendChild(transactionRow);
|
||||
}
|
||||
updateElement('transactions', transactionsRows);
|
||||
```
|
||||
|
||||
Di sini kita menggunakan kaedah [`document.createDocumentFragment()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment) yang membuat serpihan DOM baru yang boleh kita gunakan , sebelum akhirnya melampirkannya ke jadual HTML kami.
|
||||
|
||||
Masih ada satu perkara lagi yang harus kita lakukan sebelum kod ini dapat berfungsi, kerana fungsi `updateElement()` kami pada masa ini hanya menyokong kandungan teks. Mari ubah kodnya sedikit:
|
||||
|
||||
```js
|
||||
function updateElement(id, textOrNode) {
|
||||
const element = document.getElementById(id);
|
||||
element.textContent = ''; // Removes all children
|
||||
element.append(textOrNode);
|
||||
}
|
||||
```
|
||||
|
||||
Kami menggunakan kaedah [`append()`](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append) kerana ia membolehkan melampirkan teks atau [DOM Nodes] (https : //developer.mozilla.org/en-US/docs/Web/API/Node) ke elemen induk, yang sangat sesuai untuk semua kes penggunaan kami.
|
||||
|
||||
Sekiranya anda cuba menggunakan akaun `test` untuk log masuk, kini anda akan melihat senarai transaksi di papan pemuka 🎉.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Bekerjasama untuk menjadikan halaman papan pemuka kelihatan seperti aplikasi perbankan sebenar. Sekiranya anda sudah menggayakan aplikasi anda, cuba gunakan [pertanyaan media](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries) untuk membuat [responsive design](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) berfungsi dengan baik pada kedua-dua desktop dan peranti mudah alih.
|
||||
|
||||
Berikut adalah contoh halaman papan pemuka yang digayakan:
|
||||
|
||||
![Tangkapan skrin hasil contoh papan pemuka selepas menggayakan](../../images/screen2.png)
|
||||
|
||||
## Kuiz Pasca Kuliah
|
||||
|
||||
[Kuiz Pasca Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/46)
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Refaktor dan komen kod anda](assignment.ms.md)
|
@ -0,0 +1,15 @@
|
||||
# Refaktor dan komen kod anda
|
||||
|
||||
## Arahan
|
||||
|
||||
Apabila pangkalan kod anda berkembang, penting untuk kerap mengubah kod anda agar tetap dapat dibaca dan dikekalkan dari masa ke masa. Tambahkan komen dan ubah semula `app.js` anda untuk meningkatkan kualiti kod:
|
||||
|
||||
- Ekstrak pemalar, seperti URL asas API pelayan
|
||||
- Faktorkan kod yang serupa: misalnya, anda dapat membuat fungsi `sendRequest()` untuk mengumpulkan kembali kod yang digunakan dalam `createAccount()` dan `getAccount()`
|
||||
- Susun semula kod untuk memudahkan membaca, dan menambah komen
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| | Kod dikomentari, disusun dengan baik dalam pelbagai bahagian dan senang dibaca Pemalar diekstrak dan fungsi `sendRequest()` yang difaktorkan telah dibuat. | Kodnya bersih tetapi masih boleh diperbaiki dengan lebih banyak komen, pengekstrakan berterusan atau pemfaktoran. | Kod tidak kemas, tidak dikomentari, pemalar tidak diekstrak dan kod tidak difaktorkan. |
|
@ -0,0 +1,281 @@
|
||||
# Bina Aplikasi Perbankan Bahagian 4: Konsep State Management
|
||||
|
||||
## Kuiz Pra Kuliah
|
||||
|
||||
[Kuiz Pra Kuliah](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/47)
|
||||
|
||||
### Pengenalan
|
||||
|
||||
Apabila aplikasi web berkembang, menjadi cabaran untuk mengawasi semua aliran data. Kod mana yang mendapat data, halaman mana yang menggunakannya, di mana dan kapan ia perlu dikemas kini ... mudah untuk berakhir dengan kod tidak kemas yang sukar dijaga. Ini benar terutamanya apabila anda perlu berkongsi data di antara halaman aplikasi anda yang berbeza, misalnya data pengguna. Konsep *state management* selalu ada dalam semua jenis program, tetapi ketika aplikasi web terus berkembang dalam kerumitan, kini menjadi titik penting untuk dipikirkan semasa pembangunan.
|
||||
|
||||
Pada bahagian akhir ini, kita akan melihat aplikasi yang kita buat untuk memikirkan kembali bagaimana keadaan dikendalikan, yang membolehkan sokongan penyegaran penyemak imbas pada bila-bila masa, dan data yang berterusan sepanjang sesi pengguna.
|
||||
|
||||
### Prasyarat
|
||||
|
||||
Anda perlu menyelesaikan bahagian [pengambilan data](../../3-data/translations/README.ms.md) pada aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [jalankan API pelayan](../../api/README.ms.md) secara tempatan supaya anda dapat menguruskan data akaun.
|
||||
|
||||
Anda boleh menguji bahawa pelayan berjalan dengan betul dengan menjalankan perintah ini di terminal:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> should return "Bank API v1.0.0" as a result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fikirkan semula state management
|
||||
|
||||
Dalam [pelajaran sebelumnya](../../3-data/translations/README.md), kami memperkenalkan konsep dasar keadaan dalam aplikasi kami dengan pemboleh ubah `akaun` global yang mengandungi data bank untuk pengguna yang sedang log masuk. Walau bagaimanapun, pelaksanaan kami sekarang mempunyai beberapa kekurangan. Cuba muat semula halaman semasa anda berada di papan pemuka. Apa yang berlaku?
|
||||
|
||||
Terdapat 3 masalah dengan kod semasa:
|
||||
|
||||
- Keadaan tidak berterusan, kerana penyegaran penyemak imbas membawa anda kembali ke halaman log masuk.
|
||||
- Terdapat pelbagai fungsi yang mengubah keadaan. Apabila aplikasinya berkembang, ini akan menyukarkan untuk mengesan perubahan dan mudah untuk melupakan pembaharuan.
|
||||
- Keadaan tidak dibersihkan, apabila anda mengklik *Logout* data akaun masih ada walaupun anda berada di halaman log masuk.
|
||||
|
||||
Kami dapat mengemas kini kod kami untuk mengatasi masalah ini satu demi satu, tetapi ini akan membuat lebih banyak pendua kod dan menjadikan aplikasi lebih rumit dan sukar untuk dijaga. Atau kita boleh berhenti sebentar dan memikirkan semula strategi kita.
|
||||
|
||||
> Masalah apa yang sebenarnya ingin kita selesaikan di sini?
|
||||
|
||||
[State Management](https://en.wikipedia.org/wiki/State_management) adalah mengenai mencari pendekatan yang baik untuk menyelesaikan dua masalah tertentu:
|
||||
|
||||
- Bagaimana agar aliran data dalam aplikasi dapat difahami?
|
||||
- Bagaimana cara menjaga data keadaan selalu selari dengan antara muka pengguna (dan sebaliknya)?
|
||||
|
||||
Setelah menyelesaikan masalah ini, masalah lain yang mungkin anda miliki mungkin sudah selesai atau menjadi lebih mudah untuk diselesaikan. Terdapat banyak kemungkinan pendekatan untuk menyelesaikan masalah ini, tetapi kami akan menggunakan penyelesaian bersama yang terdiri daripada **memusatkan data dan cara mengubahnya**. Aliran data akan seperti ini:
|
||||
|
||||
![Skema yang menunjukkan aliran data antara HTML, tindakan pengguna dan keadaan](../images/data-flow.png)
|
||||
|
||||
> Kami tidak akan membahas di sini bahagian di mana data secara automatik mencetuskan kemas kini paparan, kerana ia berkaitan dengan konsep [Pemrograman Reaktif](https://en.wikipedia.org/wiki/Reactive_programming). Ini adalah subjek susulan yang baik jika anda ingin menyelam.
|
||||
|
||||
✅ Terdapat banyak perpustakaan di luar sana dengan pendekatan yang berbeza untuk pengurusan negeri, [Redux](https://redux.js.org) menjadi pilihan yang popular. Lihat konsep dan corak yang digunakan kerana ini sering kali merupakan kaedah yang baik untuk mengetahui potensi masalah yang mungkin anda hadapi dalam aplikasi web besar dan bagaimana ia dapat diselesaikan.
|
||||
|
||||
### Tugas
|
||||
|
||||
Kita akan mulakan dengan sedikit refactoring. Ganti pernyataan `akaun`:
|
||||
|
||||
```js
|
||||
let account = null;
|
||||
```
|
||||
|
||||
With:
|
||||
|
||||
```js
|
||||
let state = {
|
||||
account: null
|
||||
};
|
||||
```
|
||||
|
||||
Ideanya adalah untuk *memusatkan* semua data aplikasi kami dalam satu objek keadaan. Kami hanya mempunyai `akaun` untuk saat ini di negeri ini sehingga tidak banyak berubah, tetapi ini menciptakan jalan untuk evolusi.
|
||||
|
||||
Kita juga harus mengemas kini fungsi menggunakannya. Dalam fungsi `register()` dan `login()`, ganti `account = ...` dengan `state.account = ...`;
|
||||
|
||||
Di bahagian atas fungsi `updateDashboard()`, tambahkan baris ini:
|
||||
|
||||
```js
|
||||
const account = state.account;
|
||||
```
|
||||
|
||||
Pemfaktoran semula ini dengan sendirinya tidak membawa banyak peningkatan, tetapi ideanya adalah untuk meletakkan asas untuk perubahan selanjutnya.
|
||||
|
||||
## Jejak perubahan data
|
||||
|
||||
Sekarang kita telah meletakkan objek `state` untuk menyimpan data kita, langkah seterusnya adalah memusatkan kemas kini. Tujuannya adalah untuk menjadikannya lebih mudah untuk mengikuti setiap perubahan dan kapan ia berlaku.
|
||||
|
||||
Untuk mengelakkan berlakunya perubahan pada objek `state`, adalah praktik yang baik untuk mempertimbangkannya [*tidak berubah*](https://en.wikipedia.org/wiki/Immutable_object), yang bermaksud bahawa ia tidak dapat diubah sama sekali. Ini juga bermaksud bahawa anda harus membuat objek keadaan baru jika anda ingin mengubah apa-apa di dalamnya. Dengan melakukan ini, anda membina perlindungan mengenai [kesan sampingan](https://en.wikipedia.org/wiki/Side_effect_ (computer_science)), dan membuka kemungkinan untuk ciri baru dalam aplikasi anda seperti melaksanakan undo / redo, sambil mempermudah debug. Sebagai contoh, anda boleh mencatat setiap perubahan yang dibuat ke negeri dan menyimpan sejarah perubahan untuk memahami sumber pepijat.
|
||||
|
||||
Dalam JavaScript, anda boleh menggunakan [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) untuk membuat versi yang tidak berubah dari sebuah objek. Sekiranya anda cuba membuat perubahan pada objek yang tidak dapat diubah, pengecualian akan ditimbulkan.
|
||||
|
||||
✅ Adakah anda tahu perbezaan antara objek *cetek* dan *dalam* tidak berubah? Anda boleh membacanya [di sini](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze).
|
||||
|
||||
### Tugas
|
||||
|
||||
Mari buat fungsi `updateState()` baru:
|
||||
|
||||
```js
|
||||
function updateState(property, newData) {
|
||||
state = Object.freeze({
|
||||
...state,
|
||||
[property]: newData
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Dalam fungsi ini, kami membuat objek keadaan baru dan menyalin data dari keadaan sebelumnya menggunakan operator [*spread (`...`) operator*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Kemudian kami menimpa harta benda objek tertentu dengan data baru menggunakan [notasi kurungan](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` untuk tugasan. Akhirnya, kita mengunci objek untuk mengelakkan pengubahsuaian menggunakan `Object.freeze()`. Kami hanya menyimpan harta `akaun` di negeri ini buat masa ini, tetapi dengan pendekatan ini anda dapat menambahkan seberapa banyak harta tanah yang anda perlukan di negeri ini.
|
||||
|
||||
Kami juga akan mengemas kini inisialisasi `state` untuk memastikan keadaan awal juga dibekukan:
|
||||
|
||||
```js
|
||||
let state = Object.freeze({
|
||||
account: null
|
||||
});
|
||||
```
|
||||
|
||||
After that, update the `register` function by replacing the `state.account = result;` assignment with:
|
||||
|
||||
```js
|
||||
updateState('account', result);
|
||||
```
|
||||
|
||||
Do the same with the `login` function, replacing `state.account = data;` with:
|
||||
|
||||
```js
|
||||
updateState('account', data);
|
||||
```
|
||||
|
||||
Kami sekarang akan mengambil kesempatan untuk memperbaiki masalah data akaun yang tidak dihapus ketika pengguna mengklik *Logout*.
|
||||
|
||||
Buat fungsi baru `logout()`:
|
||||
|
||||
```js
|
||||
function logout() {
|
||||
updateState('account', null);
|
||||
navigate('/login');
|
||||
}
|
||||
```
|
||||
|
||||
Di `updateDashboard()`, ganti pengalihan `return navigate('/login');` dengan `return logout()`;
|
||||
|
||||
Cuba daftarkan akaun baru, log keluar dan masuk sekali lagi untuk memeriksa bahawa semuanya masih berfungsi dengan betul.
|
||||
|
||||
> Petua: anda dapat melihat semua perubahan keadaan dengan menambahkan `console.log(state)` di bahagian bawah `updateState()` dan membuka konsol di alat pengembangan penyemak imbas anda.
|
||||
|
||||
## Kekalkan keadaan
|
||||
|
||||
Sebilangan besar aplikasi web perlu mengekalkan data agar dapat berfungsi dengan betul. Semua data kritikal biasanya disimpan di pangkalan data dan diakses melalui API pelayan, seperti data akaun pengguna dalam kes kami. Tetapi kadang-kadang, juga menarik untuk mengekalkan beberapa data pada aplikasi klien yang berjalan di penyemak imbas anda, untuk pengalaman pengguna yang lebih baik atau untuk meningkatkan prestasi pemuatan.
|
||||
|
||||
Apabila anda ingin menyimpan data dalam penyemak imbas anda, terdapat beberapa soalan penting yang harus anda tanyakan kepada diri sendiri:
|
||||
|
||||
- *Adakah data sensitif?* Anda harus mengelakkan menyimpan data sensitif pada pelanggan, seperti kata laluan pengguna.
|
||||
- *Berapa lama anda perlu menyimpan data ini?* Adakah anda merancang untuk mengakses data ini hanya untuk sesi semasa atau adakah anda ingin menyimpannya selamanya?
|
||||
|
||||
Terdapat banyak cara untuk menyimpan maklumat di dalam aplikasi web, bergantung pada apa yang ingin anda capai. Sebagai contoh, anda boleh menggunakan URL untuk menyimpan pertanyaan carian, dan menjadikannya boleh dibagikan antara pengguna. Anda juga boleh menggunakan [kuki HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) jika data perlu dikongsi dengan pelayan, seperti [pengesahan](https://en.wikipedia.org/wiki/Authentication) maklumat.
|
||||
|
||||
Pilihan lain adalah menggunakan salah satu dari banyak API penyemak imbas untuk menyimpan data. Dua daripadanya sangat menarik:
|
||||
|
||||
- [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage): a [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) yang memungkinkan untuk mengekalkan data khusus untuk laman web semasa di pelbagai sesi. Data yang disimpan di dalamnya tidak akan luput.
|
||||
- [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage): ini berfungsi sama seperti `localStorage` kecuali data yang disimpan di dalamnya dibersihkan semasa sesi berakhir (semasa penyemak imbas ditutup).
|
||||
|
||||
Perhatikan bahawa kedua-dua API ini hanya membenarkan menyimpan [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String). Sekiranya anda ingin menyimpan objek yang kompleks, anda perlu membuat siri ke siri [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) menggunakan [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
|
||||
|
||||
✅ Sekiranya anda ingin membuat aplikasi web yang tidak berfungsi dengan pelayan, anda juga boleh membuat pangkalan data pada klien menggunakan [`IndexedDB` API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). Yang ini dikhaskan untuk kes penggunaan lanjutan atau jika anda perlu menyimpan sejumlah besar data, kerana lebih kompleks untuk digunakan.
|
||||
|
||||
### Tugas
|
||||
|
||||
Kami mahu pengguna kami terus masuk sehingga mereka mengklik butang *Logout* secara eksplisit, jadi kami akan menggunakan `localStorage` untuk menyimpan data akaun. Pertama, mari tentukan kunci yang akan kami gunakan untuk menyimpan data kami.
|
||||
|
||||
```js
|
||||
const storageKey = 'savedAccount';
|
||||
```
|
||||
|
||||
Kemudian tambahkan baris ini pada akhir fungsi `updateState()`:
|
||||
|
||||
```js
|
||||
localStorage.setItem(storageKey, JSON.stringify(state.account));
|
||||
```
|
||||
|
||||
Dengan ini, data akaun pengguna akan dikekalkan dan sentiasa terkini semasa kami memusatkan semua kemas kini negeri sebelumnya. Di sinilah kita mula mendapat manfaat daripada semua reaktor kita sebelumnya 🙂.
|
||||
|
||||
Semasa data disimpan, kita juga harus menjaga memulihkannya ketika aplikasi dimuat. Oleh kerana kita akan mempunyai lebih banyak kod inisialisasi, mungkin ada baiknya membuat fungsi `init` baru, yang juga merangkumi kod sebelumnya di bahagian bawah `app.js`:
|
||||
|
||||
```js
|
||||
function init() {
|
||||
const savedAccount = localStorage.getItem(storageKey);
|
||||
if (savedAccount) {
|
||||
updateState('account', JSON.parse(savedAccount));
|
||||
}
|
||||
|
||||
// Kod permulaan kami sebelumnya
|
||||
window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
}
|
||||
|
||||
init();
|
||||
```
|
||||
|
||||
Di sini kami mengambil data yang disimpan, dan jika ada, kami akan mengemas kini keadaan dengan sewajarnya. Penting untuk melakukan ini *sebelum* mengemas kini laluan, kerana mungkin ada kod yang bergantung pada keadaan semasa kemas kini halaman.
|
||||
|
||||
Kami juga dapat menjadikan halaman *Dashboard* sebagai halaman lalai aplikasi kami, karena kami sekarang masih menyimpan data akun. Sekiranya tidak ada data, dashboard akan mengalihkan ke halaman *Login*. Dalam `updateRoute()`, ganti fallback `return navigate ('/login');` dengan `return navigate('dashboard');`.
|
||||
|
||||
Sekarang log masuk dalam aplikasi dan cuba memuat semula halaman, anda harus terus berada di papan pemuka. Dengan kemas kini itu, kami telah menangani semua masalah awal kami ...
|
||||
|
||||
## Muat semula data
|
||||
|
||||
... Tetapi kita mungkin juga telah membuat yang baru. Alamak!
|
||||
|
||||
Pergi ke papan pemuka menggunakan akaun `test`, kemudian jalankan perintah ini di terminal untuk membuat transaksi baru:
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
|
||||
http://localhost:5000/api/accounts/test/transactions
|
||||
```
|
||||
|
||||
Cuba muat semula halaman papan pemuka anda di penyemak imbas sekarang. Apa yang berlaku? Adakah anda melihat transaksi baru?
|
||||
|
||||
Keadaan ini berterusan selama-lamanya berkat `localStorage`, tetapi itu juga bermaksud ia tidak akan dikemas kini sehingga anda log keluar dari aplikasi dan log masuk semula!
|
||||
|
||||
Salah satu strategi yang mungkin untuk diperbaiki adalah memuat semula data akaun setiap kali dashboard dimuat, untuk mengelakkan data terhenti.
|
||||
|
||||
### Tugas
|
||||
|
||||
Buat fungsi baru `updateAccountData`:
|
||||
|
||||
```js
|
||||
async function updateAccountData() {
|
||||
const account = state.account;
|
||||
if (!account) {
|
||||
return logout();
|
||||
}
|
||||
|
||||
const data = await getAccount(account.user);
|
||||
if (data.error) {
|
||||
return logout();
|
||||
}
|
||||
|
||||
updateState('account', data);
|
||||
}
|
||||
```
|
||||
|
||||
Kaedah ini memeriksa bahawa kita sedang log masuk dan memuat semula data akaun dari pelayan.
|
||||
|
||||
Buat fungsi lain bernama `refresh`:
|
||||
|
||||
```js
|
||||
async function refresh() {
|
||||
await updateAccountData();
|
||||
updateDashboard();
|
||||
}
|
||||
```
|
||||
|
||||
Yang ini mengemas kini data akaun, kemudian mengurus mengemas kini HTML halaman papan pemuka. Inilah yang perlu kita panggil semasa laluan papan pemuka dimuat. Kemas kini definisi laluan dengan:
|
||||
|
||||
```js
|
||||
const routes = {
|
||||
'/login': { templateId: 'login' },
|
||||
'/dashboard': { templateId: 'dashboard', init: refresh }
|
||||
};
|
||||
```
|
||||
|
||||
Cuba muatkan semula papan pemuka sekarang, ia akan memaparkan data akaun yang dikemas kini.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Cabaran
|
||||
|
||||
Setelah kita memuatkan semula data akaun setiap kali papan pemuka dimuat, adakah anda fikir kita masih perlu meneruskan *semua data* akaun?
|
||||
|
||||
Cuba bekerjasama untuk mengubah apa yang disimpan dan dimuat dari `localStorage` untuk hanya memasukkan perkara yang benar-benar diperlukan agar aplikasi berfungsi.
|
||||
|
||||
## Post-Lecture Quiz
|
||||
|
||||
[Post-Lecture Quiz](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/48)
|
||||
|
||||
## Tugasan
|
||||
|
||||
[Laksanakan dialog "Tambah transaksi"](assignment.ms.md)
|
||||
|
||||
Inilah hasil contoh setelah menyelesaikan tugasan:
|
||||
|
||||
![Tangkapan skrin yang menunjukkan contoh dialog "Tambah transaksi"](../images/dialog.png)
|
@ -0,0 +1,25 @@
|
||||
# Laksanakan dialog "Tambah transaksi"
|
||||
|
||||
## Arahan
|
||||
|
||||
Aplikasi bank kami masih belum mempunyai satu ciri penting: kemungkinan untuk melakukan transaksi baru.
|
||||
Menggunakan semua yang telah anda pelajari dalam empat pelajaran sebelumnya, laksanakan dialog "Tambah transaksi":
|
||||
|
||||
- Tambahkan butang "Tambah transaksi" di halaman papan pemuka
|
||||
- Buat halaman baru dengan templat HTML, atau gunakan JavaScript untuk menunjukkan / menyembunyikan HTML dialog tanpa meninggalkan halaman papan pemuka (anda boleh menggunakan [`hidden`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden) property for that, or CSS classes) untuk itu, atau kelas CSS)
|
||||
- Pastikan anda mengendalikan [kebolehcapaian pembaca papan kekunci dan skrin](https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/) untuk dialog
|
||||
- Terapkan borang HTML untuk menerima data input
|
||||
- Buat data JSON dari data formulir dan kirimkan ke API
|
||||
- Kemas kini halaman papan pemuka dengan data baru
|
||||
|
||||
Lihat [server API specifications](../../api/README.ms.md) untuk melihat API mana yang perlu anda panggil dan format JSON yang diharapkan.
|
||||
|
||||
Inilah hasil contoh setelah menyelesaikan tugasan:
|
||||
|
||||
![Tangkapan skrin yang menunjukkan contoh dialog "Tambahkan peralihan"](../images/dialog.png)
|
||||
|
||||
## Rubrik
|
||||
|
||||
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
|
||||
| -------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------|
|
||||
| | Menambah transaksi dilaksanakan sepenuhnya mengikuti semua amalan terbaik yang dilihat dalam pelajaran. | Menambah urus niaga dilaksanakan, tetapi tidak mengikuti amalan terbaik yang dapat dilihat dalam pelajaran, atau hanya bekerja sebahagian. | Menambah urus niaga tidak berfungsi sama sekali. |
|
@ -0,0 +1,32 @@
|
||||
# Bank API
|
||||
|
||||
> > API Bank dibina dengan [Node.js](https://nodejs.org) + [Express](https://expressjs.com/).
|
||||
|
||||
API sudah dibina untuk anda dan bukan sebahagian daripada latihan.
|
||||
|
||||
Walau bagaimanapun, jika anda berminat untuk belajar membuat API seperti ini, anda boleh mengikuti siri video ini: https://aka.ms/NodeBeginner (video 17 hingga 21 merangkumi API tepat ini)
|
||||
|
||||
Anda juga boleh melihat tutorial interaktif ini: https://aka.ms/learn/express-api
|
||||
|
||||
## Menjalankan pelayan
|
||||
|
||||
Pastikan anda telah memasang [Node.js](https://nodejs.org).
|
||||
|
||||
1. Git klon repo ini.
|
||||
2. Buka terminal dalam folder `api`, kemudian jalankan` npm install`.
|
||||
3. Jalankan `npm start`.
|
||||
|
||||
Pelayan harus mula mendengar di port `5000`.
|
||||
|
||||
> Catatan: semua entri disimpan dalam memori dan tidak berterusan, jadi apabila pelayan dihentikan semua data akan hilang.
|
||||
|
||||
## Perincian API
|
||||
|
||||
Route | Description
|
||||
---------------------------------------------|------------------------------------
|
||||
GET /api/ | Dapat server info
|
||||
POST /api/accounts/ | Daftar akaun, ex: `{ user: 'Yohan', description: 'My budget', currency: 'EUR', balance: 100 }`
|
||||
GET /api/accounts/:user | Dapatkan semua data untuk akaun yang ditentukan
|
||||
DELETE /api/accounts/:user | Keluarkan akaun yang ditentukan
|
||||
POST /api/accounts/:user/transactions | Tambahkan transaksi, ex: `{ date: '2020-07-23T18:25:43.511Z', object: 'Bought a book', amount: -20 }`
|
||||
DELETE /api/accounts/:user/transactions/:id | Keluarkan transaksi yang ditentukan
|
@ -0,0 +1,13 @@
|
||||
# Aplikasi bank
|
||||
|
||||
> Contoh penyelesaian untuk projek aplikasi bank, dibangun dengan vanilla HTML5, CSS dan JavaScript (tidak ada kerangka atau perpustakaan yang digunakan).
|
||||
|
||||
## Menjalankan aplikasi
|
||||
|
||||
Mula-mula pastikan anda menjalankan [pelayan API](../../api/translations/README.ms.md).
|
||||
|
||||
Mana-mana pelayan web boleh digunakan untuk menjalankan aplikasi, tetapi kerana anda seharusnya memasang [Node.js](https://nodejs.org) untuk menjalankan API, anda boleh:
|
||||
|
||||
1. Git klon repo ini.
|
||||
2. Buka terminal, kemudian jalankan `npx lite-server solution`. Ia akan memulakan pelayan web pengembangan di port `3000`
|
||||
3. Buka `http://localhost: 3000` di penyemak imbas untuk menjalankan aplikasi.
|
@ -0,0 +1,21 @@
|
||||
# :dollar: Bina Bank
|
||||
|
||||
Dalam projek ini, anda akan belajar membina bank fiksyen. Pelajaran ini merangkumi petunjuk bagaimana mengatur aplikasi web dan menyediakan laluan, membina borang, mengurus keadaan, dan mengambil data dari API dari mana anda dapat mengambil data bank.
|
||||
|
||||
| ![Screen1](../images/screen1.png) | ![Screen2](../images/screen2.png) |
|
||||
|--------------------------------|--------------------------------|
|
||||
|
||||
## Pembelajaran
|
||||
|
||||
1. [Templat dan Laluan HTML dalam Aplikasi Web](../1-template-route/README.md)
|
||||
2. [Bina Log Masuk dan Borang Pendaftaran](../2-forms/README.md)
|
||||
3. [Kaedah Mengambil dan Menggunakan Data](../3-data/README.md)
|
||||
4. [Konsep Pengurusan Negeri](../4-state-management/README.md)
|
||||
|
||||
### Kredit
|
||||
|
||||
Pelajaran ini ditulis dengan :hearts: oleh [Yohan Lasorsa](https://twitter.com/sinedied).
|
||||
|
||||
Sekiranya anda berminat untuk mempelajari cara membina [server API](./api/README) yang digunakan dalam pelajaran ini, anda boleh mengikuti [rangkaian video ini](https://aka.ms/NodeBeginner) (khususnya video 17 hingga 21).
|
||||
|
||||
Anda juga boleh melihat [tutorial Belajar interaktif ini](https://aka.ms/learn/express-api).
|
Loading…
Reference in new issue