簡體   English   中英

映射數組以返回具有不同類名的組件

[英]Map array to return components with different classNames

我正在嘗試做一個應用程序,該應用程序創建一個帶有7 段 LED 顯示屏的組件,但 LED 顯示屏應顯示輸入的數字。 我一直試圖用邏輯來思考這個問題,但它不起作用。


邏輯:

  1. 對於每個輸入的數字,創建一個組件。
  2. 在這個組件內部,它有一個switch ,並且根據輸入的數字,它會將包含禁用樣式的className添加到每個div

當我嘗試只輸入一個數字時,它工作正常! 但是當我用兩個數字嘗試它時,它只是錯誤。 正如您在圖片中看到的:

一號一號


我只有兩個組件: <App/><Numbers/>

應用程序:

function App() {
  const [input, setInput] = useState('');
  const [number, setNumber] = useState([]);

  const changeNumbers = () => {
    // Splitting inputted numbers to add each number to array.
    const inputSplit = input.toString().split('');
    const inputArray = inputSplit.map(Number);
    setNumber(inputArray);
  }

  return (
    <div>      
      <input onChange={(e) => {setInput(e.target.value)}}/>
      <button onClick={() => {changeNumbers()}}>Confirm</button>

      { 
        number.length ? 
        number.map((singleNumber, idx) => (
          <Numbers singleNumber={singleNumber} key={idx} />
        ))
        :
        <Numbers singleNumber={0} /> 
      }
    </div>
  );
}

數字:

const Numbers = ({ singleNumber }) => {
    const switchDisabled = (element) => {                
        const segmentB = document.querySelector('.segment-b');
        const segmentC = document.querySelector('.segment-c');        
        const segmentF = document.querySelector('.segment-f');        

        switch(element) {
            case 2:
                segmentC.classList.add('segment-disabled');
                segmentF.classList.add('segment-disabled');
                break;
            case 6:
                segmentB.classList.add('segment-disabled');
                break;            
            default:                
                break;
        }
    }

    useEffect(() => {
        switchDisabled(singleNumber);
    }, [singleNumber]);

    return (
        <div className="container">
            <div className="segment segment-a"></div>
            <div className="segment segment-b"></div>
            <div className="segment segment-c"></div>
            <div className="segment segment-d"></div>
            <div className="segment segment-e"></div>
            <div className="segment segment-f"></div>
            <div className="segment segment-g"></div>
        </div>
    )
}

款式:

.container {
    width: 110px;
    height: 160px;
    position: relative; }        

.segment {
    position: absolute;
    background-color: red; }

.segment-a {    
    top: 0; 
    left: 10px;     
    width: 90px;
    height: 10px; }

.segment-b {
    top: 13px;
    right: 0;
    height: 60px;
    width: 10px; }

.segment-c {
    bottom: 13px;
    right: 0;
    height: 60px;
    width: 10px; }

.segment-d {
    bottom: 0; 
    left: 10px;     
    width: 90px;
    height: 10px; }

.segment-e {
    bottom: 13px;
    left: 0;
    height: 60px;
    width: 10px; }

.segment-f {
    top: 13px;
    left: 0;
    height: 60px;
    width: 10px; }

.segment-g {
    top: 75px; 
    left: 16px;     
    width: 80px;
    height: 10px; }

.segment-disabled {opacity: 0.1;}

Obs:我沒有張貼importsexports以節省空間。

問題是在Numbers組件中調用document.querySelector來獲取一個段,例如

const segmentB = document.querySelector('.segment-b');

此調用將在整個頁面上找到第一個 DOM 元素,該元素的類包含segment-b ,這意味着錯誤的數字在呈現第二個數字時更改了它的段。 您可以通過輸入一個兩位數相同的數字來驗證這一點,例如 66 - 第一個數字應呈現為6 ,而第二個數字將不正確。

您可以不使用帶有classList.addclassList.remove document.querySelector ,而是使用動態變量來計算每個 Number 組件中所需的禁用段類,然后在該特定 Number 組件上呈現這些類:

const Numbers = ({ singleNumber }) => {
  const switchDisabled = (element) => {
    const allSegments = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
    let disabledSegments = [];

    switch (element) {
      case 2:
        disabledSegments.push("c");
        disabledSegments.push("f");
        break;
      case 6:
        disabledSegments.push("b");
        break;
      default:
        break;
    }
  };

  return (
    <div className="container">
      {allSegments.forEach(segmentLetter => {
        const disabledClass = disabledSegments.includes(segmentLetter) ? 'segment-disabled' : '';

        return (
          <div className={`segment segment-${segmentLetter} ${disabledClass}`} />
        )
      })}
    </div>
  );
};

PS 一般來說,由於這些類型的問題,您希望在 99.99% 的時間內調用document.querySelector

反應方式是不通過調用 dom 節點而是構建 dom 節點來操縱 dom。 因此,不要通過調用 dom 節點來添加類,只需使用已經到位的類來構建 dom 節點。

在您的應用程序組件中,您可以將輸入設置為字符串,然后將其拆分並循環遍歷它,為每個組件放置一個數字組件。 在您的數字組件中,您只需在數組中設置所需的段,並通過它們映射放置組件呈現時所需的類名。

這是一個codesandbox示例led顯示codeandbox

應用程序.js

import { useState } from "react";
import Number from "./Number";

function App() {
  const [input, setInput] = useState("0");

  return (
    <>
      <input
        onChange={(e) => {
          setInput(e.target.value);
        }}
      />
      {input.split("").map((number, i) => (
        <Number key={i} number={number} />
      ))}
    </>
  );
}

export default App;

數字.js

const Number = ({ number }) => {
  let segments = [];

  switch (number) {
    case "1":
      segments = ["b", "c"];
      break;
    case "2":
      segments = ["a", "b", "d", "e", "g"];
      break;
    case "3":
      segments = ["a", "b", "c", "d", "g"];
      break;
    case "4":
      segments = ["b", "c", "f", "g"];
      break;
    case "5":
      segments = ["a", "c", "d", "f", "g"];
      break;
    case "6":
      segments = ["a", "c", "d", "f", "e", "g"];
      break;
    case "7":
      segments = ["a", "b", "c"];
      break;
    case "8":
      segments = ["a", "b", "c", "d", "e", "f", "g"];
      break;
    case "9":
      segments = ["a", "b", "c", "d", "f", "g"];
      break;
    case "0":
      segments = ["a", "b", "c", "d", "e", "f"];
      break;
    default:
      segments = ["a", "b", "c", "d", "e", "f"];
  }

  return (
    <div className="container">
      {segments.map((segment) => (
        <div key={segment} className={`segment segment-${segment}`}></div>
      ))}
    </div>
  );
};

export default Number;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM