2016-09-29 200 views
0

首先,我找到了一些似乎解決這個問題的鏈接,但是我對javascript(以及一般的代碼)的理解非常糟糕,解決方案/解釋對我來說很難概括這裏。我知道這與封閉有關(我隱約明白)。用for循環創建多個函數

背景: 我創建使用循環中,每個與應該當複選框被選中出現4單選按鈕10項的複選框。我可以通過逐個創建10個以上的函數來完成「出現/消失」,但我更喜歡用循環創建我的十個函數。下面的代碼顯示了每個複選框如何在更改時調用可變函數(例如,t0Disp())。

<? 
for ($row = 0; $row <10; $row++) 
{ 
    $topic = $topic[$row]; 
    ?> 
    <input id="C<? echo $row ?>" type="checkbox" value="true" onchange="t<? echo $row ?>Disp()" /><? echo $topic ?> 
    <br /> 
    <div id="<? echo $row ?>div" style="display: none"> 
     <? for ($col = 0; $col < 4; $col++) 
    { 
     ?> 
     <input type="radio" name="r<? echo $row ?>" value="<? echo $col ?>" onchange="disable<? echo $col ?>(); disable<? echo $row ?>();" /> 
     <? echo $col+1; ?> 
    <? 
    } 
    ?> 
     <br /> 
     <br /> 
    </div> 
<? 
} 
?> 

上面的代碼工作正常,如果我通過t9Disp()函數手動輸入我的t0Disp()。當我試圖使一個for循環才能實現這些功能(如下圖),該功能僅適用於t9Disp()

for (var i=0; i<10; i++) { 
    var idiv = i + "div"; 
    var eldiv = document.getElementById(idiv); 
    var ci = "C" + i; 
    var elci = document.getElementById(ci); 
    window['t' + i + 'Disp'] = function() { 
     if(elci.checked == true) { 
      eldiv.style.display = "inherit"; 
     } 
     else { 
      eldiv.style.display = "none"; 
     } 
    } 
} 

我只需要明白,爲什麼JavaScript的循環不只是吐在10層不同的功能我的PHP循環吐出10個不同的複選框的方式?

謝謝!

+0

你不需要多個函數..從來沒有在循環.. – Rayon

+1

可能重複[JavaScript閉合內部循環 - 簡單實用的例子](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops -simple-practical-example) – vlaz

+0

除了重複之外,我甚至不知道爲什麼要使用10個函數,而不是簡單地使用1個參數。 – vlaz

回答

0

你不需要多個函數,只有一個帶參數的函數可以爲你做!

function disp(elci, eldiv) { 
    eldiv = document.getElementById('eldiv'); 
    if (elci.checked == true) { 
    eldiv.style.display = "inherit"; 
    } else { 
    eldiv.style.display = "none"; 
    } 
} 

而且您的標記將是:

<input id="C<? echo $row ?>" type="checkbox" value="true" onchange="Disp(this,'<? echo $row ?>div')" /><? echo $topic ?> 
+0

這太聰明瞭!我不知道我爲什麼沒有這樣想,因爲它更符合我的編碼能力......謝謝! – danny

+0

@danny - 謝謝你的補充..我欣賞那.. – Rayon

1

您的問題是var懸掛,所以你得到10個不同的功能,每個人指着一個共享變量...指向在最後一組複選框。

第一解決問題的方法是使用letconst(如果你只需要支持現代瀏覽器):

for (var i=0; i<10; i++) { 
    const idiv = i + "div"; 
    const eldiv = document.getElementById(idiv); 
    const ci = "C" + i; 
    const elci = document.getElementById(ci); 
    window['t' + i + 'Disp'] = function() { 
     if(elci.checked == true) { 
      eldiv.style.display = "inherit"; 
     } 
     else { 
      eldiv.style.display = "none"; 
     } 
    } 
} 

但是,還有更多你可以這樣做:

const checkboxes = document.querySelectorAll('.js-showChoices'); 
[].slice.apply(checkboxes).forEach(checkbox => { 
    checkbox.addEventListener('change', event => { 
    if (event.target.checked) getDivFor(event.target).style.display = 'inherit'; 
    else getDivFor(event.target).style.display = 'none'; 
    }); 
}); 

function getDivFor(checkbox) { 
    // Find div based on checkbox and return it 
} 
+0

謝謝,這太棒了!第二個代碼框遠遠超出了我,但它看起來比我一直在做的更優雅。不過,我想我會堅持人造絲的解決方案。 – danny

0

與您的代碼的問題是,當獲得附加功能還記得那些變量eldielci最後的值。

您可以使用閉包來記住變量的適當值。 對於做這樣的事情

function addFunction(name, elementDiv, elementCi) { 
    window[name] = function() { 
    if(elementCi.checked == true) { 
     elementDiv.style.display = "inherit"; 
    } 
    else { 
     elementDiv.style.display = "none"; 
    } 
} 

} 

for (var i=0; i<10; i++) { 
    var idiv = i + "div"; 
    var eldiv = document.getElementById(idiv); 
    var ci = "C" + i; 
    var elci = document.getElementById(ci); 
    addFunction('t' + i + 'Disp', eldiv, elci); 
} 
0

肖恩有問題,但那裏是做比consts更簡單的方法,並會支持以前的瀏覽器

for (var i=0; i<10; i++) { 
    window['t' + i + 'Disp'] = (function() { 
     var idiv = i + "div"; 
     var eldiv = document.getElementById(idiv); 
     var ci = "C" + i; 
     var elci = document.getElementById(ci); 

     return function() { 
      if(elci.checked == true) { 
       eldiv.style.display = "inherit"; 
      } else { 
       eldiv.style.display = "none"; 
      } 
     }; 
    })(); 
} 

JsFiddle

該作品通過將變量存儲在只能由返回函數訪問的第一個函數中的範圍內。

人造絲擁有比循環功能更好的解決方案,但是可以處理任何行的函數意味着它會擴展或縮小到您的需求。