zoukankan      html  css  js  c++  java
  • 【like-react】手写一个类似 react 的框架

    平时写写 react,却不了解内部是怎么把 jsx 转化为 vdom,然后渲染在界面上,以及当数据流更新时,视图又是怎么更新的呢。 

    于是我查阅了大量资料后,自己手写了一个简单版的 react,从中大概能了解到 react 基本的运行机制。

     react 一个很方便之处是我们可以像写原生 html 那样写组件,这就是 jsx 语法,那么 jsx 是如何转化为 dom 的呢。首先通过 babel 语法树解析转化成为 vdom,它的结构大概是

    /* <div id="container">xxxxxx</div> */
    { type:
    'div', props: { id: 'container' }, children: ['xxxxx'] }

    之后通过 react 内部的 render 方法将 vdom 转为 dom 节点。

    render 方法实现如下:

    const _render = (vdom, parent = null) => {
        // custom component 经过 babel 转义 然后 React.createElement 返回的 vdom.type 类型是 function
        // <p id="label">title</p> vdom = { type: 'p', props: {id: 'label'}, children: ['title']}
        const mount = parent ? (el => parent.appendChild(el)) : (el => el);
        if (typeof vdom === 'string' || typeof vdom === 'number') {
          return mount(document.createTextNode(vdom));
        } if (typeof vdom === 'boolean' || vdom === null) {
          return mount(document.createTextNode(''));
        } if (typeof vdom === 'object' && typeof vdom.type === 'function') {
          return Component.render(vdom, parent);
        } if (typeof vdom === 'object' && typeof vdom.type === 'string') {
          const dom = mount(document.createElement(vdom.type));
          for (const child of [].concat(...vdom.children)) _render(child, dom);
          for (const prop in vdom.props) {
            if (Object.prototype.hasOwnProperty.call(vdom.props, prop)) {
              setAttribute(dom, prop, vdom.props[prop]);
            }
          }
          return dom;
        }
        throw new Error(`Invalid VDOM: ${vdom}.`);
      };

    值得一提的是在 ReactDOM.render() 时,首先会遍历所有节点,然后实例化节点,调用 componentWillMount 方法,接着 调用内部的 render 将 vdom 转化为 真实 dom,接受一个 标识符 key 值,这在更新组件时将会派上用场。紧接着调用 componentDidMount 方法。

    接下来讲一下 react 更新 state 时发生了什么。众所周知,传统的比较两棵树是否相同的时间复杂度是 O(n^3),而 react 基于一套比较规则将时间复杂度降到了 O(n),这大大提高了计算的时间,提高了渲染的速度。因此 react 在更新状态时的 patch 方法都做了什么。其实就是基于 react 的比较算法:1. 两棵树的节点类型都不同时则整棵树都替换;2.当节点的 key 值相同时则直接递归比较所有子节点。

    详细实现参见: https://github.com/Vxee/like-react

  • 相关阅读:
    [Ps]图层混合模式——排除
    [Swift]自定义View
    [Swift]Closures概念与使用
    [Swift]Class的概念与使用
    [Swift][OC]tableView去掉顶部空白
    html引用css的四种方法
    plSQL技巧:“tns:无法解析指定的连接标识符”问题详解
    桌面任务栏右侧的输入法状态(也就是语言栏)不见了,通常有以下几种解决方法:
    Myeclipse下java.lang.OutOfMemoryError: Java heap space的解决
    Tomcat使用相对路劲来访问
  • 原文地址:https://www.cnblogs.com/fjl-vxee/p/11027025.html
Copyright © 2011-2022 走看看