Mendedahkan keajaiban javascript
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>
<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>
<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 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="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="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><span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');</span>
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="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>/<<span>\s*\w.*?></span>/g</span>.exec(str); </span> <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</g</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>
<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>
<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>
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="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><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="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><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="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>/<<span>\s*\w.*?></span>/g</span>.exec(str); </span> <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</g</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 < users.length; i++) { </span> html <span>+= '<p>' + users[i] + '</p>'; </span> <span>} </span> domEl<span>.innerHTML = html; </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="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><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="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>/<<span>\s*\w.*?></span>/g</span>.exec(str); </span> <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</g</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>
<span>var wrapMap = { </span> <span>option: [1, '<select multiple="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 match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str); </span><span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');</span>
<span>var stringToDom = function(str) { </span> <span>var wrapMap = { </span> <span>option: [1, '<select multiple="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>/<<span>\s*\w.*?></span>/g</span>.exec(str); </span> <span>if(match != null) { </span> <span>var tag = match[0].replace(<span>/</g</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>
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>
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!

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

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Soalan dan penyelesaian yang sering ditanya untuk percetakan tiket kertas terma depan dalam pembangunan front-end, percetakan tiket adalah keperluan umum. Walau bagaimanapun, banyak pemaju sedang melaksanakan ...

JavaScript adalah asas kepada pembangunan web moden, dan fungsi utamanya termasuk pengaturcaraan yang didorong oleh peristiwa, penjanaan kandungan dinamik dan pengaturcaraan tak segerak. 1) Pengaturcaraan yang didorong oleh peristiwa membolehkan laman web berubah secara dinamik mengikut operasi pengguna. 2) Penjanaan kandungan dinamik membolehkan kandungan halaman diselaraskan mengikut syarat. 3) Pengaturcaraan Asynchronous memastikan bahawa antara muka pengguna tidak disekat. JavaScript digunakan secara meluas dalam interaksi web, aplikasi satu halaman dan pembangunan sisi pelayan, sangat meningkatkan fleksibiliti pengalaman pengguna dan pembangunan silang platform.

Tidak ada gaji mutlak untuk pemaju Python dan JavaScript, bergantung kepada kemahiran dan keperluan industri. 1. Python boleh dibayar lebih banyak dalam sains data dan pembelajaran mesin. 2. JavaScript mempunyai permintaan yang besar dalam perkembangan depan dan stack penuh, dan gajinya juga cukup besar. 3. Faktor mempengaruhi termasuk pengalaman, lokasi geografi, saiz syarikat dan kemahiran khusus.

Perbincangan mengenai realisasi kesan animasi tatal dan elemen Parallax dalam artikel ini akan meneroka bagaimana untuk mencapai yang serupa dengan laman web rasmi Shiseido (https://www.shiseido.co.jp/sb/wonderland/) ... ...

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.

Pembelajaran JavaScript tidak sukar, tetapi ia mencabar. 1) Memahami konsep asas seperti pembolehubah, jenis data, fungsi, dan sebagainya. 2) Pengaturcaraan asynchronous tuan dan melaksanakannya melalui gelung acara. 3) Gunakan operasi DOM dan berjanji untuk mengendalikan permintaan tak segerak. 4) Elakkan kesilapan biasa dan gunakan teknik debugging. 5) Mengoptimumkan prestasi dan mengikuti amalan terbaik.

Bagaimana cara menggabungkan elemen array dengan ID yang sama ke dalam satu objek dalam JavaScript? Semasa memproses data, kita sering menghadapi keperluan untuk mempunyai id yang sama ...

Terokai pelaksanaan fungsi seretan panel dan drop panel seperti VSCode di bahagian depan. Dalam pembangunan front-end, bagaimana untuk melaksanakan vscode seperti ...
