手写简版React虚拟dom及渲染流程

此文章没什么难度

// 类型校验工具
function typeOf (obj, type) {
  const testType = Object.prototype.toString.call(obj).split(' ')[1].split(']')[0].toLowerCase();
  return type === testType;
}
/**
 * 创建虚拟dom对象
 */
export function createElement (type, props, ...childs) {
  let jsxObj = {
    type,
    props: {},
    key: null,
    ref: null
  };
  if (props) {
    // => 处理key和ref
    if (props.hasOwnProperty("key")) {
      jsxObj.key = props.key;
      delete props.key;
    }
    if (props.hasOwnProperty("ref")) {
      jsxObj.ref = props.ref;
      delete props.ref;
    }
    jsxObj.props = Object.assign(jsxObj.props, props);
  }
  // => childrens 处理
  if (childs.length > 0) {
    childs = childs.length === 1 ? childs[0] : childs;
    jsxObj.props["children"] = childs;
  }

  return jsxObj;
}
/**
 * 把虚拟dom转化为真实dom
 */
export function render (jsxObj, container, callback) {
  let { type, props } = jsxObj;
  // 1. 根据type创建一个dom(真实dom)
  let elem = document.createElement(type);
  // 1.1 根据props,中的属性依次给创建的元素进行设置
  for (let key in props) {
    // 1.2 关于某些特殊属性的处理:className/style/children
    if (/^className|style|children$/.test(key)) {
      if (!props.hasOwnProperty(key)) break;
      if (key === 'className') elem.className = props.className;
      if (key === 'style') {
        let styObj = props.style;
        for (let sKey in styObj) {
          if (!styObj.hasOwnProperty(sKey)) break;
          elem["style"][sKey] = styObj[sKey];
        }
      }
      if (key === 'children') {
        let val = props['children'],
          childrenArr = Array.isArray(val) ? val : [val];
        // 循环迭代所有的子节点:如果是字符产 直接插入到当前dom中,如果是一个新的dom对象,递归调用render,再次创建元素插入到当前dom
        childrenArr.forEach(item => {
          if (typeOf(item) === 'string') {
            elem.appendChild(document.createTextNode(item));
            return;
          }
          render(item, elem);
        })
      }
      continue;
    }
    elem.setAttribute(key, props.key);
  }
  // 2. 把创建的对象添加到指定容器中
  container.appendChild(elem);
  typeOf(callback, 'function') && callback();
}

你可能感兴趣的:(手写简版React虚拟dom及渲染流程)