什么是 React
React是一个简单的javascript UI库,用于构建高效、快速的用户界面。它是一个轻量级库,因此很受欢迎。它遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效。它使用虚拟DOM来有效地操作DOM。它遵循从高阶组件到低阶组件的单向数据流。
前言
我们认为,React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式。它在 Facebook 和 Instagram 上表现优秀。官网地址
react 的理念是在于对大型项目的快速响应
,对于新版的 react 16.8 而言更是带来的全新的理念fiber
去解决网页快速响应时所伴随的问题,即 CPU 的瓶颈,传统网页浏览受制于浏览器刷新率、js 执行时间过长等因素会造成页面掉帧,甚至卡顿
react 由于自身的底层设计从而规避这一问题的发生,所以 react16.8 的面世对于前端领域只办三件事:快速响应、快速响应、还是 Tmd 快速响应 !,这篇文章将会从一个 html 出发,跟随 react 的 fiber 理念,仿一个非常基础的 react
一开始的准备工作
html
我们需要一个 html 去撑起来整个页面,支撑 react 运行,页面中添加<div></div>
,之后添加一个 script 标签,因为需要使用import
进行模块化构建,所以需要为 script 添加 type 为module
的属性
<!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 type="module" src="./index.js" ></script> </body> </html>
推荐安装一个 Live Server
插件,有助于我们对代码进行调试,接下来的操作也会用到
JavaScript
我们会仿写一个如下的 react,实现一个基础的操作,在 <input/>
绑定事件,将输入的值插入在 <h2/>
标签内:
... function App() { return ( <div> <input onInput={updateValue} value={value} /> <h2>Hello {value}</h2> <hr /> </div> ); } ...
在 react 进行 babel 编译的时候,会将 JSX
语法转化为 React.createElement()
的形式,如上被 retuen 的代码就会被转换成
... React.createElement( "div", null, React.createElement("input", { onInput: updateValue, value: value, }), React.createElement("h2", null, "Hello ", value), React.createElement("hr", null) ); ...
在线地址
从转换后的代码我们可以看出 React.createElement 支持多个参数:
type,节点类型 config, 节点上的属性,比如 id 和 href children, 子元素了,子元素可以有多个,类型可以是简单的文本,也可以还是 React.createElement,如果是 React.createElement,其实就是子节点了,子节点下面还可以有子节点。这样就用 React.createElement 的嵌套关系实现了 HTML 节点的树形结构。
我们可以按照 React.createElement
的形式仿写一个可以实现同样功能的 createElement
将 jsx 通过一种简单的数据结构展示出来即 虚拟DOM
这样在更新时,新旧节点的对比也可以转化为虚拟 DOM 的对比
{ type:'节点标签', props:{ props:'节点上的属性,包括事件、类...', children:'节点的子节点' } }
这里我们可以写一个函数实现下列需求
原则是将所有的参数返回到一个对象上 children 也要放到 props 里面去,这样我们在组件里面就能通过 props.children 拿到子元素 当子组件是文本节点时,通过构造一种 type 为 TEXT_ELEMENT
的节点类型表示
/** * 创建虚拟 DOM 结构 * @param {type} 标签名 * @param {props} 属性对象 * @param {children} 子节点 * @return {element} 虚拟 DOM */ const createElement = (type, props, ...children) => ({ type, props: { ...props, children: children.map(child => typeof child === "object" ? child : { type: "TEXT_ELEMENT", props: { nodeValue: child, children: [], }, } ), }, });
react 中 createElement 源码实现
实现 createElement
之后我们可以拿到虚拟 DOM,但是还需要 render
将代码渲染到页面,此时我们需要对 index.js
进行处理,添加输入事件,将 createElement
和 render
通过 import 进行引入,render 时传入被编译后的虚拟 DOM 和页面的根元素 root
, 最后再进行executeRender
调用,页面被渲染,在页面更新的时候再次调用executeRender
进行更新渲染
import {createElement,render} from "./mini/index.js"; const updateValue = e => executeRender(e.target.value); const executeRender = (value = "World") => { const element = createElement( "div", null, createElement("input", { onInput: updateValue, value: value, }), createElement("h2", null, "Hello ", value), createElement("hr", null) ); render(element, document.getElementById("root")); }; executeRender();
评论(0)