【问题标题】:Prefixing flexbox styles for ReactReact 的 flexbox 样式前缀
【发布时间】:2015-06-08 22:34:24
【问题描述】:

我真的很喜欢 React 为你净化事件的方式,所以我很惊讶地发现它们并没有为你的 CSS 样式添加前缀!

无论如何,我开始像这样实现自己的基本前缀:

var prefixes = ["ms", "Moz", "Webkit", "O"];
var properties = [
  'userSelect',
  'transform',
  'transition',
  'transformOrigin',
  'transformStyle',
  'transitionProperty',
  'transitionDuration',
  'transitionTimingFunction',
  'transitionDelay',
  'borderImage',
  'borderImageSlice',
  'boxShadow',
  'backgroundClip',
  'backfaceVisibility',
  'perspective',
  'perspectiveOrigin',
  'animation',
  'animationDuration',
  'animationName',
  'animationDelay',
  'animationDirection',
  'animationIterationCount',
  'animationTimingFunction',
  'animationPlayState',
  'animationFillMode',
  'appearance',
  'flexGrow',
];


function vendorPrefix(property, value) {
  var result = {}
  result[property] = value

  if( properties.indexOf(property) == -1 ){
    return result;
  }

  property = property[0].toUpperCase() + property.slice(1);

  for (var i = 0; i < prefixes.length; i++) {
    result[prefixes[i] + property] = value;
  };

  return result;
}

React.prefix = function(obj) {
  var result = {};

  for(var key in obj){
    var prefixed = vendorPrefix(key, obj[key])
    for(var pre in prefixed){
      result[pre] = prefixed[pre]
    } 
  }
  return result;
};

但是我realized a big problem,React 使用对象作为样式并适当地为弹性框添加前缀,您需要为值添加前缀,而不是属性。因此,我不能同时包含以下所有样式:

.page-wrap {
  display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
  display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
  display: -ms-flexbox;      /* TWEENER - IE 10 */
  display: -webkit-flex;     /* NEW - Chrome */
  display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
 }

任何想法如何解决这个问题?

【问题讨论】:

  • 内联样式功能今天是有限的。我建议在这些情况下只使用传统的类/className
  • 或者你可以检测浏览器版本,但是类可能是要走的路。
  • 啊,我明白了。我希望最终取消 CSS 和 CSS 预处理器

标签: css reactjs


【解决方案1】:

嗯,实际上使用非常小的 XSS 技巧,您可以轻松实现您想要的。不要害怕,我们不会走向“黑暗面”;)

只需添加小函数,您就可以像这样编写 React CSS

var divStyle = multipleValues({
  color: 'white',
  padding: '10px 20px',
  // if you want property to have multiple values
  // just write them all in the array
  display: [
    '-webkit-box',
    '-webkit-flex',
    '-ms-flexbox',
    'flex'
  ],
  background: ['red', 'blue'],

  extraStyles: {
    background: [ 'yellow', 'pink' ]
  }
});

所有属性将按照它们在数组中表示的顺序应用。很酷不是吗? :)

它本身的功能很简单

// function that will do a "magic" XSS-ish trick
function multipleValues(style) {
  var result = {};
  // feel free to replace for..in+hasOwnProperty with for..of
  for (var key in style) { 
    if (style.hasOwnProperty(key)) {
      var value = style[key];
      if (Array.isArray(value)) {
        // by adding semicolon at the begging we applying
        // a trick that ofthen used in XSS attacks
        result[key] = ';' + key + ':' + value.join(';' + key + ':');
      } else if (typeof value === "object" && value !== null) {
        // here we doing recursion
        result[key] = multipleValues(value);
      } else {
        // and here we simply copying everything else
        result[key] = value;
      }
    }
  }
  return result;
}

工作演示

https://jsfiddle.net/z5r53tdh/1/

PS:如果我们使用 XSS 技术 - 我们不会引入任何新的安全问题。标准的 XSS 保护也适用于此。

【讨论】:

  • 我认为这不再适用于当前版本的 react。
【解决方案2】:

我更喜欢将我的样式放在单独的文件中并使用Autoprefixer

使用 grunt 和其他任务运行程序设置起来非常容易,并且可以针对您想要支持的特定浏览器。它会检查 caniuse 数据库以保持最新状态,甚至会从您的 css 中删除任何不必要的前缀。

它也可以作为后编译器使用 less 和 sass。

希望有帮助!

【讨论】:

    【解决方案3】:

    自动供应商前缀已被声明为 React 团队不想维护的东西。这真的很有意义,每个应用程序对支持哪些浏览器都有不同的要求。根据支持的距离,问题会呈指数级增长。

    确实认为开箱即用的 React 应该支持以供应商为前缀的 ,因为单独使用内联样式你不能使用 flexbox(你好现代网络!?)。

    认为对象字面量语法几乎没有其他地方无法提供的价值,而且主要增加了样式的摩擦。猜测它与向后兼容性支持有关,并且能够将 CSS 对象作为道具传递,并且不想强迫人们使用模板字符串 (` `) 语法的 ES5 / ES6。如果我们将字符串与+ 运算符一起添加以将我们的变量粘贴在其中,那将是非常难看的……但是对于模板文字不再需要了! (参见mdn

    对攻击此问题的所有其他软件包不满意,因此制作了一个最简单的软件包来统治它们。名为Style It 的包,它可以让您编写 CSS。还自动子树范围,因此您不在使用 CSS 的全局名称空间中(类似于内联,但没有那么高的特异性)。与内联样式类似,默认情况下它也是 XSS 安全的(使用 React 使用的相同库来转义您的 CSS),是同构的,并且在 1.8kb 压缩后很小。哦,没有构建步骤。

    npm install style-it --save

    函数语法 (JSFIDDLE)

    import React from 'react';
    import Style from 'style-it';
    
    class Intro extends React.Component {
      render() {
        return Style.it(`
          .flex-container {
            padding: 0;
            margin: 0;
            list-style: none;
    
            display: -webkit-box;
            display: -moz-box;
            display: -ms-flexbox;
            display: -webkit-flex;
            display: flex;
    
            -webkit-flex-flow: row wrap;
            justify-content: space-around;
          }
    
          .flex-item {             
            background: tomato;
            padding: 5px;
            width: 200px;
            height: 150px;
            margin-top: 10px;
    
            line-height: 150px;
            color: white;
            font-weight: bold;
            font-size: 3em;
            text-align: center;
          }
        `,
          <ul class="flex-container">
            <li class="flex-item">1</li>
            <li class="flex-item">2</li>
            <li class="flex-item">3</li>
            <li class="flex-item">4</li>
            <li class="flex-item">5</li>
            <li class="flex-item">6</li>
          </ul>
        );
      }
    }
    
    export default Intro;
    

    JSX 语法 (JSFIDDLE)

    import React from 'react';
    import Style from 'style-it';
    
    class Intro extends React.Component {
      render() {
        return (
          <Style>
          {`
            .flex-container {
              padding: 0;
              margin: 0;
              list-style: none;
    
              display: -webkit-box;
              display: -moz-box;
              display: -ms-flexbox;
              display: -webkit-flex;
              display: flex;
    
              -webkit-flex-flow: row wrap;
              justify-content: space-around;
           }
    
           .flex-item {
              background: tomato;
              padding: 5px;
              width: 200px;
              height: 150px;
              margin-top: 10px;
    
              line-height: 150px;
              color: white;
              font-weight: bold;
              font-size: 3em;
              text-align: center;
            }
          `}
    
          <ul class="flex-container">
            <li class="flex-item">1</li>
            <li class="flex-item">2</li>
            <li class="flex-item">3</li>
            <li class="flex-item">4</li>
            <li class="flex-item">5</li>
            <li class="flex-item">6</li>
          </ul>
        </Style>
      }
    }
    
    export default Intro;
    

    HTML / CSS 从 Chris Coyier 的 A Complete Guide to Flexbox 帖子中提取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-15
      • 2016-11-27
      • 2012-05-31
      • 1970-01-01
      • 2022-11-13
      • 2022-01-01
      • 1970-01-01
      • 2019-04-19
      相关资源
      最近更新 更多