Inferno是一个可构建高性能用户界面的同构库,这类库针对移动设备尤其关键。Inferno和典型的虚拟DOM库不同,比如React、Mithril、Cycle和Om等,Inferno采用了智能技术来区分静态和动态的内容,这让Inferno仅仅“区分”渲染那些有动态值的内容。
除此之外,我们精心优化代码以确保它的开销尽可能的少,我们相信Inferno是当前业界最快的虚拟DOM实现框架 —— 如我们的基准测试所示,Inferno完全是为性能而生,同时还提供了一个健壮的API库,复制了诸如React等库的最佳特性。
关键特性
- 最快的DOM UI渲染前端框架之一
- 拥有类似React ES2015 API的组件
inferno-component - 完全支持无状态组件,感谢Inferno的hooks系统提供了更多可用性
- 同构(或通用)使得服务端渲染在Inferno-server上更简易
基准测试
安装
和React很相似,Inferno需要引入inferno包和inferno-dom包,用于浏览器DOM内的消费,还有一个用于服务端渲染的inferno-server包,用于将虚拟DOM变为HTML字符串(和React的route不一样,它是用react-dom/server做服务端渲染)。此外,组件在一个独立的inferno-component包内,具有更好的模块化,而不是像React那样通过类在核心内引入ES2015组件。
核心包:
npm install --save inferno
ES2015有状态组件包(带生命周期事件):
npm install --save inferno-component
浏览器DOM渲染包:
npm install --save inferno-dom
创建Inferno的VNotes (和React.createElement相同):
npm install --save inferno-create-element
服务端渲染包:
npm install --save inferno-server
浏览器的预加载文件:
http://infernojs.org/releases/0.7.8/inferno.min.js
http://infernojs.org/releases/0.7.8/inferno-create-element.min.js
http://infernojs.org/releases/0.7.8/inferno-component.min.js
http://infernojs.org/releases/0.7.8/inferno-dom.min.js
http://infernojs.org/releases/0.7.8/inferno-server.min.js
概述
让我们看些代码。正如你所见,Inferno在组件上有意保持了和React一致的良好设计思想:单向数据流和关注点分离。下面这些例子里,JSX通过Babel插件提供了一种展现Inferno的虚拟DOM的简单方法。
import Inferno from 'inferno';
import InfernoDOM from 'inferno-dom';
const message = "Hello world";
InfernoDOM.render(
,
document.getElementById("app")
)
此外,Inferno和React一样也使用了ES6组件:
import Inferno from 'inferno';
import { Component } from `inferno-component`;
import InfernoDOM from 'inferno-dom';
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
}
}
render() {
return (
Header!
Counter is at: { this.state.counter }
)
}
}
InfernoDOM.render(, document.body);
React和Inferno的真正区别是运行时的性能差异,Inferno能轻松处理大量复杂的DOM模型,这对于平板或手机一类的低配设备是至关重要的,用户往往要求他们的低速设备像桌面设备那样性能快速。
Inferno.createVNode
创建一个具有链式方法的Inferno VNode对象
import createVNode from `inferno`;
InfernoDOM.render(createVNode().setTag('div').setClassName('foo').setAttrs({ id: 'test' }).setChildren('Hello world!'), document.body);
Inferno.createBlueprint
创建一个具有预定义蓝图的Inferno VNode,使用该蓝图的引用可以减少开销,提高性能。
import InfernoDOM from 'inferno-dom';
const myBlueprint = Inferno.createBlueprint({
tag: 'div',
attrs: {
id: 'foo'
},
children: { arg: 0 }
});
InfernoDOM.render(myBl ueprint('foo'), document.body);
createBlueprint的对象中的每个属性,只要是用{ arg: X }形式定义的,都会被当成一个动态值(匹配调用该blueprint的参数),其他形式则被当成静态值。举个例子:如果对象是const blueprint = Inferno.createBlueprint({ tag: { arg: 0 } }),那么应该这样调用,blueprint(‘div’),即使用第一个参数作为VNode的标签。
InfernoCreateElement
创建一个Inferno VNode,这个API和React的createElement很相似。
InfernoServer.renderToString
import InfernoServer from 'inferno-server';
InfernoServer.renderToString(, document.body);
渲染一个虚节点,并添加至HTML字符串,假定已提供虚拟DOM。
钩子
请注意:钩子由inferno-dom提供;
Inferno支持DOM节点上的多种基本事件,比如onClick、onMouseOver 和onTouchStart,此外Inferno允许直接将普通钩子附加到组件和DOM节点上。下列表格展示了inferno-dom中的所有可用钩子:
名称触发条件回调参数onCreated一个DOM节点被创建domNodeonAttached一个DOM节点被附加在文档domNodeonWillDetach一个DOM节点将要被从文档中移除domNodeonWillUpdate一个DOM节点将要执行潜在的更新domNodeonDidUpdate一个DOM节点已经执行潜在的更新domNodeonComponentWillMount一个无状态组件即将挂载domNode, propsonComponentDidMount一个无状态组件已经挂载domNode, propsonComponentWillUnmount一个无状态组件即将被卸载domNode, propsonComponentShouldUpdate一个无状态组件已被触发更新domNode, lastProps, nextPropsonComponentWillUpdate一个无状态组件即将执行更新domNode, lastProps, nextPropsonComponentDidUpdate一个无状态组件已经更新domNode, props
InfernoServer.renderToString
import InfernoServer from 'inferno-server';
InfernoServer.renderToString(, document.body);
渲染一个虚节点,并添加至HTML字符串,假定已提供虚拟DOM。
钩子
请注意:钩子由inferno-dom提供;
Inferno支持DOM节点上的多种基本事件,比如onClick、onMouseOver 和onTouchStart,此外Inferno允许直接将普通钩子附加到组件和DOM节点上。下列表格展示了inferno-dom中的所有可用钩子:
名称触发条件回调参数onCreated一个DOM节点被创建domNodeonAttached一个DOM节点被附加在文档domNodeonWillDetach一个DOM节点将要被从文档中移除domNodeonWillUpdate一个DOM节点将要执行潜在的更新domNodeonDidUpdate一个DOM节点已经执行潜在的更新domNodeonComponentWillMount一个无状态组件即将挂载domNode, propsonComponentDidMount一个无状态组件已经挂载domNode, propsonComponentWillUnmount一个无状态组件即将被卸载domNode, propsonComponentShouldUpdate一个无状态组件已被触发更新domNode, lastProps, nextPropsonComponentWillUpdate一个无状态组件即将执行更新domNode, lastProps, nextPropsonComponentDidUpdate一个无状态组件已经更新domNode, props
InfernoServer.renderToString
import InfernoServer from 'inferno-server'; InfernoServer.renderToString(, document.body);
将一个虚拟节点渲染进 HTML 字符串,并提供虚拟的 DOM 结构。
钩子
请注意:钩子是通过 inferno-dom 提供的;
Inferno 支持很多 DOM 节点的基本事件,例如 onClick, onMouseOver 和 onTouchStart。此外,Inferno 允许你直接在组件和 DOM 节点中附加通用事件。下表是 inferno-dom 提供的所有钩子:
| 名称 | 触发提交 | 回调参数 |
|---|---|---|
onCreated |
DOM 节点创建时 | domNode |
onAttached |
DOM 节点被附加到文档时 | domNode |
onWillDetach |
DOM 节点将被文档移除时 | domNode |
onWillUpdate |
DOM 节点将要执行任何潜在的更新 | domNode |
onDidUpdate |
DOM 节点已经支持完更新操作 | domNode |
onComponentWillMount |
将要安装无状态的组件 | domNode, props |
onComponentDidMount |
已经成功安装无状态组件 | domNode, props |
onComponentWillUnmount |
将要卸载无状态组件 | domNode, props |
onComponentShouldUpdate |
无状态组件被触发用于更新 | domNode, lastProps, nextProps |
onComponentWillUpdate |
无状态组件将要更新 | domNode, lastProps, nextProps |
onComponentDidUpdate |
无状态组件完成更新操作 | domNode, props |
使用钩子
为DOM节点和无状态组件隐式的分配钩子是很简单的,请注意:从inferno-component来的有状态组件(ES2015类)不支持钩子。
function createdCallback(domNode, props) {
// [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)
// [props] will only be passed for stateless components
}
InfernoDOM.render(, document.body);
function StatelessComponent({ props }) {
return Hello world;
}
InfernoDOM.render(, document.body);
性能
Inferno尝试处理创建UI组件时的两大难题:
- 在大团队中编写大的应用程序是很慢的,尤其在开发效率和成本开销方面 —— 其实不应该
- 通常在手机、平板或老设备上编写复杂的应用程序会导致很差的性能 —— 其实不应该
- 编写加强的现代UI界面需要进行多次更新和加入许多动画,很容易崩溃,界面变得过于复杂 —— 其实不应该
JSX
Inferno有自己的JSX Babel plugin。
和React的区别
Inferno努力保持和React基本API的兼容,只是在某些地方做了替代式的实现,当这些替换的解决方法容易采用,不用做太多改变时,一些非永久的特性就被彻底去除或是取代了。
自定义命名空间
Inferno一直想交付高性能的框架并计划如此,因此不得不对DOM状态和元素的可变性做出明智的假设,但自定义命名空间与此冲突,它可能会改变元素和属性的工作模式,所以Inferno不打算试图支持命名空间。相反,SVG的命名空间是自动应用到元素和属性上的,根据它们自身的标签名称。
有状态的ES2015组件位于独立包内
React的ES2015组件一般是作为React引用,为了减少Inferno核心的膨胀,我们提取了ES2015组件放入它自身的独立包内,具体点是inferno-component而非Inferno.Component,很多用户选择和Inferno的钩子一起使用无状态组件,它和ES2015组件具有同样的功能。
属性间的自动单位插入
Inferno不会试图在数值属性或特性上添加单位,但React会自动添加。举个例子:React处理样式
时将会造成px被自动添加。为保证。
参考
测试
npm run test:browser // browser tests
npm run test:server // node tests
npm run test // browser and node tests
npm run browser // hot-loaded browser tests
编译
npm run build
检查
npm run lint:source // lint the source