目錄
鑰匙要點
>這是一個典型的AngularJS控制器。它執行HTTP請求,從JSON文件中獲取數據,然後將其傳遞給當前範圍。我們沒有執行todoctrl函數 - 我們沒有機會通過任何參數。框架確實如此。那麼,這些$範圍和$ http變量來自哪裡?這是一個超級酷的功能,非常類似於黑魔法。讓我們看看它是如何完成的。
>有一個具有名稱和姓氏屬性的類。計算的屬性fullname返回包含人的全名的串聯字符串。奇怪的是,我們使用.property方法來針對應用於fullname的函數的部分。我個人在其他任何地方都沒有看到。而且,快速查看框架的代碼揭示了魔術:
瘋狂的反應模板
首頁 web前端 js教程 揭示JavaScript的魔力

揭示JavaScript的魔力

Feb 21, 2025 am 09:38 AM

揭示JavaScript的魔力

>我們每天使用大量工具。不同的圖書館和框架是我們日常工作的一部分。我們之所以使用它們,是因為我們不想為每個項目重新發明輪子,即使我們不了解引擎蓋下的情況。在本文中,我們將揭示最受歡迎的圖書館中發生的一些神奇過程。我們還將查看是否可以復制他們的行為。

>

鑰匙要點

  • > jQuery(例如jQuery)簡化dom操縱(例如,從字符串創建元素),正確處理複雜的情況(如嵌套元素)(如嵌套元素)。 ember.js使用計算屬性增強JavaScript對象,允許屬性像函數一樣行為,在依賴性更改時自動更新。 React的JSX語法允許將HTML嵌入JavaScript中,然後由React的JSX Transformer處理以創建動態UI組件。
  • >本文展示了用於依賴注入和計算屬性的自定義解決方案,展示了開發人員如何在其項目中實施相似的功能。
  • 了解流行的JavaScript框架的基本力學可以使開發人員能夠編寫更有效和可維護的代碼。
  • >從字符串創建DOM元素
  • 隨著單頁應用程序的興起,我們正在使用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樹。最後,通過使用一段時間循環,我們將越來越深,直到達到想要的標籤為止。

    這是一個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="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>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
    </span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
    登入後複製
    登入後複製
    使用該方法,我們將有機會使用所需的依賴項調用該功能。同時,我們沒有更改應用程序的工作流程。噴油器仍然是獨立的,並且不具有與邏輯相關的功能。

    >

    當然,將顯示器的功能傳遞到Resolve方法無濟於事。

    >我們仍然遇到相同的錯誤。下一步是找出傳遞的目標需求。它的依賴性是什麼?這是我們可以從Angularjs中採用的棘手部分。我再次對框架的代碼進行了一些挖掘,並找到了以下內容:
    <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>
    登入後複製
    登入後複製

    如果我們獲得了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>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    我們的示例在行動中:

    參見codepen上的krasimir tsonev(@krasimir)的筆bxdar。

    採用ember的計算屬性

    Ember是當今最受歡迎的框架之一。它具有許多有用的功能。有一個特別有趣的 - 計算屬性。總而言之,計算的屬性是充當屬性的函數。讓我們看看一個簡單的示例從灰燼的文檔中獲取:

    >有一個具有名稱和姓氏屬性的類。計算的屬性fullname返回包含人的全名的串聯字符串。奇怪的是,我們使用.property方法來針對應用於fullname的函數的部分。我個人在其他任何地方都沒有看到。而且,快速查看框架的代碼揭示了魔術:

    庫通過添加新屬性來調整全局函數對象的原型。這是在類的定義期間運行一些邏輯的好方法。
    <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>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    >

    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="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的計算屬性。

    > 現在

    >一旦添加上述行,我們將能夠將.compented()添加到每個函數定義的末尾:>
    <span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
    </span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
    登入後複製
    登入後複製
    結果,名稱屬性不再包含函數,而是計算出等於true and func屬性的對象填充了舊功能。真正的魔術發生在計算助手的實現中。它通過對象的所有屬性並使用對象。 DefineProperty我們已經計算出屬性:

    >

    <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>
    登入後複製
    登入後複製
    請注意,我們正在刪除原始屬性名稱。在某些瀏覽器對像中。 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="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>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    >我們正在獲取

以上是揭示JavaScript的魔力的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1658
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles