2017-07-29 52 views
2

我有一種感覺,這是如此明顯,當(如果)解決時我會感到羞愧 - 但我不能讓它工作。在函數中分組變量

我有一個html + javascript頁面,多個項目都需要通過用戶點擊來顯示或隱藏。 所以我有div的像X量:

<div id="myDIVA" style="display:none;">blabla 1</div> 
<div id="myDIVB" style="display:none;">blabla 2</div> 
<div id="myDIVC" style="display:none;">blabla 3</div> 

,他們通過點擊div的隱藏和/或所示:

<div onClick="myClickFunctionA()">Show only ONE</div> 
<div onClick="myClickFunctionB()">Show only TWO</div> 
<div onClick="myClickFunctionC()">Show only THREE</div> 

簡單的腳本雲:

<script> 
    var a = document.getElementById('myDIVA'); 
    var b = document.getElementById('myDIVB'); 
    var c = document.getElementById('myDIVC'); 
function myClickFunctionA() { 
     a.style.display = 'block'; 
     b.style.display = 'none'; 
     c.style.display = 'none'; 
} 
function myClickFunctionB() { 
     a.style.display = 'none'; 
     b.style.display = 'block'; 
     c.style.display = 'none'; 
} 
</script> 

我會喜歡做的是能夠將變量分組,因此我可以擁有如下功能:

function myClickFunctionA() { 
     a.style.display = 'block'; 
     b + c.style.display = 'none'; 
} 

我有很多的div!所以這可能看起來很愚蠢,但對我來說,能夠「集體」增值稅以便更容易編輯是很有意義的。

所以我希望有人註冊一個簡單的解決方案:-) 感謝

+2

織補附近獨自upvoted的第一道防線。往往人們似乎充滿了自己,很高興看到謙遜的人。 –

回答

1

可能是一個很好的用例爲一個數組:

var elemsById = ["myDIVA","myDIVB","myDIVC"] 
.map(id=>[id,document.getElementById(id)]); 

所以每當我們要顯示這些元素之一,我們遍歷所有的人,並隱藏/顯示他們,根據他們的ID:

function showThisAndHideRest(showId){ 
    elemsById.forEach(function([id,el]){ 
    el.style.display=id===showId?"block":"none"; 
    }); 
} 

所以你可以做:

showThisAndHideRest("myDIVA"); 

注意:鞋面使用了一些很酷的ES6功能,所有瀏覽器都不支持。而其實孤單沒有必要存儲ID在陣列中,其已經EL的一部分(el.id),但我只是想用一些參數解構......

Run

+0

不知道它出錯的地方,但是當我嘗試運行這段代碼時,我沒有看到顯示。我假設我應該這樣做;

Show NEW VERSION
?? ...(((我正在測試這個Firefox 52.2.1(32位)和Chrome 49.0.2623.112 - 兩者都不是最新的))) – morganF

+0

@ morganF正好!我會添加一個片段... –

+0

@morganF哦不!其實它因爲「myDivA」!==「myDIVA」...我很抱歉:/ –

1

我想你不要希望每個div都有獨立的功能。你不需要。 :-)你可以有一個處理點擊的函數,並且可以處理一系列div。

首先,讓我們這些div的數組:

var divs = Array.prototype.slice.call(document.querySelectorAll("[id^=myDIV]")); 

(。這將是更好,如果我們可以給他們一個共同的類,它通過其ID開始抓住它們)

那麼,讓我們可點擊的div說哪個的div它們涉及到:

<div onClick="myClickFunction('myDIVA')">Show only ONE</div> 

那麼,讓我們來處理點擊一個功能:

function myClickFunction(id) { 
    divs.forEach(function(div) { 
     div.style.display = div.id === id ? "block" : "none"; 
    }); 
} 

(請參閱最後的兼容性說明。)

但是,使用onxyz - 屬性風格的事件處理程序通常是一個壞主意。首先,他們要求你使用的函數是全局變量。

相反,讓我們掛起來動態,並使用data-*屬性說哪個目標,他們涉及到:

// Scoping function to avoid globals 
 
(function() { 
 
    var divs = Array.prototype.slice.call(document.querySelectorAll(".showable")); 
 
    Array.prototype.forEach.call(document.querySelectorAll("div[data-show]"), function(dshow) { 
 
     dshow.addEventListener("click", myClickFunction, false); 
 
    }); 
 

 
    function myClickFunction() { 
 
    var idToShow = this.getAttribute("data-show"); 
 
    divs.forEach(function(div) { 
 
     div.style.display = div.id === idToShow ? "block" : "none"; 
 
    }); 
 
    } 
 
})();
<div data-show="myDIVA">Show A</div> 
 
<div data-show="myDIVB">Show B</div> 
 
<div data-show="myDIVC">Show C</div> 
 
<div class="showable" id="myDIVA">A</div> 
 
<div class="showable" id="myDIVB" style="display: none">B</div> 
 
<div class="showable" id="myDIVC" style="display: none">C</div>

現在我們沒有全球性的功能,以及標記定義元素之間的關係。


兼容性說明:

如果您有支持沒有addEventListener(如IE8   —和可悲的是許多人)過時的瀏覽器,this answer有一個跨瀏覽器hookEvent功能您的使用。

請注意,如果您支持IE8,則還必須使用for循環而不是Array.prototype.forEach,因爲IE8沒有它並且無法合理地增亮它(因爲IE8也不支持)將一個不可枚舉的屬性添加到JavaScript對象)。

+0

@Jonasw:是的,剛剛發現添加了一個適當的事件處理實例。 :-) 謝謝。 –

+0

並且你不能離開nodeList到數組coconversion? –

+0

@Jonasw:我沒有看到任何理由。如果我們要像使用數組那樣使用它,那麼一次構建數組似乎是合理的。否則,我們每次使用'forcach'時都必須使用'.call'。 –

0

下面是使用addEventListener一個解決方案,不再需要爲onclick屬性:

// Select the buttons and items 
 
var buttons = Array.prototype.slice.call(document.querySelectorAll('.showhidebutton')) 
 
var items = Array.prototype.slice.call(document.querySelectorAll('.showhideitem')) 
 

 
// Add a click eventListener for each button 
 
buttons.forEach(function(button, i) { 
 
    button.addEventListener('click', function() { 
 
    // When a button is clicked, loop through the items 
 
    items.forEach(function(item, j) { 
 
     // If this is the item that should be shown, show it 
 
     if (i === j) item.style.display = 'block' 
 
     // Otherwise, hide it 
 
     else item.style.display = 'none' 
 
    }) 
 
    }) 
 
}) 
 

 
// This code hides all but item 1 on pageload 
 
// can remove this code if you don't want that 
 
items.forEach(function(item, j) { 
 
    // Arrays are zero-indexed in JS, so the first item is 0 
 
    if (i === 0) return 
 
    // Hide all the other items 
 
    else item.style.display = 'none' 
 
})
<div class="showhideitem">blabla 1</div> 
 
<div class="showhideitem">blabla 2</div> 
 
<div class="showhideitem">blabla 3</div> 
 

 
<div class="showhidebutton">Show only ONE</div> 
 
<div class="showhidebutton">Show only TWO</div> 
 
<div class="showhidebutton">Show only THREE</div>

+0

querySelectorAll返回一個NodeList,它已經有一個forEach方法... –

+1

有一個非標準的'forEach',但它在IE中不支持:https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach – RyanZim

+0

@RyanZim其實,如果你看看那篇文章的結尾,它引用了標準。很高興看到他們已經將其添加到標準中!而且人們可以輕鬆地將它放在IE8 +上。但是,是的,**沒有**版本的IE支持它(在添加之前已經發布了什麼)的小細節是推薦它時不應該遺漏的問題('@'喬納斯)。 –

0

可以定義一個通用類各元素組成,其中click事件使用.querySelectorAll()與選擇預期".myClickFunction",使用for循環重複NodeList;將每個元素的Element.dataset設置爲當前的迭代索引;將click處理程序附加到元素;再次使用.querySelectorAll()與選擇器"[id^myDIV]"來選擇所有元素,其中id"myDIV"開頭;在click事件集每個"myDIV".style"display:none";在索引Element.dataset.style"display:block"處設置"myDIV"

for (var i = 0, el = document.querySelectorAll(".myClickFunction") 
 
    ; i < el.length; i++) { 
 
    el[i].dataset.index = i; 
 
    el[i].onclick = function(event) { 
 
    for (var n = 0, el_ = document.querySelectorAll("[id^=myDIV]") 
 
    ; n < el_.length; n++) { 
 
     el_[n].style.display = "none" 
 
    } 
 
    document.querySelectorAll("[id^=myDIV]")[event.target.dataset.index] 
 
     .style.display = "block" 
 
    } 
 
}
<div id="myDIVA" style="display:none;">blabla 1</div> 
 
<div id="myDIVB" style="display:none;">blabla 2</div> 
 
<div id="myDIVC" style="display:none;">blabla 3</div> 
 
and they are hidden and/or shown by clicking div's: 
 

 
<div class="myClickFunction">Show only ONE</div> 
 
<div class="myClickFunction">Show only TWO</div> 
 
<div class="myClickFunction">Show only THREE</div>