Material-ui: [RFC] 迁移到样式化组件

创建于 2017-02-11  ·  164评论  ·  资料来源: mui-org/material-ui

我们可以切换到styled-components吗?


过时的比较

它对 JSS 有很多优势
这里有对比表,下个版本甚至会避免 SSR 样式重新渲染!

特点 | 样式组件 | 反应-jss
------------ | ------------- | -------------
无构建要求 | ✅| ✅
小巧轻便 | ✅ | ✅
支持全球 CSS | ✅ | ✅
支持整个 CSS | ✅ | ✅
同地| ✅ | ✅
隔离 | ✅ | ✅
不会破坏内联样式 | ✅ |✅
易于覆盖 | ✅ | ✅
主题 | ✅ | ✅
服务器端渲染 | ✅ | ✅
无包装组件 | ❌ | ✅
ReactNative 支持 | ✅ | ❌

图例:✅ = 是,❌ = 否,😕 = 有点,请参阅注释或括号

discussion enhancement

最有用的评论

@oliviertassinari根据我们正在进行的性能测试,如https://github.com/mui-org/material-ui/issues/6115#issuecomment -643398897 中所述,我只是希望材料团队不要仅仅因为它很受欢迎而选择样式化组件。 它很慢。 一直都是。 就个人而言,作为一名开发人员,您需要学习诸如 CSS 的 JS 表示法之类的东西。

这是工作的一部分。

让开发者的生活更轻松是我们作为包维护者工作的一部分(对于我自己的项目),但在让它变得简单和让它变得高效之间有一条界限。

这就是为什么我只使用 makeStyles 并且自推出以来一直使用它的原因。

我上一个团队架构师不听,而是继续使用样式化的组件,现在网站速度很慢。 我在测试分支中切换到 makeStyles 并在移动设备上的 TTI 上节省了 50%(10 秒),但就像你在那条评论中所说的那样,JS 表示法并不是每个人都知道,所以它没有被接受。

内部材料可以选择任何它想要的,但请默认使其具有性能。

所有164条评论

@kybarg感谢您打开该问题! CSS-in-JSS 是一个动态的领域,随着问题和解决方案的变化,我们过去所做的选择可能不再有效。

为什么过去不使用 styled-components?

在选择 JSS 之前,我们一直在比较可用的不同样式解决方案。

我们没有选择styled-components的原因如下:

  • 抽象的成本。 css-in-js-perf-tests是一个很好的资源,styled-components 在内部使用 glamor。
  • 公开 className 和 CSS 深度选择器功能允许高性能实现。 例如<Grid /> :#6010。
  • 不可能有服务器端渲染并发。 它依靠单例来收集样式,而 JSS 实例化一个新实例以在每个请求时收集样式。 蒸汽真的很有限。

实际上,当@nathanmarks开始致力于摆脱内联样式时,样式组件甚至都不是(存在的)。

对照表

支持全局 CSS

使用https://github.com/cssinjs/jss-global您可以编写类似

const styles = {
  '<strong i="35">@global</strong> body': {
    color: 'green'
  }
}

易于覆盖

这怎么不容易? Material-UI 方面我们有一个预定义的注入顺序表。 在用户端,他们可以使用aphrodisiac来实现很棒的 aphrodite override API。

没有包装组件

我们在 Material-UI 端没有任何包装器组件。 我们本来可以使用withStyles ,但出于性能原因我们不这样做。 我们向用户公开该高阶组件以抽象上下文实现。

主题化

我们在内部使用jss-theme-reactor 。 JSS 公开了一个低级 API,使之成为可能。

ReactNative 支持

这是一个很好的观点, react-with-styles API 非常有趣。 这是我们可以改进的地方!

未来

展望未来,我认为最有希望的途径是拥有一个允许切换样式实现的 API。 这会给我们带来两个好处:

  • Material-UI 与任何样式解决方案的耦合度较低
  • 使用styled-components / aphrodite/...的用户可以节省内部使用的 JSS开销

react-toolbox正在遵循该路径。 我唯一担心的是它增加的开销。 我的意思是,值得吗?

我将@kof@mxstbr添加到循环中。

@kybarg实际上,我不确定完全理解您的建议。
我们没有按照您的问题建议使用react-jss

当您说我们时,您是在谈论用户还是 Material-UI?

我的观点是:

  • styled-components是一个比 JSS 核心更高级别的库,您肯定可以在应用程序层中使用它。
  • 上面的对比表是关于 react-jss 的,不是 JSS 核心,是 Max 的主观意见。 这部分是不正确的,部分只是从我们从表格中看不到的某些特定角度来看。
  • 我们正在研究动态规则渲染以实现更有效的动态样式,jss-theme-reactor 现在已经完成了这项工作,它只是一个优化问题,这可能与 MUI 不太相关。
  • MUI 内部使用的内容应该完全不受最终用户的关注。 用户需要做的所有事情都应该是可能的,甚至不知道 MUI 在内部使用什么,或者至少不知道它或多或少的常规 cssinjs 主题语法。
  • 我们需要获取 MUI 目前不支持的用例并解决它们。 我总是很乐意帮助集成过程并在 gitter 上可用。
  • 无论如何,什么是 react-native 支持? 它不只是网络平台的一个子集吗? 如果是这样,它应该可以工作,否则让我知道 JSS 需要能够做什么来支持 react-native,这就是问题所在

该表确实非常主观,并且基于我自己的经验。 FWIW, styled-components适用于任何第三方组件库:

import { Button } from 'material-ui'

const MyButton = styled(Button)`
  // Only these styles will be overridden
  background: red;
`

只要组件在内部将className属性附加到某个 DOM 节点,它就可以工作:

const MaterialUIButton = (props) => {
  /* ... */
  // As long as props.className is attached, the above usage will work
  return <button className={`bla ${props.className}`} />
}

无论如何,什么是 react-native 支持? 它不只是网络平台的一个子集吗?

不,这不是那么容易 😉 添加对 JSS 的支持应该不难,因为您所要做的就是将样式对象传递给StyleSheet.create() 。 这需要styled-components方面的更多努力才能使 CSS 字符串正常工作。


我已经和@javivelasco谈了一段时间了,我喜欢他和react-toolbox一起去的地方。 他的实现令人惊叹,我很想看到所有第三方组件库都采用它。 给他打电话,这样他就可以在这里表达他的想法!


不可能有服务器端渲染并发。 它依靠单例来收集样式,而 JSS 实例化一个新实例以在每个请求时收集样式。 蒸汽真的很有限。

完全不相关,介意在这个问题上用你对 API 的想法发表评论吗? 我们还没有决定我们要做什么,所以非常感谢您的意见。

嗨,我在 gitter 中询问了这个问题。 只是为了获得其他人的意见,我也将其发布在这里:

我知道 material-ui _next_ 在自定义 jss 解决方案上投入了大量资金。
有没有人发现使用 jss 优于 styled-components 的任何重大优势?

虽然 jss 很好,因为它支持多种模式,如装饰器(注入样式)和插件,但我认为 styled-components 直接方法更简洁,因为不需要装饰器、自定义设置和插件,因为它不需要。

在 styled-comp 中,每个组件都已设置样式,因此无需传递样式。 然后你传递可以评估以产生不同风格的道具
没有设置(createJss)
没有插件(前缀)
没有 JSON DSL

有人必须锁定这个线程。

@rainice jss 没有装饰器,HOC 是 react-jss 的一个实现细节,这里没有使用。

为什么要锁定这个? 这是一个理智的讨论 IMO

因为这里基于最终用户的内容(不是 lib 维护者)非常肤浅,这是可以理解的,因为他们没有阅读他们使用的代码背后的一行代码。

由于样式解决方案的选择已经被详细讨论过,决策背后的理性被记录在案,并且针对下一个主要版本的开发工作正在进行中,这不是一个有用的问题,所以我将关闭它。

希望人们足够成熟,不会继续在已关闭的线程上发帖,但如果需要,我们可以锁定它。

我希望我们可以使用耦合较少的样式解决方案推进该线程!
但是,我认为目前我们的首要任务应该是完成组件的迁移/整体改进。

@mxstbr感谢样式组件

只要组件在内部将 className 属性附加到某个 DOM 节点,它就可以工作

mui:next发布时,这可能值得在您的使用指南中突出显示。 这条评论刚刚救了我。

IE10 的 Flex 样式不能与 jss 一起使用,但可以与 styled-components 一起使用,就像一个魅力

@yhaiovyi Material-UI 不支持 IE10。

供应商前缀 evtl。 jss 将很快修复,但这并不意味着如果 mui 从未在 IE10 上测试过,它将解决所有问题

无论如何,到目前为止,我还没有发现任何其他问题,然后是 IE10 的 css flex

看起来我们有 3 种方法(可能更容易,但并非一切都是鲜花)使用 Styled Components 覆盖 Material UI 样式。 这是我的要点

您还可以通过几行代码获得样式化组件 API: https: //material-ui-next.com/customization/css-in-js/#styled -components-api-15-lines-

您也可以使用styled-jss ,例如: https ://codesandbox.io/s/32mvjyjyxq

一般而言,JSS 的唯一缺点是代码编辑器中缺乏自动完成功能,就像这里所说的那样,但是好处是存在的,像在 styled-components 中那样将 css 解析为 js 有点过载

编辑:刚刚注意到上面提到的问题,很有趣

令人讨厌的是 Mui 的上下文和withStyles HOC 似乎不能很好地与核心 react-jss 和 styled-jss ThemeProvider https://codesandbox.io/s/32mvjyjyxq (我试着把Typography但这不起作用,编辑:nvm,仍在摆弄它)

我想知道以后(我猜是 v1 之后)是否不值得简化src/styles/withStyles和 MuiThemeProvider + JSSProvider 双层,并且有一些更简单的东西,比如 react-jss 和 styled-jss 有

完全为了它!

2018 年 3 月 13 日 13:55,“Cyril Auburtin” [email protected]写道:

烦人的是梅的上下文和 withStyles HOC 似乎没有发挥作用
与核心 react-jss 和 styled-jss ThemeProvider 配合得很好
https://codesandbox.io/s/32mvjyjyxq

我想知道以后(我猜是 v1 之后)是否不值得简化
src/styles/withStyles 和 MuiThemeProvider + JSSProvider 双层


您收到此消息是因为您订阅了此线程。
直接回复此邮件,在 GitHub 上查看
https://github.com/mui-org/material-ui/issues/6115#issuecomment-372655385 ,
或使线程静音
https://github.com/notifications/unsubscribe-auth/AADOWAbwLOnRoypx9ANCZnKyalZyD0M9ks5td8HNgaJpZM4L-GwD
.

像在 styled-components 中一样将 css 解析为 js 有点超载

就像将对象解析为 CSS 一样 :wink: 解析字符串的速度大致相同,老实说,这并不重要。 https://github.com/A-gambit/CSS-IN-JS-Benchmarks/blob/master/RESULT.md

解决方案 | 使用 CSS | 使用内联样式 | 挂载时间(毫秒)| 重新渲染时间(毫秒)
:--- | :--- | :--- | :--- | :---
...
样式组件| + | - | 182 | 146.84
样式组件解耦单元| + | - | 213.53 | 152.39
...
反应-jss | + | - | 198.97 | 297.74

@mxstbr在运行时用 js 编写的完整 css 解析器肯定是有代价的。 该基准并未衡量其成本。

在运行时用 js 编写的完整 css 解析器肯定是有代价的。

当然可以,但不仅仅是一个处理对象而不是字符串的完整 CSS 解析器。 除此之外,对实际 CSS 字符串进行操作的 CSS 解析器已经优化和探索了很长时间,而处理对象的解析器则更少。 :脸红:

我很好奇使用您的解析器将引导 CSS 作为对象与使用我们的解析器 stylis 的引导 CSS 进行基准测试,但我很确定差异充其量可以忽略不计。

我很好奇使用您的解析器将引导 CSS 作为对象与使用我们的解析器 stylis 的引导 CSS 进行基准测试,但我很确定差异充其量可以忽略不计。

是的,这将是一个合适的基准,我已经测试了一点,使用对象要快得多,比如快 10-20 倍。

但是话又说回来,这取决于您将包含哪些 jss 插件,我们有很多语法糖插件。

还有。 如果我们都搬到 ISTF 也没关系。

我已经测试了一下,使用对象要快得多,比如快 10-20 倍。

当然,但是 10 毫秒(这是 stylis 解析整个引导样式表所需的时间)与解析应用程序的整个 CSS 的 1 毫秒在总体方案中并不重要,你知道吗? 它不会制造或破坏任何人的应用程序。

无论如何,让我们停止在这个问题上用不必要的通知来烦人。

顺便提一句。 这个基准似乎更准确:http: //necolas.github.io/react-native-web/benchmarks/我不确定它是否在第一次解析后不依赖缓存。

@mxstbr虽然这个问题现在已经锁定,但一点健康的竞争对每个人都有好处。 随时回来 - 如果某个问题不适合讨论,您可以在 gitter chat 中找到我们。

这个问题已经一年多了。 各位,请不要再评论了。 我们可以将讨论转移到一个新的讨论。 自讨论开始以来发生了很多变化。

但是让我们尽量避免锁定问题。 我们需要尽可能多地收集反馈,以便做出更好的决定。

我认为锁定问题作为一种清楚地传达这一点的工具很好,没有人因此受到冒犯,也没有言论自由被剥夺。 在这种情况下,它真的很好。

我正在重新开放以收集更多反馈,我很好奇这是否是人们仍然感兴趣的东西:

Capture d’écran 2019-03-10 à 10 38 56

我们正在进行一项开发人员调查,我们将使用结果来更新我们的路线图。
我们对样式解决方案有以下要求:

  1. 捆绑大小。 我们希望人们能够使用单个组件,而无需支付 20 KB 的 gzip 压缩费用。 按排名:

    1. 情感是这个方向的最佳候选: 10kB gzipped 。 但是,很少有人使用它。 如果您查看下载统计数据, 80% 来自故事书

    2. styled-components 重约16 KB gzipped 。 他的优势来自使用它的人数。 也许 20% 的 React 用户?

    3. JSS 的 react 包装器重量约为 15 KB,压缩后。 如果您查看下载统计信息,很多使用来自 Material-UI。

  2. 性能。 我们希望人们不能定制我们的组件。 他们应该尽可能快。 我可以做的基准测试产生以下排名:

    1. 情感

    2. jss

    3. 样式化组件

  3. 自定义 API 。 自定义变体应该很容易,自定义嵌套元素应该很容易,添加新变体应该很容易。 现在,我们有一个classes API、一个theme.overrides API 和具有全局确定性类名的能力。
  4. 互操作性。 使用!important不是解决方案。
  5. RTL 支持

我只提到了样式组件、情感和 JSS,但它们是不同的选择:linaria、SASS 等。

我相信添加以下两个问题可能是值得的,因为它们可能有助于影响您何时有时间处理 Material-UI 使用的 CSS-in-JS 库的决定:

@o-alexandrov JSS 是否遵循与样式组件相同的策略? 我不明白你的意思。 你能澄清一下吗? 有什么不同? 它如何更好或值得?

@oliviertassinari
在上一条消息中,我对styled-components只字未提,只是我欢迎评估styled-components或任何其他 CSS-in-JS 库的使用的想法,这些库将具有以下完美平衡:

  • 开发经验(熟悉度和灵活性、进一步的贡献、开发者的实际使用情况等)
  • 表现

上述两个问题的链接仅讨论了当前使用 JSS 的负面影响。
我忘记了我在哪里看到以下内容,但我记得你提出了一个很好的观点,即为了能够做出决策,我们应该首先添加所有类型的基准,以便更容易评估决策。

就个人而言,我喜欢:

  • jss上的styled-components用于更广泛的社区采用。
    我相信社区的采用是 Material UI 应该考虑的关键方面。

@o-alexandrov 好的,在这种情况下,我将您的第一条评论标记为离题。 在 v5 中,我们希望将核心组件与样式解决方案隔离开来。 我希望我们可以提供裸版、JSS、情感、linaria 和 styled-components(作为默认)版本的组件。 这就是愿景。 现在实施将具有挑战性!

捆绑大小

styled-components已被证明在@5.0.0-beta.8中改进12.3kB

自定义 API

如果他们在包或外部包中引入https://github.com/styled-components/styled-components/pull/2625我相信 API 与 Mui 相同,因为它缺少有时我们可能需要的非样式组件 API ,尤其是在遗留系统中,但我认为您不会经常在 Mui 本身中需要该 API。

除此之外,

我不确定您想收集什么信息,因为根据我的个人经验, styled-components提供了我们需要的功能。

互操作性。

在这种情况下,这对你来说是什么? 据我所知,您可以像任何其他框架一样覆盖styled-components中的内容。

RTL 支持

这不是基于我们对组件的编码方式吗? styled-components或任何 CSS-in-JS 库为此提供了什么?

我的想法

速度

与其他解决方案相比,它曾经速度较慢,但​​贡献者的支持和惊人的努力使它变得比 JSS 更快。

尺寸

v5变得更加精简,就像我说的12.3kB16.2kB代表他们在这个主题上的努力。

熟悉度

人们对 API 很熟悉,因为它是最流行的,事实上,当我们使用styled(...) ... API 时,大多数人调用styled-components时指的是 API,而不是实际的包。

反应原生

对 Mui 来说,网络确实如此重要,但人们会因此而继续采用styled-components

核心团队

强大的核心团队,截至今天有 81 个问题和 14 个 PR 开放,对于使用该软件包的人数来说,这些都是不错的数字。

此外,像@mxstbr这样的人实际上使用spectrum中的包,所以他有使用该包的实际经验,这太棒了,这意味着他实际上知道使用该包的感觉。

工具包

好吧,再好不过了 https://www.styled-components.com/docs/tooling

对于 UI 作者

到今天为止, styled-components用于设计系统组件的采用率已经大大增加; Atlassian、GitHub、Orbit 等等。

这对梅有好处,因为你不会孤单,所以人们可能已经处理了你可能遇到的潜在情况,他们想出了如何处理它。

TL;博士

我支持styled-components

我喜欢 JSS,因为 CSS 的对象语法对我来说变得更容易了,有时我很懒,我什至只是将这些样式传递为style={{styles.dialogTitle}}内联样式,以后很容易重构

它可以以不同的方式使用,像 styled-components 这样的元素包装器https://material-ui.com/styles/basics/#styled -components-api

我真的很喜欢 styled-components,但我最近发现它引入了许多问题,使得 tree-shaking 始终如一地工作变得困难。 我知道 material-ui 团队刚刚做了很多工作来让 tree-shaking 完全为这个库工作,显然应该避免任何回归。

幸运的是,它的大部分摇树问题都通过使用babel-plugin-styled-components和设置pure: true得到解决(参见 https://www.styled-components.com/docs/tooling#dead-code-elimination )。 但仍有一些遗留问题。 例如:
https://github.com/styled-components/babel-plugin-styled-components/issues/245

另一个是在样式中使用外部辅助函数可能会破坏摇树(除非您将 terser/uglify 配置为忽略该特定函数),例如:

const Button = styled.button`
  font-size: ${externalHelperFunction()};
`

我认为应该可以解决所有这些问题以使 tree-shaking 正常工作,但它肯定会很棘手,并且不能像目前的情况那样以开箱即用的理想方式工作。 我实际上仍然认为切换到样式组件可能是一个好主意,但前提是这些问题可以解决。

@mbrowne我无法重现摇树和样式化组件的任何问题。 该问题不包括可重现的示例,因此我尝试使用

// components.js
import React from "react";
import styled from "styled-components/macro";

const Wrapper = styled.div`
  color: blue;
`;

export function MyComponent() {
  return <Wrapper>styled</Wrapper>;
}

MyComponent.displayName = "FancyName";

export function OtherComponent() {
  return "only";
}

// App.js
import React from 'react';
import { OtherComponent } from "./components";

/* code */

使用默认create-react-appMyComponent不会出现在生产包中。

这是只有rollup有问题的东西吗? 我希望有一个可重现的例子来理解这个问题。

@eps1lon我认为在样式化组件上设置静态属性时会出现问题,你可以试试吗?

const Wrapper = styled.div`
  color: blue;
`;

Wrapper.displayName = "FancyName";

export function MyComponent() {
  return <Wrapper>styled</Wrapper>;
}

export function OtherComponent() {
  return "only";
}

@mxstbr是的,尽管在这两种情况下都捆绑了样式组件。 虽然在MyComponent上设置 displayName 并没有在包中包含MyComponent ,但它仍然包含styled-components 。 它基本上删除了对MyComponent所做的任何事情,这就是为什么我最初认为它正确地摇树(只是搜索FancyName

但它仍然包括styled-components 。 即使您认为styled调用有副作用,我也会考虑

import React from "react";
import styled from "styled-components";

export function Wrapper() {
  // nonsense
  return styled.div``;
}

export function MyComponent() {
  return <Wrapper>styled</Wrapper>;
}

export function OtherComponent() {
  return "only";
}

导入{ OtherComponent }时没有副作用,但 styled-components 仍会出现在包中(即使没有宏)。 所以要么这是一些错误,要么我错过了一些大事。 甚至

// Wrapper.js
import React from "react";
import styled from "styled-components";

export default function Wrapper() {
  // side-effect free module even if styled has side-effects
  const Component = styled.div``;
  return <Component />;
}

// components.js
// commenting this out removes styled-components from the bundle
export { default as Wrapper } from "./Wrapper";

export function OtherComponent() {
  return "only";
}

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { OtherComponent } from "./components";
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<OtherComponent />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

将包括styled-components (https://github.com/eps1lon/styled-components-shake)。

可能是 react-scripts、webpack 或 styled-components 中的错误。 无论如何,如果没有重现,调试这些问题是非常困难的。

有道理,感谢您对此进行调查。

对于这个用例,我认为styled-components是否包含在包中并不重要(因为所有组件都应该使用它),而是您不使用的组件是否包含在内 - 它不听起来就是这样,所以这很好,对吧?

@mxstbr这可能是一个重要的问题,我们有几个没有样式的组件和通用组件(Modal、Popper、TextareaAutosize、useMediaQueries 等),假设有人使用

import { Modal } from '@material-ui/core';

与 SASS。 我们预计 gzipped 会增加 +5kB(截至今天),而不是 +20kB gzipped。

但是,假设我们将@material-ui/unstyled向前推,实际上,它可能没有任何区别,因为人们可以使用这个包。

@eps1lon抱歉,我认为静态属性的问题对其他人来说更容易重现,因为它似乎影响了我们所有的组件......事实证明有很多不同的事情会触发这个问题,但至少在一些简单的情况下它有效。

我在这里创建了一个可重现的演示:
https://github.com/mbrowne/CRA-error-template/tree/styled-components-tree-shaking
git clone --single-branch --branch styled-components-tree-shaking [email protected]:mbrowne/CRA-error-template.git

请注意只有 Component1 正确地摇树。

好消息是我认为这些问题都是可以解决的, @mxstbr在这里似乎很投入。 我将很快着手进行 PR,至少可以解决静态道具问题(我已经有一个使用我编写的单独 Babel 插件的工作 POC)。

我在 babel-plugin-styled-components 中打开了一个 PR,以解决 tree-shaking 问题。 如果这里有人想帮助测试它,我想@mxstbr会欢迎的(我当然也会):
https://github.com/styled-components/babel-plugin-styled-components/pull/248

大家好,请问这张票目前在哪里? 如果这确实是项目在 v5 中的发展方向,我将非常乐意参与并为 MUI 编写一些样式化的组件

我想除非我们想一口气做到这一点(我怀疑我们想要那个)。 我们应该先让 styled-components 从 jss 中读取主题,或者让 jss 从 styled 组件中读取主题。 目标应该是我们可以在每个组件的基础上迁移样式。

这可能应该发生在另一个分支上。 虽然我们不想一次性更改 master 上的所有内容,但我们可能应该通过一次更改来发布它(在 v5 中)。 否则这会变得更加混乱。

已请求删除评论。

嘿,伙计们,我也准备好做出贡献了……一个单独的分支对我们来说似乎是一件明智的事情……让我们这样做……!

@caprica-Six 感谢您的能量,但不需要新的分支。 我们应该能够逐步提供样式化的组件版本(+ jss 和情感)(在 v4 期间不稳定),同时将无样式的故事向前推进。 我有一个需要提交的 POC。 Styled-components (v5 beta) + 动态 props 比我们使用 JSS 和静态样式的要慢一些,但这仍然是可以接受的。

@oliviertassinari有没有我们可以参与其中的地方? 我有点等待维护人员指出我正确的方向,然后才开始做任何事情

为什么你不喜欢情感而不是样式组件? 原因似乎是“[情感]被少数人使用。如果您查看下载统计信息,80%来自故事书?”,但这是错误的。 它比 styled-components 更常用(比较),我不明白为什么 80% 的下载来自故事书。 它的增长速度显然比故事书快得多。

我问这个问题是因为我厌倦了使用样式组件(因为我遇到了多个问题)并寻找替代方案,然后我发现了 Emotion。 我对其进行了测试,发现与样式组件相比具有优势。

它更轻、更快并且具有更多功能:属性转发、开箱即用的 TypeScript(与样式组件相比得到完美支持)、开箱即用的 Next.js SSR(无需覆盖 _app. js 和 _document.js 文件,我第一次花了一个小时处理)

而且,它比 styled-components 更常用,并且具有明显的动力。

@lcswillems我认为我们也应该支持喜欢情绪的人。 但我不认为它应该是默认值。

  • “打火机”:不准确: https ://bundlephobia.com/[email protected] (12.2 kB) vs https://bundlephobia.com/result?p=@emotion/ styled + https://bundlephobia.com/result?p=@emotion/core + https://bundlephobia.com/result?p=emotion-theming(13.1 kB 不考虑共享依赖)
  • 《Next.js SSR out-of-the-box》:我觉得是个大问题,内联

谢谢你的回答和纠正我。

  • “打火机”:你说得对
  • “Next.js SSR out-of-the-box”:我现在明白了为什么他们可以让 SSR 开箱即用,以及为什么他们的做法不是很好。
  • “比样式组件更常用”:我不确定这是否可靠。 但我的消息来源可能也不可靠。
  • “更快”:我只看到过时的基准,所以不,我没有。

我面临的主要问题是道具转发/过滤: https ://github.com/styled-components/styled-components/issues/439。 它经常发生在我身上,每次手动进行过滤都很痛苦。

但是根据您的言论,情感似乎不是一个好的选择。

“打火机”:不准确: https ://bundlephobia.com/[email protected] (12.2 kB) vs https://bundlephobia.com/result?p=@emotion/样式+ https://bundlephobia.com/result?p=@emotion/core + https://bundlephobia.com/result?p=emotion-theming (13.1 kB 不带

如果使用 Emotion,您很可能不会使用@emotion/styled包来支持css props + @jsx pragma。 此外,您可能不需要emotion-theming包, ThemeContext已经包含在@emotion/core中。 所以它是 12.2KB 与 6.5KB。

内联

只是好奇:这些更新对于非 MUI 组件的@material-ui/styles库的用户意味着什么? 在我的公司,我们将它用作大型内部组件库的基础,故意选择它而不是styled-components ,我们对此非常满意。

只是想如果@material-ui/styles包有任何形式的弃用计划,我会提前检查,以便我可以相应地计划。

无论如何,感谢你们继续提供的所有伟大的东西!

@nickjohnson-dev 迁移到 react-jss 应该很简单。 这对您的组织有用吗?

@oliviertassinari我认为它可能会。 只要我们可以保持组件本身的公共 API 基本相同(基于classes prop 的本地覆盖,主题中可能的全局覆盖),我认为更改实现细节不是问题。

在 MUI 更加解耦之后,您是否预计会有任何官方文档用于从@material-ui/styles迁移到其他样式选项? 乍一看,我没有看到我们在@material-ui/styles react-jss中缺少的任何功能,但我不确定我是否遗漏了 MUI 包正在做的任何特别之处在幕后。

@nickjohnson-dev 我们会尽力而为。

如果我理解正确,将会出现以下问题。
我们有可重复使用的ComponentA 。 我们制作了使用ComponentA ComponentB

const ComponentA = ({className}) => (
  <div className={className}>
    <div className='inner' />
  </div>
);

const ComponentB = ({ className, classNameInner }) => (
  <div className={className}>
    <div className='inner'>
      <ComponentA className={classNameInner} />
    </div>
  </div>
)

const StyledComponentB = styled(ComponentB)`
     ???
`;

请注意ComponentAComponentB如何具有相同的元素className='inner' 。 我们将如何仅针对ComponentB上的.inner元素?

@oliviertassinari ,感谢您分享下一个版本的 Material UI 样式背后的所有想法。

还要感谢 Material UI。 现在我正在在它之上构建一个设计系统。

关于采用styled-components ,似乎这是一个既定的决定,并且已经开始朝着这个目标努力。

但是,我分享了@croraf@lcswillems的一些观察结果

当前 Material UI 样式的优点是classes属性。

这是一个简单的想法,对样式定制和可维护性有很大帮助,因为classes的输入是公共界面的一部分。 例如,如果我需要自定义某些东西并且我使用像& .Component-root这样的选择器,则没有任何东西可以保证Component将在各个版本中维护该 css 类。 通过<Component classes={{root: ....}} />至少我可以获得关于接口更改的类型检查错误(如果使用 TypeScript)。

作为组件作者,我可以决定记录公共(和受支持)的类,而让其他类不记录。

我用style-components大约 2 年。 是的,它很受欢迎,并且发展了很多。 但是,在 MUI 文档示例中,我看到了@croad提到的相同问题:使用后代选择器& .inner非常脆弱,因为您可以将样式传播到子组件(根据我自己的经验,我可以说这不是一个极端情况......它发生在我身上几次)。 两种可能的解决方案是:

  • 使用&.inner ,然后在任何地方使用${props.className}.inner 。 我这样写了很多次,写起来很痛苦。
  • 使用> .inner但它取决于组件结构。 在中间添加一些额外的div ,它就会中断。

确实,JSS 不流行。 我是因为 MUI 而了解它的。 但是在使用styled-components工作了这么长时间之后,我发现 MUI 样式的方法令人耳目一新并且更易于使用(一段时间后,随处可见 Styled HOC 增加了很多额外的工作,我开始讨厌那些HOCs ...至少这是我的个人经验)。 情绪或多或少与当前的方法相匹配。 在阅读了您的评论以及某些情况下有关 JSS 性能的一些问题之后,我正在评估将 Emotion 用于设计系统。

但是,我看到你对styled-components如此确信,我很乐意看到更多关于如何使用classes道具解决样式自定义的示例。 当前 MUI 文档中提供的那些共享我上面提到的问题。

还有其他方法可以将styled-components与 classes 属性一起使用吗? 你对此有什么想法?

JSS 足够好,使用起来非常方便。 有什么强烈的离开的理由吗?

就我个人而言,我认为 styled-component 是一种退步,说实话,JSS 是我开始使用这个库的主要原因。

@powerfulj为什么你更喜欢 JSS 而不是 Styled-components? 我必须在这两个和 styled-components 之间做出选择,这对我来说似乎更好。

@lcswillems
我喜欢它,因为我认为它不会引入新组件,而是您只需对属性进行操作。 如果您确实需要一个新的可重用组件,您可以使用 JSS 解决方案轻松创建它。

此外,从内联样式转换为 JSS 样式更快,这对我来说很方便,因为我通常在实现过程中使用内联样式,然后如果它变得更大并重用,则将其转换为 JSS。

不利的一面是,如果您有一些 CSS(例如来自浏览器 devtools)并且需要将其转换为 JSS,则必须花费更多时间来调整语法。 使用 styled-component 这会更快。

只是为了分享我对这个问题的发现。
我尝试按照#16947 的要求将一些演示迁移到样式化组件。 问题在于默认主题。 makeStyles接受可以传递 defaultTheme 的选项。 有makeStyles包装器将提供defaultTheme 。 然后useStyles钩子将检查ThemeProvider是否提供主题,如果没有,则注入defaultTheme

似乎样式组件中没有这样的功能。 在没有ThemeProvider defaultTheme 的情况下只能用.attrs方法注入。 我们可以创建类似于makeStyles包装器的东西

import styledWithoutDefault from 'styled-components';
import defaultTheme from './defaultTheme';

const styled = Component => {
  return styledWithoutDefault(Component).attrs({ theme: defaultTheme });
};

export default styled;

但是.attrs方法只会覆盖ThemeProvider提供的主题(如果有的话)。 我目前不知道如何解决这个问题。

另一个问题是makeStyles使用jss-plugin-default-unit预设,而样式组件似乎不是。 所以样式组件不添加pxspacing()函数的返回值。
最后一个问题的可能解决方案是使用 Styled-JSS 而不是 styled-components。

我很高兴在这里提出您的想法/建议。

@fyodore82 .attrs用作函数(请参阅https://www.styled-components.com/docs/api#attrs),因此可以这样做:

```js
.attrs(({ theme = defaultTheme, ...props }) => ({ ...props, theme }))
````

@croraf

我喜欢它,因为我认为它不会引入新组件,而是您只需对属性进行操作

我认为你错过了 Styled-components的一个非常好的东西: css道具。 它允许您将 CSS 添加到组件中,而无需创建新组件。

此外,从内联样式转换为 JSS 样式更快,这对我来说很方便,因为我通常在实现过程中使用内联样式,然后如果它变得更大并重用,则将其转换为 JSS。

使用 CSS 属性,请注意带有 CSS 属性的组件没有style属性,它已经转换为样式组件,因此具有class 。 如果 CSS 变得更大并被重用,您还可以创建一个新组件。

不利的一面是,如果您有一些 CSS(例如来自浏览器 devtools)并且需要将其转换为 JSS,则必须花费更多时间来调整语法。 使用 styled-component 这会更快。

我同意。 这是我没有使用它的主要原因。 网上写的大部分CSS都是用CSS写的,而不是JSS。 所以如果要使用StackOverflow的一些代码,需要先转换成JSS,非常痛苦。

其他让我使用 Styled-components 的附加论点:

  • 写 JSS 更痛苦:你必须加引号,你没有语法高亮(或者我找不到)。
  • 新手比较难理解。 每个人都知道 CSS,因此每个人都可以使用 Styled-components 轻松阅读代码,而 JSS 则不然(JSS 语法通常有点奇怪,特别是对于伪选择器和媒体查询)。
  • 代码的可读性要差得多。 为了说明这一点,我用 Styled-components 重写了这个Card 组件示例,以显示使用它们可以更加清晰。

JSS 版本:

import React from 'react';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import SkipNextIcon from '@material-ui/icons/SkipNext';

const useStyles = makeStyles(theme => ({
  card: {
    display: 'flex',
  },
  details: {
    display: 'flex',
    flexDirection: 'column',
  },
  content: {
    flex: '1 0 auto',
  },
  cover: {
    width: 151,
  },
  controls: {
    display: 'flex',
    alignItems: 'center',
    paddingLeft: theme.spacing(1),
    paddingBottom: theme.spacing(1),
  },
  playIcon: {
    height: 38,
    width: 38,
  },
}));

export default function MediaControlCard() {
  const classes = useStyles();
  const theme = useTheme();

  return (
    <Card className={classes.card}>
      <div className={classes.details}>
        <CardContent className={classes.content}>
          <Typography component="h5" variant="h5">
            Live From Space
          </Typography>
          <Typography variant="subtitle1" color="textSecondary">
            Mac Miller
          </Typography>
        </CardContent>
        <div className={classes.controls}>
          <IconButton aria-label="previous">
            {theme.direction === 'rtl' ? <SkipNextIcon /> : <SkipPreviousIcon />}
          </IconButton>
          <IconButton aria-label="play/pause">
            <PlayArrowIcon className={classes.playIcon} />
          </IconButton>
          <IconButton aria-label="next">
            {theme.direction === 'rtl' ? <SkipPreviousIcon /> : <SkipNextIcon />}
          </IconButton>
        </div>
      </div>
      <CardMedia
        className={classes.cover}
        image="/static/images/cards/live-from-space.jpg"
        title="Live from space album cover"
      />
    </Card>
  );
}

样式化组件版本:

import React from 'react';
import styled from 'styled-components';
import { useTheme } from '@material-ui/core';
import MuiCard from '@material-ui/core/Card';
import MuiCardContent from '@material-ui/core/CardContent';
import MuiCardMedia from '@material-ui/core/CardMedia';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
import MuiPlayArrowIcon from '@material-ui/icons/PlayArrow';
import SkipNextIcon from '@material-ui/icons/SkipNext';

export default function MediaControlCard() {
  const theme = useTheme();

  return (
    <Card>
      <Details>
        <CardContent>
          <Typography component="h5" variant="h5">
            Live From Space
          </Typography>
          <Typography variant="subtitle1" color="textSecondary">
            Mac Miller
          </Typography>
        </CardContent>
        <Controls>
          <IconButton aria-label="previous">
            {theme.direction === 'rtl' ? <SkipNextIcon /> : <SkipPreviousIcon />}
          </IconButton>
          <IconButton aria-label="play/pause">
            <PlayArrowIcon />
          </IconButton>
          <IconButton aria-label="next">
            {theme.direction === 'rtl' ? <SkipPreviousIcon /> : <SkipNextIcon />}
          </IconButton>
        </Controls>
      </Details>
      <CardMedia
        image="/static/images/cards/live-from-space.jpg"
        title="Live from space album cover"
      />
    </Card>
  );
}

const Card = styled(MuiCard)`
  display: flex;
`

const Details = styled.div`
  display: flex;
  flex-direction: column;
`

const CardContent = styled(MuiCardContent)`
  flex: 1 0 auto;
`

const CardMedia = styled(MuiCardMedia)`
  width: 151px;
`

const Controls = styled.div`
  display: flex;
  align-items: center;
  padding-left: ${props => props.theme.spacing(1)}px;
  padding-bottom: ${props => props.theme.spacing(1)}px;
`

const PlayArrowIcon = styled(MuiPlayArrowIcon)`
  height: 38px;
  width: 38px;
`

最后,我找不到使用 JSS 的任何优势。

css 属性非常好,基本解决了我提到的缺点。 (模仿形式样式组件:D)

关于这两个示例的比较,我觉得它的可读性不高,并且它使组件数量增加了一倍。

@lcswillems

不争论一个解决方案或另一个,只是拿起你的几点:

如果要使用StackOverflow中的一些代码,需要先转换成JSS,非常痛苦

有一个用于将 CSS 转换为 CSS-in-JS 的 VSCode 扩展,尽管它并不总是能完美运行。 无论如何,我不会称之为痛苦。

你没有语法高亮

我不太明白这个论点。 它只是一个 JS 对象,所以任何编辑器的语法高亮都有效:

image

(但也许您正在寻找更具体的东西?)

关于这两个示例的比较,我发现它的可读性并不高。 虽然缺少 className 属性可以说是更简洁,但从主 JSX 代码块中看不出组件是引用 MUI 原生组件,还是重新样式化的组件,而无需交叉引用styled()组件。 在更大的组件中,这些可能会被远远删除。

styled()调用(对我而言)比 JSS 对象可读性差(尽管我认为您已经习惯了它们)。

@powerfulj为什么你更喜欢 JSS 而不是 Styled-components? 我必须在这两个和 styled-components 之间做出选择,这对我来说似乎更好。

因为我自己是一名 Typescript 开发人员,我更喜欢在 Typescript 对象中构建所有内容。 特别是我讨厌琴弦。

虽然我们需要将 CSS 代码转换为 JSS 代码,但我还是更喜欢阅读 JSS 代码,因为它的结构看起来像传统的 CSS(面向类),我会花更多时间阅读样式化的组件代码,因为它更长并且可以在这里和那里。

我认为人们声称这种变化只是因为他们过去在 Styled-component 方面有经验。 它给我的感觉是“我们为什么不选择一个我们熟悉但没有明显好处的库呢?”。

从我的角度来看,就像 JSS 很方便,我们可以使用所有的 Javascript 方式来组织对象,比如

{
...共享JSS1,
...共享JSS2,
任何
}

此外,我们还拥有与类型集成的无缝动态主题,并且我们从 className 和 css 类型中获得了所有类型提示。

对于新开发人员,尤其是 Typescript 开发人员,他们只会喜欢 JSS。

仅供参考,如果您不总是希望所有内容都使用单独的组件,则可以在样式组件中进行一些嵌套。 通常不鼓励这样做,因为根据 styled-components 哲学,使用具有有意义名称的单独组件被认为更干净且更具可读性,但文档说如果“谨慎使用”就可以了。 当然,对于那些不认同这种理念的人,他们可以自由地做更多的嵌套。 作为我所说的嵌套的一个例子:

const Wrapper = styled.div`
  display: block;

  .inner {
    flex: 1;
  }
`

...
  <Wrapper>
    <div class="inner">...</div>
  </Wrapper>

有关更多详细信息,请参阅https://www.styled-components.com/docs/faqs#can -i-nest-rules。

关于编码风格偏好的讨论可以永远持续下去。

使用styled-components一段时间后,我更喜欢 JSS 方法,因为:

  • 当样式变长时,我通常将它们移动到单独的文件中。
    我也用styled-components做到了这一点,我发现useStyles / makeStyles更容易编写、阅读和维护。 例如。 import useStyles from './MyComp.styles' vs import {XStyled, YStyled,...} from './MyComp.styles' ... 在 TS 中保持这些...Styled变体很烦人。
  • 我倾向于以渐进的方式做事:首先我从一个使用 div 和类的草稿开始,然后我将它们重构为组件。 使用styled-components时,我通过使用内部类(如 @mbrowne 的示例)来做到这一点,但它需要更多的重构工作。 我发现useStyles方法更适合使用该工作流程。
  • 模板文字可以很好地粘贴 CSS 代码,但是当您必须使用主题/属性变量时就很糟糕了。 粘贴代码问题很容易通过插件解决,但在模板文字中使用变量和函数进行编辑就没有那么多了。

但这些是我个人的喜好,你的可能会有所不同。

我最大的悬而未决的问题是关于classes使用的变化。

使用className和内部类的示例有问题(请参阅我之前的评论)。 $#$ styled-components css属性不是解决这些问题的选项。 与 Emotion 中的css函数不同, css属性依赖于附加到组件(这意味着您不能在useStyle/makeStyles/classes代码样式中使用它)。

将样式附加到组件不是一个次要的设计决定。 对我来说,这是 JSS 的好与坏。 样式化的组件和 Emotion 依赖 Babel 插件并与 React 交互来处理 SSR 的缓存和类名生成。 JSS 的优点是它不需要任何 Babel 插件。 不好的部分是 JSS 中的 SSR 需要更多的工作,而且我已经看到该领域报告的错误。

回到 MUI,我的印象是采用样式组件意味着使用className和内部类作为自定义样式的唯一方法。 跨框架的样式变得更加一致:您可以使用styledcss属性,只要组件使用className就可以了。

但对我来说,删除classes道具是退后一步。 该道具有助于记录和键入检查样式自定义。 也许可以找到一个中间立场,比如使用样式组件但保持对classes的支持(不需要内部类 hack)。 在这种情况下,我在 styled-components API 中找不到任何有用的东西。 这就是为什么最好评估一下 JSS 的技术问题。 因为如果流行度是主要问题,那么 Emotion 也变得流行起来(参见 https://2019.stateofcss.com/technologies/css-in-js/#tools-section-overview),它可能很容易作为一种重写makeStyles

@dfernandez-asapp 你只回复了这个 fwiw 的一小部分就提出了一些很好的观点 @styled-components 确实支持使用类似于 jss 的对象而不是字符串https://www.styled-components.com/docs/advanced#风格对象

尽管样式组件删除了一流的打字稿支持并总体上同意您的看法,但在您描述的其他方式上似乎倒退了一步,这非常令人失望

仅供参考,如果您不总是希望所有内容都使用单独的组件,则可以在样式组件中进行一些嵌套。 通常不鼓励这样做,因为根据 styled-components 哲学,使用具有有意义名称的单独组件被认为更干净且更具可读性,但文档说如果“谨慎使用”就可以了。 当然,对于那些不认同这种理念的人,他们可以自由地做更多的嵌套。 作为我所说的嵌套的一个例子:

const Wrapper = styled.div`
  display: block;

  .inner {
    flex: 1;
  }
`

...
  <Wrapper>
    <div class="inner">...</div>
  </Wrapper>

有关更多详细信息,请参阅https://www.styled-components.com/docs/faqs#can -i-nest-rules。

对此有任何类型的支持吗? 或者我们必须在任何地方放置字符串?

我不明白为什么对样式化组件有这么多的炒作。 老实说,感觉就像退了一步。 带有 TypeScript 的 JSS 的类型化 CSS 属性更方便且更易于维护,另外还有作为 JS 一部分的语法检查 - 任何现代/配置的编辑器都会告诉你是否打错了字,甚至可以帮助你自动完成,如果需要的话。

编辑:它是打字的,见下面南爪的回复。

@martinjlowm对我来说好像有打字?

image

请参阅: https: //styled-components.com/docs/advanced#style -objects

你说你不理解炒作......但我也没有得到它得到的所有仇恨。 🤷‍♂

情感和样式组件是对 CSS 样式对象 IMO 的巨大改进

@martinjlowm对我来说好像有打字?

...

请参阅: https: //styled-components.com/docs/advanced#style -objects

你说你不理解炒作......但我也没有得到它得到的所有仇恨。 🤷‍♂

情感和样式组件是对 CSS 样式对象 IMO 的巨大改进

我懂了! 我不知道它支持这样的对象。 我的担心与模板字符串中的 CSS 有关——但如果对象是一个选项,那么我没有什么反对的!

显然,JSS 也不完美,我知道 - 可重用的服务器生成的工作表将是一个杀手级功能 - 样式组件是否以某种方式支持它? 有人知道吗?

现在,不得不删除服务器生成的样式表并强制客户端重新渲染所有样式感觉很愚蠢:(

@martinjlowm对我来说好像有打字?
...
请参阅: https: //styled-components.com/docs/advanced#style -objects
你说你不理解炒作......但我也没有得到它得到的所有仇恨。 🤷‍♂
情感和样式组件是对 CSS 样式对象 IMO 的巨大改进

我懂了! 我不知道它支持这样的对象。 我的担心与模板字符串中的 CSS 有关——但如果对象是一个选项,那么我没有什么反对的!

显然,JSS 也不完美,我知道 - 可重用的服务器生成的工作表将是一个杀手级功能 - 样式组件是否以某种方式支持它? 有人知道吗?

现在,不得不删除服务器生成的样式表并强制客户端重新渲染所有样式感觉很愚蠢:(

我还想澄清标记的模板文字也可以输入。 TypeScript 会正确地将它们标记为无效,并且语言服务将提供自动完成建议等。

image

@南爪

情感和样式组件是对 CSS 样式对象 IMO 的巨大改进

我仍然很困惑为什么任何 React 开发人员都会参与其中。 如果您想将 CSS 放入模板字符串中,为什么不直接使用 Angular 并将 HTML 放入模板字符串中呢? React 的优势在于 JSX 元素实际上只是 JS 对象,您可以检查和转换它们,JSS 也是如此。

推动 CSS 在 JS 运动中的全部因素是 JS 在做动态事情方面远远优于 CSS,而 JS 对象的力量是其中不小的一部分。

styled-components支持对象的事实有点像红鲱鱼:

  • 它支持它们,但出于某种原因说“当您有现有的样式对象并希望逐渐转向样式化组件时,这特别有用。” 他们显然没有看到能够操纵对象的价值,而且听起来样式对象在他们的 API 中总是被视为二等公民。
  • 文档没有明确说明它是否支持像 JSS 这样的真实世界 CSS 选择器:
{
  color: 'black',
  '&$error': {
    color: 'red'
  }
}

甚至 Emotion 也对风格对象的价值给予了应有的尊重,并将它们视为更多的一等公民:

用对象书写风格是一种直接内置于情感核心的强大模式。

@lcswillems ,您低估了始终创建所有这些小 HOC 的麻烦(事实上大多数自动导入系统都不够聪明,无法知道您是否要将@material-ui/core/Card导入为CardMuiCard (如果您仍在手动编写导入语句,那么您将严重浪费您的时间))

const Card = styled(MuiCard)`
  display: flex;
`

const Details = styled.div`
  display: flex;
  flex-direction: column;
`

const CardContent = styled(MuiCardContent)`
  flex: 1 0 auto;
`

const CardMedia = styled(MuiCardMedia)`
  width: 151px;
`

这种事情会导致可怕的决策疲劳,因为您必须不断地决定如何命名每个包装器和包装的组件。

这就是@dfernandez-asapp 所说的:

(一段时间后,随处可见 Styled HOC 会增加很多额外的工作,我开始讨厌那些 HOC ......至少这是我的个人经历)

HOC几乎需要死。 这是一个过时的模式。 例如, react-redux推出了useSelector钩子,它比connect HOC 方便 100 倍,Apollo 从 HOC 转移到钩子, useStyles也是如此这个库中的withStyles更方便。

将复制粘贴的 CSS 转换为 JSS 的麻烦是一个更容易解决的问题,如果有兴趣,我什至会制作一个 VSCode 扩展来自动化它或网站。

如果有兴趣,我什至会做一个 VSCode 扩展来自动化它

@jedwards1211paulmolluzzo.convert-css-in-js ,但是如果您可以针对 JSS 改进它,我相信这会受到欢迎。

是的,看起来我肯定可以改进它,它只转换 CSS 属性,而不是规则和选择器。

@jedwards1211我读了你所说的,并从这一切中退后了一会儿——这让我想起了那些争论使用制表符而不是空格的人的评论。 现实情况是,只要它最终产生有用的产品,它就不会真正改变你使用的东西。

在 Twitter 或 Reddit 上留下您的意见/热门观点,我们可以在那里讨论它们 - 但我们不要继续用模板字符串与 CSS 对象的无意义的火焰战争来破坏这个问题......我想我们都同意我们更好比那个😄

感谢您指出不值得改变 MUI 的现状? 😉

我主要担心的是我的 webpack 包是否因混合了样式组件代码和 JSS 代码而变得臃肿,因为我们的应用程序中有太多现有的 JSS 无法抽出并替换为其他内容,和/或因为我想坚持使用无论如何,我们的样式都是 JSS。

公平地说,我不关心制表符与空格,但如果我必须为我制作的每个组件编写半打 HOC,我将不会享受我的工作。 现有的所有工具都具有生产有用产品的能力; 如果任何东西在所有情况下都非常方便使用,那么生态系统就不会发生持续变化,我们也不会进行这些辩论。 因此,当您考虑它时,它确实会有所作为。

@jedwards1211即使您被迫使用样式化组件,您也可以使用v4中引入的另一种css prop语法 - 至少,这样您就不必担心为样式化组件(MuiCard、StyledCard 等)提供前缀。

import { Avatar } from '@material-ui/core';

// CSS is separate from the markup 👍
const avatarStyle = css`
  width: 32px;
  height: 32px;
  border-radius: 50%
`;

// No wrappers, prefixes in the markup (such as <MuiAvatar>, <StyledAvatar> etc.) 👍
function SomeComponent(props) {
  return <div> ... <Avatar css={avatarStyle} /> ... </div>
}

@jedwards1211如果您使用样式化组件,您的示例也可以简化为以下内容

const Card = styled(MuiCard)`
  display: flex;

  ${MuiCardContent} {
    flex: 1 0 auto;
  }

  ${MuiCardMedia} {
    width: 151px;
  }
`

const Details = styled.div`
  display: flex;
  flex-direction: column;
`

@koistya css道具有点酷,但重要的警告是它是使用 Babel 插件实现的,所以它并不适合所有人,尤其是使用 tsc 编译其 tsx 文件的人。 另外我认为它会导致 TypeScript 或至少 Flow 抱怨该组件没有css道具。

我想我主要是对这可能会在我的应用程序中造成的潜在破坏感到不满。 @oliviertassinari 前几天提到他正在考虑将styled-components设为 MUI v5 中的默认值。 希望它是可选的,仍然可以使用 JSS,但我们会看看他们是否可以实现这一点,你知道的。 这让我感到震惊——真的对整个用户群的偏好进行了彻底的公投吗? 如果有的话,我会期待 Emotion,因为它现在更受欢迎。

另外我认为它会导致 TypeScript 或至少 Flow 抱怨该组件没有 css prop。

可以配置。

但是,是否真的对整个用户群的偏好进行了彻底的公投?

这是不可能的。 我们只能假设参与 GitHub 的人是“我们的”用户。 这个问题是我们遇到的最受好评的问题。

如果有的话,我会期待 Emotion,因为它现在更受欢迎。

你是如何衡量受欢迎程度的?

⚠️ 开发人员对情感的选择明显少于样式组件(我记得是/6)。 如果您考虑 npm 上的下载,请删除 storybook 和 react-select 下载计数(它很大)。

@eps1lon这是我正在查看的内容: https ://2019.stateofcss.com/technologies/css-in-js/

不过我错了,不幸的是,我只记得看似上升的趋势,尽管这不是随时间推移的流行图表(非常有问题的图表设计):
image

可配置

实际上有没有办法让 TypeScript 假设所有 JSX 元素都支持css道具? 我不知道如何配置 Flow 来做到这一点。

编辑:幸运的是我找到了 TypeScript 的方法,不确定是否有 Flow 的方法。

这个问题是我们遇到的最受好评的问题。

我知道了。 叹

FWIW, styled-components的主要贡献者之一似乎对类型系统持不友好的态度:

https://github.com/styled-components/styled-components/issues/3012#issuecomment -583878486

如果他们似乎关心 TS/Flow 用户的开发体验,我会对迁移到样式化组件的想法感到更加放心......

@jedwards1211有一个css的 Babel 宏,如果有帮助的话。 特别是来自 css/scss/less 我不认为每个人都喜欢转向“风格化”的方式。

目标是什么? 性能呢? 例如,一些系统支持原子 css。 来自 Tailwinds,它让事情变得更干净,也许更快。

@hc-codersatlas 你可以在packages/material-ui-benchmark中找到一些基准。

@koistya如果我没看错的话,情绪看起来比其他人快得多。

@oliviertassinari大多数开发人员是否真的“做出”了这个选择? 根据您提到的 react-select 和 storybook,大多数开发人员可能会使用与 UI 组件捆绑在一起的任何东西,而 material-ui 是一个很大的 1。除非捆绑的东西很糟糕,否则 1 不会增加他们的捆绑包大小并花费在 UI 框架已经使用的基础上,使用不同的系统付出更多的努力。

这些UI框架大部分来自大部队,即少数人实际上正在做出这种“选择”。

例如,扣眼使用样式组件,许多公司在 1 点都在/正在使用。

在那张纸条上,npm 下载是什么意思? 企业使用可能意味着防火墙和内部 npm 缓存,这会扭曲这些指标。

如果要进行更改,请根据技术优势而不是受欢迎程度更改为最佳 1。 我预测,如果 material-ui 使用任何库,它将成为流行的 1,因为 mui 本身就是最流行的 ui 框架之一。

image

@South-Paw 您提议的简化不起作用,您不能在示例中使用${MuiCardContent}因为MuiCardContent不是样式组件。

https://styled-components.com/docs/advanced#referring -to-other-components

基本上没有办法避免所有单独的 HoC 包装器。 尽管在考虑了一段时间后,我意识到这与使用 JSS 所做的键入/命名决定的数量基本相同。

@mbrookes @oliviertassinari如何处理条件样式和内部组件样式?
例如,以下基于styled-components的等价物是什么?

// conditional class name
<MenuItem classes={{selected: classes.selectedItem}}>...</MenuItem>

// inner component class name
<Dialog classes={{paper: classes.dialogPaper}}>...</Dialog>

对于切换到styled-components的想法,我已经冷静下来,但我想确保有一个可靠的计划来处理这些用例,因为我认为 API 必须非常不同或依赖关于 BEM 样式类名称。

@jedwards1211啊我的错。 我的印象是,这个例子是如果它们样式化的组件 - 但如果它们不是,那确实是行不通的👍

@jedwards1211 clsx是我过去看到的与样式化组件配对的条件类 - 这就是你的意思吗?

我目前正在做的项目根据需要使用包装 MUI 组件的样式组件,因此我没有使用任何 MUI 条件样式

@South-Paw (或classnames )可能是解决方案的内部细节,但我的意思是因为styled-components包装器只注入一个className AFAICT,所以不会这并不是将多个覆盖类名称传递到组件中的便捷方式。 相反,我们可能不得不做类似<Dialog Paper={StyledPaper}>...</Dialog>的事情,我什至不确定所选的MenuItem类示例是什么。

@jedwards1211你有时间做一个简单的例子,这样我就可以更好地理解你描述的用例是什么以及你觉得问题出在哪里? 我希望能够尝试提供解决方案的帮助,但我只是不明白这适用于什么😄

是的,我今晚没时间,但明天我会的。
此外,我还在jss-codemorphs上进行了工作,最终计划制作一个 VSCode 扩展,用于将粘贴的 CSS 转换为 JSS。

从来不喜欢样式化的组件语法或维护包的方式,不喜欢这个提议。 我最喜欢 Material ui 的一件事是当前的样式解决方案。

有趣的是,我读到 Facebook 可能也在开源 CSS-in-JS 解决方案。 当它出来时,看看它也是有价值的。

关于手头的实际话题。 由于 Typescript 的体验不是很好,我不喜欢 styled-components。 这些类型往往弊大于利。 缓慢的编译时间,疯狂的界面(试图理解样式组件如何通过界面工作是一场噩梦,因为所有嵌套的Pick魔法)。 只要 styled-components 有这种类型的 DX,material-ui 就会觉得采用这种 DX 是一种倒退。

有趣的是,我读到 Facebook 可能也在开源 CSS-in-JS 解决方案。

@venikx它发生的可能性有多大? 我最后一次听说可能暗示它的内容是在https://reactpodcast.simplecast.fm/75中,这似乎是一个 5 年的目标。

哇塞!真的么? 我不知道他们已经给出了“时间表”。 出于某种原因,我认为它会在并发模式下同时出现。 太糟糕了。

话虽如此,我关于样式化组件的观点仍然成立。 我更喜欢使用纯 Material-ui 处理样式的方式而不是使用样式化组件。 styled-components 的类型似乎是用于编译器的,而不是用于文档的。

另一件烦人的事情(但这可能又是个人喜好)是您如何处理将样式动态应用于组件的方式。 我非常喜欢添加或删除类名而不是将该逻辑嵌入到样式组件中。

Material-ui api 目前真的很干净,恕我直言。

由于 Typescript 的体验不是很好,我不喜欢 styled-components。

到目前为止,我已经在至少 4 个大型项目中一起使用了 styled-components 和 Typescript,并且这些类型没有任何问题 - 在组件库中做事时它们可能有点毛茸茸,但那是在 MUI 端- 不是在消费者端。

编译时间慢

在我从事的任何使用它们的项目中,我都没有经历过这种情况——你有什么例子说明你的意思吗?

疯狂的界面(由于所有嵌套的 Pick 魔法,试图了解样式化组件如何通过界面工作是一场噩梦)

如果您认为可以以某种方式改进它们,您也可以考虑为@types项目做出贡献 - 我相信每个人都会欣赏那里的任何工作,如果它比现在的改进更好!

我非常喜欢添加或删除类名而不是将该逻辑嵌入到样式组件中。

没有什么能阻止您使用带有样式组件的类:

const Box = styled.div`
  height: 160px
  width: 160px;
  background-color: black;

  .red {
    background-color: red;
  }
`;

// simple usage
<Box className="red" />

// get more complex with conditionals and using something like clsx (https://www.npmjs.com/package/clsx)
const isRed = true;
<Box className={clsx({ red: isRed })} />

值得注意的是,尽管有一些评论声称并非如此,但有 150 👍 和 27 🎉 关于父问题,只有 18 👎 和 9 😕。 似乎有少数人不喜欢这个讨论,而大多数人认为这是一个积极的步骤🤷‍♂

@South-Paw 投票的问题是唯一的选择是:JSS vs styled-components。 声音部分是关于不喜欢样式化的组件,而不是他们喜欢 JSS。 也许如果投票

归根结底,任何东西都比 JSS 更好。 它是旧的。 它又慢又笨重(捆绑大小),应该继续前进。 所以投票根本不支持你的结论。

你们都可以转移到 Spectrum 聊天或其他不会让这个问题充满关于人们互相争斗看谁赢得争论的噪音吗?

我正在关注核心团队关于这个话题的讨论。

我觉得你低估了核心团队的判断力,个人觉得你应该停止在这个话题上争论,多信任核心团队; 最终,由核心团队决定 Material UI 的方向。

如果你真的对它有强烈的意见,Material UI 是令人惊讶的 MIT 许可,分叉它,并继续你的愿景,我鼓励你这样做,也许我们将来会从多样化的环境中学习。

但是,我求求你,让核心团队做好他们的工作,相信他们,因为他们是真正能干的人,拥有惊人的技能。

这里有一些美丽的东西值得一看

image

归根结底,任何东西都比 JSS 更好。 它是旧的。

@hc-codersatlas 旧 == 成熟——你能详细说明为什么这是一个问题吗?

好的似乎是一个热门问题,但有人可以确认这个简单的信息:目前是否可以在当前的 Mui 版本(4 或 5)中使用类似styled-components的语法,带有看起来像 CSS 的标记模板文字?
对于这个问题,我找不到任何明确的是或否的答案。 我并不真正关心底层技术,只关心开发人员的便利性。 在某些情况下,从 InVision 复制粘贴 CSS 基本上非常有用。

这个问题是关于 Material-UI 中使用的样式解决方案,您的问题似乎是关于您如何设置应用程序的样式/重新设置组件的样式,您可以使用任何解决方案:

https://material-ui.com/guides/interoperability/

JSS 对作为插件的模板文字有基本的支持。

我刚刚完成了一个非常全面的 CSS 到 JSS 转换器:

希望能消除将 CSS 复制和粘贴到 JSS 样式中的麻烦。

@jedwards1211看到这个
https://css2js.dotenv.dev/

@nainardev我注意到其他实用程序非常有限,它们转换 CSS 属性,但不转换选择器、嵌套选择器、动画关键帧、媒体查询等。因此,我使我的工具非常全面,它可以转换希望你扔给它的任何成熟的CSS。

可能在某个地方错过了这个答案,但无论如何都想提出它。 我们正在迁移到 Material UI 组件以及评估我们的样式解决方案( less vs makeStyles vs styled-components ),我们的大部分样式都是通过 less文件和大多数新的 MUI 代码都在使用makeStyles ,我想澄清一下,因为这将是 v5 的一部分,我们可以做些什么来减少围绕样式的技术债务?

  1. makeStyles会出现在 v5 中吗? 它如何与styled-components和主题一起使用? 例如,使用styled-components会怎样:
const useStyles = makeStyles((theme) => ({
  paper: {
    padding: theme.spacing(2),
    textAlign: 'center',
    color: theme.palette.text.secondary,
  },
}));
  1. (v4) 有没有比这更好的方法来检索样式模板字符串中的theme对象,所以我可以多次使用它?
const StyledContainer = styled.div`
  color: ${({ theme }) => theme.palette.primary.main};
  padding: ${({ theme }) => theme.spacing(1)};
  background-color: ${({ theme }) => theme.palette.background.paper};
`;
  1. 假设在 v5 中存在makeStyles ,如果我们同时使用styled-components主题提供程序和 Material UI 主题提供程序来处理大型代码库,我们是否应该期待任何性能损失?

喜欢使用 Material UI,感谢所有的辛勤工作!

@egilsster

  1. 是的,无论是从@material-ui/styles 还是 react-jss,都会看到。
  2. https://material-ui.com/guides/interoperability/#theme ,
const StyledContainer = styled.div`
  ${({ theme }) => `
  color: ${theme.palette.primary.main};
  padding: ${theme.spacing(1)};
  background-color: ${theme.palette.background.paper};
  `}
`;
  1. 主要问题是 1. 配置开销,一次成本,2. 加载两个 CSS-in-JS 运行时,其 gzip 开销约为 15 kB,成本类似,包括 Sentry: https ://bundlephobia.com

感谢您的快速回复,非常感谢。

  1. 是 material-ui.com/guides/interoperability/#theme

这很酷。 一些围绕工具的工作可能会遵循这一点,我正在迁移的项目没有使用 TS,但 VSCode/语言服务器似乎不知道在这种情况下theme是什么,我失去styled-components语法高亮也是如此。

再次感谢,将继续关注这一发展。

@oliviertassinari如果迁移到样式组件,这是否意味着我们不能再依赖像<ListItem classes={{ selected: myCustomClassName}}>这样的 CSS API 存在?

@jedwards1211 classes API 将保留。

好的。 我有点困惑 MUI 如何在内部使用 styled-components,因为 styled-components 只能将单个类应用于根元素。

const MyRoot = styled('div')`
  // some nice styles
`;

const MyAwesomeChild = styled('div')`
  // some nice styles
`;

export function AwesomeRoot(props) {
  return (
    <MyRoot className={props.classes?.root}>
      <MyAwesomeChild className={props.classes?.child}/>
      {props.children}
    </MyRoot>
  );
}

这有意义@jedwards1211吗?

@yordis我知道这看起来很简单,但是您将如何重构复合选择器,例如https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Button/Button.js #L75

我真的想不出用styled-components保留这种现有行为的方法,因此它可能会导致比人们预期的更多的破坏性变化。

  outlined: {
    '&$disabled': {
      border: `1px solid ${theme.palette.action.disabledBackground}`,
    },
  },

在某些情况下,现有代码和人们的自定义覆盖也可能取决于 CSS 特异性。

也许这个? 我不确定是否会遵循,因为这对我来说很基础,我可能缺少一些上下文和/或信息。

const MyOutlinedComponent = styled('div')`
  ${props.disabled && `
      border: `1px solid ${({ theme }) => theme.palette.action.disabledBackground}`,
  `}
`;

<MyOutlinedComponent disabled/>

@yordis可能。 正如我所说,尽管人们可能没有考虑这会给用户带来多少重大变化,但我认为该示例不会阻止重大变化。

你介意分享真实的例子,以及真正潜在的重大变化吗?

当您不分享强有力的案例时,很难跟随您。 根据您的留言,我认为您并没有完全理解这个话题,或者我可能做出了错误的判断。 请帮助我理解,我可能是错误的。

@oliviertassinari将在 v5 中不修改主题覆盖仍然有效吗? 为了使下面的覆盖示例正常工作,除了styled-components生成的根类名之外,MUI 似乎仍然必须应用 JSS 生成的类名。

const theme = createMuiTheme({
  overrides: {
    MuiButton: {
      root: {
        '&$disabled': {
          color: myCustomColor,
        },
      },
    },
  },
});

@yordis 仔细考虑之后,我意识到通过classes prop 传递的样式的复合选择器仍然可以正常工作,幸运的是。 虽然不确定主题覆盖样式。

我很高兴在 MUI 上使用这两个样式组件以及使用 style={object} 设置样式的普通 MUI。

拿一个包含 50 张卡片的结果列表页面,每张卡片都有媒体轮播、信息、点击处理程序、按钮等。

使用样式化的组件几乎增加了半秒的渲染时间; 与const useStyles = makeStyles或 style={object} 相比。

我将不得不接受这个路线图规划的结果; 但是,如果它不能被其他完全自上而下的东西覆盖,它肯定会在我们的 UI 采用计划中出现问题。

@Icehunter你能把你的结果和示例项目发布到网上供人们查看吗?

@Icehunter你能把你的结果和示例项目发布到网上供人们查看吗?

示例项目会很困难,因为它会包含专有代码。 我将很快发布渲染图像和性能选项卡的计时结果部分。

拿一个包含 50 张卡片的结果列表页面,每张卡片都有媒体轮播、信息、点击处理程序、按钮等。

@Icehunter您是否正在向这些样式发送任何道具? 无论是 50 张卡还是 500 张卡,生成的类别数量都应该相同。 听起来您的特定示例包含无法共享的专有代码,但是您是否可以使用可以共享的代码重现此问题?

styled() / styled.div API 增加了渲染 _every_ 元素的开销,因此即使缓存了类名,它也会变慢。 使用makeStyles ,您可以一次附加一组样式,然后手动应用类名,这通常要快得多。

我整理了一个CodeSandbox 示例来说明依赖样式组件styled的解决方案可能比 MUI makeStyles慢 3-4 倍:
image

styled API 很方便,但我赞同@Icehunter的观点,即在列表/表格中大量使用它可能会成为性能问题。 很高兴有makeStyles作为备份。

@schnerd感谢您将这些示例放在一起,它很好地说明了这一问题。 就像旁注一样,认为在帖子前加上“不难看出……”可能会显得居高临下,并没有真正添加到其他出色的示例中

@tuxracer道歉 - 更新。

@Icehunter我不明白你的意思,你使用了SC或JSS的常用样式?

@Icehunter我不明白你的意思,你使用了SC或JSS的常用样式?

实际上两者都是。 我们最终选择了 makeStyles,但无论是使用还是使用 styled={object} 都会得到相同的性能结果。

我们正在迁移过程中,以在整个组件库和主站点中获得更好的性能。

堆栈明智的是,它是用 nextjs 编写的。

为了清楚起见(编辑):

我按预期使用了 SC,包装了 mui 组件。 结果很慢。

然后我使用来自共享文件设置和本地(模拟级联)的 makeStyles 和/或 style={object} 使用 mui 组件。 快得多。

我根本不想阻止这个想法。 但如果它是默认的; 那么应该有一种方法可以覆盖全局自上而下的默认选择并注入您自己的。

也许这个? 我不确定是否会遵循,因为这对我来说很基础,我可能缺少一些上下文和/或信息。

const MyOutlinedComponent = styled('div')`
  ${props.disabled && `
      border: `1px solid ${({ theme }) => theme.palette.action.disabledBackground}`,
  `}
`;

<MyOutlinedComponent disabled/>

也许我来晚了这场比赛。 但我认为@jedwards1211正在寻找一种如何用 SC 表达这一点的方法: https ://codesandbox.io/s/magical-snow-5bzd8

我自己在某些地方有这个。 如果那一天到来时迁移到 v5 很简单,那就太好了

实际上,我不确定使用样式组件如何工作。

例如,如果 Material UI 将来会支持覆盖Typography的默认变体,我猜 JSS 比 styled-components 更容易。

@heb-mm 这里有一个详细的RFC@oliviertassinari在 3 月 7 日提到了这个线程。

我花了不到一分钟的时间向上滚动并看到提及。

编辑:对于那些想知道的人,heb-mm 现在已经删除了他们的评论。

我整理了一个CodeSandbox 示例来说明依赖样式组件styled的解决方案可能比 MUI makeStyles慢 3-4 倍:

@schnerd我已经更新了你的基准测试,以包括 Material-UI 内部styled api,它应该模仿styled-components 。 与其他选项相比,我很惊讶地看到它的速度非常慢。 见https://codesandbox.io/s/css-in-js-comparison-ljtjz?file=/src/App.js

image

有谁知道@emotion/styled (它具有与样式组件基本相同的 API)是否同样慢? 我只是想知道他们的实现是否有任何可以更好优化的地方。

有谁知道@emotion/styled (它具有与样式组件基本相同的 API)是否同样慢? 我只是想知道他们的实现是否有任何可以更好优化的地方。

https://codesandbox.io/s/css-in-js-comparison-sej1m

image

大约与样式化组件一样快。 仍然不如 makeStyles 快。 我看到的大部分问题是对象创建和对象缓存/记忆差异。

嗯,这可能会给我们向 MUI 的迁移计划带来很大的麻烦。 在管理我们的 CSS、主题和性能遇到很多麻烦之后,我们目前正从styled-components转向 Material UI 样式系统。 styled components开始还不错,我们在其上构建了自己的主题解决方案,但随着 UI 的增长,CSS 也随之增长。 我们使用 TypeScript,因此我们可以轻松重构 JS 对象而不是内联 CSS 字符串这一事实是一个巨大的卖点。 😕

所以我对 Material UI 很陌生,也刚刚看到了 v5 的 alpha 版本。 @ldiego08你说:

我们目前正在从 styled-components 转向 Material UI 样式系统

在使用 react 时,我通常使用样式化组件。 什么是 Material UI 样式系统,以及未来在 Material UI 中使用样式和 CSS 的推荐方式是什么? 我通读了这个页面,我不清楚你是否支持 CSS-IN-JS: https://material-ui.com/system/basics/。 我通常更喜欢用对象语法而不是对象语法来编写 CSS,我很享受使用 CSS-IN-JS 的好处,因为你可以使用“普通的 css 语法”,而且手头也有 JS 的力量。

感谢您的帮助!

我不知道为什么 styled-components API 如此受欢迎。 它更慢,您必须将所有内容包装到组件中,而不仅仅是生成类名。 此外,标记模板文字有什么用? 我们不想在 css 文件中编写 css,因为用 javascript 字符串编写它会更好吗? :D 在组合和重构等方面,对象语法要强大得多。对我来说,接受 css 对象并返回类名的普通情感 css 和 cx 函数是最灵活和强大的 API。 所以简单地用情感生成类名并使用类 API 是超级灵活和强大的。 所以我不明白你为什么要用性能和灵活性来换取“更方便的开发人员 API”(对某些人来说,对我来说,这是糟糕的 API)。

我不知道为什么 styled-components API 如此受欢迎。 它更慢,您必须将所有内容包装到组件中,而不仅仅是生成类名。 此外,标记模板文字有什么用? 我们不想在 css 文件中编写 css,因为用 javascript 字符串编写它会更好吗? :D 在组合和重构等方面,对象语法要强大得多。对我来说,接受 css 对象并返回类名的普通情感 css 和 cx 函数是最灵活和强大的 API。 所以简单地用情感生成类名并使用类 API 是超级灵活和强大的。 所以我不明白你为什么要用性能和灵活性来换取“更方便的开发人员 API”(对某些人来说,对我来说,这是糟糕的 API)。

我也有同样的担忧 :) 也许它可以解决一些问题:
https://github.com/mui-org/material-ui/issues/6115#issuecomment -580449539

@martinjlowm是的,我们在同一页上 :) 我认为材料 UI 团队最聪明的方法是实现某种可插拔的解决方案,而不是与 js 解决方案中的任何 css 结合,让人们选择使用什么和这样可以节省一些捆绑包的大小。 并且还保留类和 createMuiTheme API,因为这是其中最强大的部分。 对我来说,js 中的 css 是关于基于组件状态的简单动态样式、重构或删除 css 或整个组件时的信心(这是对象方法优越的地方)、性能(而不是从一堆外部样式表中下载一堆未使用的样式)等等。再说一次,我不明白为什么人们喜欢用一些编辑器突出显示来编写字符串。 我的意思是,您必须使用 ${} 从上下文中访问道具。 对于比设置背景 od div 元素更复杂的东西,我认为这种方法很混乱且不可读。 我不是在抨击它,只是说出我的想法,并试图证明并不是每个开发人员都喜欢样式化组件,即使他们喜欢,我也不认为用性能和灵活性来换取它是多么划算:)

@vdjurdjevic确实,当 css-in-js 实践不可避免地朝不同方向发展时,将 material-ui 耦合到一个 css in js 解决方案几乎肯定会引发冲突。

使用特定的 css-in-js 提供程序应用样式的适配器模式怎么样? 样式本身应该在 material-ui 包中以一致的格式定义。 这些样式的应用由相应的适配器以不同的方式执行。

类似于以下内容:

import {EmotionAdapter, StyledComponentAdapter, ThemeProvider} from "@material-ui/core/styles";
...
return 
    (<ThemeProvider theme={theme} adapter={EmotionAdapter}>
        ...
    </ThemeProvider>)

@vdjurdjevic我非常同意您对https://github.com/mui-org/material-ui/issues/6115#issuecomment -652762320 的看法。 您可能会喜欢我最近在https://github.com/mui-org/material-ui/issues/16947#issuecomment -653797178 中分享的我们正在采取的方向的总结。

我不明白为什么人们喜欢用一些编辑器突出显示来写字符串

从我的角度来看有几个原因:

  • 接近为什么我们不写React.createElement('div', {})
  • 网络开发经验有限的人(他们很多)很难学习 JavaScript API,使用 CSS 语法感觉更简单。 以设计师为例,去问问你团队中的人他们是怎么想的:)。
  • 无法在开发工具和源代码之间复制和粘贴(我讨厌这个)。

@oliviertassinari好的,我同意,这些是一些可靠的观点:) 但是,对于我(不是设计师,不是初学者,高级开发人员)来说,样式化组件和标记模板文字永远不会是一种选择。 我阅读了您对进一步发展方向的总结,我很高兴听到 css 引擎将是可选的。 我不介意将 styled-components 作为默认设置(如果这是大多数用户喜欢的),只要我可以切换它。 老实说,我想我会在下一个项目中坚持使用带有 v4 的 JSS,它有一些不错的功能(比如扩展和编写插件)。 我必须为情感编写 stylis 插件才能有类似的东西。

PS。 我也不是 JSX 的忠实粉丝 :) 它很快就会变得一团糟,你最终会得到箭头代码,对于应该呈现动态元素的组件,你别无选择,只能使用 createElement。 并不是说直接使用 createElement 会更好,只是说 JSX 并不理想。 在我看来,Flutter 拥有最好的 DX,我希望它有一天能够很好地处理 Web 平台。

@oliviertassinari根据我们正在进行的性能测试,如https://github.com/mui-org/material-ui/issues/6115#issuecomment -643398897 中所述,我只是希望材料团队不要仅仅因为它很受欢迎而选择样式化组件。 它很慢。 一直都是。 就个人而言,作为一名开发人员,您需要学习诸如 CSS 的 JS 表示法之类的东西。

这是工作的一部分。

让开发者的生活更轻松是我们作为包维护者工作的一部分(对于我自己的项目),但在让它变得简单和让它变得高效之间有一条界限。

这就是为什么我只使用 makeStyles 并且自推出以来一直使用它的原因。

我上一个团队架构师不听,而是继续使用样式化的组件,现在网站速度很慢。 我在测试分支中切换到 makeStyles 并在移动设备上的 TTI 上节省了 50%(10 秒),但就像你在那条评论中所说的那样,JS 表示法并不是每个人都知道,所以它没有被接受。

内部材料可以选择任何它想要的,但请默认使其具有性能。

[问题移至 StackOverflow。]

@haysclark请使用 StackOverflow 解决支持问题,而不是在 RFC 中添加它们。

@haysclark请使用 StackOverflow 解决支持问题,而不是在 RFC 中添加它们。

@mbrookes感谢您的提醒!

有谁知道@emotion/styled (它具有与样式组件基本相同的 API)是否同样慢? 我只是想知道他们的实现是否有任何可以更好优化的地方。

https://codesandbox.io/s/css-in-js-comparison-sej1m

image

大约与样式化组件一样快。 仍然不如 makeStyles 快。 我看到的大部分问题是对象创建和对象缓存/记忆差异。

我想知道 Box 组件的性能与您的分析相比如何,并添加了 Chakra-UI 的 Box 以进行良好的衡量,结果......令人惊讶:P
https://codesandbox.io/s/css-in-js-comparison-forked-mg3gx?file=/src/App.js

image

@Nvveen你试过 Chakra-UI v1 吗? 它已被重写,希望应该更好。 还有情感 v11,尽管仍处于测试阶段。

@Nvveen你试过 Chakra-UI v1 吗? 它已被重写,希望应该更好。 还有情感 v11,尽管仍处于测试阶段。

刚用最新的 RC 试了一下,没有明显区别; 它仍然比普通 SC 慢 1.5 到 2 倍。 对我来说最大的问题是为什么 MUI Box 这么慢。

@Nvveen你试过 Chakra-UI v1 吗? 它已被重写,希望应该更好。 还有情感 v11,尽管仍处于测试阶段。

刚用最新的 RC 试了一下,没有明显区别; 它仍然比普通 SC 慢 1.5 到 2 倍。 对我来说最大的问题是为什么 MUI Box 这么慢。

它使用 Jss。 SC至少要好一些。

在我的机器上,测试用例的运行顺序会影响结果。 比较

  1. 先装箱https://codesandbox.io/s/css-in-js-comparison-forked-tqlg1?file=/src/App.js
    Capture d’écran 2020-08-16 à 19 49 55

  2. 最后一个盒子https://codesandbox.io/s/css-in-js-comparison-forked-js6th?file=/src/App.js
    Capture d’écran 2020-08-16 à 19 49 45

@oliviertassinari垃圾收集和来自 v8 的 jit 是导致它的原因。 最好让测试运行真正隔离/分离。 后面的测试有更好的 jit,但偶尔会触发垃圾收集。

看起来 Emotion、SC 和 Chakra 都接近理论上的最大性能,因为每个小组件都有自己的挂载样式,而 MUI 样式尚未完全优化。 似乎获得比这更好的性能的唯一方法是为整个组件树设置一个样式表,就像在 makeStyles/pure CSS 中一样。 我猜情绪、SC 等额外的 30 毫秒是每个小组件必须确保其样式已安装的不可避免的开销。

@jedwards1211如果是关于保留 dx,Atlassian 制作了一个将其编译为 css 的库,称为已编译

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

finaiized picture finaiized  ·  3评论

reflog picture reflog  ·  3评论

ericraffin picture ericraffin  ·  3评论

anthony-dandrea picture anthony-dandrea  ·  3评论

activatedgeek picture activatedgeek  ·  3评论