CSSPropertyOperations

CSSPropertyOperations模块用于拼接样式字符串,或者对节点添加样式。

dangerousStyleValue模块对数值或数值型字符串拼接"px"单位,其他转化为字符串输出。

CSSProperty模块存储无单位样式名的集合、background等复合样式名的集合。

 

CSSPropertyOperations.js

'use strict';

// 无单位样式及复合样式的集合
var CSSProperty = require('./CSSProperty');

var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
var ReactInstrumentation = require('./ReactInstrumentation');

// 字符串拼接的样式名转化为驼峰式输出
var camelizeStyleName = require('fbjs/lib/camelizeStyleName');

// 对数值或数值型字符串添加”px“单位处理,其他转化为字符串
var dangerousStyleValue = require('./dangerousStyleValue');

// 将"backgroundColor"转化为"background-color","MozTransition"转化为"-moz-transition"
// "msTransition"转化为"-ms-transition"
// 驼峰式样式名转化为连字符输出
var hyphenateStyleName = require('fbjs/lib/hyphenateStyleName');

// 键值对缓存,回调函数以属性名为参数,返回值作为属性值;有属性值直接取值,不执行回调
var memoizeStringOnly = require('fbjs/lib/memoizeStringOnly');

var warning = require('fbjs/lib/warning');

// 驼峰式样式名转化为连字符输出,并键值对缓存驼峰式样式名、连字符拼接的样式名
var processStyleName = memoizeStringOnly(function (styleName) {
  return hyphenateStyleName(styleName);
});

// ie8下,是否不能对background等复合样式属性设为"",需要逐个设置backgroundColor样式为""
var hasShorthandPropertyBug = false;
// 特定浏览器下浮动样式属性名
var styleFloatAccessor = 'cssFloat';
if (ExecutionEnvironment.canUseDOM) {
  var tempStyle = document.createElement('div').style;
  try {
    tempStyle.font = '';
  } catch (e) {
    hasShorthandPropertyBug = true;
  }

  if (document.documentElement.style.cssFloat === undefined) {
    styleFloatAccessor = 'styleFloat';
  }
}

if (process.env.NODE_ENV !== 'production') {
  // 'msTransform' is correct, but the other prefixes should be capitalized
  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;

  var badStyleValueWithSemicolonPattern = /;\s*$/;

  var warnedStyleNames = {};
  var warnedStyleValues = {};
  var warnedForNaNValue = false;

  // 样式属性名含有"-"连字符号时作警告处理
  var warnHyphenatedStyleName = function (name, owner) {
    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
      return;
    }

    warnedStyleNames[name] = true;
    process.env.NODE_ENV !== 'production' ? 
      warning(false, 'Unsupported style property %s. Did you mean %s?%s', 
        name, camelizeStyleName(name), checkRenderMessage(owner)) 
      : void 0;
  };

  // 特定浏览器样式属性名校验,webkit|moz|o首字母须为大写形式
  var warnBadVendoredStyleName = function (name, owner) {
    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
      return;
    }

    warnedStyleNames[name] = true;
    process.env.NODE_ENV !== 'production' ? 
      warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', 
        name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) 
      : void 0;
  };

  // 样式值不能含有分号校验
  var warnStyleValueWithSemicolon = function (name, value, owner) {
    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
      return;
    }

    warnedStyleValues[value] = true;
    process.env.NODE_ENV !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon.%s ' + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;
  };

  // 样式值为NaN时警告处理
  var warnStyleValueIsNaN = function (name, value, owner) {
    if (warnedForNaNValue) {
      return;
    }

    warnedForNaNValue = true;
    process.env.NODE_ENV !== 'production' ? 
      warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', 
        name, checkRenderMessage(owner)) 
      : void 0;
  };

  var checkRenderMessage = function (owner) {
    if (owner) {
      var name = owner.getName();
      if (name) {
        return ' Check the render method of `' + name + '`.';
      }
    }
    return '';
  };

  // 样式校验,样式名不能含有"-"连字符、webkit|moz|o首字母须为大写形式;样式值不能含有分号,及不能是NaN
  var warnValidStyle = function (name, value, component) {
    var owner;
    if (component) {
      owner = component._currentElement._owner;
    }

    // 样式属性含有"-"连字符号时作警告处理
    if (name.indexOf('-') > -1) {
      warnHyphenatedStyleName(name, owner);

    // 特定浏览器样式属性名校验,webkit|moz|o首字母须为大写形式
    } else if (badVendoredStyleNamePattern.test(name)) {
      warnBadVendoredStyleName(name, owner);

    // 样式值不能含有分号校验
    } else if (badStyleValueWithSemicolonPattern.test(value)) {
      warnStyleValueWithSemicolon(name, value, owner);
    }

    // 样式值为NaN时警告处理
    if (typeof value === 'number' && isNaN(value)) {
      warnStyleValueIsNaN(name, value, owner);
    }
  };
}

// 以字符串拼接节点的样式,或以node.style[styleName]=value设置节点的样式
var CSSPropertyOperations = {

  // 将样式拼接为字符串输出
  createMarkupForStyles: function (styles, component) {
    var serialized = '';
    for (var styleName in styles) {
      if (!styles.hasOwnProperty(styleName)) {
        continue;
      }
      var styleValue = styles[styleName];
      if (process.env.NODE_ENV !== 'production') {
        warnValidStyle(styleName, styleValue, component);
      }
      if (styleValue != null) {
        // processStyleName函数将驼峰式样式名转化为连字符输出
        serialized += processStyleName(styleName) + ':';
        // dangerousStyleValue函数对数值或数值型字符串添加”px“单位处理,其他转化为字符串
        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';
      }
    }
    return serialized || null;
  },

  // 通过node.style[styleName]=value以对象形式设置节点的样式
  setValueForStyles: function (node, styles, component) {
    if (process.env.NODE_ENV !== 'production') {
      ReactInstrumentation.debugTool.onHostOperation({
        instanceID: component._debugID,
        type: 'update styles',
        payload: styles
      });
    }

    var style = node.style;
    for (var styleName in styles) {
      if (!styles.hasOwnProperty(styleName)) {
        continue;
      }
      if (process.env.NODE_ENV !== 'production') {
        // warnValidStyle样式校验,样式名不能含有"-"连字符、webkit|moz|o首字母须为大写形式;样式值不能含有分号,及不能是NaN
        warnValidStyle(styleName, styles[styleName], component);
      }

      // dangerousStyleValue函数对数值或数值型字符串添加”px“单位处理,其他转化为字符串
      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);

      // 置换为特定浏览器下浮动样式属性名,'cssFloat'或'styleFloat'
      if (styleName === 'float' || styleName === 'cssFloat') {
        styleName = styleFloatAccessor;
      }

      if (styleValue) {
        style[styleName] = styleValue;
      } else {
        // ie8下,对background等复合样式属性,逐个设置backgroundColor样式为""
        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];
        if (expansion) {
          for (var individualStyleName in expansion) {
            style[individualStyleName] = '';
          }
        } else {
          style[styleName] = '';
        }
      }
    }
  }

};

module.exports = CSSPropertyOperations;

 

dangerousStyleValue.js

'use strict';

var CSSProperty = require('./CSSProperty');
var warning = require('fbjs/lib/warning');

// 无单位样式
var isUnitlessNumber = CSSProperty.isUnitlessNumber;
var styleWarnings = {};

// 数值或数值型字符串样式值添加"px"作单位,其他转化为字符串输出
function dangerousStyleValue(name, value, component) {
  var isEmpty = value == null || typeof value === 'boolean' || value === '';
  if (isEmpty) {
    return '';
  }

  // 无单位样式直接转化为字符串
  var isNonNumeric = isNaN(value);// 数值或数值型字符串返回false
  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
    return '' + value;
  }

  // 数值型且非0字符串警告未来将作为无单位样式值处理,不会自动拼接上"px"单位
  if (typeof value === 'string') {
    if (process.env.NODE_ENV !== 'production') {
      if (component && value !== '0') {
        var owner = component._currentElement._owner;
        var ownerName = owner ? owner.getName() : null;
        if (ownerName && !styleWarnings[ownerName]) {
          styleWarnings[ownerName] = {};
        }
        var warned = false;
        if (ownerName) {
          var warnings = styleWarnings[ownerName];
          warned = warnings[name];
          if (!warned) {
            warnings[name] = true;
          }
        }
        if (!warned) {
          process.env.NODE_ENV !== 'production' ? 
            warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' 
              + 'for CSS property `%s` (value: `%s`) which will be treated ' 
              + 'as a unitless number in a future version of React.', 
              component._currentElement.type, ownerName || 'unknown', name, value) 
            : void 0;
        }
      }
    }
    value = value.trim();
  }

  // 数值或数值型字符串样式值添加"px"作单位
  return value + 'px';
}

module.exports = dangerousStyleValue;

 

CSSProperty.js

'use strict';

// 无单位样式,有单位样式会对数值型字符串拼接px单位
var isUnitlessNumber = {
  animationIterationCount: true,
  borderImageOutset: true,
  borderImageSlice: true,
  borderImageWidth: true,
  boxFlex: true,
  boxFlexGroup: true,
  boxOrdinalGroup: true,
  columnCount: true,
  flex: true,
  flexGrow: true,
  flexPositive: true,
  flexShrink: true,
  flexNegative: true,
  flexOrder: true,
  gridRow: true,
  gridColumn: true,
  fontWeight: true,
  lineClamp: true,
  lineHeight: true,
  opacity: true,
  order: true,
  orphans: true,
  tabSize: true,
  widows: true,
  zIndex: true,
  zoom: true,

  // SVG-related properties
  fillOpacity: true,
  floodOpacity: true,
  stopOpacity: true,
  strokeDasharray: true,
  strokeDashoffset: true,
  strokeMiterlimit: true,
  strokeOpacity: true,
  strokeWidth: true
};

function prefixKey(prefix, key) {
  return prefix + key.charAt(0).toUpperCase() + key.substring(1);
}

var prefixes = ['Webkit', 'ms', 'Moz', 'O'];

// 特定浏览器下的无单位样式
Object.keys(isUnitlessNumber).forEach(function (prop) {
  prefixes.forEach(function (prefix) {
    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
  });
});

// background等复合样式,ie8不能对style.background赋值为"",而需要对style.background.backgroundColor等赋值为""
var shorthandPropertyExpansions = {
  background: {
    backgroundAttachment: true,
    backgroundColor: true,
    backgroundImage: true,
    backgroundPositionX: true,
    backgroundPositionY: true,
    backgroundRepeat: true
  },
  backgroundPosition: {
    backgroundPositionX: true,
    backgroundPositionY: true
  },
  border: {
    borderWidth: true,
    borderStyle: true,
    borderColor: true
  },
  borderBottom: {
    borderBottomWidth: true,
    borderBottomStyle: true,
    borderBottomColor: true
  },
  borderLeft: {
    borderLeftWidth: true,
    borderLeftStyle: true,
    borderLeftColor: true
  },
  borderRight: {
    borderRightWidth: true,
    borderRightStyle: true,
    borderRightColor: true
  },
  borderTop: {
    borderTopWidth: true,
    borderTopStyle: true,
    borderTopColor: true
  },
  font: {
    fontStyle: true,
    fontVariant: true,
    fontWeight: true,
    fontSize: true,
    lineHeight: true,
    fontFamily: true
  },
  outline: {
    outlineWidth: true,
    outlineStyle: true,
    outlineColor: true
  }
};

var CSSProperty = {
  // 无单位样式名的集合,有单位样式会对数值型字符串拼接px单位
  isUnitlessNumber: isUnitlessNumber,
  // background等复合样式,ie8不能对style.background赋值为"",而需要对style.background.backgroundColor等赋值为""
  shorthandPropertyExpansions: shorthandPropertyExpansions
};

module.exports = CSSProperty;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值