美文网首页
React 源码解析(1)React之JSX和虚拟DOM

React 源码解析(1)React之JSX和虚拟DOM

作者: DayBreak_a625 | 来源:发表于2020-04-25 17:53 被阅读0次
    React
    本文主要介绍React 大概思路,实现自己的简易版React。知其然知其所以然,用了React必定要了解和掌握其中的知识。废话不多说....
    • React之JSX和虚拟DOM (当前)
    • React之组件实现
    • React之生命周期方法
    • React之Diff算法
    • React之封装子组件更新
    • React之异步的setState

    1.用过React的同学都知道,在我们开发过程中都会引用React和ReactDOM,同时我们也必须知道React.createElement()ReactDOM.render()这两个方法,我们就从这里开始讲起。
    2.我们同时也要装几个babel的插件npm i babel-core babel-preset-env babel-plugin-transform-react-jsx 将jsx语法转换成js对象(虚拟dom)
    3.这里打包用的是 parcel npm install -g parcel-bundler 可以去官网了解parcel

    .babelrc 配置文件

    {
      "presets": ["env"],
        "plugins": [
          ["transform-react-jsx", {
            "prama": "React.createElement"
          }]
        ]
    }
    
    有两个主要的文件夹 react 与 react-dom src下的index.js

    1.index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div id="root"></div>
      <script src='index.js'></script>
    </body>
    </html>
    

    2.index.js文件

    import React from './react';
    import ReactDOM from './react-dom';
    
    const ele = (
      <div className="ele" title="123">
        hello,<span>react</span>
      </div>
    )
    
    ReactDOM.render(ele, document.querySelector('#root'))
    

    3.react

    const React = {
      createElement
    }
    
    function createElement(tag, attrs, ...childrens) {
      return {
        tag,       //外层标签 
        attrs,     //属性 是一个对象
        childrens  //子级节点 是一个数组
      }
    };
    
    export default React
    
    • react 目前只有一个文件 index.js
    • createElement(tag,attrs,child1,child1...)会将我们的组件转换成对象形式

    4.react-dom

    WechatIMG693.png
    • render(vnode, container) 方法
      1.vnode是我们的虚拟dom,就是createElement所返回的对象
      2.container就是我们前边用到的 document.querySelector('#root')
    • setAttribute(dom, key, val)方法
      1.dom当前节点
      2.key比如className、styel、onClick
      3.val属性值
    • 代码里面的每一步注释都写的很清楚,剩下的大家可以看代码了
    
    const ReactDOM = {
      render
    }
    // 渲染
    function render(vnode, container) {
      // 如果不存在
      if (!vnode) return
      //如果是字符串
      if (typeof vnode === 'string') {
        const str = document.createTextNode(vnode)
        return container.appendChild(str)
      }
      //如果是个对象
      if (typeof vnode === 'object') {
        // 标签 属性 子级
        const { tag, attrs, children } = vnode
        if (tag) {
          // 创建节点对象
          const dom = document.createElement(tag)
          // 属性 val :attrs[key]
          if (attrs) {
            Object.keys(attrs).forEach(key => {
              const val = attrs[key]
              setAttribute(dom, key, val)
            })
          }
          // 递归调用 child == vnode, dom == container
          vnode.childrens.forEach(child => render(child, dom))
          return container.appendChild(dom)
        }
      }
    }
    // 设置属性
    function setAttribute(dom, key, val) {
      //将classNname转换class
      if (key == 'className') key = 'class'
      //事件 onClick :onclick 正则
      if (/on\w+/.test(key)) {
        key = key.toLowerCase()
        dom[key] = val
      } else if (key == 'style') {
        // 如果没有或者是字符串
        if (!val || typeof val == 'string') {
          dom.style.cssText = val
        } else if (typeof val == 'object') {
          // 例如 { width:20 }
          for (let k in val) {
            // 数字
            if (typeof val[k] == 'number') {
              dom.style[k] = val[k] + 'px'
            } else {
              dom.style[k] = val[k]
            }
          }
    
        }
      } else {
        // 其他属性
        if (key in dom) {
          dom[key] = val || ''
        }
        if (val) {
          dom.setAttribute(key, val)
        } else {
          dom.removeAttribute(key)
        }
      }
    
    }
    
    export default ReactDOM
    

    5.两个问题

    1.为什么ReactDOM.render()必须要引入React?
    2.函数组件、类组件、创建出的对象是否又跟当前的ele对象相似呢?
    下篇文章《React之组件实现》我们就来实现对应的组件一些相关的封装

    5.小结

    这些就是本篇文章的主要内容,有问题可以在下方提问,双击加关注,还可以打赏 哈哈哈 😁,谢谢大家!

    相关文章

      网友评论

          本文标题:React 源码解析(1)React之JSX和虚拟DOM

          本文链接:https://www.haomeiwen.com/subject/sxekwhtx.html