SPA, 单页应用是指在浏览器中运行的应用,在使用期间页面不会重新加载。本项目是一个从前端到后端都是用JS语言来实现的应用,即纯'js'栈。
Chapter 01 在一个页面上完成的一个demo.
Chapter 03 渲染功能容器与管理应用状态。 ####深入理解Shell Shell 是单页应用的主控制器( master controller ), 在我们的架构中是必需的。可以看作是与MVC中Master Controller是一致的,因为它是协调所有从属功能模块的控制器。 Shell 负责以下事情。
- 渲染和管理功能容器。
- 管理应用状态。
- 协调功能模块。 ####创建文件和名字空间 我们会为js/css创建平行的文件结构,这种约定能加快开发,提升质量和简化维护。我们已经选择spa作为单页应用的根名字空间,JS和CSS文件名,JS名字空间和CSS选择器名称都同步使用。这样就可以很容易的追踪那个JS文件搭配那个CSS文件了。 ###管理功能容器 Shell渲染并管理着功能容器。
我们对聊天滑块函数的要求是适度的。我们需要它具有产品级的质量,但不用过度设计。 下面是我们想要完成的需求。
- 开发人员能配置滑块的运动的速度和高度。
- 创建单个方法来展开或者收起聊天滑块。
- 避免出现竞争条件(race condition ) 即,滑块可能同时在展开和收起。
- 开发人员能够传入一个可选的回调函数,会在滑块运动结束时调用。
- 创建测试代码,以便确保滑块功能正常。
锚组件的一个特殊功能是,在它改变的时候,浏览器不会重新加载页面,但是,锚的改变却会影响浏览器的前进/后退事件。锚组件是只给客户端使用的控件,它是保存应用状态的理想地方。很多单页应用都使用这个技巧。 我们把想保存在浏览器历史当中的应用状态( 本应用的状态就是 extend/retract 啦 )称之为历史事件( history events ),即我们认为 开始或结束聊天是历史事件, 我们通过在单击时改变锚来记住这个历史状态。
关于感叹号
http://localhost/spa.html#!chat=closed
, 中哈希符号后的感叹号(#!),用于告诉Google和其它搜索引擎,这个URI可以被搜索索引。
我们希望始终让锚组件来驱动可书签化的应用状态,这能确保历史功能一直按预期工作。下面的伪代码概括了我们是如何来处理历史事件的。
- 当发生历史事件(应用状态改变)时,更改URI的 anchor component( 锚组件 ),以便体现更改的状态。
- 接收事件的处理程序(onClickChat)调用Shell的工具方法(uriAnchor)来改变锚。
- 然后事件处理程序退出。
- Shell的hashchange事件处理程序注意到了URI变化并按它行事。
- 将当前状态和新的锚表示的状态做比较
- 根据比较确定的结果,尝试更改需要修改的应用部分。
- 如果不能处理请求的变化,则保持当前状态,并恢复锚,以便和状态匹配。
###V4.0 将chat功能模块完全从shell模块分离出来实现。 主要应用的开发模式是:FMVC( Fractal MVC)。设计的架构是,
- Shell 可以调用单页应用中的任何子模块。
- 功能模块只调用共享的公用模块。
- 功能模块之间的相互调用是不允许的。
- 功能模块的唯一数据源或者功能只能来自Shell,在配置和初始化期间以参数的形式会给模块的公开方法。
我们希望一直由URI 锚来驱动页面状态,而不是倒过来。
- Chat配置API spa.chat.configModule();
- Chat初始化API spa.chat.initModule();
- Chat的setSliderPosition API sap.chat.setSliderPosition();
###V5.0 Chapter05 将设计和构建Model的people对象。 Model向Shell和功能模块提供业务逻辑和数据。Model不依赖于用户界面(UI),它被分离出来负责逻辑和数据管理。 Model自身通过使用Data模块,从Web服务分离出来。
Model是Shell和所有功能模块访问单页应用的数据和业务逻辑的地方。如果需要登入,我们就调用Model提供的方法。如果想获取人员列表,就从Model获取。如果想获取头信息.....,好了,你懂得!任何希望在功能模块之间共享的或者对应用极为重要的数据和业务,都应该放在Model里面。
*Model不需要浏览器。*这就意味着Model不可以假定存在document对象,或者存在像document.location这种浏览器特有的方法。让Shell和功能模块来表示Model的数据是『干净的』MVC。 这样分离使得自动化测试和回归测试变得简单。