Home Reference Source Repository

src/utils.js

import config from './config';
import React from 'react';
import {render} from 'react-dom';

const {namespace} = config;
const hasOwn = {}.hasOwnProperty;

/**
 * 包装返回 className
 * @param  {string|object} args 要被包装的 className
 * 所有 className 都回被加上项目的 namespace 前缀。
 * 如果参数是对象,则其属性是 class 名,值为 true 则该 class 名被返回。
 * 如果参数的属性是 `_user` 则直接返回其值,不作包装
 * @return {string}         一个或多个 class。例如:"class1 class2 class3"
 *
 * @example
 * let classes = classNames('dialog', {
 *   'dialog-btn': false,
 *   'dialog-title': true,
 *   '_user': 'user-class'
 * });
 * console.log(classes);
 * // 假设 namespace='rd'
 * // output: "rc-dialog rc-dialog-title user-class"
 */
export function classNames(...args) {
  let classes = [];
  let arg, argType, key;

  for (let i = 0, len = args.length; i < len; i++) {
    arg = args[i];
    argType = typeof arg;

    if (!arg) continue;

    if (argType === 'string' || argType === 'number') {
      prePush(classes, arg);
    } else if (Array.isArray(arg)) {
      classes.push(classNames.apply(null, arg));
    } else if (argType === 'object') {
      for (key in arg) {
        if (!hasOwn.call(arg, key) || !arg[key]) continue;

        // 用户传入的
        if (key === '_user') {
          classes.push(arg[key]);
        } else {
          prePush(classes, key);
        }
      }
    }
  }

  return classes.join(' ');
}

function prePush(arr, value) {
  value = `${namespace}-${value}`;
  return arr.push(value);
}


/**
 * 根据传入的 Component 创建一个实例,并渲染到 container
 * @param  {Component} Component React 组件
 * @param  {node} container 实例将渲染到该 dom 节点,
 * 如果缺少,内部创建 dom 节点。
 * @return {PropTypes.element}           Component 的实例
 */
export function createInstance(Component, container) {
  if (!container) {
    container = createContainer();
  }

  return render(<Component />, container);
}

/**
 * 创建一个 dom 节点,div.${namespace}-apicontainer
 * @return {dom} 节点
 */
function createContainer() {
  let div = document.createElement('div');
  div.className = classNames('api-container');
  document.body.appendChild(div);

  return div;
}