最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • build your own React

    正文概述 掘金(指甲盖)   2020-12-11   376

    index.js

    /**build your own react */
    
    // JSX是如何被解析的?
    // JSX通过babel会被解析成 React.createElement
    // // 比如
    // const element = <h1 >Hello</h1>
    // // 他会被解析成
    // const element1 = React.createElement(
    //     'h1', // 标签名
    //     { title: 'foo' }, // attributes
    //     "Hello", // children,一般是数组
    // )
    
    // Step1: 实现简易createElement
    function createElement(type, props, ...children) {
        return {
            // 标记 元素类型
            type,
            // 元素属性
            props: {
                ...props,
                // 子元素
                children: children.map((child) => {
                    // 为了区分 基本类型 和引用类型,单独使用 createTextElement来创建文本节点
                    return typeof child === "object" ? child : createTextElement(child);
                })
            }
        };
    }
    function createTextElement(text) {
        return {
            type: "TEXT_ELEMENT",
            props: {
                nodeValue: text,
                children: []
            }
        };
    }
    /**
    * var h=document.createElement("H1")
      var t=document.createTextNode("Hello World");
      h.appendChild(t);
      输出 <h1>Hello World </>的效果
    * 
    */
    
    // Step6
    function commitRoot() {
        commitWork(wipRoot.child)
        // commit阶段完成后,保存当前的fiber树
        currentRoot = wipRoot
        wipRoot = null
    }
    function commitWork(fiber) {
        if (!fiber) {
            return
        }
        const domParent = fiber.parent.dom
        domParent.appendChild(fiber.dom)
        commitWork(fiber.child)
        commitWork(fiber.sibling)
    }
    
    // Step2 我们需要render到真实的dom节点上
    function render(element, container) {
        // 设置fiber root
        wipRoot = {
            dom: container,
            props: {
                children: [element]
            },
            // 和上一次的commit阶段的 旧fiber 树建立连接
            alternate: currentRoot
        }
        nextUnitOfWork = wipRoot
    }
    let nextUnitOfWork = null
    // work in progress  fiber root
    let wipRoot = null
    let currentRoot = null
    // Step3 并发模式
    // Step4 fiber
    function workLoop(deadline) {
        // 是否需要暂停
        let shouldYield = false
        while (nextUnitOfWork && !shouldYield) {
            // 执行 一个工作单元并返回下一个工作单元
            nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
            // 判断空间时间是否足够
            shouldYield = deadline.timeRemaining() < 1
        }
        // 所有工作单元都执行完成后,我们一并进行提交操作
        // commitRoot里进行所有元素 往dom 树上添加的动作
        if (!nextUnitOfWork && wipRoot) {
            commitRoot()
        }
        // 需要暂停响应优先级更高的操作(比如用户交互)
        requestIdleCallback(workLoop)
    
        function performUnitOfWork(fiber) {
            // 创建一个dom元素,挂载到fiber的dom属性
            if (!fiber.dom) {
                fiber.dom = createDom(fiber)
            }
            const elements = fiber.props.children
            // reconcileChildren
            reconcileChildren(fiber, elements)
    
        }
        function reconcileChildren(wipFiber, elements) {
    
            let index = 0
            let oldFiber = wipFiber.alternate && wipFiber.alternate.child
            // 保存上一次fiber
            let preSibling = null
    
            while (index < elements.length || oldFiber != null) {
                const element = elements[index]
                const newFiber = null
                const sameType = oldFiber && element && element.type === oldFiber.type
                //  相同节点,属性迁移
                if (sameType) { }
                // 节点不同,且有新元素,执行新增
                if (element && !sameType) { }
                // 节点不同,且有旧元素,执行删除
                if (oldFiber && !sameType)
    
                    // 第一个子元素 作为 child,其余的 子元素 作为 sibling
                    if (index === 0) {
                        fiber.child = newFiber
                    } else {
                        preSibling.sibling = newFiber
                    }
                // 执行完后将fiber保存在preSibling
                preSibling = newFiber
                index++
            }
            // fiber链访问流程: 先孩子,然后是sibling,然后是uncle(uncle是孩子的parent, 是sibling的parent),以此类推
            if (fiber.child) {
                // 第一个孩子存在
                return fiber.child
            }
            let nextFiber = fiber
            while (nextFiber) {
                // 其他孩子在react中,被称为fiber的sibling
                if (nextFiber.sibling) {
                    return nextFiber.sibling
                }
                // 
                nextFiber = nextFiber.parent
            }
        }
    
    
    }
    
    
    // 给库命名
    const MyReact = {
        createElement,
        render
    };
    /** @jsx MyReact.createElement */
    const element = (
        <div style="background: salmon">
            <h1>Hello World</h1>
            <h2 style="text-align:right">from myReact</h2>
        </div>
    );
    const container = document.getElementById("root");
    MyReact.render(element, container);
    
    

    package.json

    {
      "name": "react",
      "version": "1.0.0",
      "description": "React example starter project",
      "keywords": [
        "react",
        "starter"
      ],
      "main": "src/index.js",
      "dependencies": {
        "react": "17.0.0",
        "react-dom": "17.0.0",
        "react-scripts": "3.4.3"
      },
      "devDependencies": {
        "typescript": "3.8.3"
      },
      "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test --env=jsdom",
        "eject": "react-scripts eject"
      },
      "browserslist": [
        ">0.2%",
        "not dead",
        "not ie <= 11",
        "not op_mini all"
      ]
    }
    

    起源地下载网 » build your own React

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元