javascript 如何避免多次使用onclick

8i9zcol2  于 2022-12-25  发布在  Java
关注(0)|答案(1)|浏览(168)

我正在寻找一个香草JS国家代码选择器从几天,现在我已经找到了一个完美的代码为我的项目,但我现在面临的问题是,该代码是使用onclick()在每个选项更新点击的数据选择菜单,这看起来很丑,并降低了代码执行的速度.
代替在每个li选项上使用onclick,我可以使用addEventListener使用'click'事件来更新数据。如果我可以做到这一点,你能解释我如何做到这一点吗?实际上,我是JS的新手,所以我需要Maven指导。
请看我的JS Snippet. addCountryFUNCTION和搜索EVENT

const wrapper = document.querySelector(".wrapper"),
selectBtn = wrapper.querySelector(".select-btn"),
searchInp = wrapper.querySelector("input"),
options = wrapper.querySelector(".options");

let countries = [
                    "<span class='flag-icon flag-icon-afg'></span> Afghanistan (+93)",
                    "<span class='flag-icon flag-icon-bel'></span> Belgium (+32)",
                    "<span class='flag-icon flag-icon-chn'></span> China (+86)",
                ];

function addCountry(selectedCountry) {
    options.innerHTML = "";
    countries.forEach(country => {
        let isSelected = country == selectedCountry ? "selected" : "";
        
// I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION //        
        let li = `<li onclick="updateName(this)" class="${isSelected}">${country}</li>`;
// I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION // 

        options.insertAdjacentHTML("beforeend", li);
    });
}
addCountry();

function updateName(selectedLi) {
    searchInp.value = "";
    addCountry(selectedLi.innerHTML);
    wrapper.classList.remove("active");
    filterData = /(<span\b[^<>]*><\/span>\s*)\w+(?:\s+\w+)*\s*\((\+[\d-]+)\)/g;
    selectBtn.firstElementChild.innerHTML = selectedLi.innerHTML.replace(filterData, `$1$2`);;
}

searchInp.addEventListener("keyup", () => {
    let arr = [];
    let searchWord = searchInp.value.toLowerCase();
    arr = countries.filter(data => {
        return data.toLowerCase().includes(searchWord);
    }).map(data => {
        let isSelected = data == selectBtn.firstElementChild.innerHTML ? "selected" : "";
        
// I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION //         
        return `<li onclick="updateName(this)" class="${isSelected}">${data}</li>`;
// I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION //         
        
    }).join("");
    options.innerHTML = arr ? arr : `<p style="margin-top: 10px;">Oops! Country not found</p>`;
});

selectBtn.addEventListener("click", () => wrapper.classList.toggle("active"));

document.addEventListener('click', (event)=> {
    if (!wrapper.contains(event.target)) {
        wrapper.classList.remove("active");
    }else{
        wrapper.classList.add("active");
    }
  });
/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  background: #4285f4;
}
::selection{
  color: #fff;
  background: #4285f4;
}
.wrapper{
  width: 370px;
  margin: 85px auto 0;
}
.select-btn, li{
  display: flex;
  align-items: center;
  cursor: pointer;
}
.select-btn{
  height: 65px;
  padding: 0 20px;
  font-size: 22px;
  background: #fff;
  border-radius: 7px;
  justify-content: space-between;
  box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
.select-btn i{
  font-size: 31px;
  transition: transform 0.3s linear;
}
.wrapper.active .select-btn i{
  transform: rotate(-180deg);
}
.content{
  display: none;
  padding: 20px;
  margin-top: 15px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
.wrapper.active .content{
  display: block;
}
.content .search{
  position: relative;
}
.search i{
  top: 50%;
  left: 15px;
  color: #999;
  font-size: 20px;
  pointer-events: none;
  transform: translateY(-50%);
  position: absolute;
}
.search input{
  height: 50px;
  width: 100%;
  outline: none;
  font-size: 17px;
  border-radius: 5px;
  padding: 0 20px 0 43px;
  border: 1px solid #B3B3B3;
}
.search input:focus{
  padding-left: 42px;
  border: 2px solid #4285f4;
}
.search input::placeholder{
  color: #bfbfbf;
}
.content .options{
  margin-top: 10px;
  max-height: 250px;
  overflow-y: auto;
  padding-right: 7px;
}
.options::-webkit-scrollbar{
  width: 7px;
}
.options::-webkit-scrollbar-track{
  background: #f1f1f1;
  border-radius: 25px;
}
.options::-webkit-scrollbar-thumb{
  background: #ccc;
  border-radius: 25px;
}
.options::-webkit-scrollbar-thumb:hover{
  background: #b3b3b3;
}
.options li{
  height: 50px;
  padding: 0 13px;
  font-size: 21px;
}
.options li:hover, li.selected{
  border-radius: 5px;
  background: #f2f2f2;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">  
    <title>Custom Select Menu</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://amitdutta.co.in/flag/css/flag-icon.css">
  </head>
  <body>
    <div class="wrapper">
      <div class="select-btn">
        <span>Select Country</span>
        <i class="uil uil-angle-down"></i>
      </div>
      <div class="content">
        <div class="search">
          <i class="uil uil-search"></i>
          <input spellcheck="false" type="text" placeholder="Search">
        </div>
        <ul class="options"></ul>
      </div>
    </div>

    <script src="script.js"></script>
        
  </body>
</html>
lsmepo6l

lsmepo6l1#

你可以使用js得到所有的li,然后使用for循环添加click监听器,这样你就不会看到li元素上的onClick事件,代码可以按预期工作

const LiElements = Array.from(document.querySelectorAll(".options li"))

LiElements.forEach(option => {
    option.addEventListener("click", updateName)
})

下面是代码中一个示例

const wrapper = document.querySelector(".wrapper"),
  selectBtn = wrapper.querySelector(".select-btn"),
  searchInp = wrapper.querySelector("input"),
  options = wrapper.querySelector(".options");

  let countries = [
    "<span class='flag-icon flag-icon-afg'></span> Afghanistan (+93)",
    "<span class='flag-icon flag-icon-bel'></span> Belgium (+32)",
    "<span class='flag-icon flag-icon-chn'></span> China (+86)",
  ];

function addCountry(selectedCountry) {
  options.innerHTML = "";
  countries.forEach((country) => {
    let isSelected = country == selectedCountry ? "selected" : "";

    let li = `<li class="${isSelected}">${country}</li>`;

    options.insertAdjacentHTML("beforeend", li);
  });
  AssignListeners();
}

addCountry();

function AssignListeners(){
    const LiElements = Array.from(document.querySelectorAll(".options li"))

    LiElements.forEach(option => {
        option.addEventListener("click", updateName)
    })
}

function updateName(selectedLi) {
  searchInp.value = "";
  addCountry(selectedLi.innerHTML);
  wrapper.classList.remove("active");
  filterData = /(<span\b[^<>]*><\/span>\s*)\w+(?:\s+\w+)*\s*\((\+[\d-]+)\)/g;
  selectBtn.firstElementChild.innerHTML = selectedLi.innerHTML.replace(
    filterData,
    `$1$2`
  );
}

searchInp.addEventListener("keyup", () => {
  let arr = [];
  let searchWord = searchInp.value.toLowerCase();
  arr = countries
    .filter((data) => {
      return data.toLowerCase().includes(searchWord);
    })
    .map((data) => {
      let isSelected =
        data == selectBtn.firstElementChild.innerHTML ? "selected" : "";

      // I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION //
      return `<li onclick="updateName(this)" class="${isSelected}">${data}</li>`;
      // I DONT WANT TO SHOW THIS onclick="updateName(this)" IN EVERY LI OPTION //
    })
    .join("");
  options.innerHTML = arr
    ? arr
    : `<p style="margin-top: 10px;">Oops! Country not found</p>`;
});

selectBtn.addEventListener("click", () => wrapper.classList.toggle("active"));

document.addEventListener("click", (event) => {
  if (!wrapper.contains(event.target)) {
    wrapper.classList.remove("active");
  } else {
    wrapper.classList.add("active");
  }
});

相关问题