首页 > 解决方案 > 当我在 REACT 中单击项目时,如何应用其余项目的样式?

问题描述

图1

在此处输入图像描述

图2

在此处输入图像描述

图3

在此处输入图像描述

当我选择一项时,我想应用一项的新样式和其余项的原始样式

例子

当我单击 SubBookmark33

当前的

图 1 -> 图 2

但是我要

图 1 -> 图 3

书签文件夹.js

import BookmarksFolderNode from './BookmarksFolderNode';
import classes from './BookmarksFolder.module.css';

import { folders } from '../../resources/data';

function BookmarksFolder() {

  return (
    <div className={classes.bookmarksFolder}>
      {folders.map((folder) => (
        <BookmarksFolderNode
          key={folder.id}
          folder={folder}
        />
      ))}
    </div>
  );
}

export default BookmarksFolder;

书签文件夹节点.js

import { useState, useRef } from 'react';
import { AiFillCaretDown, AiFillCaretRight } from 'react-icons/ai';
import Folder from '../../resources/img/folder.svg';
import OpenedFolder from '../../resources/img/opened_folder.svg';

import classes from './BookmarksFolderNode.module.css';

function BookmarksFolderNode(props) {
  const [folderIsOpen, setFolderIsOpen] = useState(false);
  const tab = useRef();
  const img = useRef();
  const title = useRef();

  const selectFolderHandler = () => {
    tab.current.style.backgroundColor = '#1a73eb';
    img.current.src = OpenedFolder;
    title.current.style.color = '#1a73eb';
  };

  const openFolderHandler = () => {
    setFolderIsOpen((prevState) => !prevState);
  };

  const paddingLeft = 20 * (props.folder.depth - 1);

return (
    <div className={classes.bookmarksFolderNode}>
      <div className={classes.bookmarksMainFolderNode}>
        <div className={classes.verticalTab} ref={tab}></div>
        <div className={classes.innerContainer} style={{paddingLeft}}>
          <div className={classes.icon} onClick={openFolderHandler}>
            {folderIsOpen ? (
              <AiFillCaretDown className={classes.ironIcon} />
            ) : (
              <AiFillCaretRight className={classes.ironIcon} />
            )}
          </div>
          <img src={Folder} className={classes.folderIcon} ref={img} />
          <div
            className={classes.menuLabel}
            onClick={selectFolderHandler}
            ref={title}
          >
            {props.folder.title}
          </div>
        </div>
      </div>
      <div className={classes.bookmarksSubFolderNode}>
        {props.folder.subFolder &&
          props.folder.subFolder.map((subFolder) => (
            <BookmarksFolderNode key={subFolder.id} folder={subFolder} />
          ))}
      </div>
    </div>
  );
}

export default BookmarksFolderNode;

数据.js

export const folders = [
  {
    id: 1,
    depth: 1,
    title: 'Bookmark 1',
    subFolder: [
      {
        id: 1,
        depth: 2,
        title: 'SubBookmark 1',
        subFolder: [
          {
            id: 1,
            depth: 3,
            title: 'SubBookmark 11',
          },
          {
            id: 2,
            depth: 3,
            title: 'SubBookmark 22',
          },
          {
            id: 3,
            depth: 3,
            title: 'SubBookmark 33',
            subFolder: [
              {
                id: 1,
                depth: 4,
                title: 'SubBookmark 111',
              },
            ],
          },
        ],
      },
      {
        id: 2,
        depth: 2,
        title: 'SubBookmark 2',
      },
    ],
  },
];

标签: javascriptreactjsfrontendweb-frontend

解决方案


这个想法是,当您选择一个文件夹时,您应该从父组件中取消选择其他文件夹BookmarksFolder。解决方案有点棘手,因为您使用BookmarksFolderNode本地状态(我的意思是folderIsOpen)选择文件夹。

好吧,让我们开始使用父组件的状态来选择/取消选择文件夹:

import BookmarksFolderNode from './BookmarksFolderNode';
import classes from './BookmarksFolder.module.css';

import { folders } from '../../resources/data';

function BookmarksFolder() {
  const [foldersSelected, setFoldersSelected] = useState(new Array(folders.length).fill(false));

  const selectFolder = (index) => {
     let result = new Array(folders.length).fill(false);
     result[index] = true;
     setFoldersSelected(result);
  }

  return (
    <div className={classes.bookmarksFolder}>
      {folders.map((folder, index) => (
        <BookmarksFolderNode
          key={folder.id}
          folder={folder}
          isSelected={foldersSelected[index]}
          select={(index) => selectFolder(index)}
          index={index}
        />
      ))}
    </div>
  );
}

export default BookmarksFolder;

所以现在BookmarksFolderNode我们必须使用isSelectedandselect而不是folderIsOpenand openFolderHandler。不仅如此,我们还必须为子文件夹复制相同的逻辑:

import { useState, useRef, useEffect } from 'react';
import { AiFillCaretDown, AiFillCaretRight } from 'react-icons/ai';
import Folder from '../../resources/img/folder.svg';
import OpenedFolder from '../../resources/img/opened_folder.svg';

import classes from './BookmarksFolderNode.module.css';

function BookmarksFolderNode(props) {
  const [subfoldersSelected, setSubFoldersSelected] = useState(new Array(props.folder.subFolder.length).fill(false));
  const tab = useRef();
  const img = useRef();
  const title = useRef();

  useEffect(() => {
     if (props.isSelected) {
        tab.current.style.backgroundColor = '#1a73eb';
        img.current.src = OpenedFolder;
        title.current.style.color = '#1a73eb';
     }
     else {
        tab.current.style.backgroundColor = 'black';
        img.current.src = Folder;
        title.current.style.color = 'black';
     }
  }, [props.isSelected])

  const openFolderHandler = () => {
    props.select(props.index)
  };

  const paddingLeft = 20 * (props.folder.depth - 1);

  const selectSubfolder = (index) => {
     let result = new Array(props.folder.subFolder.length).fill(false);
     result[index] = true;
     setSubFoldersSelected(result);
  }

return (
    <div className={classes.bookmarksFolderNode}>
      <div className={classes.bookmarksMainFolderNode}>
        <div className={classes.verticalTab} ref={tab}></div>
        <div className={classes.innerContainer} style={{paddingLeft}}>
          <div className={classes.icon} onClick={openFolderHandler}>
            {props.isSelected ? (
              <AiFillCaretDown className={classes.ironIcon} />
            ) : (
              <AiFillCaretRight className={classes.ironIcon} />
            )}
          </div>
          <img src={Folder} className={classes.folderIcon} ref={img} />
          <div
            className={classes.menuLabel}
            onClick={openFolderHandler}
            ref={title}
          >
            {props.folder.title}
          </div>
        </div>
      </div>
      <div className={classes.bookmarksSubFolderNode}>
        {props.folder.subFolder &&
          props.folder.subFolder.map((subFolder, index) => (
            <BookmarksFolderNode key={subFolder.id} folder={subFolder} index={index} isSelected={subfoldersSelected[index]} select={(index) => selectSubfolder(index)} />
          ))}
      </div>
    </div>
  );
}

export default BookmarksFolderNode;

所以现在,如果您选择一个文件夹(或子文件夹),其他文件夹(或子文件夹)将被取消选择,useEffect并将应用所需的 css。


推荐阅读