<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <link href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link href="https://www.jb51.net/article/assets/style/app.css"/> <script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script src="https://www.jb51.net/socket.io/socket.io.js"></script> <script src="https://cdn.bootcss.com/angular.js/1.4.3/angular.min.js"></script> <script src="https://www.jb51.net/article/assets/js/app.js"></script> </head> <body></body> </html>
我们并不立即深入逻辑细节,把框架搭好先。
首先,在body上加上ng-app属性,标记一下angularjs的“管辖范围”。这个练习中我们只用到了一个控制器,同样将ng-controller属性加到body标签。
复制代码 代码如下:
<body ng-app="chatRoom" ng-controller="chatCtrl">
接下来在js中,我们来创建module及controller。
var app=angular.module("chatRoom",[]); app.controller("chatCtrl",['$scope','socket','randomColor',function($scope,socket,randomColor){}]);
注意这里,我们用内联注入添加了socket和randomColor服务依赖。这里我们不用推断式注入,以防部署的时候用uglify或其他工具进行了混淆,变量经过了重命名导致注入失效。
在这个练习中,我们自定义了两个服务,socket和randomColor,前者是对socket.io的包装,让其事件进入angular context,后者是个可以生成随机色的服务,用来给头像指定颜色。
//socket服务 app.factory('socket', function($rootScope) { var socket = io(); //默认连接部署网站的服务器 return { on: function(eventName, callback) {...}, emit: function(eventName, data, callback) {...} }; }); //randomcolor服务 app.factory('randomColor', function($rootScope) { return { newColor: function() { return '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);//返回一个随机色 } }; });
注意socket服务中连接的语句“var socket = io();”,我们并没有传入任何url,是因为其默认连接部署这个网站的服务器。
考虑到聊天记录以及在线人员列表都是一个个逻辑及结构重复的条目,且html结构较复杂,为了其复用性,我们把它们封装成两个指令:
app.directive('message', ['$timeout',function($timeout) {}]) .directive('user', ['$timeout',function($timeout) {}]);
注意这里两个指令都注入了'$timeout'依赖,其作用后文会解释。
这样一个外层框架就搭好了,现在我们来完成内部的细节。
登录
页面刚加载时只显示登录界面,只有当输入昵称提交后且收到服务端通知昵称有效方可跳转到聊天室。我们将ng-show指令添加到登录界面和聊天室各自的dom节点上,来帮助我们显示或隐藏元素。用'hasLogined'的值控制是显示或隐藏。
<!-- chat room --> <div ng-show="hasLogined"> ... </div> <!-- end of chat room --> <!-- login form --> <div ng-show="!hasLogined"> ... </div> <!-- end of login form -->
JS部分
$scope.login = function() { //登录 socket.emit("addUser", {...}); } //收到登录结果 socket.on('userAddingResult', function(data) { if (data.result) { $scope.hasLogined = true; } else { //昵称被占用 $scope.hasLogined = false; } });
这里监听了socket连接上的'userAddingResult'事件,接收服务端的通知,确认是否登录成功。
socket连接监听
成功登录以后,我们还监听socket连接上的其他事件:
复制代码 代码如下: