Skip to content

组件

什么是组件?

此时 App 是一个单体,我们在真正做项目的时候,我们需要把它分解成可管理的,可描述的组件。 React 对于什么是组件和什么不是组件并没有任何硬性规定,这完全取决于你!

React 优秀项目 https://win11.blueedge.me/

定义第一个组件

如果你没有组件开发的经验,那你一定要记住我的准则:

  • 如果它在程序里是一个块,那么它就是一个组件
  • 如果它在程序里面经常出现,那么也它也是组件

使用通用的 UI 元素作为组件,可以让你只更改一处,就能更改所有使用该组件的地方

编写 Card 组件

例如项目中经常会用到一个卡片组件我们来编写一个卡片组件

我们新建一个文件夹components

目录结构:

  • components
  • Card
    • index.tsx
    • index.css

index.css

css
.card {
  background: white;
  border-radius: 5px;
  border: 1px solid #ccc;
  max-width: 500px;
  box-shadow: 3px 3px 3px #ccc;

  header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid #ccc;
    padding: 10px;

    div:last-child {
      color: #1677ff;
    }
  }

  main {
    min-height: 200px;
    border-bottom: 1px solid #ccc;
    padding: 10px;
  }
  footer {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 10px;
    button {
      margin-left: 10px;
      padding: 3px 10px;
    }
  }
}

index.tsx

tsx
import './index.css';

export default function Card() {
  return (
    <div className="card">
      <header>
        <div>标题</div>
        <div>副标题</div>
      </header>
      <main>内容区域</main>
      <footer>
        <button>确认</button>
        <button>取消</button>
      </footer>
    </div>
  );
}

App.tsx 引入 Card 组件

这种称之为局部组件在哪一个页面需要使用就在哪一个页面引入即可

tsx
import Card from './components/Card';
function App() {
  return (
    <>
      <Card></Card>
      <Card></Card>
      <Card></Card>
    </>
  );
}

全局组件

目录结构:

  • components
    • Message
      • index.tsx
      • index.css

Message/index.css

css
.message {
  width: 160px;
  height: 30px;
  position: fixed;
  top: 10px;
  left: 50%;
  margin-left: -80px;
  background: #fff;
  border: 1px solid #ccc;
  text-align: center;
  line-height: 30px;
  border-radius: 5px;
}

Message/index.tsx

创建一个 queue 队列因为可以点击多次需要存到数组,并且累加每次的高度,使元素没有进行重叠,而是顺移,所以需要一个 queue 队列,删除的时候就按顺序删除即可。

tsx
import ReactDom from 'react-dom/client';
import './index.css';
const Message = () => {
  return <div>提示组件</div>;
};
interface Itesm {
  messageContainer: HTMLDivElement;
  root: ReactDom.Root;
}
const queue: Itesm[] = [];
window.onShow = () => {
  const messageContainer = document.createElement('div');
  messageContainer.className = 'message';
  messageContainer.style.top = `${queue.length * 50}px`;
  document.body.appendChild(messageContainer);
  const root = ReactDom.createRoot(messageContainer);
  root.render(<Message />); //渲染组件
  queue.push({
    messageContainer,
    root,
  });
  //2秒后移除
  setTimeout(() => {
    const item = queue.find(
      item => item.messageContainer === messageContainer
    )!;
    item.root.unmount(); //卸载
    document.body.removeChild(item.messageContainer);
    queue.splice(queue.indexOf(item), 1);
  }, 2000);
};

//声明扩充
declare global {
  interface Window {
    onShow: () => void;
  }
}

export default Message;

在 main.tsx 注入即可使用 import './components/Message/index.tsx'

App.tsx Card.tsx 使用

tsx
<button onClick={() => window.onShow()}>确认</button>

Keep Reading, Keep Writing, Keep Coding