DOMPropertyOperations

DOMPropertyOperations Node property operations to add or remove node properties.

 

'use strict';

var DOMProperty = require ('./ DOMProperty');
var ReactDOMComponentTree = require('./ReactDOMComponentTree');
var ReactInstrumentation = require('./ReactInstrumentation');

// Boolean, numeric type is converted into string, the string is transcoded by html, and processed ["'&<>]; wrapped in quotation marks
var quoteAttributeValueForBrowser = require('./quoteAttributeValueForBrowser');

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

// Used to verify attribute names, English letters a-zA-Z, ":", "-", numbers, some Unicode characters
var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');

var illegalAttributeNameCache = {};// Cache the attribute name that failed to verify
var validatedAttributeNameCache = {};// Cache the attribute name that has been validated successfully

// Check attribute name, English letters a-zA-Z, ":", "-", numbers, some Unicode characters
function isAttributeNameSafe(attributeName) {
  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
    return true;
  }
  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
    return false;
  }
  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
    validatedAttributeNameCache[attributeName] = true;
    return true;
  }
  illegalAttributeNameCache[attributeName] = true;
  process.env.NODE_ENV !== 'production' ?
    warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;
  return false;
}

// Boolean truth check (no value is ignored), numeric check, positive number check for attribute value conventions
function shouldIgnoreValue(propertyInfo, value) {
  return value == null || propertyInfo.hasBooleanValue && !value ||
    propertyInfo.hasNumericValue && isNaN(value) ||
    propertyInfo.hasPositiveNumericValue && value < 1 ||
    propertyInfo.hasOverloadedBooleanValue && value === false;
}

var DOMPropertyOperations = {

  // Set the 'data-reactid' attribute and value of the node as a string; use when creating a node by splicing strings
  createMarkupForID: function (id) {
    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
  },

  // Set the 'data-reactid' property of the node; used when creating a node in the document.createElement method
  setAttributeForID: function (node, id) {
    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
  },

  // Set the 'data-reactroot' attribute and value of the node as a string; use when creating a node by splicing strings
  createMarkupForRoot: function () {
    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""';
  },

  // Set the 'data-reactroot' property of the node; use document.createElement to create a node
  setAttributeForRoot: function (node) {
    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');
  },

  // Extract specific attributes and their values, concatenate them into strings
  // DOMProperty.properties, DOMProperty.isCustomAttribute convention can set node properties
  // DOMProperty.properties is used to extract or ignore property values, such as properties.hasBooleanValue will ignore configuration items whose property value is no value
  // DOMProperty.isCustomAttribute verifies customizable properties, such as data- or aria-starting properties
  createMarkupForProperty: function (name, value) {
    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
    if (propertyInfo) {

      // Some property values ​​are ignored with the property value type agreed by propertyInfo. For example, the property.hasBooleanValue setting will ignore the value of the property value of no value.
      if (shouldIgnoreValue(propertyInfo, value)) {
        return '';
      }
      var attributeName = propertyInfo.attributeName;
      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
        return attributeName + '=""';
      }
      return attributeName + '=' + quoteAttributeValueForBrowser(value);
    } else if (DOMProperty.isCustomAttribute(name)) {
      if (value == null) {
        return '';
      }
      return name + '=' + quoteAttributeValueForBrowser(value);
    }
    return null;
  },

  // Set custom properties in string form
  createMarkupForCustomAttribute: function (name, value) {
    if (!isAttributeNameSafe(name) || value == null) {
      return '';
    }
    return name + '=' + quoteAttributeValueForBrowser(value);
  },

  // Set node attributes, most often use the setAttribute or setAttributeNS method
  // Especially when propertyInfo.mutationMethod exists, use this method to set node properties
  // or when propertyInfo.mustUseProperty is true, use node[propertyInfo.propertyName]=value to set node properties
  // or through the attributes verified by DOMProperty.isCustomAttribute, remove or add node attributes according to the value value
  setValueForProperty: function (node, name, value) {
    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
    if (propertyInfo) {

      // Add node attributes with the DOMMutationMethods configuration method of the node attribute plugin
      var mutationMethod = propertyInfo.mutationMethod;
      if (mutationMethod) {
        mutationMethod(node, value);

      // Some property values ​​are ignored with the property value type agreed by propertyInfo. For example, the property.hasBooleanValue setting will ignore the value of the property value of no value.
      } else if (shouldIgnoreValue(propertyInfo, value)) {
        this.deleteValueForProperty(node, name);
        return;

      // When propertyInfo.mustUseProperty is true, do not use setAttribute method to set node attributes
      // Handle the compatibility problem of ie8, 9setAttribute method converting attribute value to string `[object]`
      } else if (propertyInfo.mustUseProperty) {
        node[propertyInfo.propertyName] = value;
      } else {
        var attributeName = propertyInfo.attributeName;
        var namespace = propertyInfo.attributeNamespace;

        // node.setAttributeNS(namespace,attr,value) adds attributes of a specific namespace
        if (namespace) {
          node.setAttributeNS(namespace, attributeName, '' + value);
        // Boolean type can be injected into the node with the property name
        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
          node.setAttribute(attributeName, '');
        } else {
          node.setAttribute(attributeName, '' + value);
        }
      }
    // For properties verified by DOMProperty.isCustomAttribute, remove or add properties according to the value
    } else if (DOMProperty.isCustomAttribute(name)) {
      DOMPropertyOperations.setValueForAttribute(node, name, value);
      return;
    }

    if (process.env.NODE_ENV !== 'production') {
      var payload = {};
      payload[name] = value;
      ReactInstrumentation.debugTool.onHostOperation({
        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
        type: 'update attribute',
        payload: payload
      });
    }
  },

  // add or remove attributes based on value
  setValueForAttribute: function (node, name, value) {
    if (!isAttributeNameSafe(name)) {
      return;
    }
    if (value == null) {
      node.removeAttribute(name);
    } else {
      node.setAttribute(name, '' + value);
    }

    if (process.env.NODE_ENV !== 'production') {
      var payload = {};
      payload[name] = value;
      ReactInstrumentation.debugTool.onHostOperation({
        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
        type: 'update attribute',
        payload: payload
      });
    }
  },

  // Remove the attribute name of the node node
  deleteValueForAttribute: function (node, name) {
    node.removeAttribute(name);
    if (process.env.NODE_ENV !== 'production') {
      ReactInstrumentation.debugTool.onHostOperation({
        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
        type: 'remove attribute',
        payload: name
      });
    }
  },

  // Remove node attributes, most often use the removeAttribute method
  // Especially when propertyInfo.mutationMethod exists, use this method to remove node properties
  // or when propertyInfo.mustUseProperty is true, use node[propertyInfo.propertyName] to remove node properties
  deleteValueForProperty: function (node, name) {
    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
    if (propertyInfo) {
      var mutationMethod = propertyInfo.mutationMethod;
      if (mutationMethod) {
        mutationMethod(node, undefined);
      } else if (propertyInfo.mustUseProperty) {
        var propName = propertyInfo.propertyName;
        if (propertyInfo.hasBooleanValue) {
          node[propName] = false;
        } else {
          node[propName] = '';
        }
      } else {
        node.removeAttribute(propertyInfo.attributeName);
      }
    } else if (DOMProperty.isCustomAttribute(name)) {
      node.removeAttribute(name);
    }

    if (process.env.NODE_ENV !== 'production') {
      ReactInstrumentation.debugTool.onHostOperation({
        instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
        type: 'remove attribute',
        payload: name
      });
    }
  }

};

module.exports = DOMPropertyOperations;

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326818372&siteId=291194637