Mô-đun CSS nhiều lớp

Thuộc tính

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
8 trong React chỉ chấp nhận một giá trị chuỗi duy nhất. Nếu bạn cần nhiều lớp và lớp có điều kiện (thêm lớp x nếu y đúng), bạn cần tạo một mảng, thêm tên lớp tùy theo điều kiện và nối các tên lại với nhau

const className = ["a", isAdmin ? "b" : ""].join(" ");
return <button className={className}>...</button>;

Nó hoạt động nhưng không tiện dụng lắm. Có các chức năng tiện ích của bên thứ ba như tên lớp giúp việc này dễ dàng hơn. Nhưng chúng ta có thể làm điều đó tốt hơn

Những gì chúng ta sẽ xây dựng

Chúng tôi sẽ xây dựng chức năng tiện ích của riêng mình hoạt động với các tên lớp có thể xâu chuỗi có thể được áp dụng theo điều kiện. Đó là cách nó sẽ trông như thế nào

<p className={$.paragraph.center.large(isLarge)}>nice!</p>

Điều này sẽ thêm các lớp

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
9,
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
0 và - nếu
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
1 là trung thực - lớp
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
2. Chức năng tiện ích sẽ hoạt động với các Mô-đun CSS, vì vậy tên lớp thực tế được băm

Mô-đun CSS là gì?

Nếu bạn đã quen thuộc với các Mô-đun CSS, bạn có thể bỏ qua phần này

Mô-đun CSS cho phép bạn viết CSS nằm trong phạm vi cục bộ cho thành phần của bạn. Nó làm cho tên lớp của bạn trở nên độc nhất bằng cách thêm giá trị băm cho chúng

Mô-đun CSS nhiều lớp

Hơn nữa, nó tạo ra một ánh xạ giữa tên lớp của bạn và tên lớp cuối cùng bao gồm hàm băm. Khi bạn nhập tệp CSS vào tệp JSX của mình, bạn sẽ nhận được ánh xạ đó dưới dạng đối tượng JS. Sau đó, bạn có thể sử dụng nó trong thành phần của mình để lấy tên lớp thực

import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}

giải pháp hiện có

Làm việc với nhiều lớp và lớp có điều kiện trong React không hoàn toàn tốt như chúng ta đã thấy ở đầu bài viết này

Các hàm tiện ích rất hữu ích để làm cho nhiệm vụ này dễ dàng hơn một chút, như gói npm

import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
3. Đó là hàm chấp nhận nhiều tên lớp, mảng và đối tượng cho các lớp có điều kiện

Trong ví dụ sau, đoạn văn sẽ có lớp

import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
4 (hoặc tên duy nhất được chuyển đổi tương ứng cho lớp đó) và, nếu
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
1 là trung thực, thì lớp
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
2

import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}

Ngay cả với chức năng tiện ích

import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
3, chúng tôi có một số chi phí để tạo tên lớp cuối cùng. Gói
import css from "./styles.module.css";

function MyButton() {
  // css.Button returns the unique class name "Button__a3mdu"
  return <button className={css.Button}>...</button>;
}
3 hỗ trợ dẫn đến ít mã hơn nhưng loại bỏ mọi loại an toàn mà bạn có bằng các công cụ như typescript-plugin-css-modules

Tổng quan về giải pháp

Đây là những gì chúng ta sẽ xây dựng

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}

Bạn có thể xâu chuỗi nhiều lớp lại với nhau chỉ bằng một dấu chấm, bạn có thể thêm các lớp có điều kiện bằng cách gọi tên lớp bằng một đối số và nó hoạt động với

import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
0

Phép thuật. Proxy JavaScript

Vấn đề chính mà chúng ta gặp phải là chúng ta cần chuyển đổi một đối tượng phẳng - đối tượng Mô-đun CSS chỉ là một đối tượng khóa-giá trị, ánh xạ từng tên lớp thành tên lớp duy nhất của chúng - thành một đối tượng lồng nhau trong đó mỗi tổ hợp tên lớp được hỗ trợ. Cả hai,

import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
1 và
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
2 đều hoạt động

Điều kỳ diệu đằng sau tiện ích tên lớp có thể xâu chuỗi là đối tượng Proxy JavaScript. Đối tượng proxy cho phép bạn chặn các hoạt động trên một đối tượng. Điều này cho phép bạn làm những điều điên rồ. Bạn có thể thao tác các giá trị, xác thực hoặc sử dụng nó cho

Với điều này, chúng ta không phải tạo một đối tượng thực với cấu trúc lồng sâu cho tất cả các hoán vị có thể. Thay vào đó, chúng tôi chỉ ủy quyền đối tượng Mô-đun CSS và chúng tôi giả vờ rằng đối tượng được lồng vào nhau

Thực hiện

API

Đây là API của chức năng tiện ích

// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;

Dưới đây là một đại diện đồ họa của cấu trúc

Khi sử dụng đối tượng

import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
3, trước tiên bạn có thể thêm bất kỳ tên lớp nào có sẵn, e. g.
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
4. Sau đó, bạn có thể lấy kết quả đầu ra
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
5 (hoặc
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
6), thêm một lớp khác
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
7 hoặc tạo điều kiện cho lớp trước đó bằng cách gọi nó là một hàm
import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
8

bản đánh máy

Chức năng tiện ích của chúng tôi phải là loại an toàn. Vì vậy, hãy sử dụng TypeScript và tạo một số loại

// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };

Tiếp theo, chúng ta cần các kiểu cho chính đối tượng đó. Điều này phức tạp hơn một chút

// The type for conditional classes. The function requires
// the condition as argument and returns an object to add more
// classes or to get the output
type CssModuleCondition<M extends CssModuleObj> = 
  (condition: unknown) => CssModuleChain<M>;

// An object with all classes as keys. Each class maps to
// the callable chain. That means it can either be called
// for conditional classes ($.foo(...)) or you can just add another
// class if it's not conditional ($.foo.bar)
type CssModuleClasses<M extends CssModuleObj> = { 
  [key in keyof M]: CssModuleCallableChain<M> 
};

// The chain combines the types above (an object with 
// all class names as key) and the output types
type CssModuleChain<M extends CssModuleObj> = 
  CssModuleClasses<M> &
  CssModuleOutput &
  CssModuleFnOutput;

// This extends the type above. In addition to all class names
// and the output property / function, the object itself
// is callable to support conditional classes.
type CssModuleCallableChain<M extends CssModuleObj> = 
  CssModuleChain<M> & CssModuleCondition<M>;

Hãy lấy hình ảnh trước và kết hợp nó với các loại này

chức năng tiện ích

Bây giờ chúng ta có tất cả các loại, chúng ta có thể tạo chức năng tiện ích của mình. Nó chấp nhận một Mô-đun CSS làm đối số và trả về một đối tượng kiểu

import cn from "classnames";
import css from "./styles.module.css";

function Component({ isLarge }) {
  return <p className={cn(css.Paragraph, { [css.large]: isLarge })}></p>;
}
9

Hàm của chúng tôi trả về một proxy có trình xử lý thực hiện hàm

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
0. Bây giờ khi bạn truy cập lớp đầu tiên, nó sẽ gọi hàm
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
1

function ccn<M extends CssModuleObj>(mod: M): CssModuleClasses<M> {
  function init(initialClass: string): CssModuleCallableChain<M> {
    // ...
  }

  return new Proxy<CssModuleClasses<M>>(mod as any, {
    get: (_, prop: string) => init(prop),
  });
}

Bây giờ hãy triển khai hàm

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
1. Trước tiên, chúng tôi tạo một
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
3 để lưu trữ tất cả các lớp được xâu chuỗi. Chúng tôi cũng triển khai hàm
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
4 để ánh xạ từng lớp được xâu chuỗi thành tên lớp duy nhất của chúng và nối chúng lại với nhau

function init(initialClass: string): CssModuleCallableChain<M> {
  const classNames = new Set<string>();
  let latestClassName: string = initialClass;

  function buildFinalClassName() {
    latestClassName && classNames.add(latestClassName);
    return Array.from(classNames)
      .map((cn) => mod[cn])
      .filter((cn) => !!cn)
      .join(" ");
  }
}

Bộ

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5 được tạo bên trong hàm
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
1. Điều này đảm bảo rằng hai Bộ riêng biệt được tạo khi bạn truy cập vào
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
7 và
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
8

Tiếp theo, chúng tôi tạo hai đối tượng proxy. Cái đầu tiên là

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
9. Proxy này hỗ trợ các lớp có điều kiện nghĩa là bạn có thể gọi nó với một điều kiện để quyết định xem có nên thêm lớp bạn vừa truy cập hay không. Ngoài ra, bạn có thể gọi nó mà không có đối số để lấy tên lớp cuối cùng, truy cập
// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
0 cũng trả về tên lớp cuối cùng hoặc xâu chuỗi một lớp khác

Người đại diện thứ hai là

// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
1. Proxy này tương tự như proxy đầu tiên nhưng không hỗ trợ các lớp có điều kiện, nghĩa là bạn không thể gọi nó bằng đối số (nhưng bạn có thể gọi nó mà không cần đối số để lấy tên lớp cuối cùng)

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
0

Hãy thực hiện

// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
2. Đầu tiên, hàm kiểm tra xem nó có nhận được bất kỳ đối số nào không. Nếu không, chúng tôi trả lại tên lớp cuối cùng (cách sử dụng.
// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
3). Nếu có tranh luận, chúng tôi kiểm tra xem nó có trung thực hay không và thêm hoặc xóa tên lớp. Lớp mà bạn đã truy cập được lưu trữ trong biến
// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
4. Sau đó, chúng tôi trả lại
// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
1 để cho phép bạn thêm một lớp khác

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
1

Và đây là việc triển khai trình xử lý proxy. Nếu bạn truy cập

// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
0, nó sẽ trả về tên lớp cuối cùng. Mặt khác, nó lưu trữ tên lớp trong một biến có tên là
// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
4 và trả về ____15_______9 để cho phép bạn thêm một lớp khác hoặc gọi lớp hiện tại với một điều kiện (đó là lý do tại sao chúng tôi lưu trữ tên lớp trong biến sẽ được sử dụng bởi ____19_______2

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
2

Cải tiến proxy

Proxy gốc có đối tượng Mô-đun CSS của bạn làm mục tiêu. Nếu bạn gọi

// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
0, bạn sẽ nhận được một mảng với tất cả các tên lớp có sẵn. Ngược lại,
// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
1 sẽ trả về một danh sách trống. Tại sao?

Chúng tôi có thể cải thiện trình xử lý proxy của mình và triển khai

// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
3,
// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
4 và
// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
5. Nhưng tôi đoán đó không thực sự là một trường hợp sử dụng để sử dụng
// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
6 trên một lớp bị xiềng xích (hoặc toán tử
// That's our CSS Module object
type CssModuleObj = Record<string, string>;

// There are two different ways to get the final class name
// Use "$" or call it as a function without arguments
type CssModuleOutput = { $: string };
type CssModuleFnOutput = { (): string };
7), vì vậy chúng tôi sử dụng phiên bản đơn giản mà chúng tôi có

Hiệu suất

Mỗi khi bạn sử dụng

// Just one class
// For the output (final class name string) you can either
// - call the name as a function without arguments
// - use the property "$"
$.Paragraph();
$.Paragraph.$;

// Multiple classes
$.Paragraph.large();
$.Paragraph.large.$;

// Conditional classes
$.Paragraph.large(isLarge)();
$.Paragraph.large(isLarge).$;
0, bạn sẽ nhận được cùng một proxy gốc. Sau đó, khi bạn truy cập một lớp, hàm
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
1 sẽ được gọi và nó tạo ra hai đối tượng proxy. Trong một thành phần có nhiều phần tử, điều này sẽ dẫn đến nhiều đối tượng proxy

Hành vi này đảm bảo rằng mọi chuỗi bạn xây dựng đều có Bộ

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5 riêng và các đối tượng proxy của riêng nó. Mỗi chuỗi độc lập với nhau và bạn có thể làm điều gì đó như thế này

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
3

Điều này sẽ xuất ra "một ba" và "hai" là chính xác. Điều này chỉ hoạt động vì các Bộ

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5 riêng biệt. Đây có thực sự là một trường hợp sử dụng mà chúng tôi cần hỗ trợ không? . Trong thực tế, bạn sẽ xây dựng chuỗi trực tiếp trên phần tử, như thế này

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
4

Lưu ý đến hạn chế này, chúng ta có thể cải thiện hiệu suất bằng cách sử dụng lại các đối tượng Bộ và proxy

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5. Chúng tôi xóa chức năng
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
1 và xóa Bộ
import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5 bất cứ khi nào một chuỗi mới được tạo

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
5

Với giải pháp này, chúng tôi luôn tạo ba đối tượng proxy và một Bộ

import css from "component.module.css";

// Our utility function ccn (chainable class names)
const $ = ccn(css); // Bind your class names (sorry jQuery)

function Component({ isLarge }) {
  return <p className={$.Paragraph.large(isLarge).center()}>nice!</p>;
}
5, bất kể bạn tạo bao nhiêu chuỗi. Chúng ta chỉ cần lưu ý rằng một chuỗi cần phải được hoàn thành trước khi có thể tạo một chuỗi mới

Chúng tôi cũng có thể thực hiện kiểm tra và đưa ra lỗi trong trường hợp này

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
6

Giải pháp cuối cùng

Đó là nó. Bây giờ chúng ta có thể sử dụng chức năng tiện ích của mình

<p className={$.paragraph.center.large(isLarge)}>nice!</p>
7

Và bạn vẫn nhận được đề xuất tự động hoàn thành.

Mô-đun CSS nhiều lớp

Thử nghiệm

Bạn có thể tìm thấy bản demo và mã đầy đủ trên GitHub

Tóm lược

Mô-đun CSS là một cách tuyệt vời để tạo kiểu trong phạm vi cục bộ thay thế cho các giải pháp CSS-in-JS khác nhau. Vì React chỉ chấp nhận một chuỗi làm tên lớp, nên sử dụng hàm tiện ích hỗ trợ nhiều lớp và điều kiện

Chúng tôi đã xây dựng một hàm tiện ích nhỏ để xâu chuỗi các tên lớp. Nó cung cấp một cú pháp ngắn gọn và dễ sử dụng, hỗ trợ các lớp điều kiện và không ảnh hưởng đến an toàn kiểu như các giải pháp khác

Chúng ta có thể sử dụng nhiều lớp trong CSS không?

Để chỉ định nhiều lớp, hãy phân tách tên lớp bằng dấu cách , e. g.

Một thành phần có thể có nhiều lớp không?

Bạn có thể liệt kê nhiều lớp và điều kiện và bạn cũng có thể bao gồm các lớp tĩnh. Không cần thiết phải thêm một thư viện bổ sung.

Tôi có nên sử dụng các mô-đun CSS không?

Mô-đun CSS cho phép bạn viết kiểu trong tệp CSS nhưng sử dụng chúng dưới dạng đối tượng JavaScript để xử lý bổ sung và đảm bảo an toàn . Mô-đun CSS rất phổ biến vì chúng tự động đặt tên lớp và hoạt hình thành duy nhất, do đó bạn không phải lo lắng về xung đột tên bộ chọn.

Làm cách nào để sử dụng các mô-đun CSS?

Sử dụng mô-đun CSS .
Tạo một tệp với. mô-đun. css làm phần mở rộng
Nhập mô-đun đó vào ứng dụng React (như chúng ta đã thấy trước đó)
Thêm một tên lớp vào một phần tử hoặc thành phần và tham chiếu kiểu cụ thể từ các kiểu đã nhập