Takeaways Key
- perpustakaan JavaScript seperti jQuery memudahkan manipulasi DOM, seperti membuat unsur -unsur dari rentetan, dengan mengendalikan kes -kes yang kompleks seperti elemen bersarang dengan betul.
- sistem suntikan pergantungan AngularJS secara ajaib menguruskan kebergantungan tanpa lulus eksplisit, menggunakan corak penyuntik untuk memberikan ketergantungan secara dinamik pada masa runtime.
- Ember.js meningkatkan objek JavaScript dengan sifat -sifat yang dikira, yang membolehkan sifat berkelakuan seperti fungsi, mengemas kini secara automatik apabila kebergantungan berubah.
- sintaks JSX React membolehkan membenamkan HTML dalam JavaScript, yang kemudian diproses oleh pengubah JSX React untuk membuat komponen UI dinamik.
- Artikel ini menunjukkan penyelesaian tersuai untuk suntikan ketergantungan dan sifat -sifat yang dikira, menunjukkan bagaimana pemaju dapat melaksanakan fungsi yang sama dalam projek mereka.
- Memahami mekanik asas kerangka JavaScript yang popular dapat memberi kuasa kepada pemaju untuk menulis kod yang lebih efisien dan dikekalkan.
Dengan kebangkitan aplikasi halaman tunggal, kami melakukan banyak perkara dengan JavaScript. Sebahagian besar logik aplikasi kami telah dipindahkan ke pelayar. Ia adalah tugas yang sama untuk menjana atau menggantikan elemen pada halaman. Kod yang serupa dengan apa yang ditunjukkan di bawah telah menjadi sangat biasa.
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>Hasilnya adalah elemen
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>Kami menentukan kaedah utiliti kami sendiri StringTodom yang mencipta elemen
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>secara visual, pada halaman, tidak ada perbezaan. Walau bagaimanapun, jika kita menyemak markup yang dihasilkan dengan alat pemaju Chrome, kita akan mendapat hasil yang menarik:
Ia kelihatan seperti fungsi StringTodom kami yang dibuat hanya nod teks dan bukan tag
JQuery berjaya menyelesaikan masalah dengan mewujudkan konteks yang betul dan mengekstrak hanya bahagian yang diperlukan. Jika kita menggali sedikit ke dalam kod perpustakaan kita akan melihat peta seperti ini:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
Setiap elemen yang memerlukan rawatan khas mempunyai array yang diberikan. Idea ini adalah untuk membina elemen DOM yang betul dan bergantung kepada tahap sarang untuk mengambil apa yang kita perlukan. Sebagai contoh, untuk elemen
Mempunyai peta, kita perlu mengetahui jenis tag yang kita mahu pada akhirnya. Kod berikut mengekstrak TR dari
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
selebihnya mencari konteks yang betul dan mengembalikan elemen DOM. Berikut adalah varian akhir fungsi StringTodom:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
Perhatikan bahawa kami sedang menyemak jika terdapat tag dalam rentetan - padanan! = Null. Jika tidak kita hanya mengembalikan nod teks. Masih terdapat penggunaan sementara
Berikut adalah codepen yang menunjukkan pelaksanaan kami:
Lihat pena XLCGN oleh Krasimir Tsonev (@Krasimir) pada codepen.
mari kita teruskan dengan meneroka suntikan ketergantungan AngularJS yang indah.
mendedahkan suntikan ketergantungan angularjs
Apabila kita mula menggunakan AngularJS, ia mengesankan dengan mengikat data dua hala. Perkara kedua yang kami perhatikan ialah suntikan pergantungan ajaibnya. Berikut adalah contoh mudah:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
Itulah pengawal AngularJS yang tipikal. Ia melakukan permintaan HTTP, mengambil data dari fail JSON, dan lulus ke skop semasa. Kami tidak melaksanakan fungsi Todoctrl - kami tidak mempunyai peluang untuk lulus sebarang hujah. Rangka kerja itu. Jadi, di manakah skop $ ini dan pembolehubah HTTP $ datang? Ia adalah ciri super sejuk, yang sangat menyerupai sihir hitam. Mari kita lihat bagaimana ia dilakukan.
Kami mempunyai fungsi JavaScript yang memaparkan pengguna dalam sistem kami. Fungsi yang sama memerlukan akses kepada elemen DOM untuk meletakkan HTML yang dihasilkan, dan pembungkus Ajax untuk mendapatkan data. Untuk memudahkan contoh, kami akan mengejek data dan HTTP meminta.
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
Kami akan menggunakan tag
sebagai pemegang kandungan. AjaxWrapper adalah objek yang mensimulasikan permintaan dan Datamockup adalah array yang mengandungi pengguna kami. Inilah fungsi yang akan kita gunakan:<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
Dan tentu saja, jika kita menjalankan paparan (badan, ajaxwrapper) kita akan melihat tiga nama yang dipaparkan pada halaman dan /API /pengguna yang diminta dalam konsol kami. Kita boleh mengatakan bahawa kaedah kita mempunyai dua kebergantungan - badan dan AjaxWrapper. Oleh itu, sekarang idea itu adalah untuk membuat fungsi berfungsi tanpa lulus argumen, iaitu kita perlu mendapatkan hasil yang sama dengan memanggil hanya displayusers (). Sekiranya kita berbuat demikian dengan kod setakat ini, hasilnya akan menjadi:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
dan itu normal kerana parameter Ajax tidak ditakrifkan.
Kebanyakan rangka kerja yang menyediakan mekanisme untuk suntikan ketergantungan mempunyai modul, biasanya dinamakan penyuntik . Untuk menggunakan kebergantungan, kita perlu mendaftarkannya di sana. Kemudian, pada satu ketika, sumber kami diberikan kepada logik aplikasi dengan modul yang sama.
mari buat penyuntik kami:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
kita hanya memerlukan dua kaedah. Yang pertama, mendaftar, menerima sumber (kebergantungan) kami dan menyimpannya secara dalaman. Yang kedua menerima sasaran suntikan kami - fungsi yang mempunyai kebergantungan dan perlu menerimanya sebagai parameter. Momen utama di sini ialah penyuntik tidak boleh memanggil fungsi kami. Itulah tugas kita dan kita harus dapat mengawalnya. Apa yang boleh kita lakukan dalam kaedah penyelesaian adalah untuk mengembalikan penutupan yang membungkus sasaran dan memanggilnya. Contohnya:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>Menggunakan pendekatan itu, kita akan berpeluang memanggil fungsi dengan kebergantungan yang diperlukan. Dan pada masa yang sama kita tidak mengubah aliran kerja permohonan. Penyuntik masih sesuatu yang bebas dan tidak memegang fungsi berkaitan logik.
Sudah tentu, lulus fungsi Displayusers ke kaedah penyelesaian tidak membantu.
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>Kami masih mendapat ralat yang sama. Langkah seterusnya adalah untuk mengetahui keperluan sasaran yang diluluskan. Apakah kebergantungannya? Dan inilah bahagian rumit yang dapat kita pakai dari AngularJS. Saya, sekali lagi, menggali sedikit ke dalam kod rangka kerja dan mendapati ini:
<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>Kami sengaja melangkau beberapa bahagian, kerana mereka lebih seperti butiran pelaksanaan. Itulah kod yang menarik untuk kami. Fungsi Annotate adalah seperti kaedah penyelesaian kami. Ia menukarkan fungsi sasaran yang diluluskan ke rentetan, menghilangkan komen (jika ada), dan mengekstrak argumen. Mari kita gunakan dan lihat hasilnya:
<span>var dataMockup = ['John', 'Steve', 'David']; </span><span>var body = document.querySelector('body'); </span><span>var ajaxWrapper = { </span> <span>get: function(path<span>, cb</span>) { </span> <span>console.log(path + ' requested'); </span> <span>cb(dataMockup); </span> <span>} </span><span>}</span>inilah output dalam konsol:
Jika kita mendapat elemen kedua array argdecl kita akan dapati nama -nama kebergantungan yang diperlukan. Itulah yang kita perlukan, kerana mempunyai nama -nama kita akan dapat menyampaikan sumber dari penyimpanan penyuntik. Berikut adalah versi yang berfungsi dan berjaya merangkumi matlamat kami:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
Perhatikan bahawa kami menggunakan .split (/,?/g) untuk menukar rentetan domel, ajax ke array. Selepas itu kami menyemak jika kebergantungan didaftarkan dan jika ya kami lulus mereka ke fungsi sasaran. Kod di luar penyuntik kelihatan seperti itu:
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
manfaat pelaksanaan sedemikian adalah bahawa kita boleh menyuntik elemen DOM dan pembalut Ajax dalam banyak fungsi. Kami juga boleh mengedarkan konfigurasi aplikasi kami seperti itu. Tidak perlu lulus objek dari kelas ke kelas. Ia hanya mendaftar dan menyelesaikan kaedah.
Sudah tentu penyuntik kami tidak sempurna. Masih terdapat beberapa ruang untuk penambahbaikan, seperti contoh sokongan definisi skop. Fungsi sasaran sekarang dipanggil dengan skop yang baru dibuat, tetapi biasanya kita akan mahu lulus sendiri. Kami harus menyokong juga menghantar hujah -hujah tersuai bersama -sama dengan kebergantungan.
Penyuntik menjadi lebih rumit jika kita mahu menyimpan kod kita selepas minifikasi. Seperti yang kita tahu minifiers menggantikan nama -nama fungsi, pembolehubah dan juga argumen kaedah. Dan kerana logik kita bergantung pada nama -nama ini kita perlu memikirkan penyelesaian. Satu penyelesaian yang mungkin sekali lagi datang dari AngularJS:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
bukannya hanya displayusers kita lulus nama dependensi sebenar.
Contoh kami dalam tindakan:
Lihat pena bxdar oleh Krasimir Tsonev (@krasimir) pada codepen.
Mengadopsi Properties Computed Ember
Ember adalah salah satu rangka kerja yang paling popular pada masa kini. Ia mempunyai banyak ciri berguna. Terdapat satu yang sangat menarik - sifat yang dikira. Ringkasnya, sifat yang dikira adalah fungsi yang bertindak sebagai sifat. Mari kita lihat contoh mudah yang diambil dari dokumentasi Ember:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
Terdapat kelas yang mempunyai NameName dan LastName Properties. FullName harta yang dikira mengembalikan rentetan yang disatukan yang mengandungi nama penuh orang itu. Perkara yang pelik adalah bahagian di mana kita menggunakan kaedah .property terhadap fungsi yang digunakan untuk FullName. Saya secara peribadi tidak melihatnya di tempat lain. Dan, sekali lagi, melihat kod rangka kerja yang cepat mendedahkan sihir:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
Perpustakaan tweak prototaip objek fungsi global dengan menambahkan harta baru. Ia adalah pendekatan yang bagus untuk menjalankan beberapa logik semasa definisi kelas.
Ember menggunakan getters dan setters untuk beroperasi dengan data objek. Itu memudahkan pelaksanaan sifat -sifat yang dikira kerana kita mempunyai satu lagi lapisan sebelum mencapai pembolehubah sebenar. Walau bagaimanapun, ia akan menjadi lebih menarik jika kita dapat menggunakan sifat yang dikira dengan objek JavaScript biasa. Seperti contohnya:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
Nama digunakan sebagai harta biasa tetapi dalam amalan adalah fungsi yang mendapat atau menetapkan nama pertama dan lastname.
Terdapat ciri pembina JavaScript yang dapat membantu kita merealisasikan idea itu. Lihat coretan berikut:
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
Kaedah Object.Defineproperty boleh menerima skop, nama harta, getter, dan setter. Apa yang perlu kita lakukan ialah menulis badan kedua -dua kaedah. Dan itu sahaja. Kami akan dapat menjalankan kod di atas dan kami akan mendapat hasil yang diharapkan:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
Object.Defineproperty adalah apa yang kita perlukan, tetapi kita tidak mahu memaksa pemaju untuk menulisnya setiap kali. Kita mungkin perlu menyediakan polyfill, menjalankan logik tambahan, atau sesuatu seperti itu. Dalam kes yang ideal, kami ingin menyediakan antara muka yang serupa dengan Ember. Hanya satu fungsi adalah sebahagian daripada definisi kelas. Dalam bahagian ini, kami akan menulis fungsi utiliti yang dipanggil mengira yang akan memproses objek kami dan entah bagaimana akan menukar fungsi nama ke harta dengan nama yang sama.
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
Kami mahu menggunakan kaedah nama sebagai setter, dan pada masa yang sama sebagai getter. Ini serupa dengan sifat -sifat yang dikira oleh Ember.
Sekarang mari kita tambahkan logik kita sendiri ke dalam prototaip objek fungsi:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
Sebaik sahaja kita menambah baris di atas, kita akan dapat menambah. Komput () hingga akhir setiap definisi fungsi:
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
Akibatnya, harta nama tidak mengandungi fungsi lagi, tetapi objek yang telah mengira harta yang sama dengan harta yang benar dan func yang diisi dengan fungsi lama. Keajaiban sebenar berlaku dalam pelaksanaan pembantu mengira. Ia melalui semua sifat objek dan menggunakan objek.defineproperty di mana kita telah mengira sifat:
<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>
Perhatikan bahawa kami memadamkan nama harta asal. Dalam beberapa objek penyemak imbas.Defineproperty hanya berfungsi pada sifat yang belum ditakrifkan.
di sini adalah versi akhir objek pengguna yang menggunakan.Fungsi yang mengembalikan nama penuh digunakan untuk menukar nama firstName dan lastName. Itulah idea di sebalik pemeriksaan hujah -hujah yang diluluskan dan memproses yang pertama. Sekiranya ada, kita memisahkannya dan menggunakan nilai -nilai kepada sifat -sifat biasa.
<span>var dataMockup = ['John', 'Steve', 'David']; </span><span>var body = document.querySelector('body'); </span><span>var ajaxWrapper = { </span> <span>get: function(path<span>, cb</span>) { </span> <span>console.log(path + ' requested'); </span> <span>cb(dataMockup); </span> <span>} </span><span>}</span>
Kami sudah menyebut penggunaan yang dikehendaki, tetapi mari kita lihat sekali lagi:
codepen berikut menunjukkan kerja kami dalam amalan:
<span>var displayUsers = function(domEl<span>, ajax</span>) { </span> ajax<span>.get('/api/users', function(users) { </span> <span>var html = ''; </span> <span>for(var i=0; i html <span>+= '<p>' + users[i] + '</p>'; </span> <span>} </span> domEl<span>.innerHTML = html; </span> <span>}); </span><span>}</span></span>
Lihat pena ahpqo oleh Krasimir Tsonev (@Krasimir) di Codepen.
Templat React Crazy
Anda mungkin pernah mendengar tentang Rangka Kerja Facebook. Ia dibina di sekitar idea bahawa semuanya adalah komponen. Apa yang menarik ialah definisi komponen. Mari kita lihat contoh berikut:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
Perkara pertama yang kita mulakan adalah bahawa ini adalah JavaScript, tetapi ia adalah yang tidak sah. Terdapat fungsi render, dan ia mungkin akan membuang kesilapan. Walau bagaimanapun, silap mata ialah kod ini dimasukkan ke dalam
Pendekatan yang diambil Facebook adalah untuk mencampur kod JavaScript dengan markup HTML. Oleh itu, katakanlah bahawa kita mempunyai templat berikut:
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
dan komponen yang menggunakannya:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>
Ideanya ialah kami menunjukkan ID templat dan menentukan data yang perlu digunakan. Sekeping pelaksanaan terakhir kami adalah enjin sebenar yang menggabungkan kedua -dua elemen tersebut. Mari kita panggil enjin dan mulakannya seperti itu:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>
Kami mendapat kandungan tag
Sekarang, mari tulis fungsi parse kami. Tugas pertama kami adalah untuk membezakan HTML dari ekspresi. Dengan ungkapan, kami bermaksud rentetan yang diletakkan di antara . Kami akan menggunakan regex untuk mencari mereka dan gelung semasa yang mudah untuk melalui semua perlawanan:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
Hasil dari kod di atas adalah seperti berikut:
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>
Hanya ada satu ungkapan dan kandungannya adalah tajuk. Pendekatan intuitif pertama yang boleh kita ambil ialah menggunakan fungsi pengganti JavaScript dan menggantikan dengan data dari objek Comp yang diluluskan. Walau bagaimanapun, ini akan berfungsi hanya dengan sifat mudah. Bagaimana jika kita mempunyai objek bersarang atau bahkan jika kita mahu menggunakan fungsi. Seperti contohnya:
<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>
Daripada membuat parser kompleks dan hampir mencipta bahasa baru kita boleh menggunakan JavaScript tulen. Satu -satunya perkara yang perlu kita lakukan ialah menggunakan sintaks fungsi baru.
<span>var dataMockup = ['John', 'Steve', 'David']; </span><span>var body = document.querySelector('body'); </span><span>var ajaxWrapper = { </span> <span>get: function(path<span>, cb</span>) { </span> <span>console.log(path + ' requested'); </span> <span>cb(dataMockup); </span> <span>} </span><span>}</span>
kita dapat membina badan fungsi yang kemudian dilaksanakan. Jadi, kita tahu kedudukan ekspresi kita dan apa yang sebenarnya berdiri di belakang mereka. Jika kita menggunakan array sementara dan kursor kita sementara kitaran akan kelihatan seperti itu:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
output dalam konsol menunjukkan bahawa kita berada di landasan yang betul:
<span>var stringToDom = function(str) { </span> <span>var temp = document.createElement('div'); </span> temp<span>.innerHTML = str; </span> <span>return temp.childNodes[0]; </span><span>} </span><span>var text = stringToDom('<div>Simple text</div>'); </span> <span>document.querySelector('body').appendChild(text);</span>
Arahan kod harus diubah menjadi rentetan yang akan menjadi badan fungsi. Contohnya:
<span>var tableRow = $('<tr><td>Simple text</td></tr>'); </span><span>$('body').append(tableRow); </span> <span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>'); </span><span>document.querySelector('body').appendChild(tableRow);</span>Ia agak mudah untuk mencapai hasil ini. Kami boleh menulis gelung yang melalui semua elemen array kod dan cek jika item itu adalah rentetan atau objek. Walau bagaimanapun, ini sekali lagi merangkumi sebahagian daripada kes. Bagaimana jika kita mempunyai templat berikut:
<span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span><span>}; </span>wrapMap<span>.optgroup = wrapMap.option; </span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span>wrapMap<span>.th = wrapMap.td;</span>kita tidak boleh menggabungkan ungkapan dan mengharapkan warna yang disenaraikan. Oleh itu, bukannya memasuki rentetan untuk rentetan, kami akan mengumpulnya dalam array. Berikut adalah versi terkini fungsi parse:
<span>var match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>Setelah array kod diisi, kami mula membina badan fungsi. Setiap baris templat akan disimpan dalam r. Jika garis adalah rentetan, kami membersihkannya sedikit dengan melepaskan petikan dan mengeluarkan baris dan tab baru. Ia ditambah kepada array melalui kaedah push. Jika kita mempunyai coretan kod maka kita periksa sama ada ia bukan pengendali JavaScript yang sah. Jika ya maka kita tidak menambahkannya ke array tetapi hanya menjatuhkannya sebagai garis baru. Konsol.log pada output akhir:
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple>', '</select>'], </span> <span>legend: [1, '<fieldset>', '</fieldset>'], </span> <span>area: [1, '<map>', '</map>'], </span> <span>param: [1, '<object>', '</object>'], </span> <span>thead: [1, '<table>', '</table>'], </span> <span>tr: [2, '<table><tbody>', '</tbody></table>'], </span> <span>col: [2, '<table> <tbody></tbody> <colgroup>', '</colgroup> </table>'], </span> <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'], </span> <span>_default: [1, '<div>', '</div>'] </span> <span>}; </span> wrapMap<span>.optgroup = wrapMap.option; </span> wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; </span> wrapMap<span>.th = wrapMap.td; </span> <span>var element = document.createElement('div'); </span> <span>var match = <span>/\s*\w.*?></span>/g</span>.exec(str); <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</span>, '').replace(<span>/>/g</span>, ''); </span> <span>var map = wrapMap[tag] || wrapMap._default, element; </span> str <span>= map[1] + str + map[2]; </span> element<span>.innerHTML = str; </span> <span>// Descend through wrappers to the right content </span> <span>var j = map[0]+1; </span> <span>while(j--) { </span> element <span>= element.lastChild; </span> <span>} </span> <span>} else { </span> <span>// if only text is passed </span> element<span>.innerHTML = str; </span> element <span>= element.lastChild; </span> <span>} </span> <span>return element; </span><span>}</span>Bagus, bukan? JavaScript yang berfungsi dengan betul, yang dilaksanakan dalam konteks komponen kami akan menghasilkan markup HTML yang dikehendaki.
perkara terakhir yang tersisa adalah berjalan sebenar fungsi kami yang hampir dibuat:
<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) { </span> $http<span>.get('users/users.json').success(function(data) { </span> $scope<span>.users = data; </span> <span>}); </span><span>}</span>Kami membungkus kod kami dengan pernyataan untuk menjalankannya dalam konteks komponen. Tanpa itu kita perlu menggunakan ini.Title dan this.colors dan bukannya tajuk dan warna.
Berikut adalah codepen yang menunjukkan hasil akhir:
Lihat pena gahej oleh Krasimir Tsonev (@krasimir) pada codepen.
Ringkasan
Di sebalik kerangka besar dan perpustakaan adalah pemaju pintar. Mereka mendapati dan menggunakan penyelesaian rumit yang tidak remeh, dan bahkan agak ajaib. Dalam artikel ini, kami mendedahkan beberapa sihir itu. Adalah baik bahawa di dunia JavaScript kita dapat belajar dari yang terbaik dan menggunakan kod mereka.
kod dari artikel ini tersedia untuk dimuat turun dari GitHub
Soalan Lazim (Soalan Lazim) Mengenai Keajaiban JavaScript
Apakah kaedah sihir dalam JavaScript dan bagaimana mereka berfungsi? Mereka tidak dipanggil secara langsung tetapi dipanggil apabila tindakan tertentu dilakukan. Sebagai contoh, kaedah ToString () adalah kaedah sihir yang secara automatik dipanggil apabila objek perlu diwakili sebagai nilai teks. Contoh lain ialah kaedah ValueOf (), yang dipanggil apabila objek diwakili sebagai nilai primitif.
Bagaimana saya boleh menggunakan kaedah sihir dalam javascript?
Kaedah sihir dalam JavaScript boleh digunakan dengan menentukannya dalam objek atau kelas anda. Sebagai contoh, anda boleh menentukan kaedah ToString () dalam objek anda untuk menyesuaikan bagaimana objek anda akan diwakili sebagai rentetan. Berikut adalah contoh mudah:
biarkan person = {
firstName: "John",
lastName: "doe",
toString: function () {
kembali ini.firstname " "this.lastName;
}
};
console.log (person.toString ()); // "John Doe"
Apakah kepentingan fungsi sihir dalam JavaScript? Mereka boleh menjadikan kod anda lebih intuitif dan lebih mudah difahami, serta menyediakan cara untuk merangkum dan melindungi data anda. Berikut adalah beberapa contoh fungsi sihir dalam JavaScript:
1. toString (): Kaedah ini mengembalikan rentetan yang mewakili objek. valueof (): Kaedah ini mengembalikan nilai primitif objek. HasownProperty (): Kaedah ini mengembalikan boolean yang menunjukkan sama ada objek mempunyai harta yang ditentukan. Kaedah sihir boleh menjadi sangat berguna, mereka juga mempunyai beberapa batasan. Untuk satu, mereka boleh membuat kod anda lebih kompleks dan lebih sukar untuk debug, terutamanya jika anda tidak biasa dengan cara mereka bekerja. Mereka juga boleh membawa kepada tingkah laku yang tidak dijangka jika tidak digunakan dengan betul.
Bagaimanakah JavaScript mengendalikan kaedah sihir berbanding dengan bahasa pengaturcaraan lain? "Kaedah Magic". Walau bagaimanapun, ia mempunyai kaedah tertentu yang berkelakuan sama, seperti ToString () dan ValueOf (). Kaedah ini secara automatik dipanggil dalam situasi tertentu, seperti kaedah sihir dalam bahasa lain. Sertakan pemahaman bila dan mengapa menggunakannya, menggunakannya dengan berhati -hati untuk mengelakkan kerumitan, dan sentiasa menguji kod anda dengan teliti untuk memastikan ia berkelakuan seperti yang diharapkan.
Bolehkah kaedah sihir digunakan dengan kerangka JavaScript seperti React atau Vue? Walau bagaimanapun, cara mereka digunakan mungkin berbeza -beza bergantung kepada rangka kerja. Selalu terbaik untuk merujuk kepada dokumentasi rangka kerja khusus untuk panduan.
Bagaimana saya boleh mengetahui lebih lanjut mengenai kaedah sihir dalam JavaScript? Anda boleh bermula dengan dokumentasi JavaScript rasmi, serta tutorial dan kursus dalam talian. Anda juga boleh mengamalkan menggunakannya dalam projek anda sendiri untuk mendapatkan pengalaman tangan. Alat yang boleh membantu menggunakan kaedah sihir dalam JavaScript. Sebagai contoh, Lodash adalah perpustakaan utiliti JavaScript yang popular yang menyediakan kaedah yang berguna untuk bekerja dengan array, objek, dan jenis data lain.
Atas ialah kandungan terperinci Mendedahkan keajaiban javascript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

C dan JavaScript mencapai interoperabilitas melalui webassembly. 1) Kod C disusun ke dalam modul WebAssembly dan diperkenalkan ke dalam persekitaran JavaScript untuk meningkatkan kuasa pengkomputeran. 2) Dalam pembangunan permainan, C mengendalikan enjin fizik dan rendering grafik, dan JavaScript bertanggungjawab untuk logik permainan dan antara muka pengguna.

JavaScript digunakan secara meluas di laman web, aplikasi mudah alih, aplikasi desktop dan pengaturcaraan sisi pelayan. 1) Dalam pembangunan laman web, JavaScript mengendalikan DOM bersama -sama dengan HTML dan CSS untuk mencapai kesan dinamik dan menyokong rangka kerja seperti JQuery dan React. 2) Melalui reaktnatif dan ionik, JavaScript digunakan untuk membangunkan aplikasi mudah alih rentas platform. 3) Rangka kerja elektron membolehkan JavaScript membina aplikasi desktop. 4) Node.js membolehkan JavaScript berjalan di sisi pelayan dan menyokong permintaan serentak yang tinggi.

Python lebih sesuai untuk sains data dan automasi, manakala JavaScript lebih sesuai untuk pembangunan front-end dan penuh. 1. Python berfungsi dengan baik dalam sains data dan pembelajaran mesin, menggunakan perpustakaan seperti numpy dan panda untuk pemprosesan data dan pemodelan. 2. Python adalah ringkas dan cekap dalam automasi dan skrip. 3. JavaScript sangat diperlukan dalam pembangunan front-end dan digunakan untuk membina laman web dinamik dan aplikasi satu halaman. 4. JavaScript memainkan peranan dalam pembangunan back-end melalui Node.js dan menyokong pembangunan stack penuh.

C dan C memainkan peranan penting dalam enjin JavaScript, terutamanya digunakan untuk melaksanakan jurubahasa dan penyusun JIT. 1) C digunakan untuk menghuraikan kod sumber JavaScript dan menghasilkan pokok sintaks abstrak. 2) C bertanggungjawab untuk menjana dan melaksanakan bytecode. 3) C melaksanakan pengkompil JIT, mengoptimumkan dan menyusun kod hot-spot semasa runtime, dan dengan ketara meningkatkan kecekapan pelaksanaan JavaScript.

Aplikasi JavaScript di dunia nyata termasuk pembangunan depan dan back-end. 1) Memaparkan aplikasi front-end dengan membina aplikasi senarai TODO, yang melibatkan operasi DOM dan pemprosesan acara. 2) Membina Restfulapi melalui Node.js dan menyatakan untuk menunjukkan aplikasi back-end.

Penggunaan utama JavaScript dalam pembangunan web termasuk interaksi klien, pengesahan bentuk dan komunikasi tak segerak. 1) kemas kini kandungan dinamik dan interaksi pengguna melalui operasi DOM; 2) pengesahan pelanggan dijalankan sebelum pengguna mengemukakan data untuk meningkatkan pengalaman pengguna; 3) Komunikasi yang tidak bersesuaian dengan pelayan dicapai melalui teknologi Ajax.

Memahami bagaimana enjin JavaScript berfungsi secara dalaman adalah penting kepada pemaju kerana ia membantu menulis kod yang lebih cekap dan memahami kesesakan prestasi dan strategi pengoptimuman. 1) aliran kerja enjin termasuk tiga peringkat: parsing, penyusun dan pelaksanaan; 2) Semasa proses pelaksanaan, enjin akan melakukan pengoptimuman dinamik, seperti cache dalam talian dan kelas tersembunyi; 3) Amalan terbaik termasuk mengelakkan pembolehubah global, mengoptimumkan gelung, menggunakan const dan membiarkan, dan mengelakkan penggunaan penutupan yang berlebihan.

Python lebih sesuai untuk pemula, dengan lengkung pembelajaran yang lancar dan sintaks ringkas; JavaScript sesuai untuk pembangunan front-end, dengan lengkung pembelajaran yang curam dan sintaks yang fleksibel. 1. Sintaks Python adalah intuitif dan sesuai untuk sains data dan pembangunan back-end. 2. JavaScript adalah fleksibel dan digunakan secara meluas dalam pengaturcaraan depan dan pelayan.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

SublimeText3 Linux versi baharu
SublimeText3 Linux versi terkini

VSCode Windows 64-bit Muat Turun
Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft

MinGW - GNU Minimalis untuk Windows
Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.

Dreamweaver Mac版
Alat pembangunan web visual

DVWA
Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini