Skip to content

Hyperapp源码分析 #16

Description

@yesvods

前言

Hyperapp是一个轻量级视图库,拥有完备的界面渲染、以及视图数据交互更新能力。专注于视图渲染的核心部分,使得它的体积非常轻巧,也使得它具备"无限可能"。在设计上并无涉及太多复杂场景,尤为适用于轻量级的移动开发场景。

特点

1. 外置Action管理

Hyperapp仅关心状态渲染、调度生成后actions对象。在状态管理上,我们可以自主使用fluxredux,甚至无需使用任何状态管理库。

2. 外置渲染模板(语法)

Hyperapp提供vnode生成辅助函数,但并不限制渲染模板的选择,我们可以自由选择类似JSX,甚至类VUE的模板语言。

3. 单向数据流原则

Hyperapp初始渲染之后,触发视图更新的唯一方式是,通过调用action变更状态,从而触发视图更新。这使得我们可以建立易于跟踪、健壮、可维性强的应用。

大话Hyperapp源码

详细的分析,可以在源码注释仓库下看到,里面有hyperapp各个源码重要细节的分析。下面来介绍一下hyperapp源码有意思的地方:

1. 麻雀虽小,五脏俱全

专注于视图渲染&数据交互更新,在实现上也是恰到好处地实现这些功能。具备内置状态驱动的视图更新引擎、标准VNode四板斧、DOM-diff机制。在这点来说,hyperapp处于新生期,需要具备完善的生态,才可以发挥出强大的内核能力。

VNode四板斧:

// 基本的HTML标签都可以被抽象成如下形式:
// {
//   nodeName,
//   attributes,
//   children,
//   key
// }
// TextNode只有一个nodeValue,SVG也是比较特殊,所以在更新时候也会对这两种类型做特殊处理

DOM-diff 原则:

// 1. 平级对比,非平级则认为是不一样的dom,直接铲平重建
// 2. 只更新同类型节点,非同类型一样铲平重建
// 3. 尽可能利用现有dom,免除额外的删除创建开销,只需要重新插入(appendChild or insertBefore)
// 4. index&key相同的vdom,对应的dom无需对比,直接复用,下一个!

2. 刚刚好,就是最好的

hyperapp在细看一些实现上,会觉得有些"不严谨",可能会被钻空子。比如:cloneget等函数实现,或者是PromiseArray的判断。

事实上,这些函数用于在有标准DOM结构的实现、自调用的源码上,作为判断能达到"刚刚好"的要求。既不会浪费性能体积,也不会导致出错。

function get(path, source) {
	for (var i = 0; i < path.length; i++) {
		source = source[path[i]]
	}
	return source
}


// const result = { winner: { name: 'Tony' } }
// get(['winner', 'name'], result)  => Tony

不必具备lodash get的兼容性,以最优形态抽象出适用于源码的函数,便是最好的。

3. 简单的生命周期

说出来你可能不信,hyperapp仅有四个生命周期函数。

他们分别是:

  • 视图渲染
    • 初始渲染后:oncreate(DOMElement)
    • 视图更新后:onupdate(DOMElement)
  • 视图销毁
    • 销毁前执行:
      • onremove(DOMElement, action)
      • 可以控制异步销毁,需要手动调用action函数才会移除DOMElement
    • 销毁前通知:
      • ondestory(DOMElement)
      • 不能控制自己被销毁,可以在销毁前做一些同步操作,比如释放第三方库,防止内存泄露

这使得hyperapp比较适用于轻交互场景,配合webpack模板语法编译能力,可以实现非常轻量级的移动应用。

4. 严格的key控制

在列表渲染时候,hyperapp严格要求组件提供对应key属性。

如果没有对应的key,相当于默认每次渲染都是全新的列表,这会涉及到原有列表DOM的销毁、新列表DOM创建以及添加,大型列表上有可能会导致性能问题。

也正因为这个特性,使得在良好结构下,hyperapp渲染性能表现不亚于现有主流渲染库。

image

5. SSR支持

Hyperapp虽然精巧,却完全支持SSR特性。在初次渲染时候,会将现有DOM结构转成vdom,当有行为触发数据变动时,高效进行dom-diff以更新现有视图。

Link

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions