12. React中的样式应用:多种方式让你的组件更出彩

在构建React应用时,为组件添加样式是创造优秀用户体验的关键部分。与传统网页开发不同,React提供了多种方法来为组件添加样式,让我们能够灵活选择最适合项目需求的方案。

React不强制特定的样式方法

首先要了解的是,React本身并不关心我们如何为组件添加样式。这是因为React更像是一个库而非框架,它不会对样式方法有特定的偏好。这给了我们极大的自由来选择:

  • 内联样式(Inline styling)
  • 外部CSS或SASS文件
  • CSS模块(CSS Modules)
  • 样式组件(Styled Components)
  • Tailwind CSS

在这篇文章中,我们将重点关注两种最基础的方法:内联样式和引入外部CSS文件。

还是套用之前的代码进行练习:
import React from "react";
import ReactDOM from "react-dom/client";
  

function App() {
  return (
    <div>
      <Header />
      <Menu />
      <Footer />
    </div>
  );
}

function Header(){
  return <h1>Fast React Pizza Co.</h1>
}

function Menu() {
  return (
    <div>
      <h2>Our Menu</h2>
      <Pizza />
      <Pizza />
      <Pizza />
      {/* 更多Pizza组件... */}
    </div>
  );
}

function Footer(){
  const hour = new Date().getHours();
  const openHour = 12;
  const closeHour = 22;
  const isOpen = hour >= openHour && hour <= closeHour;

  console.log(isOpen);
  
  return (
  <footer>{new Date().toLocaleDateString()}. We're currently open.</footer>
  )
}

function Pizza(){
    return <div>
        <img src="pizzas/spinaci.jpg"></img>
        <h2>Pizza Spinaci</h2>
        <p>Tomato, mozarella, spinach, and ricotta cheese</p>
    </div>
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

内联样式:最直接的方式

在普通HTML中,我们使用style属性并在字符串中编写样式:

<h1 style="color: red; font-size: 32px;">标题文本</h1>

但在JSX中,内联样式需要使用JavaScript对象来定义。这需要两对花括号:第一对用于进入JavaScript模式,第二对用于创建对象.

让我们在Header组件里面的h1添加内联样式⬇️

function Header(){
  return <h1 style={{color: 'red', fontSize: '48px', textTransform: 'uppercase'}}>Fast React Pizza Co.</h1>
}

效果⬇️

注意几个关键点:

  1. CSS属性名需要使用驼峰命名法(camelCase),例如font-size变为fontSize
  2. 属性值通常需要是字符串
  3. 你也可以将样式对象提取出来使用:
function Header(){
  const style = {
    color: 'red', 
    fontSize: '48px', 
    textTransform: 'uppercase'
  };

  return <h1 style={style}>Fast React Pizza Co.</h1>
}

虽然内联样式简单直接,但当应用变得复杂时,为每个组件创建样式对象可能会变得繁琐,这不是大多数开发者在真实项目中的首选方法。

外部CSS文件:传统而有效

使用外部CSS文件是为React应用添加样式的最简单方式之一,它与为普通网页添加样式几乎相同。

首先,需要在上方导入CSS文件:(css等一些材料已在第7篇文章里上传)

import './index.css';

这让webpack能够处理CSS文件并将样式注入到应用中。

然后,我们可以为JSX元素添加类名。这里有一个重要的JSX规则:在JSX中,我们使用className而不是class,因为class是JavaScript的保留关键字。

// 错误方式
<div class="container">内容</div>

// 正确方式
<div className="container">内容</div>

按照这种方式,我们可以构建一个完整的布局结构:

以下是修改后的完整代码⬇️

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
  

function App() {
  return (
    <div className="container">
      <Header />
      <Menu />
      <Footer />
    </div>
  );
}

function Header(){
  const style = {};

  return (
    <header className="header">
      <h1 style={style}>
        Fast React Pizza Co.
      </h1>
    </header>
  )
}

function Menu() {
  return (
    <main className="menu">
      <h2>Our Menu</h2>
      <Pizza />
      <Pizza />
      <Pizza />
      {/* 更多Pizza组件... */}
    </main>
  );
}

function Footer(){
  const hour = new Date().getHours();
  const openHour = 12;
  const closeHour = 22;
  const isOpen = hour >= openHour && hour <= closeHour;

  console.log(isOpen);
  
  return (
  <footer className="footer">
    {new Date().toLocaleDateString()}. We're currently open.
  </footer>
  )
}

function Pizza(){
    return <div>
        <img src="pizzas/spinaci.jpg"></img>
        <h3>Pizza Spinaci</h3>
        <p>Tomato, mozarella, spinach, and ricotta cheese</p>
    </div>
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

效果⬇️

为了使整体效果好看,我们把index.css里面的.header h1::after{width: 12rem;}改为width: 4rem;

值得注意的是,这种方式导入的样式是全局的,不会限定在特定组件中。这意味着同一个类名可以应用到不同组件上,它们会共享相同的样式。这对小型应用来说很方便,但随着应用规模增长,可能会导致样式冲突。


总结

React为我们提供了多种为组件添加样式的方法。内联样式使用JavaScript对象,是最直观但不总是最方便的方式。外部CSS文件则是一种传统而有效的方法,特别适合从传统网页开发过渡到React的开发者。

对于更大型的应用,样式组件(Styled Components)或CSS模块等方法可能更适合,它们能够提供更好的样式隔离和组件化,我们将在以后的文章中深入探讨这些高级样式方法。

记住,选择合适的样式方法取决于你的项目需求、团队偏好和开发环境。没有绝对的最佳方案,重要的是找到最适合你具体情况的解决方法。


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注