优化和重构在连接字符串 (Javascript) 中交换值的不同样式的按钮组?

Optimize & refactor differently styled button groups that swap values in concatenated string (Javascript)?

我正在尝试 JavaScript(和 CSS)。刚开始在这里提问;接受反馈。我发帖的部分目的是帮助其他人找到我面临的挑战的答案。我无法通过谷歌搜索和挠头找到我试图做的事情的例子。

代码完成了我想要的。有哪些优化和重构它的方法?

多个按钮组...独立样式...每个按钮都可以通过单击更新连接字符串的各个部分。

https://jsfiddle.net/ncarlton/by8ragpc/1/

我正在使用 HTML、CSS 和 JavaScript。

包含的代码目标:

  1. 根据用户选择(在我的例子中是按钮)连接变量。
  2. 从默认选项开始。
  3. 独立设置每个按钮组的样式。这是因为这三个变量将存在于我最终实现的 GUI 的不同区域……它们代表不同的功能。模型中每个按钮组的样式都不同。
  4. 单击任何按钮都会更新连接的字符串;没有“提交”按钮。
  5. 更新会替换连接字符串各自位置的值...因此每次单击按钮都会“换掉”之前的值(不要重新排列第一个、中间的、最后一个的顺序)。

JS:

//make default variables in UPPER to show that values should come from .js and not from .html
let _firstName = "MARTIN";
let _middleName = "LUTHER";
let _lastName = "KING";
//build the full Name
let fullName = _firstName + " " + _middleName + " " + _lastName;
//replace the <span>Need A. Change with the default values
//default values start as UPPERcase to show they came from variables and not innerHTML
document.getElementById("myName").innerHTML = fullName;
//swap out any of the name parts by a single button click: first, middle, last
//also style the buttons in each group to look different
function changeName() {
  //First Name Selections and Style changes
  const btnFirstSelect = function() {
    this.parentNode.getElementsByClassName("btnSelFirst")[0].classList.remove("btnSelFirst");
    this.classList.add("btnSelFirst");
    _firstName = this.innerHTML;
    fullName = _firstName + " " + _middleName + " " + _lastName;
    document.getElementById("myName").innerHTML = fullName;
  };
  document.querySelectorAll(".btnsFirstName .btnFirst").forEach(btnFirst => btnFirst.addEventListener('click', btnFirstSelect));
  //Middle Name Selections and Style changes
  const btnMiddleSelect = function() {
    this.parentNode.getElementsByClassName("btnSelMiddle")[0].classList.remove("btnSelMiddle");
    this.classList.add("btnSelMiddle");
    _middleName = this.innerHTML;
    fullName = _firstName + " " + _middleName + " " + _lastName;
    document.getElementById("myName").innerHTML = fullName;
  };
  document.querySelectorAll(".btnsMiddleName .btnMiddle").forEach(btnMiddle => btnMiddle.addEventListener('click', btnMiddleSelect));
  //Last Name Selections and Syle changes
  const btnLastSelect = function() {
    this.parentNode.getElementsByClassName("btnSelLast")[0].classList.remove("btnSelLast");
    this.classList.add("btnSelLast");
    _lastName = this.innerHTML;
    fullName = _firstName + " " + _middleName + " " + _lastName;
    document.getElementById("myName").innerHTML = fullName;
  };
  document.querySelectorAll(".btnsLastName .btnLast").forEach(btnLast => btnLast.addEventListener('click', btnLastSelect));
}
window.onload = changeName;
//click a button and then reload the console with this
//confirm your selection changed the var by grabbing the innerHTML
//confirm the full name was also rebuilt
console.log(_firstName, _middleName, _lastName, fullName);

HMTL:

<body>
  <h4>Name Builder from Button Choices</h4>
  <div>My name is: <span id="myName">Need A. Change</span>
  </div>
  <hr />
  <div class="btnsFirstName ">First name Choices:
    <button class="btnFirst btnSelFirst">Martin</button>
    <button class="btnFirst">Barack</button>
    <button class="btnFirst">Jelly</button>
  </div>
  <div class="btnsMiddleName">Middle Name Choices:
    <button class="btnMiddle btnSelMiddle">Luther</button>
    <button class="btnMiddle">Hussein</button>
    <button class="btnMiddle">Roll</button>
  </div>
  <div class="btnsLastName">Last Name Choices:
    <button class="btnLast btnSelLast">King</button>
    <button class="btnLast">Obama</button>
    <button class="btnLast">Morton</button>
  </div>
  <p>(Each button click should build the full name by swapping out the value of the clicked button in the correct position. Ideally the button groups would change styles independently too.)</p>
</body>

CSS:

.btnFirst,
.btnMiddle,
.btnLast {
  background-color: grey;
  color: green;
}

.btnSelFirst {
  background-color: black;
  color: white;
  outline: none;
}

.btnFirst:hover {
  background-color: black;
  color: white;
  outline: none;
}

.btnSelMiddle {
  background-color: white;
  color: black;
  outline: none;
}

.btnMiddle:hover {
  background-color: white;
  color: black;
  outline: none;
}

.btnSelLast {
  background-color: pink;
  color: blue;
  outline: none;
}

.btnLast:hover {
  background-color: pink;
  color: blue;
  outline: none;
}

body {
  font-family: Helvetica, Arial, Sans-Serif;
}

使用以下问题,我有点“添加”了额外的冗余功能代码以使按钮按我想要的方式“工作”:

我已经尝试了一些方法来减少代码冗余,但我希望学习各种技术。

嘿,我有办法了。

HTML
要点:

  1. <button ... name="firstname">:
  • name 属性是指这组按钮,因为 lastname midname 和 firstname 使用一个 func
  1. <button ... onClick="changeName(this)">:
  • 虽然这似乎是重复的,但当您做出反应时,这就是您在反应中所做的。所以如果你要学习反应是件好事
  • AddEventListener 可以隐藏在代码中,因此可能会对查找造成挑战
  1. 确保js附加在
  2. 的末尾
<body>
  <h4>Name Builder from Button Choices</h4>
  <div>My name is: <span id="myName">Need A. Change</span>
  </div>
  <hr />
  <div class="btnsFirstName ">First name Choices:
    <button class="btnFirst active" name="firstname" onClick="changeName(this)">Martin</button>
    <button class="btnFirst" name="firstname" onClick="changeName(this)">Barack</button>
    <button class="btnFirst" name="firstname" onClick="changeName(this)">Jelly</button>
  </div>
  <div class="btnsMiddleName">Middle Name Choices:
    <button class="btnMiddle active" name="middlename" onClick="changeName(this)">Luther</button>
    <button class="btnMiddle" name="middlename" onClick="changeName(this)">Hussein</button>
    <button class="btnMiddle" name="middlename" onClick="changeName(this)">Roll</button>
  </div>
  <div class="btnsLastName">Last Name Choices:
    <button class="btnLast active" name="lastname" onClick="changeName(this)">King</button>
    <button class="btnLast" name="lastname" onClick="changeName(this)">Obama</button>
    <button class="btnLast" name="lastname" onClick="changeName(this)">Morton</button>
  </div>
  <p>(Each button click should build the full name by swapping out the value of the clicked button in the correct position. Ideally the button groups would change styles independently too.)</p>
  <script src="./script.js"></script>
</body>


JS
要点:

  1. 创建一个函数来更新 dom
  2. 中的全名
  3. 合并所有按钮的点击处理程序
//make default variables in UPPER to show that values should come from .js and not from .html
let _firstName = "MARTIN";
let _middleName = "LUTHER";
let _lastName = "KING";

// set as a func to conveniently update fullname in the DOM
const setFullname = () => {
  document.getElementById("myName").innerHTML = `${_firstName} ${_middleName} ${_lastName}`;
}

// refer this function in HTML, example:
// <button class="btnFirst" onClick="changeName(this)">Jelly</button>
const changeName = el => {
  el.parentNode.getElementsByClassName("active")[0].classList.remove("active");
  el.classList.add("active");

  switch(el.name) {
  // el.name is the <button ... name="firstname">
    case 'firstname':
      _firstName = el.innerHTML;
      break;
    case 'middlename':
      _middleName = el.innerHTML;
      break;
    case 'lastname':
      _lastName = el.innerHTML;
      break;
  }

  setFullname();
}

// call once in the beginning to set default
setFullname()

console.log("firstname: ", _firstName)
console.log("middlename: ", _middleName)
console.log("lastname: ", _lastName)

CSS
要点:

  1. 不要重复,如果可以,请将相同的样式组合在一起。
  2. CSS是cascading style sheet意味着继承起着很大的作用,.element的样式定义可以级联到.element.activeelement:hover等等
.btnFirst,
.btnMiddle,
.btnLast {
  background-color: grey;
  color: green;
  /* no need to set same css on every definition
   * this will be also inherited to .btnFirst.active
   * and so on
   * */
  outline: none;
}

.btnFirst.active,
.btnFirst:hover {
  background-color: black;
  color: white;
}

.btnMiddle.active,
.btnMiddle:hover {
  background-color: white;
  color: black;
}

.btnLast.active,
.btnLast:hover {
  background-color: pink;
  color: blue;
}

body {
  font-family: Helvetica, Arial, Sans-Serif;
}