React中的虚拟DOM和JSX到底是什么

332 阅读1分钟

react开发者的日常都是在写JSX,但是我们平常写的JSX到底是个啥你知道吗?其实JSX并不是js中的合法代码,我们写的JSX都会经过babel-plugin-transform-react-jsx进行转换。

{
  "presets": ["env"],
  "plugins": [
    ["transform-react-jsx", {
      "pragma": "React.createElement"
    }]
  ]
}

我们来看一下他转换后会生成啥

console.log(<p className='test'>123</p>);

babel会把他转换成一个对象,tag是dom名称,children是里面包含的元素,attrs是属性 这个对象就是我们常说的虚拟DOM,

我们可以根据这个虚拟Dom自己写一个render函数把这个DOM转换成真实的DOM,类型于下面的代码一样

const myJSX = (
  <div className={'test'}>
    <p className={'test'}>test</p>
    <p>test</p>
  </div>
);

const render = (vnode, container) => {
  // 如果vnode 是字符串的话就渲染文本节点;
  if (typeof vnode === 'string') {
    const textNode = document.createTextNode(vnode);
    container.appendChild(textNode);
    return;
  }

  // 根据虚拟dom生成一个dom;
  const dom = document.createElement(vnode.tag);
  //判断这个虚拟dom是否有属性
  if (vnode.attrs) {
    // 遍历vnode.attrs
    Object.keys(vnode.attrs).forEach(attr => {
      // 在dom上设置他的属性
      console.log(attr);
      dom.setAttribute(attr, vnode.attrs[attr]);
    })
  };
  // 遍历子节点
  vnode.children.forEach(child => {
    render(child, dom);
  });
  container.appendChild(dom);
};

render(myJSX, rootDom);

render出来的dom就是这样的

这样我们就完成了一个简单的render函数,当然我们还需要把设置attrs的功能抽成一个函数,因为我们需要对className 之类的属性做一下处理。

那如果是封装好的组件因该怎么样处理?封装好了的组件在虚拟dom的tag里面是一个函数。怎么处理下次有机会说 哈哈哈。