
文章插图
根据以上信息,我们可以使用 snabbdom 创建我们内部的 虚拟DOM节点 ,然后我们才能将其用于我们的协调(reconciliation) 过程,可以使用如下的命令安装 snabbdom:
npm install snabbdom 当 QndReact.createElement(...) 被调用时吗,创建和返回 虚拟DOM节点 。
//src/qnd-react.js import { h } from 'snabbdom'; const createElement = (type, props = {}, ...children) => {return h(type, { props }, children); }; const QndReact = {createElement }; export default QndReact; 很好,现在我们可以解析 JSX 并创建自己的虚拟DOM节点,但是仍然无法在浏览器中呈现出来 。为此,我们在 src/qnd-react-dom.js 添加一个 render 方法 。
//src/qnd-react-dom.js //React.render(<App />, document.getElementById('root')); const render = (el, rootElement) => {//将el渲染到rootElement的逻辑 } const QndReactDom = {render } 与其我们自己去处理将元素放到 DOM 上的繁重工作,不如让 snabbdom 去处理 。为此我们可以引入模块去初始化 snabbdom 。snabbdom 中的模块可以看做是插件,可以支持 snabbdom 做更多的事 。
//src/qnd-react-dom.js import * as snabbdom from 'snabbdom'; import propsModule from 'snabbdom/modules/props'; const reconcile = snabbdom.init([propsModule]); const render = (el, rootDomElement) => {//将el渲染到rootElementreconcile(rootDomElement, el); } const QndReactDom = {render } export default QndReactDom; 我们使用这个新的 render 函数去 src/index 中去做一些魔法 。
//src/index.js import QndReact from "./qnd-react"; import QndReactDom from './qnd-react-dom'; const App = (<div><h1 className="primary">QndReact is Quick and dirty react</h1><p>It is about building your own React in 90 lines of JavsScript</p></div> ); QndReactDom.render(App, document.getElementById('root')); 瞧,我们的JSX已经可以渲染到屏幕上了 。

文章插图
等下,这个有一个小问题,当我们两次调用 render 时,我们会在控制台看到一些奇怪的错误(译者注: 可以在 index.js 中多次调用 render,查看控制台错误),背后的原因是我们只有在第一次渲染时,可以在真实的DOM节点上调用 reconcile 方法,然后,我们应该在之前返回的虚拟DOM节点上调用 。
//src/qnd-react-dom.js import * as snabbdom from 'snabbdom'; import propsModule from 'snabbdom/modules/props'; const reconcile = snabbdom.init([propsModule]); let rootVNode; //QndReactDom.render(App, document.getElementById('root')) const render = (el, rootDomElement) => {if(rootVNode == null) {//第一次调用 render 时rootVNode = rootDomElement;}rootVNode = reconcile(rootVNode, el); } const QndReactDom = {render } export default QndReactDom; 很开心,我们的应用程序中有一个能正常工作的 JSX 渲染,现在让我们开始渲染一个函数组件,而不仅仅是一些普通的 html 。
让我们向 src/index.js 添加一个 Greeting 函数组件,如下所示:
//src/index.js import QndReact from "./qnd-react"; import QndReactDom from './qnd-react-dom'; const Greeting = ({ name }) => <p>Welcome {name}!</p>; const App = (<div><h1 className="primary">QndReact is Quick and dirty react</h1><p>It is about building your own React in 90 lines of JavsScript</p><Greeting name={"Ameer Jhan"} /></div> ); QndReactDom.render(App, document.getElementById('root')); 此时,在控制台会出现以下错误:

文章插图
我们可以在 QndReact.createElement(...) 方法中打印出数据看一下原因 。
//src/qnd-react.js import { h } from 'snabbdom'; const createElement = (type, props = {}, ...children) => {console.log(type, props, children);return h(type, { props }, children); }; ...

文章插图
如果可以看到,函数组件传递过来的 type 是一个JS函数 。如果我们调用这个函数,就能获得组件希望渲染的 HTML 结果 。
我们根据 type 参数的类型,如果是函数类型,我们就调用这个函数,并将 props 作为参数传给它,如果不是函数类型,我们就当作普通的 HTML 元素处理 。
//src/qnd-react.js import { h } from 'snabbdom'; const createElement = (type, props = {}, ...children) => {//如果是函数组件,那么调用它,并返回执行结果if (typeof (type) == 'function') {return type(props);}return h(type, { props }, children); }; const QndReact = {createElement }; export default QndReact;
推荐阅读
- ThinkPHP5任意代码执行分析全记录
- 五峰,多角度广思维构建现代茶产业体系 打造土家生态茶乡
- Swoole简介
- 佳能喷墨打印机报错不能用?看到这些代码这样做立马解决
- php之"EXCEL导出"代码生成器的实现思路
- 运行 JavaScript 代码片段的 20 种工具
- 博士|复旦博士写了130行代码:2分钟搞定繁琐的核酸筛查
- 十五个常见的WordPresswp-config.php设置代码
- 如何优雅的在头条插入代码,介绍几款在线源代码转图片工具
- 暴雪|魔兽正式服:玩家复原暴雪代码,10.0增加新职业,兼顾3个职责?
