写在前面
最近忙于公司的事情,好久没有动手写点什么了,感觉心里怪怪的,昨天又忙于吃狗粮,肚子有点不舒服,不过总算过去了。又是周末啦,继续node之路咯。
基础版
首先着手页面布局,我们的布局很简单,就是一个单页面的应用,使用jade模板已经bootstrap样式,实现布局。我们所需要的样式以及交互的增强效果,主要通过bootstrap以及其扩展库来支持,模板引擎的使用jade。
layout.jade页面布局模板如下:
doctype html
html
head
title= title
meta(name="viewport",content="width=device-width, initial-scale=1")
link(rel='stylesheet', href='http://cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/main.css')
script(src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js")
script(src="http://cdn.bootcss.com/bootstrap/3.2.0/js/bootstrap.min.js")
body
block content
首页index布局如下:
extends layout
block content
link(rel='stylesheet', href='/stylesheets/sco.message.css')
link(rel='stylesheet', href='/stylesheets/message.css')
.container
.row
.col-sm-3
.panel.panel-primary(style="margin-right:-10px;")
.panel-heading
span.glyphicon.glyphicon-user
span 在线成员
.panel-body
.msg-list-body.user-content
ul
li(style="display:none;")
a(href="#")
img.img-thumbnail(src="/images/1.jpg")
span
.panel-footer
.btn-group
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-home
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-user
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-film
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-music
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-heart
button.btn.btn-primary(type="button")
span.glyphicon.glyphicon-envelope
.col-sm-9
.panel.panel-primary
.panel-heading
span.glyphicon.glyphicon-comment
span 聊天室
span#spanuser(style="float:right;")
.panel-body
.msg-list-body.msg-content
.panel-footer
.input-group
.input-group-addon
a(href="#")
img(src="/images/bq.png")
.input-group-addon(style="padding-bottom:0px;")
label(style="position:relative;")
img(src="/images/jt.jpg",title="send images",style="cursor:pointer;")
input#sendImage(type="file",value="images",style="display:none;")
input.form-control#msg(type="text",placeholder="请输入聊天内容",onkeydown="javascript:keywordsMsg(event);")
span.input-group-btn
button.btn.btn-primary#sendMsg(type="button") 发送/Send
.modal.fade#myModal(tabindex="-1")
.modal-dialog
.modal-content
.modal-header
h4.modal-title#myModalLabel 请设置聊天昵称
.modal-body
.form-group
.input-group
.input-group-addon 昵称
input.form-control#username(type="text",value="李阳",onkeydown="javascript:keywordsName(event);")
.modal-footer
input.btn.btn-primary#btn-setName(type="button",value="应用昵称")
.modal.fade#setMsgToOne(tabindex="-1")
.modal-dialog
.modal-content
.modal-header
h4.modal-title#myModalLabel1
.modal-body
input.form-control#input_msgToOne(type="text",onkeydown="javascript:keywordsName1(event);")
.modal-footer
input.btn.btn-primary#btn_toOne(type="button",value="发送/Send")
//script(src="/socket.io/socket.io.js")
//script(src='/javascripts/chat.js')
//script(src='/javascripts/client.js')
//script(src='/javascripts/sco.message.js')
到现在为止,我们只在乎页面布局,js等先一概不管。
使用jade时注意缩进,否则布局可能会出错哦。
此时打开我们的浏览器,页面已经出来喽:
世间竟有这般美貌的女子!
万事俱备,只欠东风,界面已了,那么接下来就是处理信息内容的发送这些功能了。
额,等等,我们还需要一个页面通知,使用sco.message.js来通知用户登录信息,在index.jade中引用所需的js文件:
script(src="/socket.io/socket.io.js")
script(src='/javascripts/chat.js')
script(src='/javascripts/client.js')
script(src='/javascripts/sco.message.js')
首先,我们在服务器server.js中写下服务器在有用户上线时向客户端chat发送信息:
// server.js
// 引入socket.io
var io = require('socket.io')();
// 创建io的连接事件
io.on('connection',function (socket) {
console.log('有一个用户登录了!');
// io是对于整个服务器而言,而用户下线这是针对某个客户端,客户端使用socket而不是io
socket.on('disconnect',function(){
console.log('用户下线了');
});
// 上线后服务器向客户端传输信息
io.emit("onLine",'');
});
// 在使用socket.io的应用中,使用io来监听服务器端口
// 创建监听器
exports.listen =function (server) {
io.listen(server);
};
emit方法即为事件派发器,向客户端发送事件。既然服务器发送了信息,那么客户端也就该有个函数来接收服务器所发送的信息:
// chat.js
var socket = io();
// 接收服务器发来的信息
socket.on("onLine",function (message) {
showMsg();
});
showMsg()在client.js中定义:
'use strict';
// 展示内容
function showMsg(message) {
$.scojs_message('This is an info message', $.scojs_message.TYPE_OK);
}
至于:
$.scojs_message('This is an info message', $.scojs_message.TYPE_OK);
这就是我们引用的soc.messgae.js来提供了,他是bootstrap用户增强效果所提供的js文件。
此时刷新一下浏览器:
而此时,若是我们使用两个浏览器同样的访问我们的聊天室,当我们刷新的时候,发现两个浏览器都会有通知,也就是说,我们会向所有在线的用户通知我自己上线了。
note:
我们使用socket.io时,需要注意,当我们派发够格事件,若是用io则是向所有客户端进行派发,若是使用socket则是向当前用户进行派发。
我们在服务器server.js中使用到了io.emit(“onLine”,’’);方法进行派发事件, 此时我们只派发了用户上线事件,那么我们也可以派发下线事件:
// server.js
'use strict';
// 引入socket.io
var io = require('socket.io')();
// 使用io则是面向所有用户(客户端),废话,服务器当然是面对所有客户端了
// 创建io的连接事件
io.on('connection',function (socket) {
console.log('有一个用户登录了!');
// io是对于整个服务器而言,而用户下线这是针对某个客户端,客户端使用socket而不是io
socket.on('disconnect',function(){
// console.log()是在cmd中打印
console.log('用户下线了');
// 向客户端派发下线事件
io.emit("offLine",'');
});
// 上线后服务器向客户端传输信息
io.emit("onLine",'');
});
// 在使用socket.io的应用中,使用io来监听服务器端口
// 创建监听器
exports.listen =function (server) {
io.listen(server);
};
注意io.emit(“offLine”,’’);的位置哦!
那么在客户端也写一个接收下线通知的函数:
// chat.js
// 接收来自服务器的上线通知
socket.on("onLine",function (message) {
showMsg(0);
});
// 接收来自服务器的下线通知
socket.on("offLine",function (message) {
showMsg(1);
});
看到了不同了么,没错,showMsg()函数,我们传入了参数,以用于判断用户是下线还是上线,所以我们还需要修改一下showMsg()来接收参数并根据不同的参数判断是下线还是上线,以便发出不同的通知:
// clinet.js
// 展示内容
function showMsg(type) {
if(type == 0){
$.scojs_message('This is an user online', $.scojs_message.TYPE_OK);
}
if (type == 1) {
$.scojs_message('This is an user offline', $.scojs_message.TYPE_ERROR);
}
}
TYPE_OK和TYPE_ERROR是soc.messgae.js的样式。我们还是打开两个浏览器,刷新之:
有如清水出芙蓉的感觉么!