Next.js - 使用 CSS 模块时无法应用动态 class 名称
Next.js - Cant apply dynamic class names when using CSS Modules
希望这里有人能帮我解决这个问题。
我正在尝试通过 NextJs 构建网站。我的一个页面有一些段落和按钮,它们根据状态和事件设置不同的样式。在使用纯 React 时以及在 NextJs 中使用全局样式表时,我可以使样式按预期工作;但是当我使用 CSS 模块时,我无法让它按预期运行。
(注意:我也可以通过使用简单的三元来让它工作
<h1 className={submitted ? styles.showresult : styles.hideresult}>Correct? {correct}</h1>
;
但我有一些其他场景,我需要依赖多个 ifs 并创建多个 classes,每个都有自己的样式,所以我无法将简单的三元组作为我的最终解决方案。
例如这是文件 pagex.js
import React from 'react';
import ReactDOM from 'react-dom';
const Pagex = () => {
const [submitted, setSubmitted] = React.useState(false); // whether the submit button was pressed
function calculateScore() {
let correct = 0
let incorrect = 0
//......some scoring logic.....
setSubmitted(true)
}
// function to create a display class based on whether the submit button has been pressed
function displayResult(){
if (submitted === true) {
return "showtheresult"
} else {
return "hidetheresult"
}
}
return (
<section className="results">
<h1 className={displayResult()}>Correct? {correct}</h1>
<h1 className={displayResult()}>Incorrect? {incorrect}</h1>
<button className={displayResult()} onClick={handleMovClick}>An instruction</button>
</section>
</div>
);
};
export default Pagex;
globals.css 文件包含
h1.hidetheresult, h3.hidetheresult {
visibility: hidden;
}
h1.showtheresult, h3.showtheresult {
visibility: visible;
}
button.hidetheresult {
border-color: pink;
}
button.showtheresult {
border-color: aqua;
}
使用 CSS 模块时的变化
- 在正确的文件夹中使用正确的名称添加一个 CSS 文件
(../styles/Pagex.module.css) 其中包含所示的相同样式
以上
- 在 pagex.js
import styles from '../styles/Pagex.module.css'
中的额外导入
- 更改函数中的引用
在 pagex.js
之内
function displayResult(){
if (submitted === true) {
return {styles.showtheresult}
} else {
return {styles.hidetheresult}
}
}
当我这样做时,'.'在 {styles.showtheresult}
和 {styles.hidetheresult}
中被 vscode 突出显示为错误,详细信息为:',' expected. ts(1005).
使用开发服务器保存 js 运行 在尝试编译后会显示类似的消息:Syntax error: Unexpected token, expected "," 并且浏览器会显示相同的消息以及“编译失败”
还尝试通过从 displayResult() 函数中删除大括号来传递 styles.showtheresult
/ styles.hidetheresult
。可以编译,但编译后的网页上没有任何反应,即按下按钮时 class 不会更新,因此无法应用样式。
还尝试在 return 语句中传递为 ${styles.showresult} 和 ${styles.hideresult}(带有 `)。这也可以编译,但页面本身给了我一个 "Unhandled Runtime Error ReferenceError: styles is not defined" 消息,我无法加载页面。
如果有人可以帮助更正我在函数本身或代码其他地方的语法,我将不胜感激。
因为你问得很好 ;)(开个玩笑)
所以 Next.js 是一个固执己见的框架,它使用 CSS 模块来强制执行组件范围内的样式。
基本上,您使用 name.module.css
文件名定义样式表并在其中添加常规 CSS。
.hidetheresult {
visibility: hidden;
}
.showtheresult{
visibility: visible;
}
.btn-hidetheresult {
border-color: pink;
}
.btn-showtheresult {
border-color: aqua;
}
现在要使用它,像导入任何 JS 模块一样导入它,
import styles from './styles.module.css'
console.log(styles);
// styles => {
// hidetheresult: 'contact_hidetheresult__3LvIF',
// showtheresult: 'contact_showtheresult__N5XLE',
// 'btn-hidetheresult': 'contact_btn-hidetheresult__3CQHv',
// 'btn-showtheresult': 'contact_btn-showtheresult__1rM1E'
// }
如您所见,样式已转换为对象,现在您可以使用它们了
像 styles.hidetheresult
或 styles['btn-hidetheresult']
.
请注意样式表中缺少元素选择器。那是因为 CSS 模块重写 class 名称,但它们不涉及标签名称。在 Next.js 中
默认行为。即它不允许元素标签选择器。
File extensions with *.module.(css | scss | sass)
are css modules and they can only target elements using classnames or ids and not using tag names. Although this is possible in other frameworks like create-react-app, it is not possible in next-js.
但您可以在 next.config.js
文件中覆盖它。 (超出本回答范围)
There is an article which explains how to override it. - disclaimer: I am the author
现在来到您的用例,您可以像这样进行条件样式设置:(假设样式按照答案中给出的示例)
import React from "react";
import styles from "./styles.module.css";
const PageX = () => {
const [submitted, setSubmitted] = React.useState(false);
const getStyle = () => {
if (submitted) return styles.showtheresult;
else return styles.hidetheresult;
};
const getButtonStyle = () => {
if (submitted) return styles["btn-showtheresult"];
else return styles["btn-hidetheresult"];
};
return (
<div>
<section className="results">
<h1 className={getStyle()}>Correct?</h1>
<h1 className={getStyle()}>Incorrect?</h1>
<button className={getButtonStyle()} onClick={handleMovClick}>
An instruction
</button>
</section>
</div>
);
};
随着您添加更多条件,方法确实会变得更复杂。这是 classnames
模块派上用场。
import styles from "./styles.module.css";
import clsx from "classnames";
const PageX = () => {
const [submitted, setSubmitted] = React.useState(false);
const headerStyle = clsx({
[styles.showtheresult]: submitted,
[styles.hidetheresult]: !submitted,
});
const btnStyle = clsx({
[styles["btn-showtheresult"]]: submitted,
[styles["btn-hidetheresult"]]: !submitted,
});
return (
<div>
<section className="results">
<h1 className={headerStyle}>Correct?</h1>
<h1 className={headerStyle}>Incorrect?</h1>
<button className={btnStyle} onClick={handleMovClick}>
An instruction
</button>
</section>
</div>
);
};
希望这里有人能帮我解决这个问题。
我正在尝试通过 NextJs 构建网站。我的一个页面有一些段落和按钮,它们根据状态和事件设置不同的样式。在使用纯 React 时以及在 NextJs 中使用全局样式表时,我可以使样式按预期工作;但是当我使用 CSS 模块时,我无法让它按预期运行。
(注意:我也可以通过使用简单的三元来让它工作
<h1 className={submitted ? styles.showresult : styles.hideresult}>Correct? {correct}</h1>
;
但我有一些其他场景,我需要依赖多个 ifs 并创建多个 classes,每个都有自己的样式,所以我无法将简单的三元组作为我的最终解决方案。
例如这是文件 pagex.js
import React from 'react';
import ReactDOM from 'react-dom';
const Pagex = () => {
const [submitted, setSubmitted] = React.useState(false); // whether the submit button was pressed
function calculateScore() {
let correct = 0
let incorrect = 0
//......some scoring logic.....
setSubmitted(true)
}
// function to create a display class based on whether the submit button has been pressed
function displayResult(){
if (submitted === true) {
return "showtheresult"
} else {
return "hidetheresult"
}
}
return (
<section className="results">
<h1 className={displayResult()}>Correct? {correct}</h1>
<h1 className={displayResult()}>Incorrect? {incorrect}</h1>
<button className={displayResult()} onClick={handleMovClick}>An instruction</button>
</section>
</div>
);
};
export default Pagex;
globals.css 文件包含
h1.hidetheresult, h3.hidetheresult {
visibility: hidden;
}
h1.showtheresult, h3.showtheresult {
visibility: visible;
}
button.hidetheresult {
border-color: pink;
}
button.showtheresult {
border-color: aqua;
}
使用 CSS 模块时的变化
- 在正确的文件夹中使用正确的名称添加一个 CSS 文件 (../styles/Pagex.module.css) 其中包含所示的相同样式 以上
- 在 pagex.js
import styles from '../styles/Pagex.module.css'
中的额外导入
- 更改函数中的引用 在 pagex.js 之内
function displayResult(){
if (submitted === true) {
return {styles.showtheresult}
} else {
return {styles.hidetheresult}
}
}
当我这样做时,'.'在 {styles.showtheresult}
和 {styles.hidetheresult}
中被 vscode 突出显示为错误,详细信息为:',' expected. ts(1005).
使用开发服务器保存 js 运行 在尝试编译后会显示类似的消息:Syntax error: Unexpected token, expected "," 并且浏览器会显示相同的消息以及“编译失败”
还尝试通过从 displayResult() 函数中删除大括号来传递 styles.showtheresult
/ styles.hidetheresult
。可以编译,但编译后的网页上没有任何反应,即按下按钮时 class 不会更新,因此无法应用样式。
还尝试在 return 语句中传递为 ${styles.showresult} 和 ${styles.hideresult}(带有 `)。这也可以编译,但页面本身给了我一个 "Unhandled Runtime Error ReferenceError: styles is not defined" 消息,我无法加载页面。
如果有人可以帮助更正我在函数本身或代码其他地方的语法,我将不胜感激。
因为你问得很好 ;)(开个玩笑)
所以 Next.js 是一个固执己见的框架,它使用 CSS 模块来强制执行组件范围内的样式。
基本上,您使用 name.module.css
文件名定义样式表并在其中添加常规 CSS。
.hidetheresult {
visibility: hidden;
}
.showtheresult{
visibility: visible;
}
.btn-hidetheresult {
border-color: pink;
}
.btn-showtheresult {
border-color: aqua;
}
现在要使用它,像导入任何 JS 模块一样导入它,
import styles from './styles.module.css'
console.log(styles);
// styles => {
// hidetheresult: 'contact_hidetheresult__3LvIF',
// showtheresult: 'contact_showtheresult__N5XLE',
// 'btn-hidetheresult': 'contact_btn-hidetheresult__3CQHv',
// 'btn-showtheresult': 'contact_btn-showtheresult__1rM1E'
// }
如您所见,样式已转换为对象,现在您可以使用它们了
像 styles.hidetheresult
或 styles['btn-hidetheresult']
.
请注意样式表中缺少元素选择器。那是因为 CSS 模块重写 class 名称,但它们不涉及标签名称。在 Next.js 中 默认行为。即它不允许元素标签选择器。
File extensions with
*.module.(css | scss | sass)
are css modules and they can only target elements using classnames or ids and not using tag names. Although this is possible in other frameworks like create-react-app, it is not possible in next-js.
但您可以在 next.config.js
文件中覆盖它。 (超出本回答范围)
There is an article which explains how to override it. - disclaimer: I am the author
现在来到您的用例,您可以像这样进行条件样式设置:(假设样式按照答案中给出的示例)
import React from "react";
import styles from "./styles.module.css";
const PageX = () => {
const [submitted, setSubmitted] = React.useState(false);
const getStyle = () => {
if (submitted) return styles.showtheresult;
else return styles.hidetheresult;
};
const getButtonStyle = () => {
if (submitted) return styles["btn-showtheresult"];
else return styles["btn-hidetheresult"];
};
return (
<div>
<section className="results">
<h1 className={getStyle()}>Correct?</h1>
<h1 className={getStyle()}>Incorrect?</h1>
<button className={getButtonStyle()} onClick={handleMovClick}>
An instruction
</button>
</section>
</div>
);
};
随着您添加更多条件,方法确实会变得更复杂。这是 classnames 模块派上用场。
import styles from "./styles.module.css";
import clsx from "classnames";
const PageX = () => {
const [submitted, setSubmitted] = React.useState(false);
const headerStyle = clsx({
[styles.showtheresult]: submitted,
[styles.hidetheresult]: !submitted,
});
const btnStyle = clsx({
[styles["btn-showtheresult"]]: submitted,
[styles["btn-hidetheresult"]]: !submitted,
});
return (
<div>
<section className="results">
<h1 className={headerStyle}>Correct?</h1>
<h1 className={headerStyle}>Incorrect?</h1>
<button className={btnStyle} onClick={handleMovClick}>
An instruction
</button>
</section>
</div>
);
};