>我們每天使用大量工具。不同的圖書館和框架是我們日常工作的一部分。我們之所以使用它們,是因為我們不想為每個項目重新發明輪子,即使我們不了解引擎蓋下的情況。在本文中,我們將揭示最受歡迎的圖書館中發生的一些神奇過程。我們還將查看是否可以復制他們的行為。
>鑰匙要點
- > jQuery(例如jQuery)簡化dom操縱(例如,從字符串創建元素),正確處理複雜的情況(如嵌套元素)(如嵌套元素)。
ember.js使用計算屬性增強JavaScript對象,允許屬性像函數一樣行為,在依賴性更改時自動更新。 React的JSX語法允許將HTML嵌入JavaScript中,然後由React的JSX Transformer處理以創建動態UI組件。 - >本文展示了用於依賴注入和計算屬性的自定義解決方案,展示了開發人員如何在其項目中實施相似的功能。
了解流行的JavaScript框架的基本力學可以使開發人員能夠編寫更有效和可維護的代碼。- 隨著單頁應用程序的興起,我們正在使用JavaScript做很多事情。應用程序邏輯的很大一部分已移至瀏覽器。在頁面上生成或替換元素是一項常見的任務。與下面顯示的相似的代碼已經變得非常普遍。
元素。這個簡單的操作僅使用一行jQuery完成。沒有jQuery,代碼有些複雜,但沒有太多:- >
我們定義了創建臨時元素的自己的實用程序方法字符串。我們更改了其InnerHTML屬性,最後我們簡單地退回了第一個孩子,實際上我們需要的是我們所需要的。它以同樣的方式工作。但是,我們將通過以下代碼觀察不同的結果:>
在頁面上,在頁面上沒有差異。但是,如果我們使用Chrome的開發人員工具檢查生成的標記,我們將獲得一個有趣的結果:
> <span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
>看起來我們的字符串todom函數僅創建了一個文本節點,而不是實際的
標籤。但與此同時,jQuery以某種方式設法這樣做。問題在於,包含HTML元素的字符串通過瀏覽器中的解析器運行。解析器忽略了未放置在正確上下文中的標籤,而我們只會得到一個文本節點。沒有表格的表行對於瀏覽器無效。 > jQuery通過創建正確的上下文並僅提取所需部分來成功解決問題。如果我們挖掘了庫的代碼,我們將看到這樣的地圖:
> <span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
需要特殊處理的每個元素都分配了一個陣列。這個想法是構造正確的DOM元素,並依賴嵌套的級別來獲取我們需要的東西。例如,對於元素,我們需要用 child創建一個表。因此,我們有兩個層次的嵌套。簡單的文本 提取TR
<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>
其餘的正在找到正確的上下文並返回DOM元素。這是函數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>
請注意,我們正在檢查字符串中是否有標籤 - 匹配! = null。如果不是,我們只是返回文本節點。仍然有一個臨時的用法,但是這次我們傳遞了正確的標籤,因此瀏覽器可以創建有效的DOM樹。最後,通過使用一段時間循環,我們將越來越深,直到達到想要的標籤為止。'], col: [2, '這是一個codepen,顯示了我們的實現:
參見codepen上的krasimir tsonev(@krasimir)的筆xlcgn。
讓我們繼續探索奇妙的AngularJS依賴注入。揭示agnularjs依賴注射
當我們開始使用AngularJs時,它的雙向數據綁定給人留下深刻的印象。我們注意到的第二件事是它的神奇依賴注入。這是一個簡單的示例:>這是一個典型的AngularJS控制器。它執行HTTP請求,從JSON文件中獲取數據,然後將其傳遞給當前範圍。我們沒有執行todoctrl函數 - 我們沒有機會通過任何參數。框架確實如此。那麼,這些$範圍和$ http變量來自哪裡?這是一個超級酷的功能,非常類似於黑魔法。讓我們看看它是如何完成的。
>我們有一個JavaScript函數,可以在系統中顯示用戶。相同的功能需要訪問DOM元素才能放置生成的HTML和AJAX包裝器以獲取數據。為了簡化示例,我們將模擬數據和HTTP請求。
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
我們將使用
標籤作為內容持有人。 AjaxWrapper是模擬請求的對象,DatamOckup是包含我們用戶的數組。這是我們將使用的功能:<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>
當然,如果我們運行顯示器(正文,AjaxWrapper),我們將在頁面上看到三個名稱,以及在我們的控制台中請求的 /api /用戶。我們可以說我們的方法具有兩個依賴性 - 身體和AjaxWrapper。因此,現在的想法是使該函數在不傳遞參數的情況下工作,即,我們必須通過調用DisplayUser()來獲得相同的結果。如果到目前為止,我們使用代碼執行此操作,則結果將是:
><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>
>正常,因為未定義Ajax參數。
>提供依賴性注入機制的大多數框架具有一個模塊,通常命名為>噴油器。要使用依賴關係,我們需要在此處註冊。後來,在某個時候,我們的資源由同一模塊提供給應用程序的邏輯。 >
讓我們創建我們的噴油器:<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 match = <span>/<<span >\s*\w.*?></span>/g</span>.exec(str); <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span >/>/g</span>, '');</span>
使用該方法,我們將有機會使用所需的依賴項調用該功能。同時,我們沒有更改應用程序的工作流程。噴油器仍然是獨立的,並且不具有與邏輯相關的功能。>
當然,將顯示器的功能傳遞到Resolve方法無濟於事。<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>
><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>
如果我們獲得了argdecl數組的第二個元素,我們將找到所需依賴項的名稱。這正是我們需要的,因為擁有名稱我們將能夠從噴油器的存儲中傳遞資源。這是有效的版本並成功涵蓋了我們的目標:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
請注意,我們正在使用.split(/,?/g)將字符串Domel,Ajax轉換為數組。之後,我們正在檢查依賴項是否已註冊,如果是,則將其傳遞給目標函數。噴油器外部的代碼看起來像:
<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>
這種實現的好處是,我們可以在許多功能中註入DOM元素和Ajax包裝器。我們甚至可以這樣分發應用程序的配置。無需將對像從類傳遞到類。這只是寄存器和解決方法。
> 當然,我們的噴油器並不完美。仍然有一些改進的空間,例如支持範圍定義。目前,目標功能通過新創建的範圍調用,但通常我們將要通過自己的範圍。我們應該支持還發送自定義參數以及依賴關係。> 如果我們想在縮小後保持代碼工作,則噴油器會變得更加複雜。眾所周知,縮影替換了函數,變量甚至方法的參數的名稱。而且,由於我們的邏輯依賴於這些名稱,因此我們需要考慮解決方法。一種可能的解決方案再次來自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>
我們的示例在行動中:採用ember的計算屬性
Ember是當今最受歡迎的框架之一。它具有許多有用的功能。有一個特別有趣的 - 計算屬性。總而言之,計算的屬性是充當屬性的函數。讓我們看看一個簡單的示例從灰燼的文檔中獲取:>有一個具有名稱和姓氏屬性的類。計算的屬性fullname返回包含人的全名的串聯字符串。奇怪的是,我們使用.property方法來針對應用於fullname的函數的部分。我個人在其他任何地方都沒有看到。而且,快速查看框架的代碼揭示了魔術:
<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>
>ember使用getters和setter與對象的數據一起操作。這簡化了計算屬性的實現,因為我們之前還有一層可以達到實際變量。但是,如果我們能夠使用普通的JavaScript對象使用計算的屬性,將會更有趣。例如:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
>名稱用作常規屬性,但實際上是一個獲取或設置firstName和lastname的函數。
>有一個JavaScript的建築功能,可以幫助我們實現這個想法。看看以下片段:
<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>
object.defineproperty方法可以接受範圍,屬性的名稱,getter和setter。我們要做的就是寫這兩種方法的主體。就是這樣。我們將能夠運行上面的代碼,我們將獲得預期的結果:
><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正是我們所需要的,但是我們不想迫使開發人員每次編寫它。我們可能需要提供多填充,運行其他邏輯或類似的東西。在理想情況下,我們希望提供與Ember類似的界面。只有一個函數是類定義的一部分。在本節中,我們將編寫一個稱為Computize的實用程序函數,該函數將處理我們的對象,並以某種方式將名稱函數轉換為具有相同名稱的屬性。
><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>
>我們想將名稱方法用作設置器,同時與Getter一起使用。這類似於Ember的計算屬性。
> 現在> <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>
結果,名稱屬性不再包含函數,而是計算出等於true and func屬性的對象填充了舊功能。真正的魔術發生在計算助手的實現中。它通過對象的所有屬性並使用對象。 DefineProperty我們已經計算出屬性:>
<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>
請注意,我們正在刪除原始屬性名稱。在某些瀏覽器對像中。 defineProperty僅在尚未定義的屬性上起作用。>
這是使用.competed()函數的用戶對象的最終版本。<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>
以下codepen在實踐中顯示了我們的工作:
參見codepen上的krasimir tsonev(@krasimir)的筆Ahpqo。
瘋狂的反應模板
>您可能已經聽說過Facebook的框架反應。它圍繞著一切都是組成部分的想法。有趣的是組件的定義。讓我們來看看以下示例:
<span>var text = $('<div>Simple text</div>'); </span> <span>$('body').append(text);</span>
>我們開始考慮的第一件事是這是JavaScript,但這是無效的。有一個渲染功能,它可能會丟失錯誤。但是,訣竅是將此代碼放在帶有自定義類型屬性的<script>標籤中。瀏覽器沒有處理它,這意味著我們免受錯誤的安全。 React有自己的解析器,將我們寫的代碼轉換為有效的JavaScript。 Facebook的開發人員稱為XML Like Language <ancland> jsx<em>。他們的JSX變壓器為390K,包含大約12000行代碼。因此,這有點複雜。在本節中,我們將創建一些簡單的方法,但仍然非常強大。以React風格解析HTML模板的JavaScript類。 > </script>
> Facebook採取的方法是將JavaScript代碼與HTML標記混合。因此,可以說,我們有以下模板:>
<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>
的想法是,我們指出了模板的ID並定義了應應用的數據。我們實施的最後一部分是將兩個要素合併的實際引擎。讓我們稱其為引擎,然後以這樣的方式啟動:<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>
>我們正在獲取', '
'], _default: [1, '', ' ', ''] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; var element = document.createElement('div'); var match = /\s*\w.*?>/g.exec(str); if(match != null) { var tag = match[0].replace(/, '').replace(/>/g, ''); var map = wrapMap[tag] || wrapMap._default, element; str = map[1] + str + map[2]; element.innerHTML = str; // Descend through wrappers to the right content var j = map[0]+1; while(j--) { element = element.lastChild; } } else { // if only text is passed element.innerHTML = str; element = element.lastChild; } return element; }>而不是創建複雜的解析器,幾乎發明了我們可能使用純JavaScript的新語言。我們要做的唯一一件事是使用新函數語法。
><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 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>
>實現這一結果非常容易。我們可能會編寫一個循環,該循環涉及代碼數組的所有元素,並檢查項目是否是字符串或對象。但是,這再次涵蓋了其中一部分。如果我們有以下模板:<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>
>我們不能僅僅使表達式加入,並期望列出顏色。因此,而不是將字符串附加到字符串中,而是將它們收集在數組中。這是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>
>填充代碼陣列後,我們開始構建函數的主體。模板的每一行都將存儲在陣列r中。如果該行是字符串,我們通過逃脫引號並刪除新行和選項卡來清理一點。它通過推送方法添加到數組中。如果我們有代碼段,則我們檢查它是否不是有效的JavaScript操作員。如果是,那麼我們不是將其添加到數組中,而只是將其刪除為新行。末端輸出的控制台。<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>
剩下的最後一件事是我們虛擬創建的函數的實際運行:> >
這是一個codepen,演示了最終結果:<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>
參見codepen上的krasimir tsonev(@krasimir)的筆
摘要大型框架和圖書館後面的
是明智的開發人員。他們發現並使用了棘手的解決方案,這些解決方案並非微不足道,甚至是神奇的。在本文中,我們揭示了一些魔術。在JavaScript世界中,我們能夠從最好的代碼中學習並使用其代碼。本文中的代碼可從github
下載經常詢問有關JavaScript
魔法的問題(常見問題解答)> JavaScript中的魔術方法是什麼?它們如何工作?它們不是直接調用的,而是在執行某些動作時被調用。例如,ToString()方法是一種魔術方法,當需要將對象表示為文本值時,它會自動調用。另一個示例是valueof()方法,當對像被表示為原始值時,該方法稱為。
>如何在JavaScript中使用魔術方法?例如,您可以在對像中定義toString()方法,以自定義對象將如何表示為字符串。這是一個簡單的示例:
讓Person = {
lastname:“ doe”, tostring:function() “ this.lastName;
}
};
console.log(person.toString()); //“ John Doe”
> JavaScript中魔術功能的意義是什麼?它們可以使您的代碼更加直觀,更易於理解,並提供一種封裝和保護您數據的方法。
>
您可以在JavaScript中提供一些魔術功能的示例?以下是JavaScript中魔術函數的一些示例:1。 ToString():此方法返回代表對象的字符串。
> 1。 valueof():此方法返回對象的原始值。
1。 HasownProperty():此方法返回一個布爾值,指示對像是否具有指定的屬性。
> >> >是否有任何限製或缺點,用於在Javascript中使用魔法方法?魔術方法可能非常有用,它們也有一些局限性。首先,它們可以使您的代碼更加複雜和更難進行調試,尤其是如果您不熟悉它們的工作方式。如果不正確使用,它們也可以導致出乎意料的行為。
與其他一些編程語言不同,JavaScript沒有正式的概念“魔法方法”。但是,它的確具有類似行為的某些方法,例如tostring()和valueof( )。這些方法會在某些情況下自動調用,就像其他語言中的魔術方法一樣。>
>如何在JavaScript中了解有關魔法方法的更多信息?您可以從官方的JavaScript文檔以及在線教程和課程開始。您還可以在自己的項目中練習使用它們來獲得動手體驗。
>是否有任何工具或庫可以幫助使用JavaScript中的魔法方法?可以在JavaScript中使用魔法方法的工具。例如,Lodash是一個流行的JavaScript實用程序庫,它為使用數組,對象和其他類型的數據提供了有用的方法。
以上是揭示JavaScript的魔力的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具