各个框架的特点
@姚冬 先生已经说的非常清楚了。我补充一点自己的体会,也供大家参考。
08 年的时候,我刚听说微软出了 WPF,非常兴奋。那时候的我写的最多的是 WinForms 的应用程序,但我对 WinForms 程序有诸多不满,主要原因是 WinForms 的设计仅仅是对系统的 Win32 API 做了一层薄薄的封装,UI 设计方面束缚依然比较大——老老实实套用内置控件倒还好,一旦要做些许“创新”,开发复杂度就陡然增大。
于是当年我就赶紧买下了 Charles Petzold 老爷子写的《Windows Presentation Foundation 程序设计指南》,如获至宝的学起来。这期间逐渐感受到 WPF 的强大,灵活,并憧憬着用它开发出更加酷炫的应用程序。
然而现实是残酷的,一个棘手的问题是 WPF 性能比预期差很多。当你为一个控件添加下拉阴影特效(DropShadowEffect)后,再让其参与到动画事件中,性能会急剧下降。起先我以为是我使用方法不正确,但最终发现这是一个普遍问题。归根结底,DropShadowEffect 在当时是用 CPU 完成计算的,当存在动画时,为了保证渲染正确,需要逐帧重新计算,导致 CPU 占用率暴涨,性能自然受到拖累。
尽管我们可以尝试一些“优化”手段,例如预先计算出一次 DropShadowEffect 后将其缓存,后续仅以位图方式重绘,这一方案自然能快很多,却也存在这样或那样的弊端,例如需要考虑缓存结果是否能与背景正确匹配的问题。另一种办法,我们还可以在纯色背景上预先计算出 DropShadowEffect 后,再将半透明化,这样既能保证性能,又能保证与背景正确匹配。但还是略有瑕疵。总之方法虽多,但需要具体情况具体设计,非常不方便。说到底这个问题还是应当由微软解决,而不是推给框架的使用者。
作为 UI 框架新贵,WPF 存在些许缺陷不足为奇。但有趣的是,下拉阴影导致性能下降的问题在同期的浏览器(如 Firefox)中却并不存在,你可以为任何元素添加下拉阴影,然后让它们动起来,浏览器依然顺畅如初。
这一个细节让当年轻视 Web 开发的我逐渐的意识到,浏览器作为一个渲染引擎,其性能经过了精心的优化,是一个优秀的 UI 容器。受此启发,在近两三年里,我便很少再用 WPF 开发了。后续的项目都采用基于内嵌浏览器内核(例如XULRunner、CEF)的方式。这样一来 UI 都用 Web 来做,就拥有极大的灵活性,例如可以使用 ExtJS、Bootstrap、Semantic UI 框架等等,而应用程序的能力则依然是 Native 的,可以完成任何之前的程序所能做到的事(调用 Win32 API?很容易)
我们交付的许多项目都是这样实现的。开发成本大大下降,而且跨平台也不再是问题。关键是可以享受到 Web 开发后续发展的所有红利,例如模板引擎,响应式界面,React UI 等等。
近来,node.js 的出现也再一次降低了这方面的开发成本,特别是 node-webkit (近来改名为 nw.js),electron 之类的程序,更是将这方面的开发门槛急剧降低——之前你如果不熟悉底层开发,你可能就不知道应当如何将 CEF 之类的控件嵌入到你的程序界面里,另外还需要解决 Web 界面与底层库的通信问题。但是使用 node-webkit(或 electron) 根本无需考虑这方面的问题。对于需要调用底层 API 的时候,直接给 node.js 增加 C++ Addon,在界面里就可以通过 JavaScript 调用。非常方便快捷。而且还有大量的 package 可用。不能更强了。
但是底层开发人员在向 Web 技术拓展的时候,常常遇到的最大的问题是在于固有思维定势带来的偏见。其中最常见的问题就是,觉得 Web 很糟糕,没有 Control 的概念,缺乏封装。因此用起来总觉得不好用。起初我也是这样认为的,但后来我发现并非如此。这其实是一个设计理念的差异。慢慢会发现各有利弊。Web 基于 Document 的设计也有颇多精彩之处。
总而言之,我总希望大家在传统 Native 框架的基础上,多试试基于 Web 的方案。你一定会因此变得更加强大,并找到更多乐趣的。
(关于 WPF 现在我了解的已经很少了,如果有错误,还请谅解)