手寫簡版React虛擬dom及渲染流程

此文章沒什么難度

// 類型校驗(yàn)工具
function typeOf (obj, type) {
  const testType = Object.prototype.toString.call(obj).split(' ')[1].split(']')[0].toLowerCase();
  return type === testType;
}
/**
 * 創(chuàng)建虛擬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轉(zhuǎn)化為真實(shí)dom
 */
export function render (jsxObj, container, callback) {
  let { type, props } = jsxObj;
  // 1. 根據(jù)type創(chuàng)建一個(gè)dom(真實(shí)dom)
  let elem = document.createElement(type);
  // 1.1 根據(jù)props,中的屬性依次給創(chuàng)建的元素進(jìn)行設(shè)置
  for (let key in props) {
    // 1.2 關(guān)于某些特殊屬性的處理: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];
        // 循環(huán)迭代所有的子節(jié)點(diǎn):如果是字符產(chǎn) 直接插入到當(dāng)前dom中,如果是一個(gè)新的dom對象,遞歸調(diào)用render,再次創(chuàng)建元素插入到當(dāng)前dom
        childrenArr.forEach(item => {
          if (typeOf(item) === 'string') {
            elem.appendChild(document.createTextNode(item));
            return;
          }
          render(item, elem);
        })
      }
      continue;
    }
    elem.setAttribute(key, props.key);
  }
  // 2. 把創(chuàng)建的對象添加到指定容器中
  container.appendChild(elem);
  typeOf(callback, 'function') && callback();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容