从0到1打造一款没人用的前端框架

Author Avatar
GeniusFunny 12月 07, 2018
  • 在其它设备中阅读本文章

如果可以,为什么我们不自己打造一款没人用的前端框架呢?

首先介绍如何创建虚拟DOM节点以及将虚拟DOM节点转化为真实DOM节点,参照React/Preact

创建虚拟DOM节点

我们在React会经常写出下列类似的代码

1
const Example = <span id='example'>Hello, Example</span>

这段代码不是合法的JavaScript代码,这段是JSX代码。JSX是JavaScript的语法拓展,用来声明React中的元素。看起来它就像一个模版语言,但是它并不是,它是完全是在JavaScript内部实现的。

那么我们写的JSX代码是如何被JavaScript解析的呢?

这里就不得不提一下Babel,Babel是一个JavaScript编译器,将用ES6/ES7等ES最新的语法书写的代码转换为浏览器支持的ES版本(如ES5、ES3)。这就让我们开发者能够最快的用上ES的新语法糖

Awesome!!!🎉🎉🎉

Babel在这里用于将我们书写的JSX代码转换为标准javaScript代码,上面的例子就被转换为:

1
var foo = h('span', {id: 'example'}, 'Hello, Example')

所以我们需要书写一个h函数用于被转译的代码调用,至于为什么叫h,因为它来源于hyperscript中的h函数。

接下来就是完成一个非常非常简单的h函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 创建一个Virtual DOM 对象
* @param nodeName 标签名称
* @param attributes 属性
* @param ...args 组件的孩子
*/

function h(nodeName, attributes, ...args) {
let children = args.length ? [].concat(...args) : null;
return {
nodeName, attributes, children
}
}

通过这个函数,我们就能创建一个简单的Virtual Dom对象,比如上面的JSX例子,调用这个函数我们会得到:

1
2
3
4
5
6
7
{
nodeName: "span",
attributes: {
"id": "example"
},
children: ["Hello, Example"]
}

当然这个函数是远远不能满足实际生产中的要求,所以后面我们会慢慢完善它。

虚拟DOM转换为真实DOM

接下来我们定义一个render函数,用于将Virtual DOM对象渲染为真实的DOM节点。

1
2
3
4
5
6
7
8
9
10
11
12
function render(vnode) {
if (vnode.split) {
return document.createTextNode(vnode);
}
let node = document.createElement(vnode.nodeName)
let attributes = vnode.attributes || {}
Object.keys(attributes).forEach(k => {
node.setAttribute(k, attributes[k])
})
(vnode.children || []).forEach(c => node.appendChild(render(c)))
return node
}

但是我们通常会将创建出来的真实DOM节点挂在现存的节点上,所以render函数需要改造一下:

1
2
3
4
function render(vnode, container) {
//...
return container.appendChild(node)
}