FAQ區塊 - 一組QA來解析程式碼


Posted by mijouhsieh on 2024-06-27

FAQ區塊常見UI是標題旁邊有+或-的icon,用來切換顯示下方的內容。
2種模式做切換 => toggle方法

預計延伸的筆記大綱:

  1. 一組QA來解析程式碼 (本篇)
  2. 兩組以上的QA
  3. plain JS 寫法
  4. React 寫法
  5. display none 和 block切換 => 效能問題?
  6. 細節優化
  7. 注意事項

1. 一組QA來解析程式碼 codepen

一組QA toggle gif file

//html
<li class="qa-item">
  <div class="question-wrapper">
    <p class="question">預設是彩色tulip且不顯示內容</p>
    <div class="modeToggle-icon-wrapper">
      <img class="modeToggle-icon" data-mode="plus" 
           src="https://im..." alt="icon-plus">
    </div>
  </div>
  <div class="answer hide">Lorem ipsum ....</div>
</li>
//js
const modeToggleIcon = document.querySelector('.modeToggle-icon')
const answer= document.querySelector('.answer')

const srcs = {
  "plus":"https://ima...",
  "minus": "https://ima..."
}
function showOrHideContent() {
  answer.classList.toggle('hide');
  answer.classList.toggle('show');
}
modeToggleIcon.addEventListener('click', function() {
  let mode = this.dataset.mode
  mode = mode === "plus" ? "minus" : "plus"
  this.src = srcs[mode]
  this.dataset.mode = mode
  document.body.classList.toggle("plus", mode==="plus")
  //顯示或隱藏內容
  showOrHideContent()
})

document.body.classList.toggle("plus", modeToggleIcon.dataset.mode==="plus")
//CSS
.question-wrapper {
  width: 100%;
  height: 38px;
  margin-bottom: 24px;
  display: flex;
  border: 1px solid blue;
  justify-content: space-between;
  align-items: center;
}
.question {
  font-weight: 600;
  font-size: 1rem;
  color: var(--dark-purple);
}
.modeToggle-icon-wrapper {
  margin-left: 24px;
  height: 30px;
  min-width: 30px;
  max-width: 30px;
}
.modeToggle-icon-wrapper img {
  width: 100%;
  height: 100%;
}
.modeToggle-icon-wrapper img:hover {
  border: 1px solid red;
  cursor: pointer;
}
.minus-wrapper img {
  width: 100%;
  height: 100%;
}
.minus-wrapper img:hover {
  border: 1px solid red;
  cursor: pointer;
}
.answer {
  border: 1px solid blue;
  font-weight: 400;
  color: var(--grayish-purple);
  font-size: 0.875rem;
  line-height: 150%;
}
.answer.hide {
  display: none;
}
.answer.show {
  display: block;
}

功能: 點擊切換icon來顯示或隱藏內容。

1. 選取元素和定義變數

const modeToggleIcon = document.querySelector('.modeToggle-icon')
const answer = document.querySelector('.answer')

const srcs = {
  "plus": "https://ima...",
  "minus": "https://ima..."
}
  • 選取元素modeToggleIcon: 選取class name 為 .modeToggle-icon 的icon元素<img>,作為切換顯示模式。
  • 選取元素answer: 選取class name 為 .answer 的元素,要被顯示或隱藏的内容。
    srcs: 一個物件,包含2個key-value pair,分別對應不同icon模式的圖片來源。

2. 顯示或隱藏内容的函式

function showOrHideContent() {
  answer.classList.toggle('hide');
  answer.classList.toggle('show');
}

showOrHideContent 函式透過在 answer 元素上切換class name .hide.show 作為切換顯示與否的狀態。
MDN | DOMTokenList: toggle() method

節點的toggle()方法,從清單中刪除現有token並回傳false。如果token不存在,則會新增該token並且函式回傳true。

toggle(token)
toggle(token, force)

token-表示您要切換的token的字串
force-(選)若有包含,則將toggle變為單向操作。
若設定為false,則token只會被刪除,不會新增。
如果設定為true,則token只會被添加,不會刪除。
傳回值
布林值true或false,表示token被呼叫後是否在列表中。

3. 點擊事件監聽器

modeToggleIcon.addEventListener('click', function() {
  1 let mode = this.dataset.mode
  2 mode = mode === "plus" ? "minus" : "plus"
  3 this.src = srcs[mode]
  4 this.dataset.mode = mode
  5 document.body.classList.toggle("plus", mode === "plus")
  // 顯示或隱藏内容
  6 showOrHideContent()
})

註冊點擊事件監聽器, .modeToggle-icon 元素被點擊時觸發。
1 獲取當前icon的模式(plus 或 minus),並切換成另一個模式。
2, 3 根據當前模式切換icon的src屬性,即對應模式的icon圖檔。
this.src = srcs[mode]

  • this 在此是被點擊的 <img .modeToggle-icon >元素
  • srcs 物件,包含了兩個 icon的圖檔
  • mode 變數,表示當前的模式,可以是 "plus" 或 "minus"。
    根據當前的 mode 值,透过 srcs[mode] 來得到相應的圖檔,並將其賦值给 this.src,更新icon。
<img class="modeToggle-icon" data-mode="plus" 
           src="https://im..." alt="icon-plus">

4 更新 dataset.mode 屬性以反應當前模式。
this.dataset.mode = mode;

dataset 屬性是 DOM 元素的屬性,用來訪問該元素上的自定義數據屬性。
mode 變數,它的值是當前的模式,可以是 "plus" 或 "minus"。
透過將 mode 賦值给 this.dataset.mode,更新了 元素上的 data-mode 屬性的值。

這個屬性通常用來儲存元素的自定義狀態或訊息,這裡用來記錄當前顯示的icon模式,以便後續的狀態切換邏輯可根據此屬性值,進行判斷和執行相應的操作。
5 根據當前模式,將 body 元素的class name 切換成 plus 或移除 plus。
6 呼叫 showOrHideContent 函式來切換顯示或隱藏的内容。

透過監聽icon的點擊事件,實現了點擊切換 icon 來顯示或隱藏内容。利用classList.toggle方法和 dataset 屬性來切換元素的狀態和屬性,同時根據當前狀態更新icon的顯示。


#classList #toggle() #switch mode #FAQ







Related Posts

Day06 SharePrefernce+滑動刪除+Update功能(上)

Day06 SharePrefernce+滑動刪除+Update功能(上)

同步 & 非同步(5) - Promise.all 與 並行

同步 & 非同步(5) - Promise.all 與 並行

JavaScript 五四三 Ep.03 Array.prototype.filter()

JavaScript 五四三 Ep.03 Array.prototype.filter()


Comments