• 实现简易版react中createElement和render方法


    function createElement(type, config, children) {
      // 1. 创建一个对象
      // 2.根据参数config修改这个对象
      // 3.把children参数作为对象中props中的一个属性
      let virtureDOM = {};
      virtureDOM.type = type;
      virtureDOM.ref = config.ref || null;
      virtureDOM.key = config.key || null;
    
      let props = {}; // 虚拟dom的props
      for (const attr in config) { // 遍历config 把除去ref和key的属性值复制到props中
        if (attr === 'key' || attr === 'ref') continue;
        else props[attr] = config[attr];
      }
    
      const childrenLength = arguments.length - 2;// create可以传多个参数 第三个开始被认为是children
      if (childrenLength === 1) {
        props.children = children; // 如果只有一个 那么children就是第三个参数
      } else if (childrenLength > 1) {
        let childArray = Array(childrenLength); // 如果不止一个,就存入childArray数组中
        for (let i = 0; i < childrenLength; i++) {
          childArray[i] = arguments[i + 2];
        }
        props.children = childArray;
      }
    
      virtureDOM.props = props;
      return virtureDOM;
    }
    
    // 把创建的对象转为真实DOM元素最后插入到页面中
    function render(virtureDOM, container, callback) {
      let { type, props } = virtureDOM || {};
      let realDom = document.createElement(type);
    
      for (let attr in props) {
        if (!props.hasOwnProperty(attr)) break; // 如果不是私有属性 直接跳出 说明已经遍历到原型上了
        if (!props[attr]) continue; // 如果这个attr没有有效值,那么继续找下一个
        const val = props[attr];
        // 处理classname变成class
        if (attr === 'className') realDom.setAttribute('class', val);
    
        else if (attr === 'children') { // 处理children
          if (typeof val === 'string') { // 如果只有一个字符串children 那么直接渲染text出来
            let text = document.createTextNode(val);
            realDom.appendChild(text);
          }
          else if (val instanceof Array) { // 如果children是数组, 那么就得遍历这个数组分情况再渲染
            for (let i = 0; i < val.length; i++) {
              if (typeof val[i] === 'string') {
                let text = document.createTextNode(val[i]);
                realDom.appendChild(text);
              } else {
                render(val[i], realDom);
              }
            }
          }
          else { // 如果children只有一个且不是数组也不是字符串 那么应该是createElement出来的虚拟dom。递归
            render(val, realDom);
          }
        }
    
        else if (attr === 'style') { // 处理style属性
          if (val === '') continue; // style 有可能值为空字符串
          for (let sty in val) {
            if (val.hasOwnProperty(sty)) realDom['style'][sty] = val[sty];
          }
        } else realDom.setAttribute(attr, val); // 基于setAttribute可以让设置的属性表现在html的结构上
      }
      container.appendChild(realDom);
      callback && callback();
    }
    
    const virtureDom2 = createElement('span',
      {}, 'age is 18!');
    
    const virtureDom = createElement('div',
      {
        id: 'box',
        className: 'lp',
        style: { color: 'red' },
        key: 12,
        ref: 'refs'
      }, 'my name is LanPang ', virtureDom2);
    
    
    render(virtureDom, document.getElementById('root'), () => console.log('finish'));
  • 相关阅读:
    分治法(求最大子序列和)
    分治法(二分查找)
    自定义选择动画提示
    将图片转为二进制字符串
    根据尺寸压缩图片
    在ios7系统下,scrollView下移20像素
    UIActionSheet警告,提示调用showFromTabBar方法
    使用Xcode5开发时的icon取消高光效果
    duplicate symbol _OBJC_METACLASS_$ 报错记录
    self.view添加UIView时添加动画
  • 原文地址:https://www.cnblogs.com/lanpang9661/p/12544735.html
Copyright © 2020-2023  润新知