如何在不使用全局变量的情况下在三个按钮上实现三个事件

huangapple go评论59阅读模式
英文:

How to implement three events on three buttons without using a global variable

问题

这是一个我无法解决的问题。我有一个解决方案,但变量 "flag" 是一个全局变量。
问题在于 "flag" 不能是全局变量的限制下。
基本上,我们首先按下 "jQuery" 或 "JS Mode" 按钮,然后按下 "Collapse Me" 按钮以执行可折叠菜单。
每个按钮应该模拟相同的功能,但使用不同的代码。
目前,我没有使用 jQuery,所以假装使用它。
代码足够直接,但我需要一个解决方案,其中 "flag" 被传递到第三个 addEventListener 而不是成为全局变量。

let coll = document.getElementsByClassName("collapsible");
let jsBtn = document.getElementById("jsBtn");
let jqBtn = document.getElementById("jqueryBtn");
let flag = null;

jsBtn.addEventListener("click", () => {
  flag = "js";
});
jqBtn.addEventListener("click", () => {
  flag = "jq";
});

coll[0].addEventListener("click", nestedColl);
function nestedColl() {
  if (flag == "js") {
    collJs(flag);
  } else if (flag == "jq") {
    pseudoJq(flag);
  }
}

function collJs(flag) {
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + "px";
  }
}

function pseudoJq(flag) {
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + "px";
  }
}
.content,
.content1 {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}
<button id="jsBtn">JS Mode</button>
<button id="jqueryBtn">jQuery Mode</button>
<button class="collapsible">Collapse Me</button>

<div class="content">
  <p>
    填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。
  </p>
</div>

我尝试了什么以及我期望什么?我将第三个 addEventListener 包装在一个函数中,其他 addEventListeners 将调用该函数以传递 "flag"。但是事件不起作用的原因是什么?

jsBtn.addEventListener("click", () => {
  collFun(flag = "js");
});
jqBtn.addEventListener("click", () => {
  collFun(flag = "jq");
});

function collFun() {
  console.log(flag);
  coll[0].addEventListener("click", nestedColl);
  function nestedColl() {
    console.log(flag);
    if (flag == "js") {
      collJs(flag);
    } else if (flag == "jq") {
      pseudoJq(flag);
    }
  }
}
英文:

This is a problem that I'm unable to solve. I have a solution, but the variable flag is a global variable.
The problem is under the constraint that flag can't be global.
Essentially, we press on either 'jQuery' or 'JS Mode' buttons first and then press 'Collapse Me' button in order to execute a collapsible menu.
Each button is supposed to simulate the same functionality but with different code.
For now, I didn't use jQuery, so pretend that it is.
The code is straightforward enough, but, again, I need a solution where flag is passed on to the third addEvenListener without being global.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let coll = document.getElementsByClassName(&quot;collapsible&quot;);
let jsBtn = document.getElementById(&quot;jsBtn&quot;);
let jqBtn = document.getElementById(&quot;jqueryBtn&quot;);
let flag = null;

jsBtn.addEventListener(&quot;click&quot;, () =&gt; {
  flag = &quot;js&quot;;
});
jqBtn.addEventListener(&quot;click&quot;, () =&gt; {
  flag = &quot;jq&quot;;
});

coll[0].addEventListener(&quot;click&quot;, nestedColl);
function nestedColl() {
  if (flag == &quot;js&quot;) {
    collJs(flag);
  } else if (flag == &quot;jq&quot;) {
    pseudoJq(flag);
  }
}

function collJs(flag) {
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + &quot;px&quot;;
  }
}

function pseudoJq(flag) {
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + &quot;px&quot;;
  }
}

<!-- language: lang-css -->

.content,
.content1 {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}

<!-- language: lang-html -->

&lt;button id=&quot;jsBtn&quot;&gt;JS Mode&lt;/button&gt;
&lt;button id=&quot;jqueryBtn&quot;&gt;jQuery Mode&lt;/button&gt;
&lt;button class=&quot;collapsible&quot;&gt;Collapse Me&lt;/button&gt;

&lt;div class=&quot;content&quot;&gt;
  &lt;p&gt;
    filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
    text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
    text. filler text. filler text. filler text. filler text. filler text. filler.
  &lt;/p&gt;
&lt;/div&gt;

<!-- end snippet -->

What did I try and what was I expecting? I wrapped the third addEventListener in a function and the other addEventListeners would call that function to pass on flag. But then the event doesn't work correctly.

Code that doesn't work but why?

jsBtn.addEventListener(&quot;click&quot;, () =&gt; {
  collFun(flag = &quot;js&quot;);
});
jqBtn.addEventListener(&quot;click&quot;, () =&gt; {
  collFun(flag = &quot;jq&quot;);
});

function collFun() {
  console.log(flag);
  coll[0].addEventListener(&quot;click&quot;, nestedColl);
  function nestedColl() {
    console.log(flag);
    if (flag == &quot;js&quot;) {
      collJs(flag);
    } else if (flag == &quot;jq&quot;) {
      pseudoJq(flag);
    }
  }
}

答案1

得分: 1

你可以通过使用 removeEventListener() 来使每个模式按钮更改作为“Collapse me”按钮点击监听器的功能。

let coll = document.getElementsByClassName("collapsible");
let jsBtn = document.getElementById("jsBtn");
let jqBtn = document.getElementById("jqueryBtn");
let flag = null;

jsBtn.addEventListener("click", () => {
  coll[0].removeEventListener("click", pseudoJq);
  coll[0].addEventListener("click", collJs);
});
jqBtn.addEventListener("click", function() {
  coll[0].removeEventListener("click", collJs);
  coll[0].addEventListener("click", pseudoJq);
});

function collJs() {
  console.log("collJS");
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + "px";
  }
}

function pseudoJq() {
  console.log("pseudoJq");
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + "px";
  }
}
.content,
.content1 {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}
<body>
  <button id="jsBtn">JS Mode</button>
  <button id="jqueryBtn">jQuery Mode</button>
  <button class="collapsible">Collapse Me</button>

  <div class="content">
    <p>
      填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。
    </p>
  </div>
</body>
英文:

You can have each mode button change which function is used as the click listener on the "Collapse me" button, using removeEventListener().

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let coll = document.getElementsByClassName(&quot;collapsible&quot;);
let jsBtn = document.getElementById(&quot;jsBtn&quot;);
let jqBtn = document.getElementById(&quot;jqueryBtn&quot;);
let flag = null;

jsBtn.addEventListener(&quot;click&quot;, () =&gt; {
  coll[0].removeEventListener(&quot;click&quot;, pseudoJq);
  coll[0].addEventListener(&quot;click&quot;, collJs);
});
jqBtn.addEventListener(&quot;click&quot;, function() {
  coll[0].removeEventListener(&quot;click&quot;, collJs);
  coll[0].addEventListener(&quot;click&quot;, pseudoJq);
});


function collJs() {
  console.log(&quot;collJS&quot;);
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + &quot;px&quot;;
  }
}

function pseudoJq() {
  console.log(&quot;pseudoJq&quot;);
  var content = coll[0].nextElementSibling;
  if (content.style.maxHeight) {
    content.style.maxHeight = null;
  } else {
    content.style.maxHeight = content.scrollHeight + &quot;px&quot;;
  }
}

<!-- language: lang-css -->

.content,
.content1 {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}

<!-- language: lang-html -->

&lt;body&gt;
  &lt;button id=&quot;jsBtn&quot;&gt;JS Mode&lt;/button&gt;
  &lt;button id=&quot;jqueryBtn&quot;&gt;jQuery Mode&lt;/button&gt;
  &lt;button class=&quot;collapsible&quot;&gt;Collapse Me&lt;/button&gt;

  &lt;div class=&quot;content&quot;&gt;
    &lt;p&gt;
      filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
      text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
      text. filler text. filler text. filler text. filler text. filler text. filler.
    &lt;/p&gt;
  &lt;/div&gt;

<!-- end snippet -->

答案2

得分: 0

你还可以向你的内容元素添加一个属性,像这样:

const
  coll_0  = document.querySelector('.collapsible')
, jsBtn   = document.querySelector('#jsBtn')
, jqBtn   = document.querySelector('#jqueryBtn')
, content = coll_0.nextElementSibling
  ;
content.flag = 'none';  // 初始值...

jsBtn.onclick =_=> { content.flag = 'js';  }
jqBtn.onclick =_=> { content.flag = 'jq';  }

//....
英文:

you can also add a property to you content element, like so:

const
  coll_0  = document.querySelector(&#39;.collapsible&#39;)
, jsBtn   = document.querySelector(&#39;#jsBtn&#39;)
, jqBtn   = document.querySelector(&#39;#jqueryBtn&#39;)
, content = coll_0.nextElementSibling
  ;
content.flag = &#39;none&#39;;  // initial value...


jsBtn.onclick =_=&gt; { content.flag = &#39;js&#39;  }
jqBtn.onclick =_=&gt; { content.flag = &#39;jq&#39;  }

//....

答案3

得分: 0

使用传递的 eventevent.target 告诉您触发操作的元素是哪个。然后,您可以读取该元素的属性。

document.querySelectorAll("button").forEach(function(button){
  button.addEventListener("click", function(event){
    let color = event.target.textContent;
    document.querySelector("div").style.backgroundColor = color;
  })
})
div {
  height: 200px;
  width: 200px;
  outline: 1px solid black;
}
<button>红色</button>
<button>黄色</button>
<div></div>
英文:

Use the event that gets passed. event.target tells you which element triggered the action. You can then read properties of that element.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

document.querySelectorAll(&quot;button&quot;).forEach(function(button){
  button.addEventListener(&quot;click&quot;,function(event){
    let color = event.target.textContent;
    document.querySelector(&quot;div&quot;).style.backgroundColor=color;
  })
})

<!-- language: lang-css -->

div {
height: 200px;
width: 200px;
outline: 1px solid black;
}

<!-- language: lang-html -->

&lt;button&gt;red&lt;/button&gt;
&lt;button&gt;yellow&lt;/button&gt;
&lt;div&gt;&lt;/div&gt;

<!-- end snippet -->

答案4

得分: 0

以下是翻译好的部分:

Instead of multiple functions, I'm delegating the click handler to the body. 
For the buttons, I add a data attribute to jQuery and Javascript. This will hold each of their representative modes.
I also add a data attribute for flag to the collapse button. This will hold the flag for whatever was clicked on.
Then I use one function for expanding/collapsing. I also attach an active class for future use and to hide expanded content.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const coll = document.querySelector(".collapsible");
document.body.addEventListener("click", (e) => {
const el = e.target;
if (el.dataset.mode) {
coll.dataset.flag = el.dataset.mode;
} else if (el.classList.contains("collapsible") && el.dataset.flag) {
expandContent();
}
});
function expandContent() {
const content = document.querySelector(".content[data-mode='" + coll.dataset.flag + "']");
const hasActive = document.querySelector(".active.content");
if (hasActive) {
hasActive.style.maxHeight = null;
hasActive.classList.remove("active");
}
content.style.maxHeight = content.scrollHeight + "px";
content.classList.add("active")
}
<!-- language: lang-css -->
.content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
<!-- language: lang-html -->
<button data-mode="js">JS Mode</button>
<button data-mode="jQuery">jQuery Mode</button>
<button data-flag class="collapsible">Collapse Me</button>
<div data-mode="js" class="content">
<h2>JS</h2>
<p>
填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充文本。填充
<details>
<summary>英文:</summary>
Instead of multiple functions, I&#39;m delegating the click handler to the body. 
For the buttons, I add a data attribute to jQuery and Javascript. This will hold each of their representative modes.
I also add a data attribute for flag to the collapse button. This will hold the flag for whatever was clicked on.
Then I use one function for expanding/collapsing. I also attach an active class for future use and to hide expanded content.
&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;
&lt;!-- language: lang-js --&gt;
const coll = document.querySelector(&quot;.collapsible&quot;);
document.body.addEventListener(&quot;click&quot;, (e) =&gt; {
const el = e.target;
if (el.dataset.mode) {
coll.dataset.flag = el.dataset.mode;
} else if (el.classList.contains(&quot;collapsible&quot;) &amp;&amp; el.dataset.flag) {
expandContent();
}
});
function expandContent() {
const content = document.querySelector(&quot;.content[data-mode=&#39;&quot; + coll.dataset.flag + &quot;&#39;]&quot;);
const hasActive = document.querySelector(&quot;.active.content&quot;);
if (hasActive) {
hasActive.style.maxHeight = null;
hasActive.classList.remove(&quot;active&quot;);
}
content.style.maxHeight = content.scrollHeight + &quot;px&quot;;
content.classList.add(&quot;active&quot;)
}
&lt;!-- language: lang-css --&gt;
.content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
&lt;!-- language: lang-html --&gt;
&lt;button data-mode=&quot;js&quot;&gt;JS Mode&lt;/button&gt;
&lt;button data-mode=&quot;jQuery&quot;&gt;jQuery Mode&lt;/button&gt;
&lt;button data-flag class=&quot;collapsible&quot;&gt;Collapse Me&lt;/button&gt;
&lt;div data-mode=&quot;js&quot; class=&quot;content&quot;&gt;
&lt;h2&gt;JS&lt;/h2&gt;
&lt;p&gt;
filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler.
&lt;/p&gt;
&lt;/div&gt;
&lt;div data-mode=&quot;jQuery&quot; class=&quot;content&quot;&gt;
&lt;h2&gt;jquery&lt;/h2&gt;
&lt;p&gt;
filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler.
&lt;/p&gt;
&lt;/div&gt;
&lt;!-- end snippet --&gt;
</details>

huangapple
  • 本文由 发表于 2023年6月29日 01:14:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575384.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定