干货|使用AngularJS+nodejs实现聊天室

Posted 中兴开发者社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货|使用AngularJS+nodejs实现聊天室相关的知识,希望对你有一定的参考价值。

每天读一篇一线开发者原创好文

▍作者简介

作者吴建是非常优秀的前端工程师。本文将结合AngularJS+Bootstrap+Node.js+socket.io

搭建一个高效美观的在线聊天室,体现了各种技术整合的优点,并采用了最佳实践方式进行编码,结构清晰,代码简洁。相信大家都能从中受到启发~


一 基本知识介绍

1.AngularJS

     通常情况下,我们编写 javascript 没有明确的结构。虽然在编写小应用程序的时候没有问题,但这显然是不适合于大规模的应用程序。使用 AngularJS,您可以通过MVC(模型 - 视图 - 控制器)或MVVM (模型 - 视图 - 视图模型)模式来组织源代码。 AngularJS 是一个 MVW 框架,其中W代表可以用于任何项目。你可以组织你的代码模块,它可显著提高应用程序的可测试性和可维护性。

    数据绑定肯定是 AngularJS 最佳功能之一。你可以声明绑定的模型到 html 元素。当模型发生变化时,视图会自动更新,反之亦然。这可以减少大量的传统样板代码,保持模型和视图同步。

    AngularJS 指令让你使用 HTML 新语法快速的构建应用程序。您可以创建可重用的自定义组件与指令的API。

    AngularJS 使用 HTML 模板,这使事情变得简单,并允许设计人员和开发人员同时工作。设计人员可以按照通常的方式创建用户界面,而开发人员可以使用声明性绑定语法很容易配合不同的UI组件的数据模型。

2.socket.io

    socket.io是一个完全由JavaScript实现、基于Node.js、支持WebSocket的协议用于实时通信、跨平台的开源框架,它包括了客户端的JavaScript和服务器端的Node.js。Socket.IO除了支持WebSocket通讯协议外,还支持许多种轮询(Polling)机制以及其它实时通信方式,并封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。Socket.IO实现的Polling通信机制包括Adobe Flash Socket、AJAX长轮询、AJAX multipart streaming、持久Iframe、JSONP轮询等。Socket.IO能够根据浏览器对通讯机制的支持情况自动地选择最佳的方式来实现网络实时应用。

3.Express

    Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。丰富的 HTTP 快捷方法和任意排列组合的 Connect 中间件,让你创建健壮、友好的 API 变得既快速又简单。

二 界面效果

    1.登录界面

干货|使用AngularJS+nodejs实现聊天室

   2.聊天界面


二. 服务器端的实现

搭建Express服务器和实现服务器端的逻辑

 
   
   
 
  1. var express = require('express')

  2.     , app = express()

  3.     , server = require('http').createServer(app)

  4.     , io = require('socket.io')(server)

  5.     , port = parseInt(process.env.PORT, 10) || 8080;

  6.  

  7. app.configure(function () {

  8.     app.use(express.methodOverride());

  9.     app.use(express.bodyParser());

  10.     app.use(express.static(__dirname + '/app'));

  11. });

  12.  

  13. server.listen(port);

  14. console.log('Now serving the app at http://localhost:' + port + '/');

  15.  

  16. var numUsers = 0;

  17.  

  18. //socket监听连接事件

  19. io.on('connection', function (socket) {

  20.     var addedUser = false;

  21.  

  22.     socket.on('add:user', function (username) {

  23.         if (addedUser) return;

  24.         socket.username = username;

  25.         ++numUsers;

  26.         addedUser = true;

  27.         socket.emit('login', {

  28.             numUsers: numUsers

  29.         });

  30.  

  31.         socket.broadcast.emit('user joined', {

  32.             username: socket.username,

  33.             numUsers: numUsers

  34.         });

  35.     });

  36.  

  37.     socket.on('new:message', function (data) {

  38.         data.username = socket.username;

  39.         socket.broadcast.emit('new:message', data);

  40.     });

  41. });


三 客户端的实现

 1.创建和配置应用级模块

 推荐将Angular应用拆分成多个模块,比如服务模块、指令模块、过滤器模块。然后用应用级模块依赖它们,便于管理和测试。

 利用路由配置将应用主界面拆分成登录View组件面和聊天View组件。

 
   
   
 
  1. 'use strict';

  2.  

  3. var app = angular.module('chat', ['chat.services', 'chat.directives','ngRoute']);

  4.  

  5. app.config(['$routeProvider', function($routeProvider) {

  6.     $routeProvider.

  7.     when('/', {

  8.         controller: 'LoginCtrl',

  9.         templateUrl:'/views/login-page.html'

  10.     }).when('/chat', {

  11.         controller: 'ChatCtrl',

  12.         templateUrl:'/views/chat-page.html'

  13.     }).otherwise({redirectTo:'/'});

  14. }]);


2.创建服务

将消息通讯的业务逻辑封装在socket服务中。

 
   
   
 
  1. 'use strict';

  2.  

  3. var services = angular.module('chat.services', []);

  4.  

  5. services.factory('socket', function ($rootScope) {

  6.     var socket = io.connect('http://localhost:8080');

  7.     var username = '';

  8.     return {

  9.         on: function (eventName, callback) {

  10.             socket.on(eventName, function () {

  11.                 var args = arguments;

  12.                 $rootScope.$apply(function () {

  13.                     callback.apply(socket, args);

  14.                 });

  15.             });

  16.         },

  17.         emit: function (eventName, data, callback) {

  18.             socket.emit(eventName, data, function () {

  19.                 var args = arguments;

  20.                 $rootScope.$apply(function () {

  21.                     if (callback) {

  22.                         callback.apply(socket, args);

  23.                     }

  24.                 });

  25.             })

  26.         },

  27.         setUsername: function (name) {

  28.             username = name;

  29.         },

  30.         getUsername: function () {

  31.             return username;

  32.         }

  33.     };

  34. });


3.创建指令

Anuglar指令能够扩展DOM的功能和行为。如下的focus指令用来确保指定的输入元素能够聚焦。

 
   
   
 
  1. 'use strict';

  2.  

  3. var directives = angular.module('chat.directives', []);

  4.  

  5. directives.directive('focus',

  6.     function () {

  7.         return {

  8.             link: function (scope, element, attrs) {

  9.                 element[0].focus();

  10.             }

  11.         };

  12.     });

比如在下面的input元素中加入focus属性,使得登录界面的输入框默认获得焦点,方便用户输入用户名。

 
   
   
 
  1. <input type="text" class="form-control" placeholder="请输入用户名" ng-model="username" focus

  2.        ng-keyup="keyupHandler($event)">

4.login控制器

实现用户登录的功能。

 
   
   
 
  1. 'use strict';

  2.  

  3. app.controller('LoginCtrl', ['$scope', 'socket', '$location', function ($scope, socket, $location) {

  4.     $scope.username = '';

  5.  

  6.     $scope.keyupHandler = function (e) {

  7.         var keycode = window.event ? e.keyCode : e.which;

  8.         if (keycode !== 13) {

  9.             return;

  10.         }

  11.  

  12.         $scope.loginHandler();

  13.     };

  14.  

  15.     $scope.loginHandler = function () {

  16.         if (!$scope.username) {

  17.             return;

  18.         }

  19.  

  20.         $scope.isLogin = true;

  21.         socket.emit('add:user', $scope.username);

  22.         socket.setUsername($scope.username);

  23.         $location.path('/chat');

  24.     };

  25. }]);

5.chat控制器

实现聊天的功能,实时收发消息。

 
   
   
 
  1. 'use strict';

  2.  

  3. app.controller('ChatCtrl', ['$scope', 'socket', function ($scope, socket) {

  4.     $scope.message = '';

  5.     $scope.username = socket.getUsername();

  6.     $scope.messages = [];

  7.  

  8.     socket.on('new:message', function (message) {

  9.         $scope.messages.push(message);

  10.     });

  11.  

  12.     $scope.sendHandler = function (e) {

  13.         var keycode = window.event ? e.keyCode : e.which;

  14.         if (keycode !== 13) {

  15.             return;

  16.         }

  17.  

  18.         if (!$scope.message) {

  19.             return;

  20.         }

  21.  

  22.         socket.emit('new:message', {message: $scope.message});

  23.         $scope.messages.push({username: $scope.username, message: $scope.message});

  24.         $scope.message = '';

  25.     };

  26. }]);

6.index.html

AngularJS的模块化开发,使得页面代码简洁干净。

 
   
   
 
  1. <!DOCTYPE html>

  2. <html ng-app="chat">

  3.  

  4. <head lang="en">

  5.     <meta charset="utf-8">

  6.     <title>Chat System</title>

  7.     <link href="assets/styles/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">

  8.     <link href="assets/styles/font-awesome/css/font-awesome.min.css" rel="stylesheet">

  9.     <link href="assets/styles/app.min.css" rel="stylesheet">

  10.     <link href="assets/styles/style.css" rel="stylesheet">

  11.  

  12.     <script src="scripts/vendor/socket.io.js"></script>

  13.     <script src="scripts/vendor/angular.js"></script>

  14.     <script src="scripts/vendor/angular-route.js"></script>

  15.     <script src="scripts/app.js"></script>

  16.     <script src="scripts/services/services.js"></script>

  17.     <script src="scripts/directives/directives.js"></script>

  18.     <script src="scripts/controllers/main-controller.js"></script>

  19.     <script src="scripts/controllers/login-controller.js"></script>

  20.     <script src="scripts/controllers/chat-controller.js"></script>

  21.  

  22. </head>

  23. <body ng-controller="MainCtrl" class="container">

  24. <div ng-view></div>

  25. </body>

  26. </html>

以上是关于干货|使用AngularJS+nodejs实现聊天室的主要内容,如果未能解决你的问题,请参考以下文章

使用 Socket.IO 和 NodeJS 实现音频聊天

nodejs是怎么实现聊天的?

角度数组不更新视图

nodejs实现多人实时聊天

nodejs实现在线聊天室

Angularjs 中的 Socket.io