재사용 가능한 구성 요소를 만드는 방법

35117 단어 reactjavascript
테이블은 데이터를 표시하는 데 사용되는 가장 일반적인 UI 중 하나입니다.표에 따라, 우리는 일반적으로 데이터를 조회하고 조작하기 위해 기능을 추가해야 한다(예를 들어 검색 표시줄).그러나 테이블은 데이터를 표시하는 데 광범위하게 사용되기 때문에 다른 기능을 가진 다른 코드를 생성하기 위해 테이블의 같은 코드 블록을 복사/붙여야 하기 때문에 고통스러울 수 있습니다.
React를 사용하기 때문에 이 문제를 해결할 수 있는 더 좋은 방법이 있어야 합니다.이것이 바로 우리가 본문에서 해야 할 일이다.React 구성 요소의 기능을 이용하여 다시 사용할 수 있는 테이블 구성 요소를 만들 것입니다. 이 구성 요소는 기능을 제공하는 동시에 유연성을 유지합니다.
이렇게 하려면 테이블 어셈블리가 다음 요구 사항을 충족해야 합니다.
  • 정확한 데이터 표시 및 사용자 정의 데이터 표시 방식
  • 지원 테마 시스템
  • 은 사용자의 의사에 따라 스타일을 설계할 수 있으며, 모든 종류의 미리 추가된 스타일을 덮어쓸 수 있습니다.
  • 은 구성 표의 밀도
  • 과 같은 모든 종류의 추가 기능을 지원합니다.
    본고의 목적은 이 구성 요소를 어떻게 구축하고 구성 요소의 유연성을 유지하며 원시 html표에 접근하는 동시에 특성을 추가하여 이 구성 요소를 보여주는 것이다.

    테이블 구성 요소 구성하기


    파일 설정


    우선, 우리는 몇 가지 일을 해야 한다.
    1 - 인덱스.js: 사용자가 시계를 어떻게 사용하는지 시뮬레이션합니다.이것이 바로 우리가 사용할 시계 구성 요소를 호출하는 곳이다.
    import React from "react";
    import ReactDOM from "react-dom";
    
    import Table from "./Table/Table";
    
    import "./styles.css";
    
    function App() {
      ...
      return (
        <div className="App">
          <Table ... />
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    
    2 - 시계.js: 실제 구성 요소.이것은 간단한 기능 구성 요소로 구성되어 있으며, 이 구성 요소는 일부 도구를 받아서 하나의 시계와 제목, 시계 데이터와 시계 줄을 표시하는 다른 기능 시계 구성 요소를 되돌려줍니다.사용자는 이 파일을 볼 수 없습니다. 왜냐하면 이것은 테이블 구성 요소의 배후 논리를 표시하기 때문입니다.
    import React from "react";
    
    export default function Table(props) {
      return <table {...props} />;
    }
    
    Table.TH = function TH(props) {
      return <th {...props} />;
    };
    
    Table.TR = function TR(props) {
      return <tr {...props} />;
    };
    
    Table.TD = function TD(props) {
      return <td {...props} />;
    };
    
    3 - 스타일시트.css: 사용자가 표 스타일을 설정하는 방법을 시뮬레이션합니다.여기서, 우리는 표 구성 요소에 나의 스타일을 추가할 수 있다.
    .App {
      font-family: sans-serif;
      text-align: center;
    }
    
    현재 우리는 이미 파일을 설정했으니, 표 데이터를 어떻게 표시하는지 고려해 봅시다.

    기능 #1: html표와 완전히 같은 표를 만듭니다.


    다음 데이터를 표시할 경우

    두 가지 방법이 있습니다.

    1 - 테이블을 사용하여 내보낸 어셈블리


    사용자는 다음과 같이 Table.TR, Table.TDTable.TH을 사용하여 이 테이블을 만들 수 있습니다.
    function App() {
      ...
      return (
        <div className="App">
          <Table>
            <thead>
               <Table.TR>
                 <Table.TH>Name</Table.TH>
                 <Table.TH>Age</Table.TH>
               </Table.TR>
            </thead>
            <tbody>
               <Table.TR>
                 <Table.TD>Anssam</Table.TD>
                 <Table.TD>20</Table.TD>
               </Table.TR>
            </tbody>
          </Table>
        </div>
      );
    }
    
    여기서 장점은 사용자가 아이콘, 이미지, 표를 추가할 수 있다는 것이다.

    2 - 데이터 속성 객체 사용


    사용자가 테이블에 원본 텍스트 데이터만 표시하기를 원한다고 가정하십시오.이 경우 사용자는 그 데이터를 도구로 테이블 구성 요소에 전달하기만 하면 된다.
    function App() {
      const data = [
        {
          Name: "Anssam",
          Age: "20"
        }
      ];
    
      return (
        <div className="App">
          <Table data={data}/>
        </div>
      );
    }
    
    데이터가 자동으로 표시됩니다!
    네, 그런데 이게 어떻게 된 일입니까?
    데이터 객체의 구조에 유의하십시오.const [data = [{Name: "Anssam", Age: "20"}];그것은 하나의 대상 수조이며, 모든 대상은 하나의 시계 줄을 대표한다.대상의 키는 열입니다. 표 제목에 표시된 바와 같이 값은 이 특정 열의 한 줄의 데이터입니다.
    우리의 시계 구성 요소는 사용자가 표시하고자 하는 데이터를 포함하기 때문에, 우리는 우선 이 데이터에서 시계의 제목을 추출하려고 시도한다.

    a) 제목


    데이터 프로필 대상의 구조를 기억하십니까?우리는 이 데이터 속성의 모든 요소의 키에서 헤더를 추출할 수 있다.이를 위해, 우리는 Object.keys(SOME_DATA_ELEMENT) 함수를 사용하여 대상 키의 수조를 되돌려주기만 하면 된다.
    헤더를 얻기 위해 데이터 그룹의 첫 번째 대상을 사용합니다.
    const firstRow = props.data[0];
    const headers = Object.keys(firstRow);
    
    headers은 헤더를 포함하는 수조이다.그러나 이것은 우리가 보여주고 싶은 내용이 아니다. 우리는 두 개의 th 제목 요소가 필요하다. 각 요소는 한 열의 제목을 포함한다.우리 Table.TH 구성 요소를 사용할 때가 됐어!
    const headerComponents = headers.map(el => <Table.TH>{el}</Table.TH>);
    
    이제 Table.TR 구성 요소에 봉인할 수 있으며, 표 기능 구성 요소에 다음과 같이 보여 달라고 요구할 수 있습니다.
    export default function Table({ children, ...props }) {
    const firstRow = props.data[0];
    const headers = Object.keys(firstRow);
    const headerComponents = headers.map(el => <Table.TH>{el}</Table.TH>);
      return (
        <table {...props}>
                <Table.TR>
                  {headers.map(el => (
                    <Table.TH>{el}</Table.TH>
                  ))}
                </Table.TR>
        </table>
      );
    }
    

    b) 표체 데이터


    이제 표체 속의 줄과 같은 표 데이터를 어떻게 나타내는지 봅시다.깊이 있게 연구하기 전에 다음 표의 데이터를 렌더링하는 방법에 대해 알아보겠습니다.

    우리는 이미 a 부분의 제목을 가지고 있지만, 지금은 "Anssam"과 "20"이라는 한 줄의 값이 필요합니다.
    <tr>
      <td>Anssam</td>
      <td>20</td>
    </tr>
    

    Quick reminder on the structure of the data prop object: 
    [{Name: "Anssam", Age: "21"}]


    우리의 데이터 속성을 보면 함수 Object.values(SOME_DATA_ELEMENT)을 사용하여 특정 줄의 값을 직접 추출할 수 있습니다.이 함수는 값 그룹(예: ["Anssam", "20")을 반환합니다.또한 데이터 속성의 모든 요소에 대해 한 줄을 렌더링해야 한다는 것을 알고 있습니다. 이를 위해 SOME_ARRAY.map(SOME_FUNCTION) 함수를 사용하여 모든 요소를 렌더링합니다.
     
    const rows = props.data.map(el => (
        <Table.TR>
          {Object.values(el).map(el => (
            <Table.TD>{el}</Table.TD>
          ))}
        </Table.TR>
      ));
    
    다음 결과를 얻기 위해 table render 함수에 추가할 수 있습니다.
     
    export default function Table({ children, ...props }) {
      ....
      const rows = props.data.map(el => (
        <Table.TR>
          {Object.values(el).map(el => (
            <Table.TD>{el}</Table.TD>
          ))}
        </Table.TR>
      ));
      return (
        <table {...props}>
          ....
              <tbody>{rows}</tbody>
        </table>
      );
    }
    
    후하다🎉! 우리는 단지 데이터를 표에 표시하기만 하면 된다:) 스타일을 시험해 보자!

    특징 #2: 스타일을 우리 표에 추가하고 스타일을 사용자 정의할 수 있도록 하기


    사용자가 테이블 어셈블리의 스타일을 상태에 따라 결정한다고 가정합니다.하나의 방법은 조건 CSS 클래스 이름을 추가하고 구성 요소의 상태에 따라 호출하는 것이다.
    그러나 보일러판과 가독성을 떨어뜨릴 수도 있다.
    따라서 우리는 동적 조형을 지원할 수 있는 도구를 사용해야 한다. 예를 들어 styled-components!스타일이 설정된 구성 요소는 태그가 지정된 템플릿 문자를 사용하여 구성 요소의 스타일을 설정합니다.페이지에 나타나는 구성 요소를 추적하고 스타일을 주입합니다. 
    1. - 우리는 먼저 스타일링을 세웠다.각 구성 요소의 모든 스타일을 포함하는 js 파일:
    export const Table = styled.table`
      table-layout: fixed;
      ...
      width: 100%;
      display: table;
    `;
    

    Note: Notice the styled.table? This is basically to say that our const Table is basically a table dom element. If we wished for it to be a div, we would do styled.div.


    2 - 그런 다음 이 스타일을 구성 요소에 따라 변경합니다.
    export default function Table({ children, ...props }) {
      return (
        <Styled.Table {...props}>
             ...
        </Styled.Table>
      );
    }
    
    보시다시피, 스타일은 구성 요소에 직접 연결되어 있기 때문에, 우리는 클래스 이름을 도입할 필요도, 무수한 CSS 파일을 통해 어떤 구성 요소가 클래스 이름을 사용했는지 검사할 필요도 없습니다. 
    잠깐만... 만약 누군가가 표 구성 요소를 프로젝트에 추가하고 스타일을 덮어쓰길 원한다면 어떻게 해야 합니까?
    그들은 스스로 맞춤형으로 만들 수 있다!테이블 어셈블리는 사용자가 추가할 모든 유형의 스타일을 지원합니다.따라서 사용자는 자신의 스타일시트로 미리 존재하는 스타일을 덮어쓰고 일반적인 CSS, 스타일링 구성 요소, Sass...

    기능 #3: 테마 추가


    이제 미리 구축된 테마 시스템을 추가합니다. 사용자가 이 시스템을 사용하여 표의 스타일을 설정할 수 있습니다.우리는 어둠과 광명이라는 두 가지 간단한 주제를 만들 것이다.

    이를 위해 사용자는 테마 도구의 테마 값'암흑'과'밝기'사이를 선택하기만 하면 된다.
     
    function App() {
     ...
      return (
        <div className="App">
          <Table
            ...
            theme={Table.THEME.LIGHT}
          />
        </div>
      );
    }
    
    이게 어떻게 된 일입니까?
    먼저 다음과 같이 THEME 변수를 만듭니다.
     
    Table.THEME = {
      DARK: "dark",
      LIGHT: "light"
    };
    
    그리고 우리는 스타일화된 구성 요소를 사용하여 테마 도구에 따라 테이블 구성 요소의 스타일을 동적 설정합니다.
    나는 모든 구성 요소의 양식을 토론하지 않을 테니, 제목 요소의 양식을 봅시다.만약에 우리가 주제에 따라 제목의 배경을 바꾸고 싶다고 가정한다.우리는 배경이 검은색의'짙은 색'주제, 흰색의'연한 색'주제이기를 바란다.이를 위해 Styled.TH 구성 요소에 테마를 도구로 전달합니다.
    그리고 우리는 스타일의 TH 구성 요소에서 이 도구를 읽을 수 있습니다.js 파일과 테마 도구에 따라 다른 스타일을 되돌려줍니다. 아래와 같습니다.
    export const TH = styled.th`
      background-color: ${props => {
        return props.theme === "dark" ? "#212529" : "#e8e5e5fa";
      }};
      ...
      border-bottom-color: ${props => {
        return props.theme === "dark" ? "#dee2e6" : "black";
      }};
      color: ${props => {
         return props.theme === "dark" ? "white" : "black";
        }
      }};
    `;
    
    그런데 주제 아이템은 어떻게 얻었나요?
    부모 시계 구성 요소는 사용자로부터 아이템을 받는다는 것을 기억하세요.또한 테마 도구는 모든 삽입식 Table.TH, Table.TRTable.TD 구성 요소의 중요한 도구입니다. 왜냐하면 우리는 선택한 테마에 따라 그 스타일을 편집하기를 원할 수 있기 때문입니다.이것은 우리가 반드시 우리의 주제 도구를 전 세계 데이터로 삼아야 한다는 것을 의미한다.이를 위해 주제를 나타내는 themeContext과 같은 컨텍스트를 정의했습니다.
    //for passing the theme to all of the components
    const themeContext = React.createContext();
    
    우리는 themeContext.Provider 구성 요소로 전체 표를 포장했다.
    export default function Table({ children, ...props }) {
      return (
        <Styled.Table {...props}>
          <themeContext.Provider value={props.theme}>
            ...
          </themeContext.Provider>
        </Styled.Table>
      );
    }
    
    그런 다음 Table.TH 갈고리를 사용하여 useContext 어셈블리의 컨텍스트에서 주제 값을 읽습니다.
    Table.TH = function TH({ children, ...props }) {
      const theme = React.useContext(themeContext);
      return (
        <Styled.TH {...props} theme={theme}>
          {children}
        </Styled.TH>
      );
    };
    
    우리는 남은 주제 스타일링에서 이런 논리를 사용할 수 있다!🎉

    피쳐 #4: 밀도 표시


    표가 지원하는 또 다른 멋진 기능은 밀도를 설정하는 능력이다.
     
    function App() {
      return (
        <div className="App">
          <Table
            ...
            density={Table.DENSITY.HIGH}
          />
        </div>
      );
    }
    
    표밀도 사용자 옵션은 두 개의 미리 구축된 주제와 같이 사용자는 세 가지 옵션 중 저밀도, 평균밀도, 고밀도만 선택할 수 있다.
     
    Table.DENSITY = {
      LOW: "low",
      AVERAGE: "avg",
      HIGH: "high"
    };
    
    각 옵션은 테이블에 전달되는 도구에 따라 구성 요소의 스타일을 편집합니다. 이 경우 표의 높이는 밀도 도구에 따라 달라집니다.
    export const Table = styled.table`
      ...
      height: ${props => {
        switch (props.density) {
          case "low":
            return "130px";
          case "avg":
            return "90px";
          case "high":
            return "5px";
          default:
            return "50vh";
        }
      }};
    `;
    
    이제 저희가 마지막 기능을 완성했습니다!🎉 당신은 우리가 한 모든 업무 here을 볼 수 있습니다.

    결론


    이제 다음을 수행할 수 있습니다.
  • 이 책상을 마음대로 사용하세요!필요에 따라 사용자 정의합니다.
  • 프로젝트
  • 을 처리할 때 시간을 벌 수 있도록 재사용 가능한 구성 요소를 만듭니다.

    Notice: I hope this article was helpful, or that you gained something from it! My brothers and I are learning more about React and publish articles every month. Follow me on twitter to get in touch! :)

    좋은 웹페이지 즐겨찾기