Saat menulis arahan dalam AngularJS, bagaimana saya memutuskan jika saya tidak memerlukan ruang lingkup baru, ruang lingkup anak baru, atau ruang lingkup terisolasi baru?


265

Saya mencari beberapa panduan yang dapat digunakan untuk membantu menentukan jenis ruang lingkup yang digunakan saat menulis arahan baru. Idealnya, saya ingin sesuatu yang mirip dengan bagan alur yang menuntun saya melalui banyak pertanyaan dan muncul jawaban yang benar - tidak ada ruang lingkup baru baru, ruang lingkup anak baru, atau ruang lingkup isolat baru - tetapi itu kemungkinan meminta terlalu banyak. Berikut seperangkat pedoman remeh saya saat ini:

Saya sadar bahwa menggunakan arahan dengan cakupan terisolasi pada elemen memaksa semua arahan lain pada elemen yang sama untuk menggunakan lingkup isolasi yang sama (satu), jadi bukankah ini sangat membatasi ketika ruang lingkup isolat dapat digunakan?

Saya berharap beberapa dari tim Angular-UI (atau yang lain yang telah menulis banyak arahan) dapat berbagi pengalaman mereka.

Tolong jangan tambahkan jawaban yang hanya mengatakan "gunakan cakupan terisolasi untuk komponen yang dapat digunakan kembali".


dengan "lingkup anak" yang Anda maksud dengan membuat ruang lingkup dalam fungsi tautan dengan "ruang lingkup. $ new ()"? Karena saya tahu, direktif dapat memiliki ruang lingkup yang terisolasi atau tidak memilikinya (jadi akan menggunakan ruang lingkup di mana telah digunakan)
Valentyn Shybanov

3
Pengaturan @ValentynShybanov scope: trueakan membuat lingkup anak menggunakan $scope.new()secara otomatis.
Josh David Miller

2
@Valentyn, apa yang dikatakan Josh: jadi, tiga kemungkinan adalah scope: false(default, tidak ada ruang lingkup baru), scope: true(ruang lingkup baru yang mewarisi secara prototipe), dan scope: { ... }(ruang lingkup isolat baru).
Mark Rajcok

1
Ya, terima kasih. Saya melewatkan perbedaan antara "benar" dan "{}". Senang mendengarnya.
Valentyn Shybanov

Ada kasus ke-4 yang umumnya orang cenderung abaikan .. itu adalah "pengontrol direktif" .. Saya pikir pertanyaannya harus diperluas untuk memasukkan mereka juga ... +1 ke pertanyaan ..
ganaraj

Jawaban:


291

Pertanyaan yang sangat bagus! Saya akan senang mendengar apa yang dikatakan orang lain, tapi di sini adalah pedoman saya gunakan.

Premis ketinggian tinggi: ruang lingkup digunakan sebagai "lem" yang kami gunakan untuk berkomunikasi antara pengendali induk, direktif, dan template direktif.

Lingkup Induk:, scope: false jadi tidak ada ruang lingkup sama sekali

Saya tidak terlalu sering menggunakan ini, tetapi seperti kata @MarkRajcok, jika direktif tidak mengakses variabel ruang lingkup (dan jelas tidak mengatur apa pun!) Maka ini baik-baik saja sejauh yang saya ketahui. Ini juga bermanfaat untuk arahan anak yang hanya digunakan dalam konteks arahan orang tua (meskipun selalu ada pengecualian untuk ini) dan yang tidak memiliki template. Pada dasarnya apa pun dengan templat tidak termasuk berbagi lingkup, karena Anda secara inheren mengekspos cakupan untuk akses dan manipulasi (tapi saya yakin ada pengecualian untuk aturan ini).

Sebagai contoh, saya baru-baru ini membuat arahan yang menggambar grafik vektor (statis) menggunakan perpustakaan SVG saya sedang dalam proses penulisan. Ini $observedua atribut ( widthdan height) dan menggunakannya dalam perhitungannya, tetapi tidak menetapkan atau membaca variabel lingkup apa pun dan tidak memiliki templat. Ini adalah kasus penggunaan yang baik untuk tidak menciptakan cakupan lain; kita tidak membutuhkannya, jadi mengapa repot-repot?

Tetapi dalam arahan SVG yang lain, saya membutuhkan satu set data untuk digunakan dan juga harus menyimpan sedikit keadaan. Dalam hal ini, menggunakan ruang lingkup orang tua tidak bertanggung jawab (sekali lagi, secara umum). Jadi sebagai gantinya ...

Lingkup Anak: scope: true

Arahan dengan lingkup anak adalah sadar konteks dan dimaksudkan untuk berinteraksi dengan lingkup saat ini.

Jelas, keuntungan utama dari ini di atas lingkup isolasi adalah bahwa pengguna bebas menggunakan interpolasi pada atribut apa pun yang mereka inginkan; mis. menggunakan class="item-type-{{item.type}}"direktif dengan cakupan isolat tidak akan berfungsi secara default, tetapi berfungsi baik pada direktif dengan cakupan anak karena apa pun yang diinterpolasi masih dapat ditemukan secara default dalam lingkup induk. Juga, arahan itu sendiri dapat dengan aman mengevaluasi atribut dan ekspresi dalam konteks ruang lingkupnya sendiri tanpa khawatir tentang polusi atau kerusakan pada induknya.

Sebagai contoh, tooltip adalah sesuatu yang baru saja ditambahkan; ruang lingkup isolasi tidak akan berfungsi (secara default, lihat di bawah) karena diharapkan kita akan menggunakan arahan lain atau atribut yang diinterpolasi di sini. Tip alat hanyalah tambahan. Tetapi tooltip juga perlu mengatur beberapa hal pada lingkup untuk digunakan dengan sub-direktif dan / atau template dan jelas untuk mengelola keadaannya sendiri, sehingga akan sangat buruk untuk menggunakan lingkup induk. Kami mencemari atau merusaknya, dan bueno juga tidak.

Saya menemukan diri saya menggunakan cakupan anak lebih sering daripada lingkup isolasi atau orangtua.

Ruang lingkup isolasi: scope: {}

Ini untuk komponen yang dapat digunakan kembali. :-)

Tapi serius, saya menganggap "komponen yang dapat digunakan kembali" sebagai "komponen mandiri". Maksudnya adalah bahwa mereka harus digunakan untuk tujuan tertentu, jadi menggabungkan mereka dengan arahan lain atau menambahkan atribut interpolasi lainnya ke simpul DOM secara inheren tidak masuk akal.

Untuk lebih spesifik, apa pun yang diperlukan untuk fungsi mandiri ini disediakan melalui atribut tertentu yang dievaluasi dalam konteks lingkup induk; mereka bisa berupa string satu arah ('@'), ekspresi satu arah ('&'), atau binding variabel dua arah ('=').

Pada komponen mandiri, tidak masuk akal untuk perlu menerapkan arahan atau atribut lain karena itu ada dengan sendirinya. Gayanya diatur oleh template sendiri (jika perlu) dan dapat memiliki konten yang sesuai ditransklusikan (jika perlu). Itu standalone, jadi kami menempatkannya dalam ruang lingkup terisolasi juga untuk mengatakan: "Jangan main-main dengan ini. Saya memberi Anda API yang didefinisikan melalui beberapa atribut ini."

Praktik terbaik yang baik adalah dengan mengecualikan hal-hal berbasis template dari directive link dan fungsi pengontrol sebanyak mungkin. Ini memberikan titik konfigurasi "seperti API" lainnya: pengguna direktif dapat dengan mudah mengganti templat! Fungsionalitasnya tetap sama, dan API internalnya tidak pernah disentuh, tetapi kami dapat mengacaukan styling dan implementasi DOM sebanyak yang kami butuhkan. ui / bootstrap adalah contoh yang bagus tentang bagaimana melakukan ini dengan baik karena Peter & Pawel mengagumkan.

Cakupan isolasi juga bagus untuk digunakan dengan transklusi. Ambil tab; mereka tidak hanya seluruh fungsionalitas, tetapi apa pun yang ada di dalamnya dapat dievaluasi secara bebas dari dalam lingkup induk sambil meninggalkan tab (dan panel) untuk melakukan apa pun yang mereka inginkan. Tab jelas memiliki sendiri negara , yang termasuk di lingkup (untuk berinteraksi dengan template), tetapi bahwa negara tidak ada hubungannya dengan konteks yang digunakan - itu sepenuhnya internal untuk apa yang membuat tab direktif direktif tab. Lebih jauh, tidak masuk akal untuk menggunakan arahan lain dengan tab. Itu adalah tab - dan kami sudah mendapatkan fungsionalitas itu!

Kelilinginya dengan lebih banyak fungsionalitas atau transklusikan lebih banyak fungsi, tetapi arahan sudah seperti itu.

Semua yang mengatakan, saya harus mencatat bahwa ada cara di sekitar beberapa keterbatasan (yaitu fitur) dari ruang lingkup yang terisolasi, seperti @ProLoser mengisyaratkan dalam jawabannya. Sebagai contoh, di bagian lingkup anak, saya menyebutkan interpolasi pada atribut non-direktif melanggar ketika menggunakan ruang lingkup isolat (secara default). Tetapi pengguna dapat, misalnya, cukup menggunakan class="item-type-{{$parent.item.type}}"dan itu sekali lagi akan berfungsi. Jadi, jika ada alasan kuat untuk menggunakan ruang lingkup terisolasi di atas ruang lingkup anak tetapi Anda khawatir tentang beberapa keterbatasan ini, ketahuilah bahwa Anda dapat mengatasi hampir semua dari mereka jika Anda perlu.

Ringkasan

Arahan tanpa ruang lingkup baru hanya untuk dibaca; mereka sepenuhnya tepercaya (yaitu internal ke aplikasi) dan mereka tidak menyentuh jack. Arahan dengan cakupan anak menambah fungsionalitas, tetapi itu bukan satu-satunya fungsi. Terakhir, lingkup isolasi adalah untuk arahan yang merupakan tujuan keseluruhan; mereka berdiri sendiri, jadi tidak apa-apa (dan paling "benar") untuk membiarkan mereka nakal.

Saya ingin mengeluarkan pikiran awal saya, tetapi karena saya memikirkan lebih banyak hal, saya akan memperbarui ini. Tapi sial - ini panjang untuk jawaban SO ...


PS: Benar-benar tangensial, tetapi karena kita berbicara tentang ruang lingkup, saya lebih suka mengatakan "prototipikal" sedangkan yang lain lebih suka "prototipal", yang tampaknya lebih akurat tetapi hanya menggelindingkan lidah sama sekali tidak baik. :-)


Terima kasih Josh, jawaban yang bagus. Saya ingin / mengharapkan jawaban panjang untuk ini. Dua hal yang tidak saya ikuti: 1) ruang lingkup anak: "pengguna bebas menggunakan interpolasi pada atribut apa pun yang mereka inginkan". 2) mengisolasi ruang lingkup: "atau tidak semua, dalam kasus '?'" Bisakah Anda sedikit menjelaskannya? (Jangan ragu untuk mengedit posting Anda daripada menulis komentar jika itu lebih mudah.)
Mark Rajcok

@ MarkRajcok Untuk (1), saya mengubahnya untuk membuatnya sedikit kurang samar - beri tahu saya jika saya tidak berhasil. Untuk (2), itu adalah kombinasi dari salah ketik dan kata-kata buruk; Saya menulis ulang paragraf agar lebih jelas. Saya juga menambahkan satu atau dua contoh tambahan, mengklarifikasi beberapa hal lagi, dan memperbaiki beberapa kesalahan ketik.
Josh David Miller

Seperti disebutkan dalam jawaban - bootstrap untuk angular adalah contoh yang bagus untuk menggabungkan ini. Saya menemukan contoh akordeon sangat berguna - GitHub - Accordion
CalM

Anda menyebutkan bahwa Anda menggunakan cakupan anak paling banyak, saya pikir bahwa pola arahan yang dapat digunakan kembali adalah yang paling umum dan saya telah menghindari menulis arahan yang hanya dimaksudkan untuk digunakan satu kali. Apakah ini tidak dibutuhkan? Terkadang ketika HTML saya menjadi terlalu besar, saya merasa ingin memindahkan bagian itu ke arahan tetapi hanya akan digunakan sekali jadi saya tinggalkan saja di html.
user2483724

2
@ user2483724 Kesalahpahaman yang sangat umum adalah bahwa arahan "dapat digunakan kembali" adalah arahan yang menggunakan lingkup isolat; tidak begitu. Jika Anda melihat arahan yang sudah dikemas sebelumnya, hampir tidak ada yang menggunakan lingkup isolasi - beberapa bahkan bukan ruang lingkup anak - tapi saya jamin mereka dapat digunakan kembali! Aturannya harus dalam bagaimana ruang lingkup dalam arahan digunakan. Jika hanya tentang menghemat ruang dalam file, saya tidak yakin arahan adalah pendekatan terbaik. Ini meningkatkan waktu pemrosesan demi pengembang. Tetapi jika Anda harus, maka lakukanlah. Atau gunakan ngInclude. Atau lakukan itu sebagai bagian dari bangunan Anda. Banyak pilihan!
Josh David Miller

52

Kebijakan dan pengalaman pribadi saya:

Terisolasi: kotak pasir pribadi

Saya ingin membuat banyak metode dan variabel lingkup yang HANYA digunakan oleh arahan saya dan tidak pernah dilihat atau diakses langsung oleh pengguna. Saya ingin memasukkan daftar putih data lingkup apa yang tersedia untuk saya. Saya dapat menggunakan transklusi untuk memungkinkan pengguna untuk melompat kembali pada lingkup induknya (tidak terpengaruh) . Saya TIDAK ingin variabel dan metode saya dapat diakses pada anak-anak yang ditransklusikan.

Anak: subbagian konten

Saya ingin membuat metode dan variabel lingkup yang BISA diakses oleh pengguna, tetapi tidak relevan dengan cakupan di sekitarnya (saudara dan orang tua) di luar konteks arahan saya. Saya juga ingin membiarkan SEMUA data cakupan induknya mengalir turun secara transparan.

Tidak ada: arahan sederhana, hanya baca

Saya tidak benar-benar perlu mengacaukan metode atau variabel ruang lingkup. Saya mungkin melakukan sesuatu yang tidak ada hubungannya dengan cakupan (seperti menampilkan plugin jQuery sederhana, validasi, dll).

Catatan

  • Anda tidak boleh membiarkan ngModel atau hal lain secara langsung memengaruhi keputusan Anda. Anda dapat menghindari perilaku aneh dengan melakukan hal-hal seperti ng-model=$parent.myVal(anak) atau ngModel: '='(mengisolasi).
  • Isolate + transclude akan mengembalikan semua perilaku normal ke arahan saudara dan kembali ke lingkup orang tua, jadi jangan biarkan itu mempengaruhi penilaian Anda juga.
  • Jangan mengacaukan ruang lingkup karena tidak ada yang seperti menempatkan data pada ruang lingkup untuk bagian bawah DOM tetapi bukan bagian atas yang masuk akal.
  • Perhatikan prioritas arahan (tidak memiliki contoh nyata tentang bagaimana hal ini dapat mempengaruhi hal-hal)
  • Suntikkan layanan atau gunakan pengontrol untuk berkomunikasi lintas arahan dengan semua jenis ruang lingkup. Anda juga dapat melakukan require: '^ngModel'untuk melihat elemen induk.

1
Saya mungkin salah mengerti bagian ini: "Iscate + transclude akan mengembalikan semua perilaku normal ke arahan saudara". Lihat penyedot ini . Anda harus melihat di konsol.
Josh David Miller

1
Terima kasih ProLoser atas wawasan / jawaban Anda. Anda adalah salah satu orang yang saya harap akan melihat posting ini jika saya menambahkan tag angularjs-ui.
Mark Rajcok

@JoshDavidMiller ketika berbicara tentang arahan pada elemen DOM yang sama hal menjadi lebih rumit, dan Anda harus mulai melihat pada properti prioritas. Transklusi lebih relevan dengan konten anak-anak.
ProLoser

1
@ ProLoser Benar, tapi saya tidak yakin apa yang Anda maksud dengan pernyataan itu. Mereka jelas mempengaruhi anak-anak, tetapi bagaimana cakupan arahan mempengaruhi arahan saudara mereka sama sekali?
Josh David Miller

18

Setelah menulis banyak arahan, saya memutuskan untuk menggunakan isolatedlingkup yang lebih sedikit . Meskipun itu keren dan Anda merangkum data dan pastikan untuk tidak membocorkan data ke lingkup induk, itu sangat membatasi jumlah arahan yang dapat Anda gunakan bersama. Begitu,

Jika arahan yang akan Anda tulis akan berlaku sepenuhnya dan Anda tidak akan membaginya dengan arahan lain, pilihlah ruang lingkup yang terisolasi . (seperti komponen, Anda cukup mencolokkannya, dengan tidak banyak penyesuaian untuk pengembang akhir) (itu menjadi sangat rumit ketika Anda mencoba menulis sub-elemen yang memiliki arahan di dalamnya)

Jika direktif Anda akan menulis akan hanya membuat manipulasi dom yang tidak memerlukan keadaan internal lingkup, atau perubahan lingkup eksplisit (sebagian besar hal-hal yang sangat sederhana); pergi tanpa ruang lingkup baru . (seperti ngShow, ngMouseHover, ngClick, ngRepeat)

Jika arahan yang akan Anda tulis perlu mengubah beberapa elemen dalam cakupan induk, tetapi juga perlu menangani beberapa kondisi internal, gunakan lingkup anak baru . (seperti ngController)

Pastikan untuk memeriksa kode sumber untuk arahan: https://github.com/angular/angular.js/tree/master/src/ng/directive
Ini sangat membantu tentang cara berpikir tentang mereka


Jika beberapa komponen perlu berkomunikasi satu sama lain, mereka dapat memiliki ruang lingkup dan penggunaan yang terisolasi require, sehingga menjaga arahan Anda masih terpisah. Jadi bagaimana membatasi kemungkinan? Itu bahkan membuat arahan lebih spesifik (jadi nyatakan apa yang Anda andalkan). Jadi saya hanya akan meninggalkan satu aturan: jika direktif Anda memiliki status atau memerlukan beberapa data dari ruang lingkup di mana ia digunakan - gunakan ruang lingkup yang terisolasi. Kalau tidak, jangan gunakan lingkup. Dan tentang "cakupan anak" - Saya juga menulis cukup banyak arahan dan tidak pernah membutuhkan fitur ini. Jika "perlu mengubah beberapa elemen dalam lingkup induk" - gunakan binding.
Valentyn Shybanov

Dan juga tentang "perlu mengubah beberapa elemen dalam lingkup induk" - jika Anda memodifikasi sesuatu dalam cakupan lingkup anak tidak diisi ke lingkup induk (kecuali jika Anda menggunakan $parenthack kotor ). Jadi sebenarnya "cakupan anak" untuk arahan adalah sesuatu yang sepertinya harus digunakan cukup belakang - seperti ngRepeatyang menciptakan lingkup anak baru untuk setiap item untuk diulang (tetapi juga membuatnya menggunakan scope.$new();dan tidak scope: true.
Valentyn Shybanov

1
Anda tidak dapat meminta beberapa lingkup terisolasi di dalam elemen yang sama, Anda tidak dapat mengakses fungsi dalam lingkup induk, kecuali jika Anda mengikatnya secara eksplisit. (Semoga berhasil menggunakan ngClickdll.) Membutuhkan menciptakan semacam decoupling, saya setuju, tetapi Anda masih perlu mengetahui arahan orang tua. Kecuali itu seperti komponen , saya menentang pergi untuk isolasi. Arahan (setidaknya, sebagian besar dari mereka) dimaksudkan untuk dapat digunakan kembali dan isolasi mematahkan ini.
Umur Kontacı

Saya juga tidak menggunakan arahan lingkup anak dalam arahan, tetapi karena lingkup anak secara prototipis mewarisi dari lingkup induk, jika akses ke properti di dalam properti di lingkup induk, perubahan diisi. Penulis Angular membicarakannya di pertemuan MTV, "senang memiliki titik di suatu tempat" youtube.com/watch?v=ZhfUv0spHCY
Umur Kontacı

5
Pertama, saya pikir Anda agak terlalu keras pada lingkup isolasi. Saya pikir mereka memiliki penerapan yang lebih luas daripada Anda memberi mereka kredit untuk memiliki dan bahwa ada cara untuk menghindari banyak tantangan yang Anda (benar) tunjukkan kita hadapi ketika menggunakannya. Saya juga tidak setuju dengan "tidak banyak penyesuaian untuk pengembang akhir" - lihat jawaban saya untuk detailnya. Yang mengatakan, jawaban Anda tidak buruk atau salah dan itu memang menjawab pertanyaan, jadi saya tidak yakin mengapa itu turun. Jadi +1.
Josh David Miller

9

Hanya berpikir saya akan menambahkan pemahaman saya saat ini dan bagaimana hubungannya dengan konsep JS lainnya.

Default (mis. Tidak dinyatakan atau ruang lingkup: false)

Secara filosofis ini setara dengan menggunakan variabel global. Arahan Anda dapat mengakses semua yang ada di pengontrol induk tetapi juga memengaruhi mereka dan terpengaruh pada saat yang sama.

cakupan:{}

Ini seperti modul, apa pun yang ingin digunakan perlu diteruskan secara eksplisit. Jika SETIAP arahan yang Anda gunakan adalah ruang lingkup isolat, itu bisa setara dengan membuat SETIAP file JS Anda menulis modul sendiri dengan banyak overhead dalam menyuntikkan semua dependensi.

ruang lingkup: anak

Ini adalah jalan tengah antara variabel global dan passthrough eksplisit. Ini mirip dengan rantai prototipe javascript dan hanya memperpanjang Anda salinan lingkup induknya. Jika Anda membuat ruang lingkup isolat dan meneruskan setiap atribut dan fungsi dari lingkup induk, itu secara fungsional setara dengan ini.


Kuncinya adalah bahwa arahan APAPUN dapat ditulis dengan cara APA SAJA. Deklarasi ruang lingkup yang berbeda hanya ada untuk membantu Anda mengatur. Anda dapat membuat semuanya modul, atau Anda bisa menggunakan semua variabel global dan sangat berhati-hati. Untuk kemudahan perawatan, lebih baik memodulasi logika Anda menjadi bagian-bagian yang logis secara koheren. Ada keseimbangan antara padang rumput terbuka dan rumah tahanan tertutup. Alasan ini rumit saya percaya adalah bahwa ketika orang belajar tentang ini mereka pikir mereka belajar tentang bagaimana arahan bekerja tetapi sebenarnya mereka belajar tentang kode / logika organisasi.

Hal lain yang membantu saya mengetahui bagaimana arahan bekerja adalah belajar tentang ngInclude. ngInclude membantu Anda memasukkan sebagian html. Ketika saya pertama kali mulai menggunakan arahan, saya menemukan bahwa Anda dapat menggunakan opsi templat untuk mengurangi kode Anda, tetapi saya tidak benar-benar melampirkan logika apa pun.

Tentu saja antara arahan sudut dan pekerjaan tim sudut-ui saya belum harus membuat arahan saya sendiri yang melakukan sesuatu yang substansial sehingga pandangan saya tentang ini mungkin benar-benar salah.


2

Saya setuju dengan Umur. Secara teori, ruang lingkup terisolasi terdengar indah dan "portabel," tetapi dalam membangun aplikasi saya untuk melibatkan fungsionalitas non-sepele, saya menemukan perlunya memasukkan beberapa arahan (beberapa bersarang di dalam yang lain atau menambahkan atribut kepada mereka) untuk sepenuhnya menulis di saya HTML sendiri, yang merupakan tujuan dari Bahasa Spesifik Domain.

Pada akhirnya, itu terlalu aneh untuk meneruskan setiap nilai global atau bersama ke rantai dengan beberapa atribut pada setiap permintaan DOM dari arahan (seperti yang diperlukan dengan ruang lingkup yang terpisah). Tampaknya bodoh untuk berulang kali menulis semua itu di DOM dan rasanya tidak efisien, bahkan jika ini adalah objek bersama. Ini juga tidak perlu memperumit deklarasi direktif. Solusi menggunakan $ parent untuk "mencapai" dan mengambil nilai dari HTML direktif sepertinya Bentuk Sangat Buruk.

Saya juga akhirnya mengubah aplikasi saya untuk memiliki sebagian besar arahan lingkup anak dengan sangat sedikit isolat - hanya mereka yang tidak perlu mengakses APA SAJA dari orang tua selain dari apa yang dapat mereka lewati melalui atribut sederhana yang tidak berulang.

Setelah memimpikan impian Domain Specific Languages ​​selama beberapa dekade sebelum ada hal seperti itu, saya gembira bahwa AngularJS menyediakan opsi ini dan saya tahu bahwa, karena lebih banyak pengembang yang bekerja di bidang ini, kita akan melihat beberapa aplikasi yang sangat keren yang juga mudah bagi arsitek mereka untuk menulis, memperluas, dan men-debug.

- D

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.