单页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.单页 ...
随机推荐
- 【洛谷】2474:[SCOI2008]天平【差分约束系统】
P2474 [SCOI2008]天平 题目背景 2008四川NOI省选 题目描述 你有n个砝码,均为1克,2克或者3克.你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系.你把其中两个砝码A ...
- bzoj 2244
没有正确分析路径可能的条数,它是指数增长的,会爆long long. 然后就是正反两次时间分治. 另一个就是max with count,即带计数的最值,即除了记录最值,还要记录最值取得的次数. /* ...
- pygame系列_弹力球
这是pygame写的弹力球 运行效果: ======================================================== 代码部分: ================= ...
- hdoj 4445 Crazy Tank 物理题/枚举角度1
Crazy TankTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- Python学习笔记(六)—元组的操作
元祖也是一个列表,它和list的区别是元祖里面的元素无法修改: 如果元祖里面只有一个元素的话,那么你必须在这个元素后边加上逗号,这样才是元祖的类型:否则类型会显示其他类型 元组的定义: 元祖中的方法: ...
- CentOS的update-grub2命令
这个和Ubuntu还是有些区别,在CentOS修改成如下: grub2-mkconfig -o /boot/grub2/grub.cfg
- LoadRunner的简单使用《第一篇》
LoadRunner是一个用压力测试的软件.这东西比较难上手,光安装就非常麻烦.好不容易一步步跟着安装说明安装好之后,还是用不了. 记录一个问题如下: 导入脚本的时候报错fail to create ...
- 使用 C++ 的 StringBuilder 提升 4350% 的性能
http://blog.jobbole.com/109663/?utm_source=blog.jobbole.com&utm_medium=relatedPosts http://msdn. ...
- 在MyEclipse上安装svn插件
最近需要用到myeclipse做一个商城的项目开发,用svn作为项目的版本控制软件.但是在myeclipse上安装svn插件就是装不好,反复折腾了好几次都安装不成功.网上提供的安装办法有两种,一是:在 ...
- 原生js实现图片预览并上传
最近主导的PC客户端网站重构工程告一段落,下一阶段开始给公司APP开发H5页面,技术栈是react.最近碰到一个需求:需要在H5页面上添加身份证照片,预览并上传.因为要兼容安卓4.4以下版本的手机,所 ...