React专题

React深入学习笔记

2023-08-19  本文已影响0人  Mstian

好久没有再好好静心学习了,总是感觉很忙碌,很疲惫,现在准备开始重新学习记录,先从学习React开始吧,学习理论,慢慢更新笔记,会整体的更新完整个React体系学习记录,看到这篇文章的有缘人,如果你也在学习或者有疑问,或者我学习记录中有错误,欢迎一起进步。

关于JSX底层处理机制
1、将JSX语法编写代码转换成虚拟对象(Virtual Dom)

基于babel-preset-react-app 把JSX转换为React.createElement()方法;
只要是元素节点,必然会基于该方法处理;

React.createElement(ele, props, ...children);
 + ele - 元素标签名
 + props - 元素的属性集合(如果没有设置过属性,该值为null)
 + children - 第三个以及以后的参数,表示当前元素的子节点
 
再通过执行React.createElement方法创建出虚拟对象(vdom);

vdom = {
    $$typeof: Symbol(react.element),
    ref: null,
    key: null,
    type: 标签名(或组件),
    props: {
        元素相关属性,
        children: 子节点信息(没有子节点,没有这个属性,属性可能是一个值,也可能是一个数组)
    }
}

实现React.createElement方法:

function createElement(ele, props, ...children){
    
    const virtualDOM = {
        $$typeof: Symbol('react.element'),
        ref: null,
        key: null,
        type: null,
        props: {}
    };
    
    virtualDOM.type = ele;
    
    if (props != null) {
        virtualDOM.props = {
            ...props,
        } 
    }
   
     if (children.length === 1) virtualDOM.props.children = children[0];
    
    if (children.length > 1) virtualDOM.props.children = children;

    return virtualDOM;
}



2、把构建的虚拟DOM转换成真实DOM

基于ReactDOM中render方法处理;
注意这里React16 和 React18语法有所不同

V16
ReactDOM.render(<App/>, document.getElementById('root'))

V18
const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(<App/>);

实现render方法:

render方法本质就是遍历虚拟dom对象,如果有子节点那么久递归,然后生成真实dom最终插入到文档。

首先实现一个可以遍历对象所有私有属性的方法(私有的,不论是否可枚举,不论类型)

Object.getOwnPropertyNames(arr); 获取对象非Symbol类私有属性(无论是否可枚举)
Object.getOwnPropertySymbols(arr);获取对象Symbole类私有属性

还可以使用ES6提供Reflect.ownKeys(obj); 直接获取对象所有私有属性方法。

function each(obj, callback) {
    // 一个好的函数一定会优先处理边界异常
    if (obj == null || typeof obj !=='object') {
        throw new TypeError('obj is not an object');
    }
    
    if (typeof callback !== 'function') {
        throw new TypeError('callback is not a function')
    }
    
    const keys = Reflect.ownKeys(obj);
    
    keys.forEach((key, index) => {
        callback(obj[key], key);
    })
}

todo:学习Reflect


const virtualDOM = {
    $$typeof: Symbol('react.element'),
    ref: null,
    key: null,
    type: null,
    props: {}
};

function render(vdom, container) {
    
    const {type, props} = vdom;
    
    if (typeof type === 'string') {
        const ele = document.createElement(type);
        
        each(props, (value, key) => {
          
          if (key === 'className') {
              ele.className = value;
              return;
          }
          
          if (key === 'style') {
              each(value, (attrV, attrK) => {
                  ele.style[attrK] = attrV;
              })
              return;
          }
        
          if (key === 'children') {
              
              let children = value;
              
              if (!Array.isArray(children)) {
                  children = [children]
              }
              
              each(children, (child) => {
                 
                 if (/^(string | number)$/.test(child)) {
                     ele.appendChild(document.createTextNode(child));
                 }
                 
                 render(child, ele);
                  
              })
              return;
          }
            
          ele.setAttribute(key, value);
        })
        
        
        container.append(ele);
    }
    
}

上一篇 下一篇

猜你喜欢

热点阅读