2011-12-07 46 views
0

我有一個函數,它是爲了在用一組新的子元素填充div之前清除所有子元素的div。Javascript函數事件不按順序執行

function displaySearchResults(resultsList) { 
var length = resultsList.length; 
var searchDiv = document.getElementById('search-results'); 

//CLEAR DIV 
if(searchDiv.hasChildNodes()) { 
    for(var i=0; i<searchDiv.childNodes.length; i++) { 
     var oldChild = searchDiv.childNodes[i]; 
     if(oldChild.id.indexOf('search-results-row') != -1) { 
      searchDiv.removeChild(oldChild); 
      console.log('Removed Result!'); 
     } 
    } 
} 

//ADD CHILDREN 
for(var i=0; i<length; i++) { 
    console.log('Added Result!'); 
    var element = resultsList[i]; 
    var rowDiv = document.createElement('div'); 
    rowDiv.id = 'search-results-row' + i; 
    rowDiv.className = 'list listRow' + i%2; 
    rowDiv.setAttribute('onclick', 'mapCurrentContact(' + i + ');'); 
    rowDiv.innerHTML = element.firstName + ' ' + element.lastName; 
    searchDiv.appendChild(rowDiv); 
} 
} 

但是它在CLEAR DIV循環有機會完成之前開始運行函數的ADD CHILDREN部分。因此,例如,如果函數在div中找到4個childNode並開始循環以刪除具有search-results-row的id的每個節點,它只會在它開始附加新的結果集之前通過2次左右最初傳入該函數。

我知道JavaScript是異步運行的,但我認爲函數本身至少會自頂向下運行,所以底部不應該做任何事情,直到我們到達代碼的那部分?我嘗試了各種其他的替代方法,例如在自己的函數中運行CLEAR DIV部分,然後在最後調用ADD CHILDREN部分,但我總是得到相同的結果。我在這裏錯過什麼!?!

+1

我不知道這是不是你的問題,但在明確的div塊,考慮循環下跌,而非上漲。當childNode被移除時,searchDiv.childNode變量的長度會發生變化。 –

+0

你是什麼意思「我知道JavaScript異步運行」?另外,請注意,變量'i'只在該函數中存在一次,而不是在每個'for'循環中都存在一次:這與該函數無關,但它確實會將人員關閉。正如Jeffrey所指出的那樣,您正在跳過子節點。 –

+0

我想我需要一點澄清。我錯過了如何跳過節點,以及我如何不隨着循環的進行而改變...... – ryandlf

回答

0

當您從列表的開頭移除項列表。您可以在刪除某些東西時減少計數器,也可以只從列表的末尾開始計數,在這種情況下,您只會影響已查看的元素的索引。後者更爲廣泛接受。

var i; //JavaScript does not have block scope, only function scope. Just declare it once here and initialize it at the beginning of each loop. 
for(i=searchDiv.childNodes.length-1; i>=0; i++) { 
+0

我沒有意識到for循環在最初調用後發生了變化。謝謝。 – ryandlf

+0

您不應該更改原始問題中的代碼。如果將來有人遇到類似問題,他們可以看到您的原始代碼並查看如何解決問題的可接受答案。 – Dennis

+0

@ryandlf for循環不會改變,您正在使用索引來訪問縮小集合中的項目。 –

0

當從本月底,而不是刪除:

for(var i=searchDiv.childNodes.length; i>=0; i--) { 
... 

您電流回路將失敗。另外JavaScript自我不是異步的。異步調用可能會象下面這樣:

V 
a b c d //Initial list with the counter being 0, pointing to 'a' 

V 
b c d //Removed the element 'a' 

    V 
b c d //Incremented the counter by one 

你結束時跳過元素b並重復同樣的錯誤在所有其他元素:

// this will be called first 
$.ajax({ 
    url: 'getsomedata.php', 
    success: function() { 
    // this will not be called until the getsomedata.php has completed 
    // and the for loop below might already be finished. 
    } 
}); 

// this directly after the ajax call 
for (var i=0; i<10; i00) { 
.... 
0

在這裏,我重構你的代碼位:

function displaySearchResults(results) { 
    var elem = document.getElementById('search-results'); 

    [].slice.call(elem.children).forEach(function (child) { 
     if (child.id.indexOf('search-results-row') > -1) { 
      elem.removeChild(child); 
     } 
    }); 

    results.forEach(function (result, i) { 
     var child = document.createElement('div'); 
     child.id = 'search-results-row' + i; 
     child.className = 'list listRow' + (i % 2); 
     child.onclick = function() { mapCurrentContact(i); }; 
     child.textContent = result.firstName + ' ' + result.lastName;  
     elem.appendChild(child); 
    }); 
} 

另外,我建議事件代表團的點擊行爲。只需綁定search-results DIV上的點擊處理程序,並使用事件對象來確定哪個子元素被點擊。

順便說一句,有CSS選擇器匹配偶/奇子元素。例如:

#search-results > :nth-child(even) { ... } 
#search-results > :nth-child(odd) { ... } 

所以,你不需要那麼listRow0listRow1班,真的。

現場演示:http://jsfiddle.net/ez4z3/