单页WEB应用(三),Chat聊天模块
Chat 聊天模块
这个模块应该就是该书全篇的唯一一个模块吧,后面差点儿全部的篇章都环绕这个模块去实现的,只是就通过这一个模块的实现和上线,也能体现单页应用开发到公布上线的整个过程,毕竟后面的数据。通信。公布什么的都是通用的东西,应用其它部分全然能够參照这个‘聊天模块’去实现。跟着作者的思路走一遍,也能熟知个大概。
先看下成型图吧,会不会有种非常老旧XP时代的感觉,囧!
!

chat 内容
该聊天模块总体分下面几块:事实上都是跟着模版去实现的,差在详细实现上而已
- 配置;
- 事件处理。
- 初始化。
涉及行为处理: 
1. 点击标题栏。显示或隐藏窗体。 
2. hash 值的变化触发聊天窗体的状态变化;
重点在 通过 hash 值(锚)的变化来管理聊天窗体显示和隐藏。前面在shell里面实现过,这里主要拎出来作为一个单独模块来讲
配置
配置三大块:
之前chat 模块是直接在shell模块中实现的,为了实现模块化,降低依赖,从而把该模块分离出来单独创建模块文件:spa.chat.js 和对应的样式和辅助文件等
- configMap- 这里包括了 - chat模块的基本配置,和所用到的模块变量,来看下里面详细都有些啥- var configMap = { // 模块的文档结构部分,通过动态载入到其父容器中
 main_html: ''
 + '<div class="spa-chat">'
 + '<div class="spa-chat-head">'
 + '<div class="spa-chat-head-toggle">+</div>'
 + '<div class="spa-chat-head-title">Chat</div>'
 + '</div>'
 + '<div class="spa-chat-closer">x</div>'
 + '<div class="spa-chat-sizer">'
 + '<div class="spa-chat-msgs"></div>'
 + '<div class="spa-chat-box">'
 + '<input type="text" />'
 + '<div>send</div>'
 + '</div>'
 + '</div>'
 + '</div>', // 这个映射表,对应配置里面的变量,从对象名便可知,是用来
 // 保存配置是否可设置状态。true:表示该变量值能够改变,反之不能改动
 settable_map: { slider_open_time : true,
 slider_close_time : true,
 slider_opened_em : true,
 slider_closed_em : true,
 slider_opened_title : true,
 slider_closed_title : true, chat_model : true,
 people_model : true,
 set_chat_anchor : true
 }, // 窗体关闭和打开的动画时间,使用 $.animate 时使用的时间
 slider_open_time : 250,
 slider_close_time : 250,
 slider_opened_em : 18,
 slider_closed_em : 2, // 两个最小阀值用来防止页面被缩放的时候。聊天窗体同比例缩放导致变的太小而做出的限制
 // 这里单位是:em
 slider_opened_min_em : 10,
 window_height_min_em : 20, // 窗体打开和隐藏状态时。鼠标放在上面时显示的提示内容,通过元素的'title'属性实现
 slider_opened_title : 'Click to close',
 slider_closed_title : 'Click to open', // 两个数据模型,该书採用了数据库插件:taffyDb 来管理和模拟数据
 chat_model : null,
 people_model : null, // 此方法是聊天窗体显示和隐藏的关键
 // 核心模块shell 正是通过这个接口来管理聊天模块触发锚的变化从而
 // 让聊天模块具备前进后台历史等浏览器功能
 // 该方法指向shell模块中的 setChatAnchor 函数,
 // setChatAnchor 在 shell 中定义,与 'uriAnchor' 插件发生联系
 // 然后通过配置模块:configModule, 将该函数与`chat`模块发生联系,从而
 // 使 chat 改变 -> setChatAnchor -> shell 锚管理
 set_chat_anchor : null
 },- 通过 - set_chat_anchor改变聊天窗体状态变化路径图 - 通过图中就能明显的看出,chat 是怎样通过 shell 来实现状态更新。以及实现自身的前进后退历史等功能 
- stateMap- 相对于基本配置容器里面的配置,在执行过程中基本都不会有变化的值来说, - stateMap里面就是一些执行过程中,会由于用户行为而发生变化的一些状态值了- 突然发现人在不同的时间和不同的认知段会对同一个事物的理解和解释大有不同(废话么。谁不知道啊! - ! - ) - var stateMap = { // 模块容器。不多说
 $container: null, // 位置值,表示模块窗体因用户行为而发生变化的状态值
 // 主要有:'closed','opened','hidden'
 position_type : 'closed', // 单位转换, px/em,实际执行过程中会涉及到元素的位置设置。通过转换
 // 得到实际像素值,去设置
 px_per_em : 0, // 下面三个就是针对三个不通状态时,窗体的位置了
 slider_hidden_px : 0,
 slider_closed_px : 0,
 slider_opened_px : 0
 }- 针对 - stateMap里面的属性,有几个针对性的函数- 第一个就是 - setPxSizes。由于页面都是通过 em 来设置大小的,因此在获取实际像素值的时候须要做个响应的转换- /*
 这里面干了下面几件事: 1. 获取 em -> px 的单位值,然后计算出当前文档窗体的总高度值:window_height_em
 2. 依据文档窗体决定模块窗体打开时的高度:opened_height_em
 3. 更新 stateMap 里面的窗体相关的状态值
 4. 最后确定聊天窗体内容体的详细高度 */
 setPxSizes = function () { var
 px_per_em, opened_height_em, window_height_em; px_per_em = getEmSize( jqueryMap.$slider.get(0) ); // 计算窗体高度:em
 window_height_em = Math.floor(
 ( $(window).height() / px_per_em ) + 0.5
 ); // 依据范围值来决定窗体打开的高度
 opened_height_em
 = window_height_em > configMap.window_height_min_em
 ? configMap.slider_opened_em
 : configMap.slider_opened_min_em; stateMap.px_per_em = px_per_em;
 stateMap.slider_closed_px = configMap.slider_closed_em * px_per_em;
 stateMap.slider_opened_px = opened_height_em * px_per_em; jqueryMap.$sizer.css({
 height: ( opened_height_em - 2 ) * px_per_em
 });
 }; // 这个函数,须要在初始化模块initModule中将模块载入到容器中之后,
 // 就须要执行,由于当中涉及的一些状态值须要在兴许执行操作过程中就要用到,
 // 比方:px_per_em, slider_closed_px,slider_opened_px 等等
 - 第二个函数就是: - setSliderPosition,这个是真正改动聊天窗体显示隐藏状态的函数,里面通过- $.animate动画实现,而且是提供给- shell模块。在 hash 值发生变化时触发了- hashchange事件调用事件处理函数:- onHashChange,里面依据详细的状态值去调用的,因此上面的状态走向图还不是非常准确。- /* 这里面的实现。主要依赖与:position_type,依据用户行为,去改变这个值。然后终于通过 hash 值的变化。传到这里,去改变窗体显示或隐藏 里面涉及到的參数:
 height_px:动画的目标属性,窗体高度
 animate_time: 动画时间
 slider_opened_title:以及窗体改变后显示的 title 属性值 最后通过动画结束后的回调:callback
 */ setSliderPosition = function ( position_type, callback ) { var
 height_px, animate_time, slider_title, toggle_text, setAttr; if ( stateMap.position_type === position_type ) {
 return true;
 } setAttr = function ( height, an_time, title, text ) { height_px = height;
 animate_time = an_time;
 slider_title = title;
 toggle_text = text;
 }; switch ( position_type ) {
 case 'opened':
 setAttr(
 stateMap.slider_opened_px,
 configMap.slider_open_time,
 configMap.slider_opened_title,
 '='
 );
 break; case 'hidden':
 setAttr( 0, configMap.slider_open_time, '', '+' );
 break; case 'closed':
 setAttr(
 stateMap.slider_closed_px,
 configMap.slider_close_time,
 configMap.slider_closed_title,
 '+'
 );
 break;
 default:
 return false;
 break;
 } // 重置位置类型
 stateMap.position_type = '';
 jqueryMap.$slider.animate(
 { height: height_px },
 animate_time,
 function () {
 jqueryMap.$toggle.prop( 'title', slider_title );
 jqueryMap.$toggle.text( toggle_text );
 stateMap.position_type = position_type;
 callback && callback( jqueryMap.$slider );
 }
 ); return true;
 };- 上面的图改动之后加入 - setSliderPosition就比較完美了 - 最后为了应对窗体的 - resize事件。窗体须要做出对应的变化:- handleResize- // spa.chat.js handleResize = function () { if ( !jqueryMap.$slider ) { return false; } setPxSizes();
 if ( stateMap.position_type === 'opened' ) {
 jqueryMap.$slider.css({ height: stateMap.slider_opened_px });
 } return true;
 }; // spa.shell.js 中应对 window 的 resize 事件 onResize = function ( event ) { if ( stateMap.resize_idto ) { return true; } spa.chat.handleResize();
 stateMap.resize_idto = setTimeout(function () {
 stateMap.resize_idto = undefined;
 }, configMap.resize_interval); return true;
 };
 - 值得一提的是应对 - window的- resize事件方案採取的是针对每一个模块实现自己的应对方法。从而使模块能自己来决定怎样应对窗体的缩放应对方式
- jqueryMap- 这里面的东西就不多记录了。都是些死的东西,缓存模块内元素的对象,方便 - jQuery使用,相同须要在该模块被追加到模块容器- shell中之后才调用- /*
 这里就不能直接用 $.html 了,而是使用 $.append 追加到模块容器 `shell` 模块当中
 */ setJqueryMap = function () { var
 $append_target = stateMap.$append_target,
 $slider = $append_target.find( '.spa-chat' ); jqueryMap = {
 $slider : $slider,
 $head : $slider.find( '.spa-chat-head' ),
 $toggle : $slider.find( '.spa-chat-head-toggle' ),
 $title : $slider.find( '.spa-chat-head-title' ),
 $sizer : $slider.find( '.spa-chat-sizer' ),
 $msgs : $slider.find( '.spa-chat-msgs' ),
 $box : $slider.find( '.spa-chat-box' ),
 $input : $slider.find( '.spa-chat-box input[type=text]' ),
 };
 };
总结
这篇主要介绍了该书对 chat 模块的处理,用这个演示样例来说明子模块怎样和模块管理器模块:shell相互作用。怎样组装子模块。怎样通过锚变化来管理子模块的状态变化,以及怎样应对 window 的 resize 事件的思想。另外还包括了怎样移除 chat 模块,当中涉及的 removeSlider 处理等。
这里面须要注意的地方也没几处,主要感觉还是要弄清楚,模块的状态值和状态的变化怎样在子模块和 shell 模块之间是怎样传递以及起作用的,上面两张过程图更直观点。
到此。模块的页面和组装基本完毕了,下一篇将会介绍该书是怎样实现数据模型,怎样让数据模型发生作用(数据管理插件:taffyDb)。
完结,待续……!
单页WEB应用(三),Chat聊天模块的更多相关文章
- 构建单页Web应用——简单概述
		一.开发框架 ExtJS可以称为第一代单页应用框架的典型,它封装了各种UI组件,用户主要使用JavaScript来完成整个前端部分,甚至包括布局.随着功能逐渐增加,ExtJS的体积也逐渐增大,即使用于 ... 
- 单页Web应用优缺点
		一.定义单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用.它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HT ... 
- 单页Web应用:
		概念: Web应用程序: WEB应用程序一般是B(浏览器)/S(服务器)模式.Web应用程序首先是“应用程序”,和用标准的程序语言,如C.C++等编写出来的程序没有什么本质上的不同.然而Web应用程序 ... 
- 构建单页Web应用
		摘自前端农民工的博客 让我们先来看几个网站: coding teambition cloud9 注意这几个网站的相同点,那就是在浏览器中,做了原先“应当”在客户端做的事情.它们的界面切换非常流畅,响应 ... 
- 单页web应用(SPA)的简单介绍
		单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用.它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML.J ... 
- 简陋的 ASP.NET CORE 单页Web应用程序“框架”
		我对ASP.NET CORE了解不多,不知道是不是重复造轮子,也或者什么也不是,这个Demo是这样的: 1.非常简单或者说原始:2.将单页Web应用增加了一个页(Page)概念(相当于MVC的 Vie ... 
- Javascript 与 SPA单页Web富应用
		书单推荐 # <单页Web应用:JavaScript从前端到后端> http://download.csdn.net/detail/epubitbook/8720475 # <MVC ... 
- 单页web应用是什么?它又会给传统网站带来哪些好处?
		文章来源:<单页Web应用:JavaScript从前端到后端> 什么是单页应用? 单页应用是指在浏览器中运行的应用,它们在使用期间不会重新加载页面.像所有的应用一样,它旨在帮助用户完成任务 ... 
- 论单页Web应用和RESTful架构
		单页Web应用 概述 单页Web应用并不是突然诞生的一门新技术,而是web展示的一种新的尝试.它将所有的动作局限于一个Web页面,在加载站点首页的时候就加载站点需要的JavaScript和CSS.单页 ... 
随机推荐
- 计算机二级软件VC++6.0下载地址
			计算机二级软件VC++6.0介绍: 适合所有参加全国计算机等级考试的童鞋们……见图如下: 下载地址:(以下两者任选其一即可) (1).计算机二级软件VC++6.0(16.35MB) (2).计算机二级 ... 
- PYQT控件使用
			QtGui.QComboBox .addItem(string)#添加字符串项到Item.addItems(list)#添加列表或元组元素到Item.clear()#清除所有Item.clearEdi ... 
- 文件上传demo
			前端代码: <form action="upload.php" enctype="multipart/form-data" method="po ... 
- Java_基础知识回顾
			1.ByteArrayInputStream. ByteArrayOutputStream String str = "ZHANGSAN"; //System.out.printl ... 
- druid数据源
			Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系. DruidDataSource 高效可管理的数据库连接池 ... 
- 使用Bootstrap 3开发响应式网站实践05,使用Tab、Modal、Form展示内容,使用Popover、Tooltip展示提示信息
			本篇体验用Tab插件显示内容.Html部分为: <div class="row" id="moreInfo"> <div class=&quo ... 
- java hashcode()和equal()方法比较
			通常equals,toString,hashCode,在应用中都会被复写,建立具体对象的特有的内容. 之所以有hashCode方法,是因为在批量的对象比较中,hashCode要比equals来得快,很 ... 
- [Apache] Apache 從 2.2 換至 2.4 httpd.conf 的調整筆記 (windows 環境)
			原文地址: http://www.dotblogs.com.tw/maplenote/archive/2012/07/20/apache24_httpd_conf.aspx 整理一下 Windows ... 
- leetCode解题报告5道题(九)
			题目一:Combinations Given two integers n and k, return all possible combinations of k numbers out of 1 ... 
- 表单提交的3种方式,http post的contentType
			application/x-www-form-urlencoded:窗体数据被编码为名称/值对.这是标准的编码格式.这是默认的方式 multipart/form-data:窗体数据被编码为一条消息,页 ... 
