单页应用要解决的第一个问题,就是浏览位置的传播问题。
你肯定不希望将看到喜欢的商品的链接地址发给好友后,好友点开看到的却是首页。如果这种现象真的被你遇到了,你十有八九碰到了一个调皮的程序员。
出现这种情况的原因,一般是客户端没有追踪用户在单页应用上的位置,并将其同步反馈至URL中;或者,客户端只有代码向URL的单向反馈,而忽略了反向的从URL读取并响应位置的功能。
这个问题,更多地应该是单页应用所使用的框架要解决的问题,也是当前部分框架的“路由功能”所要或已经解决的问题。如果你的单页应用没有用到任何框架,那么是时候将其抽取出来,以业务无关的方式为业务代码提供底层支持了。
由传播问题延伸出来的另一个问题,是对于部分要求操作先后顺序的应用(如:包含多个步骤的注册),如何限定应用在传播过程中,不论传播者所处何处,都不会被其他用户访问到中间步骤。 亦即,中间步骤是不能“直接访问”的。
对于这一问题,View.js提供了它自己的解决办法:设定视图不能直接访问。同时,开发者也可以为不能直接访问的视图设定回退视图。回退视图,亦即不能直接访问的视图在被尝试直接访问时要呈现的视图。
第二个需要开发者解决的,是单页应用页面被打开时的耗时问题。
由于单页应用预置了多个功能体, 因此页面打开时,不可避免地要将所有功能体的样式和脚本下载至浏览器中。而这些功能体的样式及脚本一般情况下在工程中独立存在。这也就意味着,如果不在发布环节做处理,代码的线上产品形态将等同于开发阶段的工程形态,那么当页面被访问时,浏览器将针对每个独立的资源分别加载。这种成本的转嫁(开发人员的开发成本转嫁为终端用户的使用成本)无疑延长了页面的加载时长,变成了应用推广使用的一大绊脚石。
为了解决这一问题,我们需要在发布环节为样式和脚本等资源加入合并操作,使得页面源码中引用的多个资源在执行发布构建时最终能够被合并、压缩为一个资源,并且同时自动调整页面中的资源引用,将多个独立的资源引用缩减为一个合并后的资源引用。npm(npm是一个存储许多使用nodejs实现的开源插件的平台)平台的gulp-build-html插件恰好就是有着这样工作特性的插件,可以非常完美地满足我们的构建需求。开发者需要做的,仅仅是按照工具的使用说明在源码中明确合并边界而已。插件的构建效果,可以参阅网站:http://wzhsoft.com。
脚本合并后,你可能会惊奇地发现:“填了这个坑的土是从其它地方挖的”。 玩笑归玩笑,虽然这么说并不贴切,但确有新的问题浮出水面。
其中一个比较直观的现象,是原本能够正常工作的功能体在资源合并后不能工作了,比如:点击没有反应等。当出现这种情况时,基本可以断定是其他功能体执行过程中遇到了错误,从而阻断了代码的顺序执行,导致原本能够正常工作的其它功能体的驱动脚本没有被执行所致。之所以合并前没有问题,是因为报错的代码段并不会跨文件影响其它文件。
这个问题,可以武断地将工程中每个脚本的正文内容使用try-catch包裹起来进行解决 。这时即使执行过程中出现了错误,也不会影响后续代码的顺序执行。
脚本资源合并后导致功能体不再正常工作的另一个可能的原因,是变量命名空间的管理问题。如果两个脚本都以开放的形式声明了同一标识符的变量,那么脚本合并后将会出现变量污染的现象。这种原因导致的问题在分析起来,往往比较费时费力。比较明智地做法,是将所有脚本撰写在闭包内,规避变量污染的可能。针对这一问题,View.js为每个功能体都提供了独立的数据存取上下文,使得使用了上下文存取数据的功能体能够将变量污染的可能缩小至一个功能体内部,而非window全局范围下,有效地节省了开发者宝贵的时间和精力。