Material-ui: 将CSS重构为Javascript

创建于 2014-11-10  ·  95评论  ·  资料来源: mui-org/material-ui

将组件CSS移到Javascript中,从而无需将CSS / Less文件添加到项目中。

建议来自观看此幻灯片演示@vjeux的https://speakerdeck.com/vjeux/react-css-in-js

所有95条评论

我喜欢那样,但是我不知道它在现实世界中是如何工作的。 想象一下,有很多元素,每个元素都会有一个自定义样式。 这将使dom变得巨大。 这不是性能问题吗? (我已经完全在react.js中使用样式创建了一个类似的UI,并且一切正常,但这只是一个小测试项目)

@ totty90是的,我确实对此感到纳闷,但是从幻灯片

也许@vjeux可以阐明该幻灯片及其在幻灯片中的建议解决方案。

也许对于某些较小的组件,这可能是更好的解决方案?

编辑:我不确定的另一件事是如何处理媒体查询和响应能力?

已经要求他向我展示使用该技术的真实应用程序。 这解决了最好的问题之一:组件位于单个文件中。 我可以与您共享一个文件,您无需进行任何设置即可完全像我的组件那样渲染我的组件。 没有CSS问题。

还有另一个项目旨在提供一种集成CSS-in-JS和React的好方法-https: //github.com/js-next/react-style以及使用它们的Material UI组件的一些初步工作-https: //github.com/SanderSpies/react-material

该项目目前具有更大的吸引力,并且实现了更多的组件,但是react-material的优点是组件可以独立工作而不必捆绑CSS文件。 您还可以从中获得@vjeux演示文稿中概述的所有好处。

如果两个项目可以合并,那就太好了!

另一个项目是最糟糕的。 唯一有趣的部分是js中的CSS。

我喜欢将JS和CSS耦合在一起的概念,但是内联样式不利于浏览器性能和实现CSP。 如果您担心的话,也许可以使用WebPack?

Webpack似乎是导入样式的唯一“合理”方法。 有一个require('component.css'); -但是您最终对组件有了依赖性。 他们也必须使用Webpack! 我不喜欢那种解决方案。 一个人应该能够轻松地共享一个组件,只需安装,使用和盈利。

这里的当前方法看起来很用户友好。 这并不完美,但是复制几个导入行非常简单。 尽管我建议再次使用Less可以将用户锁定在该预处理器中...

使事情变得简单很难! 有人有任何建议吗? 这比这个项目要广泛得多。 整个反应/聚合物/组分社区需要解决方案。

PS-在JS内耦合CSS似乎是个坏主意。 对于一个人,您最终编写了一个带有驼峰式属性和字符串化值的伪CSS,并且您在认知上混合了各种顾虑,这使得推理代码变得更加困难。 我从来没有编写CSS的问题。 是的,这可能很困难,而且可能会出错(全局名称空间,意外后果等),但是将其转移到JS并不能解决问题。 编写更好的CSS是。

@ pspeter3您有基准吗? :)

这两个JsPerfs主要是http://jsperf.com/class-vs-inline-styles/2http://jsperf.com/classes-vs-inline-styles。 但是http://jsperf.com/inline-style-vs-css-class/9似乎暗示了相反的含义。 对性能不利的是夸大其词。 我敢肯定,使用不良的选择器也会导致样式表的性能下降。 使用内联样式时,您对实施内容安全策略有任何建议吗?

@jarsbe

PS-在JS内耦合CSS似乎是个坏主意。 对于一个人,您最终编写了一个带有驼峰式属性和字符串化值的伪CSS,并且您在认知上混合了各种顾虑,这使得推理代码变得更加困难。 我从来没有编写CSS的问题。 是的,这可能很困难,而且可能会出错(全局名称空间,意外后果等),但是将其转移到JS并不能解决问题。 编写更好的CSS是。

我在JS中写了很多CSS和CSS。 第一个比较容易,但是在大型项目中比较混乱,我认为另一个(因为我只构建了一个小型应用)在较大的应用中会更好。 尝试使用所有全局和合并的东西对js应用程序进行编程,这真是太糟糕了! (或者我总是做错了...)

这是我用react.js完成的测试http://jsperf.com/react-class-name-vs-inline-css2

是的,我希望对此有一个简单的答案。 :)最后,我认为两种方法都有其优点。

我最关心的是在JS组件中包含样式与代码维护有关。 例如,跨浏览器重置所需的CSS发生了什么? 这些样式是否也包含在组件中? 此外,使用LESS(如混合包,变量等)会给我们带来很多便利,而我们可以通过某种方式在JS内部进行替换和抽象。

话虽如此,我们用“ mui”命名了该项目中使用的所有CSS类的名称,然后尝试编写面向对象的CSS。 将来,可能应该有一些流程可以让用户选择要下载到自定义版本中的组件。

谢谢你的问题。 真正带来的好处是讨论!

是什么真正使组件的样式比其结构(html)和功能(js)少了该组件的一部分? 在我看来,我们已经把一种缓解一个问题(代码的可维护性)的方法误认为是一种固有的明智设计模式,而忘记了它确实是一个补丁。 可以说,React比将结构,功能和样式划分为自己的语言更能解决代码的可维护性。 它有其自身的问题(在css情况下是速度),但是如果我们同意这种重新编写组件的方式是好的,我们可以开始尝试解决速度问题。

应当指出,我个人认为这是Web组件规范的失败之一。 在将不同的语言归为一个模块的地方,React挑战了html和css的概念。

@mcwhittemore是的,样式与HTML或JS一样,都是组件的一部分。 它们共同组成一个组件。 这并不一定要将该组件写为一个“单元”,这就是它应该如何分配的方式。

React紧密地结合了结构和功能。 它迫使您进入这种模式,我发现这很简单且合乎逻辑。 我可以很容易地理解我正在查看的代码,而我的大脑却不会过载。

另一方面,JS文件中的CSS使代码更难于理解。 视觉样式的描述不太适合功能和结构。 我不只是为此感到烦恼,因为我不得不处理多个问题,所以我感到困惑和放慢了脚步。 它还将样式与组件紧密结合在一起,这使得其他作者更难以编写自己的样式。

我想将我的组件作为一个捆绑分发。 乐高积木开发是梦想! 听起来我们都和那个最终目标在同一页上。 内联CSS听起来不错,但我认为这不是正确的解决方法。

@jarsbe 100%同意组件中的阅读风格不够清晰。 有时很难找到样式的创建地。 我一直在使用style.json文件,其中其defaultspermanentsthis.props.style合并起了清晰的作用。

{
  "defaults": {
    "backgroundColor": "#efefef"
  },
 "permanents": {
    "width": "100%"
  }
}

反对在JS vs CSS中进行样式设置的另一个论点是, style属性的功能与CSS选择器不同。 举例来说,我不认为*:after目前不太可能实现。

@mcwhittemore试图获取一个伪元素正是让我走的原因,“呵呵,是的,在这种情况下不存在...”。 是的,提取到另一个文件中确实有帮助。 我必须看看bespoke.js上的系统以设置新主题的样式。 我听说在JS中实现CSS,但很累。

@mcwhittemore为什么您需要*:after

@ totty90目前是CSS的一部分。 可能有解决此问题的方法,但这不是一个简单的“将CSS转换为JS”的情况。 对于我只是没有想到的:after:before选择器,您有解决方案吗?

IMO:after和:before是一种骇客,我从不需要它们,我想知道您需要什么来为您提供解决方案/意见。

@ totty90我将在另一个项目的另一个问题中提及您,以免使这个项目混乱。

@ hai-cea牢记SMACSS工作流程(https://smacss.com/book/categorizing)一个好的方法可能是将_Base_,_Layout_和(也许)_Theme_类别的css保留在好的ol's cs文件中。 _Module_和_State_ css似乎很适合我做JS样式。

@WRidder感谢您的链接-这很有意义。

我不知道该放在哪里的随机想法...本机组件如何实现样式? 我设想,反应组件在本质上应与本地组件相似。 这可能是寻找想法的好地方。

我对将CSS放置在JS中的方法持怀疑态度-演示文稿本身讨论了将样式与组件相关联的问题,好像没有花整整多年的精力来完成Shadow DOM那样标准。 现在很明显,React目前不使用该机制,但是如果及时使用,我不会感到惊讶。

该标准之所以有效,是因为它为组件创建者提供了一种方法,使其可以将一些最小的基本样式与其组件相关联,然后由设计人员覆盖到阴影DOM即可覆盖它们。 如果设计人员自己不直接使用带有react的组件,那么他们将如何覆盖纯粹在Javascript中设置的样式还远远不够。

我刚刚从react conf回来,非常感谢@vjeux的组织。 我也对此方法表示怀疑,但我认为它确实有其优势。 如果我们采用这种方法,那么这个项目会有一些挑战,我希望能获得一些帮助解决。

  1. 我们希望这些组件具有主题性。 它们将具有一些默认样式,但是开发人员应该能够更改外观以适应他们的需求。 当前,他们可以通过覆盖LESS中的某些变量来做到这一点。 我们如何使用js样式提供相同的功能?
  2. 很多时候,组件会生成嵌套子级。 我们如何让开发人员自定义嵌套子代的样式。 我的直觉是,我们应该只在那些可以自定义的孩子身上展示样式道具吗? 但这是否会使我们的样式与组件的dom结构紧密结合? 我的意思是,如果我们最终改变了组件的dom结构,我们是否也会改变它的样式道具?

到目前为止,感谢您的所有帮助和反馈-我期待每个人都可以说。

在React会议上有关于这个想法的视频吗?

@vjeux感动在他的一个小阵营本地通话- http://conf.reactjs.com/schedule.html#react -native

他还告诉了我他在NationJS上发表的演讲,但我不知道是否有音频?
http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html

嗨@ hai-cea,
我的团队对主题问题进行了很小的实验。 我的团队解决方案是将实质性的ui库公开设置功能的主题:
https://github.com/agencyrevolution/material-ui/blob/css-in-js-experiment/src/index.js

当我们使用material-ui时,我们使用自定义define属性调用此函数。 material-ui将调用此函数的更新。 您可以在以下位置看到:
https://github.com/agencyrevolution/material-ui/blob/css-in-js-experiment/src/js/scaffold-styles.js

以及我们在这些文件上使用的示例:
https://github.com/agencyrevolution/material-ui/blob/css-in-js-experiment/src/js/raised-button.jsx
https://github.com/agencyrevolution/material-ui/blob/css-in-js-experiment/example/src/app/custom-styles.js
https://github.com/agencyrevolution/material-ui/blob/css-in-js-experiment/example/src/app/components/main.jsx

谢谢@ cuongcua90-我和你的想法类似。

将有一个主题对象,将保存所有在custom-variables.less

//Override Theme Variables
Theme.set({
  textColor: 'red'
});

为了提供对样式的更精细控制,每个组件都将包含将与默认样式合并的样式道具:

//merge styles that are passed in
var styles = this.mergePropStyles(defaultStyles, this.props.style);

此外,在测试中还遇到了其他一些挑战:

  1. 我们将如何处理供应商前缀?
  2. 媒体查询呢?

@ cuongcua90和@ hai-cea-如果我们利用另一个框架来做到这一点怎么办? 我还没有读太多,但是看来http://jhudson8.github.io/fancydocs/index.html#project/jhudson8/react -css-builder?focus = outline很合适。

它支持混合和变量。

绅士

我创建了一个css-in-js分支来解决此问题,并在example文件夹中有一个原型。

开发人员有2个定制点。 首先是覆盖默认主题变量。 变量将包括组件颜色,字体等内容。
https://github.com/callemall/material-ui/blob/css-in-js/example/src/app/app.jsx#L16

为了进行更精细的控制,开发人员还可以通过props覆盖默认的组件样式:
https://github.com/callemall/material-ui/blob/css-in-js/example/src/app/components/main.jsx#L10

这是一个如何在MUI端实现组件的示例:
https://github.com/callemall/material-ui/blob/css-in-js/src/js/svg-icons/svg-icon.jsx

您会看到,我们将合并主题变量,样式道具以及基于特征检测的自动前缀。

关于此模式有任何反馈吗?

将所有CSS移到基于JS的系统中会很好,并且可以解决#316。 我不确定在可维护性方面知道多少,并且某些通用样式适用于_all_元素(例如reset和less/core/的东西),因此我不确定如何获得什么计划这些样式进入人们的应用。 一些悬而未决的问题,但绝对很有趣。

我们可以创建某种经典的继承系统来创建样式对象。 对于常见样式,只有一个可继承的BaseStyle对象。

我很好奇您正在尝试解决将CSS混入JS的真正问题。

1-使构建更容易,因为我们不必担心“我需要在哪里使用CSS?”
2-主题形式的JavaScript?
3-覆盖样式?

这些问题从一开始就存在,在我的情况下,所有问题都通过使用简单的文件夹结构以及带有@import规则的“ page。(css | less | sass)”来解决,所有规则均与文件有关。

有人可以详细/解释/分享为什么将CSS混入JS是一个好主意吗?

谢谢你的时间!

我不是程序包的作者,但是使用JS动态创建样式最近变得越来越流行。

一般来说,CSS存在许多问题。 CSS是用许多静态变量编译的,例如(例如)网格的大小,主类型的颜色等等。 之后,您将无法更改它们,除非您手动选择受影响的元素并设置覆盖已编译CSS的自定义样式。

将CSS放入JS意味着它变得完全动态,您可以随意更改任何基础变量。 这也意味着(特别是在React的情况下)您可以将相关样式保留在组件内部。

我不是100%卖掉它。 这也意味着在JS完成加载之前,您没有样式。 对于单页应用程序而言,这不是什么大不了的事,但是将来可能需要考虑一下。 (或者服务器端渲染可能已经以一种有效的方式解决了这个问题?我也希望听到有更多实际操作经验的人的声音。)拥有一个单独的CSS文件也意味着浏览器可以开始并行加载样式。

@dendril-@vjeux提供的演示文稿大规模描述了CSS的问题。 使用JS编写CSS可以解决的一些问题包括:

  • 模块,变量,计算和混入都可以使用JS已经拥有的现有工具-CommonJS模块,JS变量,JS表达式,而不必使用单独的语法和工具集来管理它们。
  • 您可以使用现有的JS工具来查找引用了特定样式的位置。 例如,如果您键入了错误的类名,则可以使用FlowType和TypeScript进一步获取编译时错误。
  • 您可以在一个地方定义结构,外观和逻辑-这是使组件易于重用的有用步骤。 Web组件通过HTML导入解决了此问题。 用一种语言定义所有内容是另一种方法。
  • 使用CSS进行动态处理更加容易。 由于静态样式和动态样式都是用相同的语言实现的,因此可以在它们之间共享常量等。

例如,我在这里使用TypeScript +内联样式实现了Material Design样式按钮的实现: https :

  • 按钮的主题+结构位于一个位置,对于开发和重用非常有用。 使用IDE,您可以轻松找到主题的所有特定元素所引用的位置。
  • 在render()函数中,我可以根据道具通过简单地引用主题的各个部分来建立按钮的样式,而不必连接类名字符串。
  • 定义主题时,我可以使用JS通过材料设计规范指定的公式来计算某些颜色(请参阅colors.premultiplyColor()

这里有一个折衷,这是声明性方法与命令性方法在指定事物上的通常折衷。 命令式语言(JS)具有强大的功能。 语法更加冗长,但是灵活性易于滥用。 对于具有许多动态样式的复杂组件,平衡倾向于JS的青睐。 对于在CSS中很容易表达的静态样式,没有太多。 我不会将这种方法用于类似文档的内容。

@msikma-在JS中指定样式不必意味着使用内联样式或等待应用程序加载。 您可以将JS用作编写样式的语言,然后将其编译为JS-基本上是SASS或LESS的替代方法。 将此与服务器端呈现相结合,浏览器的实际输出看起来很像CSS,并且可以与浏览器开发工具很好地协同工作。

@robertknight非常感谢您的回答,您仅添加了足够的信息以完全理解该想法。

我更喜欢SASS / LESS的发展,而不是在节目中添加更多的JavaScript,最后,如果您想重用机制,我们可以改进用JavaScript编码的LESS,并尽可能地从JavaScript中重用,但是看起来只需设计一个新的API并开始将所有内容混合到一个文件中就很容易了。

希望我们能找到一个更好的解决方案,因为失去CSS的声明性想法将不是一个好主意,而在使所有声明性而不是命令性的情况下都不会。 \ o /

@msikma-在JS中指定样式不必意味着使用内联样式或等待应用程序加载。

是否可以全局声明样式(通过动态构造样式元素)? 我想是这样,因为这是必不可少的。

但是,如何避免等待JS加载呢?

@msikma-是的。 在我链接的示例中,在文件顶部定义的'theme'var中的所有样式都在构建时编译为CSS。 在render()函数中,有对style.mixin(theme.someElement,otherProps)的调用,该返回的对象带有className属性,该属性是通常用空格分隔的类名称列表。 如果在服务器上运行React,您将获得一个普通的HTML字符串,其中包含具有“类”和“样式”属性的元素,这些元素可以在客户端上呈现而无需运行任何代码。

@dendril-声明性CSS的替代方法不必是命令性JS。 可以以功能/声明的方式编写JS-所有静态样式都可以是简单的Javascript对象。 如果您需要在动态样式和静态样式中引用相同的常量(例如,颜色或字体大小),则变得很容易做到。

感谢您的解释,听起来非常不错。

我只是进入这个线程,但是很感兴趣,因为我正在尝试使用material-ui开发一个项目。 我已经切换到SASS版本,发现在Material-UI中没有实现网格系统,然后意识到SASS版本不同步。 因此,我很想知道这个项目在未来的发展方向。 似乎在将css放入组件本身中存在很多折衷,这不是一个明确的选择。 凭直觉,我觉得这个想法有点危险,因为它是迄今为止建立的Web开发实践的根本形式。 另一方面,React也是如此!

@ hai-cea您是否考虑过JSS库? 我一直在将它用于我正在从事的新React项目,到目前为止,我真的很喜欢它。 很好的是,如果需要,您可以选择声明全局类名。 您几乎可以在css中执行的任何操作都可以在JSS中进行,因为它创建了自己的命名空间类并将它们添加到<head><style>标签中。

有一个关于React样式的新项目供您考虑。 这里是一个链接:

刚看到这个线程,希望我早些遇到它。 我们正在使用reapp-ui中包含的iOS主题在JS中使用CSS进行处理。 在发布之前,它已经开发了几个月。

实际上,@ hai-cea我使用的系统与您的系统非常相似。

  1. 加载“常量”(认为:颜色,特征检测)。 实际上,我们执行两个级别的常量,第一是特征检测和颜色,第二是特定组件的常量
  2. 组件的加载
  3. 加载动画

这是将主题与三个元素一起加载自定义主题的方法,该

这有一些非常棒的好处:

  1. 用户不必加载不需要的任何其他样式。
  2. 组件具有一致的名称和样式声明。
  3. 一切在每个级别上都是主题化的。
  4. 易于添加其他平台的主题。

我们正在使用react-style进行所有操作,并且效果非常好。 与Styled mixin一起使用,它使我们能够进行真正很棒的声明式添加样式。 那,以及Tappable mixin还提供了Focus / Active状态。 两者都将在短时间内提取出来。

实际上,我想在正式文档中写出更多的内容。

实际上,我们的下一步实际上是在Reapp中构建一个实质性的UI主题,我已经将该项目添加了书签一段时间。 想知道我们是否不能共同努力!

@ hai-cea您的Theme对象实际上将非常适合React的上下文功能。 万一您不熟悉它,上下文基本上就是会自动沿组件层次结构传递的道具。 在层次结构中的任何给定级别,组件都可以查询其上下文以获取某些值。

对于您的情况,建议您在上下文中设置theme变量。 它会像这样工作:

var App = React.createClass({
  childContextTypes: {
    theme: React.PropTypes.instanceOf(Theme)
  },
  getChildContext() {
    return {
      theme: CustomTheme
    };
  },
  // ...

然后,在您的<Button>组件中,您可以执行

var Button = React.createClass({
  contextTypes: {
    theme: React.PropTypes.instanceOf(Theme)
  },
  getTheme() {
    return this.context.theme || DefaultTheme;
  },
  render() {
    return <button style={this.getTheme().getButtonStyle()}>...</button>;
  }
});

我喜欢这种方法的事情:

  • 没有全局Theme对象
  • 只需更改单个父组件中的上下文,就可以使UI的整个部分主题化(考虑使用一个声明来主题化整个模式)

无论如何,你们在这里所做的工作真棒。 我希望这有帮助 :)


我已经创建了一个用于将CSS写入React视图的库,

它的作用:用JavaScript编写具有名称空间,专有名称,无冲突和react.js预期结果的CSS。

@mjackson我真的很喜欢您按照层次结构发送主题上下文的方法,但是这一部分

this.getTheme()。getButtonStyles()

扩展性不太好,因为主题应该了解样式。 我认为主题应该是名称,调色板和一些间距定义,而不是完整的CSS样式。 这将启用真正可定制和可扩展的组件和应用程序。
你怎么看?

@mjackson我喜欢上下文的想法。 我们使用的装饰器基本上可以完成相同的操作。

@hackhat是的,如果正确使用常量,则可以加载任意数量的常量,以便对它们进行分层。 从颜色的“基础”开始,然后是特定的“组件”等。这就是我们允许“主题”甚至从素材到iOS到Window的工作方式(以后)。

无论哪种方式,祝一切顺利! 我认为我们正朝着同一方向前进,但这是一件好事。 如果您有兴趣合并,请保持联系。 由于我们已经为iOS和Android开发了大量功能,因此我们已经对CSS / JS进行了相当多的探索,因此很有用。 无论哪种方式,我都在此处添加了一些有助于实现这一目标的文档: https :

对Threadjack感到抱歉,刚刚看到了一些团队合作的机会:+1:

@natew很高兴听到您的项目。 看来我们走在正确的轨道上。 :)

@mjackson感谢您向我介绍React的上下文功能-我以前从未使用过它,但是在react会议上听说过它,还看到它在React Router中使用。 似乎是一个很好的解决方案-我一定会尝试一下。

在将样式转换为js方面,我们取得了相当不错的进展。 我认为,我看到的最大优势之一就是我们对每个组件的样式都更加明确。 到目前为止,我们还没有必要引入像JSS,Radium或React Styles这样的库。 虽然我可以说服其他人。

我期待完成此体系结构更改,以便我们可以重新加强现有的组件。

此更改是否会使覆盖默认样式变得困难?

@DylanPiercey很好的问题。 正如@ hai-cea所提到的,我们没有必要使用任何与样式相关的库。 所有组件样式都将内联定义,因此将不再有任何Less文件(除了docs站点中的文件)。

当前,这是我们覆盖样式的方法:

  • 组件还将获得一个style道具,以覆盖组件根元素的内联样式。 这将由StylePropable mixin进行。

    • _Some_组件将具有用于对内部组件元素进行样式设置的其他支持。 没有这些附加道具的组件将无权覆盖这些样式。 这是重构完成后的预期重大更改。 我们很想听听您对此的想法。 我们的理由是,覆盖这些样式有悖于Material Design规范。

  • 对于仍在使用Less的用户,组件将在其根元素上获得className属性,以便用户可以添加其他样式(这是我们
  • 另一个重大变化是删除了包括Less变量在内的所有Less文件。 这会将mui从css-framework和一组react组件更改为_only_作为一组react组件。 我们相信,随着我们继续完成更多的材料设计组件,这种转变更为合适。

最后一件事:我们还将使用@mjackson建议的使用react的上下文功能提供主题文件,以增加自定义。

每个人对这种方法有何想法?

顺便说一下,我们通过reapp-ui通过上下文发布了

const theme = {
  styles: {
    List: {
      self: { background: '#000', ... }
    }
  },
  animations: {},
  constants: {}
}

// top level component
export default React.createClass({
  render() {
    return (
      <Theme {...theme}>
        <RouteHandler />
      </Theme>
    );
  }
});

查看主题文件以了解如何设置上下文:
https://github.com/reapp/reapp-ui/blob/4355556dee24407e5e7827df7a484944aeaf32cc/helpers/Theme.jsx

我们还发现将常量用作第一层很有帮助,因此您可以设置各种属性,从isRetinalistBorderColor ,然后将这些常量通过帮助程序加载时传递给样式。 。 用法如下:

import UI from 'reapp-ui';

UI.addConstants({
  borderColor: '#000'
});

UI.addStyles({
  List: c => ({
    firstItem: {
      border: `1px solid ${c.borderColor}`
    }
  })
})

// exports the theme object you need for the <Theme /> helper
export default UI.makeTheme()

认为当您深入研究它时可能会有所帮助。

@natew我一直倾向于这种方法。 您能详细说明c的含义吗? 我对ES6的胖箭头功能不太熟悉。 c是新的常量参数吗? 当前,内联样式通过我们的StylePropable mixin使用React的浅表合并来覆盖。

但是,除非显式传递嵌套的json对象,否则此方法将无法处理。 我们已经讨论过使用递归合并,但这会很昂贵,因为每个组件都会多次使用合并功能。 看到我们已经在使用ES6,这看起来很有希望。

我喜欢将Material-ui的CSS重构为Javascript的想法!

但是当我尝试在JS中使用内联样式而不是在我的一个项目中使用LESS时,确实遇到了一些麻烦的问题...

Safari:按钮组件上的波纹样式错误

最大的问题是这个: https :
我只能使用grunt-autoprefixer解决Safari问题
但是autoprefixer仅适用于LESS / CSS。 因此,那时我不得不放弃内联样式,并将我的应用重写为使用LESS。 (真是个无赖...)

不支持伪样式和媒体选择器

react的内联样式不支持某些CSS功能,例如所有伪样式和媒体选择器。 一开始,我最终使用LESS来处理缺少的部分,并使用内联样式来处理其余部分。

自动在数字后加上“ px”

有很多属性,反应内联样式决定将px附加到数字上。 例如, order: 1变成order: 1px ,这是胡说八道。
必须处理不必要的px似乎是一个常见问题,请参阅https://github.com/facebook/react/pull/3499

缩小支持不足

我的项目必须使用Google的Closure Compiler和ADVANCED_MODE 。 当我尝试使用React内联样式时,我最终至少要替代以下这些属性:

/**
* <strong i="27">@type</strong> {*}
*/
var __REACT_DEVTOOLS_GLOBAL_HOOK__;

/**
* <strong i="28">@type</strong> {*}
*/
var Symbol;

/**
* <strong i="29">@type</strong> {*}
*/
var MSApp;

此外,我还必须为属性名称使用字符串,例如backgroundSizefloat
例如,代替使用

var iconStyle = {
  backgroundSize: "300px 400px",
  float: "left"
};

我必须改用字符串才能在ADVANCED_MODE中使用Google的Closure编译器进行编译

var iconStyle = {
  'backgroundSize': "300px 400px",
  'float': "left"
};

但是除了那些问题之外,一切都很好!
不要误会我的意思:我认为内联样式是正确的方法。 路上只有几处颠簸。 我希望所有这些问题都可以通过Facebook(即@vjeux)解决。

感谢大家的投入,我们昨天能够完成对内联样式的较少重构! 当前的母版包含v0.8.0的预发行版,供您签出,我们希望您收到任何反馈。

您也可以在本地运行docs网站,以查看更新的文档。 以下是我们能够实现的一些重点:

  1. 现在,所有组件样式都可以内联完成。 这不仅使我们能够更清楚地了解每个组件的样式,而且使每个组件都更加可移植。 由于没有任何外部的less / css依赖性,因此您应该只需要所需的每个组件即可。 此外,MUI库中的样式不会与您自己的应用程序中的样式冲突。
  2. 可以在2个级别上实现定制。 您可以使用主题上下文对象覆盖将影响所有子组件的主题变量。 此外,每个组件都接受一个样式道具,您可以使用该样式道具实现更精细的自定义。
  3. 使用自定义的轻量级Modernizr通过特征检测来完成自动供应商前缀。 前缀仅在需要时才做,并且是最好的部分? 它是为您在每个组件中自动完成的。

我想先将其烘烤一到两个星期,然后再发布。 在这段时间里,我们将努力将示例代码放在一起,并将某些docs网站样式转换为使用嵌入式样式。

再次感谢大家的投入和耐心等待。 我们非常期待发布此版本,并重新解决问题并添加新组件。 :)

除了使用组件之外,我们还需要做些其他事情吗?

请注意,我试图将其打包为流星包(本质上是使用browserify捆绑所有组件),并且我可能做错了什么。

看起来我们必须实例化ThemeManager并将其设置为使用Material-ui组件的组件上的主题childContext。

编辑: theme已重命名为muiTheme

@ukabu ,您好,只需在应用程序的最外层组件中实例化ThemeManager。 然后它将传递给其所有子孙。 您可以在此处此处了解有关React的上下文功能的更多信息。

将此代码包含在最外层的组件中:

如果您使用的是ES6

var React = require('react');
var mui = require('mui');
var ThemeManager = new mui.Styles.ThemeManager();
class OuterMostParentComponent extends React.Component {
  // Important!
  getChildContext() { 
    return {
      muiTheme: ThemeManager.getCurrentTheme()
    };
  }
};
// Important!
OuterMostParentComponent.childContextTypes = {
  muiTheme: React.PropTypes.object
};
module.exports = OuterMostParentCompone

如果您使用的是ES5

var React = require('react');
var mui = require('mui');
var ThemeManager = new mui.Styles.ThemeManager();
var OuterMostParentComponent = React.createClass ({
  // Important!
  childContextTypes: {
    muiTheme: React.PropTypes.object
  },
  // Important!
  getChildContext: function() { 
    return {
      muiTheme: ThemeManager.getCurrentTheme()
    };
  }
});
module.exports = OuterMostParentComponent

如果您在本地运行文档并转到#/customization/themes则可以看到有关如何使用主题的更多文档。

谢谢。 现在正在工作:+1:

现在所有样式都是内联的,我们仍然需要重置CSS。 似乎src /树中没有css或更少的文件。 您打算增加一个吗?

@ hai-cea @mmrtnz恭喜! 您是否有依赖CSS伪类的代码食谱? 我肯定会错过:hover ,请参阅https://github.com/reactjs/react-future/issues/13@vjeux建议使用onMouseOver但这很痛苦。 0.8.0是否带有一些方便的:hover替换代码?

@bparadie我对此改变了主意。 我想我希望以下工作:

<div
  style={{color: 'blue'}} 
  hoverStyle={{color: 'red'}}
/>

@vjeux是在React框架级别谈论的还是项目将单独实现的事情? 因为在框架级别这将是令人兴奋的...

它乞求一些变化,例如pressedStyle focusedStyle disabledStyle (用于输入)等。

同时,也祝贺所有为此做出巨大贡献的人:微笑:

我想知道,为主题使用更具体的上下文键是否会更好? 例如muiTheme -那么如果页面上还有另一个想要使用该上下文键的库,或者我想在我的应用程序中使用context.theme ,这也不会冲突自己的东西。

@vjeux我喜欢!

@bparadie

我一直在尝试使用这个工具,以使悬停样式变得不那么烦人...

'use strict';

const React = require('react');

const withHoverStyle = (Component, compType) => {
  class ComponentWithHover extends React.Component {
    _handleMouseOver() {
      const theme = this.context.theme.component[compType];

      React.findDOMNode(this).style.backgroundColor = theme.hoverColor;
    }

    _handleMouseOut() {
      const theme = this.context.theme.component[compType];

      React.findDOMNode(this).style.backgroundColor = theme.color;
    }

    render() {
      const hoverProps = {
        onMouseOver: this._handleMouseOver.bind(this),
        onMouseOut: this._handleMouseOut.bind(this)
      };

      return React.createElement(Component, Object.assign({}, this.props, hoverProps));
    }
  }

  ComponentWithHover.contextTypes = {
    theme: React.PropTypes.object
  };

  return ComponentWithHover;
};

module.exports = withHoverStyle;

https://github.com/troutowicz/geoshare/blob/css-in-js/app/utils/withHoverStyle.js

可以这样使用:

'use strict';

const React = require('react');
const FlatButton = require('material-ui/lib/flat-button');

const withHoverStyle = require('../utils/withHoverStyle');

class AuthButton extends React.Component {
  render() {
    return <FlatButton {...this.props} />;
  }
}

AuthButton.propTypes = {
  label: React.PropTypes.string,
  onClick: React.PropTypes.func
};

AuthButton.defaultProps = {
  label: 'Login',
  onClick() {}
};

module.exports = withHoverStyle(AuthButton, 'flatButton');

https://github.com/troutowicz/geoshare/blob/css-in-js/app/components/AuthButton.jsx

我想要在React级别和dom级别:)不清楚我什么时候实现它

@troutowicz感谢您的分享!


我已经看到您谈论js中的CSS已有一段时间了。 这是JS lib比较中的CSS https://github.com/hackhat/css-in-js-comparison看看。 已经评论了3个库,可能会很有趣地看到解决此问题的不同方法。

还可以看看https://github.com/hackhat/smart-css ,您不需要onMouseOver添加“:hover”

有人对我的想法使用theme使用其他上下文密钥有任何反馈吗? 例如muiTheme

@vjeux如果您向我指出了正确的方向,以在React中实现它,我很乐意尝试一下,尽管也不想劫持该线程,所以让我们在其他地方进行讨论:)

我希望可以使用依赖于上下文的其他react模块对其进行全面测试,因为到目前为止,我至少遇到了一个可以掩盖其他库中上下文的库-flocks.js。 那里的作者正在研究它,但是请确保material-ui不会破坏反应堆路由器或使用上下文的任何其他模块。 不过,这是个好主意,很高兴看到内联样式,并希望使用材料ui可以使我们的生活更轻松:+1:

@JedWatson是的,我认为这是个好主意。 我们一定会的。

@ hai-cea很棒,很高兴听到它:smile:

@anyong / @vjeux /任何人-是否有任何文档说明当有多个库使用上下文时上下文如何表现? 即我们(作为图书馆作者)如何确保我们比赛顺利? 对于在不同级别定义上下文的工作方式,我还没有做很多测试。

@bparadie我想在不久的将来为类选择器添加一个像@troutowicz的示例这样的mixin或类,但是现在您必须使用onMouseOver 。 尽管我同意这可能会很痛苦。

@JedWatson这是一个好主意,我会尽快进行更新。

@ukabu当前没有任何读取resets.css文件的计划。 我们决定让Material-UI从一个CSS框架转变为一组React组件。 但是,如果需要,可以在线找到resets.css

@mmrtnz我了解,但就目前而言,某些组件无法以用户代理样式正确显示。 例如:如果我不包括任何CSS,则h1具有最高边距(用户代理样式),这会导致AppBar标题无法正确对齐。

@ukabu我明白你的意思,谢谢你指出这一点。 样式取决于resets.css和其他相关支持css文件的组件已内联重新定义。 这似乎是重构期间我错过的一个示例。 如果发现更多与resets.css或任何其他样式表的需求相关的问题,我们可以将其添加回去,但在尝试首先在组件级别解决该问题之前,不能添加它们。

为了悬停等,我打开了#684。

感谢大家的精彩讨论。 我们能够在v0.8中发布此功能。

我很期待使用该库,但是看到所有东西都使用内联样式是个很大的拒绝,我不明白您为什么要这样做,我阅读了有关为什么这样做的幻灯片,但没有意义,为什么合并外观,视图将逻辑整合为一件事,将关注点分离,这是软件工程最可靠的陈述之一。

巴勃罗,这些担忧不是分开的。 如果你想让事情看起来
您可以使用主题管理器以不同的方式将关注点真正分离。
其余的,组件应该做什么以及它们的html和css紧密相关
耦合,将其分离会使事情变得更加复杂。

在2015年8月23日,星期日,05:35 Pablo Fierro [email protected]写道:

我很期待使用这个库,但是看到所有东西都用了
内联样式被拒之门外,我不明白您为什么会这么做
为此,我阅读了有关为什么这样做的幻灯片,但没有意义,为什么合并
外观,观点和逻辑融为一体,关注点分离
人们,这是软件工程最可靠的陈述之一。

-
直接回复此电子邮件或在GitHub上查看
https://github.com/callemall/material-ui/issues/30#issuecomment -133778140

Wout。
(在手机上键入,请简洁)

我同意@pablofierro —浏览器无法缓存内联样式,并且我们失去了相当基本的CSS功能,例如:hover ,同级选择器或任何级联样式的概念。

使用内联样式来启用静态客户端专用应用程序并避免依赖预处理工具链(Webpack等)是一个折衷,但是它会使具有附加功能的大型项目失败(同构应用程序最为突出)。 我喜欢使用外部样式表或使用CSS模块支持的选项,但它会解决一些较简单的情况。

无论如何,@ grrowl级联在大型样式表代码库中被认为是不好的做法。 参见例如BEM方法。

@加贺美被认为是谁的坏习惯? 如果您将样式表分为可重用的模块(类似于react原理),那么它将变得高度可维护。 甚至React的网页上都提到它是您组件的View,而不是外观,强制所有内容都内联的决定简直是荒谬的。

这需要更改。 内联无疑在某些用例中有其好处,但最终的标记是:

  • --大量带宽将被耗尽,仅用于发送样式。 在每个请求中。 5倍,这并不是没有道理的。磨应用如果您的应用程序具有许多DOM节点,该怎么办? 以及这如何影响内存开销和性能? 这带来了很多我们不必处理的隐含含义
  • 丑陋-有趣地阅读它生成的内容,就像阅读原始/未格式化的缩小CSS一样有趣。
  • 和_stupid_-一直追溯到CSS 1规范,WW3C包含类是有原因的。 这种方法样式通过创建LESS / SCSS / etc抛出了社区获得的灵活性/快速原型/功能。 等等。 您已经可以看到轮子已经被重新发明; 向上滚动通过该线程,并查看所有建议使用不同库的注释/从JavaScript中提取CSS的所有注释。

可是等等! 还有更多:

  • 没有开箱即用的IDE支持
  • 不支持伪类

伙计们:_这是jquery可以做的_。 我们为什么要疏通水面呢? 而且默认情况下强制使用它吗?

一个有趣的例子

打开Chrome开发者工具
尝试对包含多个具有相同类型的MUI组件的页面进行一些样式编辑-更改背景颜色或其他内容-例如。 导航菜单中的<MenuItem ...>

它只会更改_that_组件。 那React Devtools呢? 不,是同一件事。

我并不是要成为一个家伙-尽管我可以肯定听起来像个家伙,但是正如@pablofierro所说,这太可笑了。 此功能可能很酷,缺少CSS依赖项非常吸引人。 但是剔除.css没有任何意义。

我应该补充; 我很乐意创建PR。 我只想听听社区对于重新实现此观点的看法; 希望就如何达成共识达成某种共识。

您建议做什么呢? 对于我的用例(Cordova应用程序),内联方法非常棒。

@oliviertassinari似乎内联样式的最大

如果是这种情况,我建议您返回到类(因为似乎很多人都希望这样做,这似乎使事情变得更简单),而不是通过字符串公开所有CSS。

/*styles.css for people who are fine with a separate file*/
.my-styles {...}
// styles.js (expose as "material-ui/theme" or something)

var css = { __html: "injected styles.css content" };

// alternatively we could expose a component.
module.exports = (
    <style dangerouslySetInnerHTMLIfYouAreSureItIsWhatYouWantToDo={ css }/>
);

这样,人们可以通过以下方式直接在JavaScript中使用主题:

theme = require("material-ui/theme");

MyJSX = (
    <div>{ theme }</div>
);

优点:

  • 它只是CSS
  • 可能将多个主题捆绑在一起
  • 可以通过js,css预处理器或在html中手动导入。

缺点:

  • 花了很多时间使所有样式内联。

@rozzzly +1111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

使用MUI-> http://recordit.co/9mBknPLZUb
没有MUI-> http://recordit.co/6MkzWhQiBt

好吧, @ rozzzly,我不同意。

  • 。 当然,当用户到达网站时,我们会使用更多带宽来发送样式。
    但是,延迟而不是带宽是大多数网站的性能瓶颈。 有关更多详细信息
    因此,我认为在第一次渲染时将样式向下内联。 这才是真正对用户重要的。 您不必等待RTT(往返时间)即可拥有样式。
  • 丑陋的。 是的,这不容易阅读。 为什么需要阅读?
  • 和愚蠢的。 Facebook解释了他们使用内联样式的动机。 非常有说服力。 链接

我已经专门使用内联样式超过6个月,这是一种解放的体验。 与CSS相比,样​​式已变得更易于管理,更灵活并且具有更少的惊喜。

我个人同意@rozzzly ,他很好地详细说明了问题。 从规模上看,这并不是一个好主意。 CSS的作品。 我们正在重新设计轮子,以使其更“轻便”。 这种疯狂的变化归结为解决了一个问题-包括CSS。 自述文件中需要进行1行解释。 更不用说,即使是菜鸟开发人员也都精通将HTML包含CSS或使用其构建工具。 这不是新人。

相反,我们正在为JS中的网页重建样式。 看起来真傻。 绝对基本的样式特征,例如伪元素? 走了 SASS / LESS编译? 走了

嘿大家。 我开始在辅助项目中使用material-ui,并且一直在这里和这里进行讨论。

我想添加一些要点:

这对于较小的应用有意义吗?
我使用引导程序等为企业编写了许多较小的内部Web应用程序。 当不得不在其标记和js中添加更多的component-css时,我从未感到太多痛苦。 _我不是一次努力。 冲突很少是一个问题,并且在大多数情况下很容易解决。

但是我现在很沮丧地在我的devtools中查看DOM。 对于所有内联样式,即使看到基本的树结构也要困难得多。 而且这种痛苦不是一次性的,每次我打开devtools时,这种痛苦就会再次出现。

我们是否通过这种方法疏远了精通CSS的设计师?
由于JavaScript中嵌入了所有样式,因此对于习惯于在CSS文件中进行草稿和编辑的设计人员来说似乎很难。 他们不是现在被迫学习JavaScript,ES6,编译器,buildtools等,并且更有可能破坏东西吗?

也许那不是一件坏事-我全都为跨职能团队服务,并且我还没有与“组件设计师”合作,但是我想确保设计师也能在本次讨论中得到考虑。

也:

+1用于分离关注点-在我的书中必须将样式和ui逻辑分离
+1考虑缺乏IDE支持

我完全同意CSS存在一些问题,尤其是在规模上。 我希望这次讨论能为我们所有人在这方面找到更好的位置。

好吧,我也觉得这次演讲很有说服力,但实际上在大多数情况下使用CSS
基于模块的重命名以及某些内联样式是最容易实现的
与恕我直言。

2015年11月24日,星期二,上午9:49 Owen Campbell-Moore [email protected]
写道:

就其价值而言,使用内联样式是我成为
MUI的忠实粉丝。 我发现Facebook的讲话令人信服,
个人认为样式和结构没有分离的意义
构建UI时。

-
直接回复此电子邮件或在GitHub上查看
https://github.com/callemall/material-ui/issues/30#issuecomment -159198060

Wout。
(在手机上键入,请简洁)

有趣的地方@mpseidel。 但是,我认为,随着越来越多的框架朝着组件发展,将JS和CSS保持为组件的一部分似乎比使全局CSS涵盖范围广泛的组件,页面等更具意义。主题组件的概念让我me不安。.我不太了解CSS,所以对于组件而言,也许有一种简单的方法可以选择主题样式来覆盖其默认样式,以便组件编写者可以将其组件与之配合使用。整体主题风格? 如果有,我想了解更多。

这里有一个很大的讨论。 而且很难猜测总体方向。
任何人都可以估计样式将返回其位置的机会吗?

我还没有使用material-ui。 从我的“新鲜”角度来看,我看到了这些问题,这些问题提醒我以后使用该项目:

  • 表示层和逻辑层混乱
  • 内联样式导致性能下降
  • 很难添加自己的样式
  • 丑陋的DOM

我看不到内联样式有任何好处。

与尝试从头开始重新设计样式相比,以更具可读性和可维护性的方式重新组织更少/ ass / css更好。

@oliviertassinari ..这意味着没有办法返回CSS?

这意味着我们正在探索改善当前样式方法的选项(CSS模块,Radiium,Looks,react-themeable)。

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

相关问题

sys13 picture sys13  ·  3评论

TimoRuetten picture TimoRuetten  ·  3评论

ryanflorence picture ryanflorence  ·  3评论

revskill10 picture revskill10  ·  3评论

pola88 picture pola88  ·  3评论