为React添加flexbox样式前缀

8
我很喜欢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;
};

但后来我意识到一个大问题,React使用对象来表示样式,为了适当地添加flexbox前缀,你需要给值加前缀,而不是属性。因此,我不能同时包含以下所有样式:

.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+ */
 }

有什么办法可以避开这个问题吗?


1
内联样式功能今天受到限制。我建议在这些情况下只使用传统的类/ className - WiredPrairie
或者您可以检测浏览器版本,但是类可能是更好的选择。 - Brigand
1
啊,我懂了。我原本希望能够最终不再使用CSS和CSS预处理器。 - Chet
3个回答

4

实际上,通过非常简单的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中已经不再适用了。 - Dobes Vandermeer

0

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

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

它还可以作为后编译器与less和sass一起使用。

希望这有所帮助!


0

自动添加供应商前缀已被指出是React团队不想维护的内容。这其实很有道理,每个应用程序都有不同的浏览器支持要求。根据支持的范围,问题会成倍增加。

你认为React是否应该支持供应商前缀的,就像内联样式一样,无法使用flexbox(你好现代网页!?)。

认为对象字面量语法的价值很小,而且大多数情况下会给样式增加阻力。猜测这与向后兼容性支持以及能够将CSS对象传递为props有关,不想强迫人们使用ES5 / ES6,其中可以使用模板字符串(` `)语法。如果我们仍在使用+操作符将字符串拼接在一起以插入变量,那么它将非常丑陋...但是现在使用模板文字不再需要这样做了!(请参见mdn

对于攻击这个问题的所有其他软件包都不满意,因此制作了最简单的软件包来解决它们。该软件包名为Style It,只需让您编写CSS即可。还会自动进行子树范围限定,因此您的CSS不会处于全局名称空间中(类似于内联但特异性不高)。与内联样式类似,它默认情况下也是XSS安全的(使用React使用的相同库转义您的CSS),具有同构性,并且在gzip压缩后仅为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的Flexbox完全指南帖子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接