基于 JSX 的动态数据绑定
笔者在 2016-我的前端之路: 工具化与工程化一文中提及,前端社区用了 15 年的时间来分割 HTML、JavaScript 与 CSS,但是随着 JSX 的出现仿佛事物一夕回到解放前。在 Angular、Vue.js 等 MVVM 前端框架中都是采用了指令的方式来描述业务逻辑,而 JSX 本质上还是 JavaScript,即用 JavaScript 来描述业务逻辑。虽然 JSX 被有些开发者评论为丑陋的语法,但是笔者还是秉持 JavaScript First 原则,尽可能地用 JavaScript 去编写业务代码。在前文React 初窥:JSX 详解中我们探讨了 JSX 的前世今生与基本用法,而本部分我们着手编写简单的面向 DOM 的 JSX 解析与动态数据绑定库;本部分所涉及的代码归纳于 Ueact 库。
JSX 解析与 DOM 元素构建
元素构建
笔者在 JavaScript 语法树与代码转化实践 一文中介绍过 Babel 的原理与用法,这里我们仍然使用 Babel 作为 JSX 语法解析工具;为了将 JSX 声明转化为 createElement 调用,这里需要在项目的 .babelrc 文件中做如下配置:
"plugins": [
"transform-decorators-legacy",
"async-to-promises",
[
"transform-react-jsx", {
"pragma": "createElement"
}
]
],
/**
* Description 从 JSX 中构建虚拟 DOM
* @param tagName 标签名
* @param props 属性
* @param childrenArgs 子元素列表
*/
export function createElement(
tagName: string,
props: propsType,
...childrenArgs: [any]
) {}
该函数包含三个参数,分别指定标签名、属性对象与子元素列表;实际上经过 Babel 的转化之后,JSX 文本会成为如下的函数调用(这里还包含了 ES2015 其他的语法转化):
...
(0, _createElement.createElement)(
'section',
null,
(0, _createElement.createElement)(
'section',
null,
(0, _createElement.createElement)(
'button',
{ className: 'link', onClick: handleClick },
'Custom DOM JSX'
),
(0, _createElement.createElement)('input', {
type: 'text',
onChange: function onChange(e) {
console.log(e);
}
})
)
),
...