看不到的React

时间:2021-1-8 作者:admin

看不到的React

React的JSX语法

JSX语法与原生语法的不同之处

JSX 原生
class类名 className class
style 需要写对象 直接写字符串

JSX语法中使用变量

JSX语法中使用变量需要{}来使用,并且不能是对象等引用数据类型(数组除外,但是如果数组中包含对象也不行)

JSX的编译

依靠babel-preset-react-app来进行编译

JSX的语法可以通过babel-preset-react-app来进行编译,通过编译之后变为CREATE-ELEMENT格式,React.createElement([标签名],[PROPS|NULL],...) 有几个子节点,从第三个实参开始分别是每一个子节点的处理(文本节点直接就是文本内容,元素节点还需要再一次CREATE-ELEMENT处理)

<div className="box" id="box" index="1">
 学习React
 <span className="text">
  欢迎大家来学习
  <i></i>
 </span>
</div>

// 转换为

React.createElement("div", {
  className: "box",
  id: "box",
  index: "1"
}, "学习React", React.createElement("span", {
  className: "text"
}, "欢迎大家来学习", React.createElement("i", null)));

执行createElement变为虚拟DOM

执行CREATE-ELEMENT
 * =>返回一个对象 {
 *   key:null,
 *   ref:null,
 *   type:标签名/组件,
 *   props:{
 *    xxx:xxx, //=>给元素标签上设置的属性(REF/KEY除外)
 *    //=>没有子节点则没有children选项,有子节点才有children,只有一个字节点它的值是单个值,如果有多个子节点,它的值是一个数组
 *    children:单个值(字符串/对象) 或者 数组
 *   }
 * }

最后将虚拟DOM通过render变为真实DOM插入到容器中

/*
 * createElement:创建出一个虚拟的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);
 }
 //=>children处理
 if (childs.length > 0) {
  childs = childs.length === 1 ? childs[0] : childs;
  jsxOBJ.props.children = childs;
 }
 return jsxOBJ;
}

/*
 * render:把虚拟的DOM变为真实的DOM
 */
export function render(jsxOBJ, container, callback) {
 let {
  type,
  props
 } = jsxOBJ;
 // 1.根据TYPE创建一个DOM元素对象(真实DOM)
 let element = document.createElement(type);
 // 1.1根据PROPS中的属性,依次给创建的元素进行设置
 for (let key in props) {
  if (!props.hasOwnProperty(key)) break;
  // 1.2关于某些属性的特殊处理:className/style/children
  if (key === 'className') {
   element.className = props['className'];
   continue;
  }
  if (key === 'style') {
   let styOBJ = props['style'];
   for (let styKey in styOBJ) {
    if (!styOBJ.hasOwnProperty(styKey)) break;
    element['style'][styKey] = styOBJ[styKey];
   }
   continue;
  }
  if (key === 'children') {
   let val = props['children'],
    childrenArr = Array.isArray(val) ? val : [val];
   // 1.3迭代所有子元素,如果是字符串直接做为文本插入到新创建的元素中,如果是一个新的虚拟DOM对象,递归调用RENDER,再次创建元素标签超入到新创建的元素中
   childrenArr.forEach(item => {
    if (typeof item === "string") {
     element.appendChild(document.createTextNode(item));
     return;
    }
    render(item, element);
   });
   continue;
  }
  element.setAttribute(key, props[key]);
 }
 // 2.把创建的元素对象添加到指定的容器中
 container.appendChild(element);
 callback && callback();
}

本文使用 mdnice 排版

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。