AngularJS+Node.js实现在线聊天室  更新时间:2015年08月28日 10:55:04   投稿:hebedich   随着互联网和信息技术的发展,如何快速构建高效、强大的动态网站成为很多人研究的热点。该文将结合AngularJS和Node.js构建一个在线聊天室,体现AngularJs和Node.js整合的优点。 不得不说,上手AngularJS比我想象得难多了,把官网提供的PhoneCat例子看完,又跑到慕课网把大漠穷秋的AngularJS实战系列看了一遍,对于基本的使用依然有很多说不清道不明的疑惑,于是决定通过做一个在线聊天室帮助理解。DEMO可以戳→chat room,代码可以戳→ChatRoom-AngularJS。 清晰图可以戳 //img.jbzj.com/file_images/article/201508/201508281040051.gif 功能 着手开发之前,首先明确一下需要实现的功能: 新用户登入,广播通知其他用户 用户下线,广播通知其他用户 可显示在线人数及列表 可群聊,可私信 用户若发送群消息,广播通知其他所有用户 用户若发送私信,单独通知收方界面 因为自己是个审美渣,所以全靠bootstrap了,另外还模仿了下微信聊天记录里的气泡设计。 界面分左右两个板块,分别用于显示在线列表和聊天内容。 在左侧的在线列表中,点击不同项可以切换右侧板块的聊天对象。 右侧显示与当前聊天对象的对话记录,不过仅显示最近的30条。每一条聊天记录内容包括发送人的昵称及头像、发送时间、消息内容。关于头像,这里做简单处理,用填充了随机色的方块代替。另外,自己发出去的消息与收到的消息样式自然要做不同设计,所有效果可以看下图。 清晰图可以戳 //img.jbzj.com/file_images/article/201508/201508281040052.png 服务端 服务端我们用Node.js以及混入express、socket.io来开发,在程序根目录打开终端,执行: 复制代码 代码如下: npm init 根据提示,生成一个package.json文件。打开并配置依赖项: “dependencies”: { “express”: “^4.13.3”, “socket.io”: “^1.3.6” } 之后执行 npm install 安装依赖模块。 接下来,我们在根目录下新建app.js,在其中写Server端代码。再新建public文件夹,存放client端代码。 app.js中主要内容如下: var express = require(‘express’); var app = require(‘express’)(); var http = require(‘http’).createServer(app); var io = require(‘socket.io’)(http); app.use(express.static(__dirname + ‘/public’)); app.get(‘/’, function (req, res) { res.sendfile(‘index.html’); }); io.on(‘connection’,function(socket){ socket.on(‘addUser’,function(data){ //有新用户进入聊天室 }); socket.on(‘addMessage’,function(data){ //有用户发送新消息 }); socket.on(‘disconnect’, function () { //有用户退出聊天室 ); }); http.listen(3002, function () { console.log(‘listening on *:3002’); }); 在上面的代码中,我们为以下事件添加了监听: -addUser,有新用户进入聊天室 该事件由客户端输入昵称后触发,服务端收到后对昵称是否已存在进行判断,如果已存在,通知客户端昵称无效: 复制代码 代码如下: socket.emit(‘userAddingResult’,{result:false}); 反之,通知客户端昵称有效以及当前所有已连接的用户信息,并把新用户信息广播给其他已连接用户: socket.emit(‘userAddingResult’,{result:true}); allUsers.push(data);//allUsers保存了所有用户 socket.emit(‘allUser’,allUsers);//将所有在线用户发给新用户 socket.broadcast.emit(‘userAdded’,data);//广播欢迎新用户,除新用户外都可看到 其中需要注意’socket.emit’与’socket.broadcast.emit’的区别,可以查看这篇博文socket.io emit的几种用法解释: // send to current request socket client socket.emit(‘message’, “this is a test”); // sending to all clients except sender socket.broadcast.emit(‘message’, “this is a test”); -addMessage,有用户发送新消息 在此事件监听里,需要分成两类情况处理: 1.私信 如果消息是发给特定用户A,那么就需要获取A对应的socket实例,然后调用其emit方法。所以每当一个客户端连接到Server端时,我们得把其socket实例保存起来,以备后续之需。 复制代码 代码如下: connectedSockets[nickname]=socket;//以昵称作下标,保存每个socket实例,发私信需要用 需要发私信时,取出socket实例做操作即可: 复制代码 代码如下: connectedSockets[nickname].emit(‘messageAdded’,data) 2.群发 群发就比较简单了,用broadcast方法即可: 复制代码 代码如下: socket.broadcast.emit(‘messageAdded’,data);//广播消息,除原发送者外都可看到 -disconnect,有用户退出聊天室 需要做三件事情: 1.通知其他用户“某用户下线” 复制代码 代码如下: socket.broadcast.emit(‘userRemoved’, data); 2.将用户从保存了所有用户的数组中移除 3.将其socket实例从保存了所有客户端socket实例的数组中移除 复制代码 代码如下: delete connectedSockets[nickname]; //删除对应的socket实例 运行一下服务端代码,观察有无错误: 复制代码 代码如下: node app.js 若没什么问题,继续编写客户端的代码。 客户端 在public目录下新建’index.html’,客户端需要用到bootstrap、angularjs、socket.io、jQuery以及我们自己的js和css文件,先把这些文件用标签引入。 我们并不立即深入逻辑细节,把框架搭好先。 首先,在body上加上ng-app属性,标记一下angularjs的“管辖范围”。这个练习中我们只用到了一个控制器,同样将ng-controller属性加到body标签。 复制代码 代码如下: 接下来在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'的值控制是显示或隐藏。 … … 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连接上的其他事件: 复制代码 代码如下: //接收到欢迎新用户消息,显示系统欢迎辞,刷新在线列表 socket.on(‘userAdded’, function(data) {}); //接收到所有用户信息,初始化在线列表 socket.on(‘allUser’, function(data) {}); //接收到用户退出消息,刷新在线列表 socket.on(‘userRemoved’, function(data) {}); //接收到新消息,添加到聊天记录 socket.on(‘messageAdded’, function(data) {}); 接收到事件以后,做相应的刷新动作,这里的socket是socket.io经过包装的服务,内部仅包装了我们需要用到的两个函数on和emit。我们在事件监听里对model做的修改,都会在AngularJS内部得到通知和处理,UI才会得到及时刷新。 监听内做的事情太具体和琐碎了,这里就不列出了,接下来介绍一下message指令。 message 指令 最后分享一下我在写message指令时遇到的问题。首先看一下其代码: app.directive(‘message’, [‘$timeout’,function($timeout) { return { restrict: ‘E’, templateUrl: ‘message.html’, scope:{ info:”=”, self:”=”, scrolltothis:”&” }, link:function(scope, elem, attrs){ $timeout(scope.scrolltothis); } }; }]) 以及其模板message.html: 系统{{info.text}}来啦,大家不要放过他~ 系统:byebye,{{info.text}} {{info.from}} @ {{time | date: ‘HH:mm:ss’ }} {{info.text}} 模板中我们用ng-switch指令监听info.type变量的值,根据其值的不同显示不同内容。比如,当info.type值为”welcome”时,创建第一个dom节点,删除下方另外两个div。 另外,普通消息下,为了在UI上区分自己发出去的和收到的消息,需要给他们应用不同的样式,这里用ng-class指令实现。 复制代码 代码如下: ng-class=”{others:self!==info.from,self:self===info.from}” 当’self===info.from’返回true时,应用’self’类,否则,应用’others’类。 在此指令中,我们创建了独立作用域,并绑定了三个属性,绑定完后还必须在父作用域的HTML标签上添加相应属性。 scope:{ info:”=”, self:”=”, scrolltothis:”&” } 在link函数中,执行一个动作:每当一个message被加到页面上时,将聊天记录滚动到最下方,一开始我是这样写的: 复制代码 代码如下: link:function(scope, elem, attrs){ scope.scrolltothis();} 结果发生了一个很奇怪的现象,总是滚动到上一条位置,而不是最新这条。调试之后发现是因为’scrolltothis’函数执行的时候,DOM还没渲染,所以在函数内部获取scrollHeight的时候获得的总是添加DOM节点之前的状态。这时候,可以把代码放到$timeout里延迟0秒执行,延迟0秒并不意味着会立即执行,因为js的单线程特性,代码实际会等到dom渲染完再执行。 复制代码 代码如下: $timeout(scope.scrolltothis); 完整代码可以戳我的GitHub→ChatRoom-AngularJS,DEMO可以戳→chat room 有任何不妥之处或错误欢迎各位指出,不胜感激~ 您可能感兴趣的文章: js实现简易聊天对话框 javascript和jQuery实现网页实时聊天的ajax长轮询 nodejs实现的一个简单聊天室功能分享 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室 nw.js实现类似微信的聊天软件 Vue.js仿微信聊天窗口展示组件功能 JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序 js编写简单的聊天室功能 nodejs基于WS模块实现WebSocket聊天功能的方法 JavaScript实现简易QQ聊天界面 AngularJS Node.js 在线聊天室 相关文章 AngulaJS路由 ui-router 传参实例 本篇文章主要介绍了AngulaJS路由 ui-router 传参实例 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 2017-04-04 angularjs中判断ng-repeat是否迭代完的实例 今天小编就为大家分享一篇angularjs中判断ng-repeat是否迭代完的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 2018-09-09 Angular中使用better-scroll插件的方法 本篇文章主要介绍了Angular中使用better-scroll插件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 2018-03-03 Angular6封装http请求的步骤详解 最近抽空学习了一下Angular6,之前主要使用的是vue,所以免不了的也想对Angular6提供的工具进行一些封装,今天主要就跟大家讲一下这个http模块 2018-08-08 详解Ubuntu安装angular-cli遇到的坑 这篇文章主要介绍了详解Ubuntu安装angular-cli遇到的坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 2018-09-09 AngularJS用户选择器指令实例分析 这篇文章主要介绍了AngularJS用户选择器指令,结合实例形式分析了angular指令实现选择器功能的具体操作步骤与相关实现技巧,需要的朋友可以参考下 2016-11-11 AngularJS上拉加载问题解决方法 这篇文章主要介绍了AngularJS上拉加载问题解决方法的相关资料,该问题在项目中一直存在,小编给大家分享解决办法,需要的朋友可以参考下 2016-05-05 Angularjs全局变量被作用域监听的正确姿势 这篇文章主要介绍了Angularjs全局变量被作用域监听的正确姿势的相关资料,需要的朋友可以参考下 2016-02-02 AngularJS中的Directive自定义一个表格 本篇文章给大家介绍在angularjs中自定义一个有关表格的directive,涉及到angularjs directive相关知识,对本文感兴趣的朋友一起学习吧 2016-01-01 Angularjs 实现一个幻灯片示例代码 本文主要介绍Angularjs 写一个幻灯片的知识,这里整理了详细的资料,及实现代码和实现效果图有需要的小伙伴可以参考下 2016-09-09 最新评论

不得不说,上手AngularJS比我想象得难多了,把官网提供的PhoneCat例子看完,又跑到慕课网把大漠穷秋的AngularJS实战系列看了一遍,对于基本的使用依然有很多说不清道不明的疑惑,于是决定通过做一个在线聊天室帮助理解。DEMO可以戳→chat room,代码可以戳→ChatRoom-AngularJS。

清晰图可以戳 //img.jbzj.com/file_images/article/201508/201508281040051.gif

功能

着手开发之前,首先明确一下需要实现的功能:

新用户登入,广播通知其他用户
用户下线,广播通知其他用户
可显示在线人数及列表
可群聊,可私信
用户若发送群消息,广播通知其他所有用户
用户若发送私信,单独通知收方界面

因为自己是个审美渣,所以全靠bootstrap了,另外还模仿了下微信聊天记录里的气泡设计。

界面分左右两个板块,分别用于显示在线列表和聊天内容。

在左侧的在线列表中,点击不同项可以切换右侧板块的聊天对象。

右侧显示与当前聊天对象的对话记录,不过仅显示最近的30条。每一条聊天记录内容包括发送人的昵称及头像、发送时间、消息内容。关于头像,这里做简单处理,用填充了随机色的方块代替。另外,自己发出去的消息与收到的消息样式自然要做不同设计,所有效果可以看下图。

清晰图可以戳 //img.jbzj.com/file_images/article/201508/201508281040052.png

服务端

服务端我们用Node.js以及混入express、socket.io来开发,在程序根目录打开终端,执行:

复制代码 代码如下:
npm init

根据提示,生成一个package.json文件。打开并配置依赖项:

 "dependencies": {
  "express": "^4.13.3",
  "socket.io": "^1.3.6"
 }

之后执行 npm install 安装依赖模块。

接下来,我们在根目录下新建app.js,在其中写Server端代码。再新建public文件夹,存放client端代码。

app.js中主要内容如下:

var express = require('express');
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

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


app.get('/', function (req, res) {
  res.sendfile('index.html');
});


io.on('connection',function(socket){
  socket.on('addUser',function(data){ //有新用户进入聊天室
  });

  socket.on('addMessage',function(data){ //有用户发送新消息
  });
  
  socket.on('disconnect', function () { //有用户退出聊天室
  );
});

http.listen(3002, function () {
  console.log('listening on *:3002');
});

在上面的代码中,我们为以下事件添加了监听:

-addUser,有新用户进入聊天室

该事件由客户端输入昵称后触发,服务端收到后对昵称是否已存在进行判断,如果已存在,通知客户端昵称无效:

复制代码 代码如下:
socket.emit('userAddingResult',{result:false});

反之,通知客户端昵称有效以及当前所有已连接的用户信息,并把新用户信息广播给其他已连接用户:

socket.emit('userAddingResult',{result:true});
allUsers.push(data);//allUsers保存了所有用户
socket.emit('allUser',allUsers);//将所有在线用户发给新用户
socket.broadcast.emit('userAdded',data);//广播欢迎新用户,除新用户外都可看到

其中需要注意’socket.emit’与’socket.broadcast.emit’的区别,可以查看这篇博文socket.io emit的几种用法解释:

// send to current request socket client
socket.emit('message', "this is a test");
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");

-addMessage,有用户发送新消息

在此事件监听里,需要分成两类情况处理:

1.私信
如果消息是发给特定用户A,那么就需要获取A对应的socket实例,然后调用其emit方法。所以每当一个客户端连接到Server端时,我们得把其socket实例保存起来,以备后续之需。

复制代码 代码如下:
connectedSockets[nickname]=socket;//以昵称作下标,保存每个socket实例,发私信需要用

需要发私信时,取出socket实例做操作即可:

复制代码 代码如下:
connectedSockets[nickname].emit('messageAdded',data)

2.群发
群发就比较简单了,用broadcast方法即可:

复制代码 代码如下:
socket.broadcast.emit('messageAdded',data);//广播消息,除原发送者外都可看到

-disconnect,有用户退出聊天室
需要做三件事情:

1.通知其他用户“某用户下线”

复制代码 代码如下:
socket.broadcast.emit('userRemoved', data);

2.将用户从保存了所有用户的数组中移除

3.将其socket实例从保存了所有客户端socket实例的数组中移除

复制代码 代码如下:
delete connectedSockets[nickname]; //删除对应的socket实例

运行一下服务端代码,观察有无错误:

复制代码 代码如下:
node app.js

若没什么问题,继续编写客户端的代码。

客户端

在public目录下新建’index.html’,客户端需要用到bootstrap、angularjs、socket.io、jQuery以及我们自己的js和css文件,先把这些文件用标签引入。

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="./assets/style/app.css"/>
  <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
  <script src="/socket.io/socket.io.js"></script>
  <script src="//cdn.bootcss.com/angular.js/1.4.3/angular.min.js"></script>
  <script src="./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 class="chat-room-wrapper" ng-show="hasLogined">
...
</div>
<!-- end of chat room -->

<!-- login form -->
<div class="userform-wrapper" 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连接上的其他事件:

复制代码 代码如下:


//接收到欢迎新用户消息,显示系统欢迎辞,刷新在线列表
socket.on('userAdded', function(data) {});
//接收到所有用户信息,初始化在线列表
socket.on('allUser', function(data) {});
//接收到用户退出消息,刷新在线列表
socket.on('userRemoved', function(data) {});
//接收到新消息,添加到聊天记录
socket.on('messageAdded', function(data) {});

接收到事件以后,做相应的刷新动作,这里的socket是socket.io经过包装的服务,内部仅包装了我们需要用到的两个函数on和emit。我们在事件监听里对model做的修改,都会在AngularJS内部得到通知和处理,UI才会得到及时刷新。
监听内做的事情太具体和琐碎了,这里就不列出了,接下来介绍一下message指令。

message 指令

最后分享一下我在写message指令时遇到的问题。首先看一下其代码:

app.directive('message', ['$timeout',function($timeout) {
  return {
    restrict: 'E',
    templateUrl: 'message.html',
    scope:{
      info:"=",
      self:"=",
      scrolltothis:"&"
    },
    link:function(scope, elem, attrs){
        $timeout(scope.scrolltothis);
    }
  };
}])

以及其模板message.html:

<div ng-switch on="info.type">
  <!-- 欢迎消息 -->
  <div class="system-notification" ng-switch-when="welcome">系统{{info.text}}来啦,大家不要放过他~</div>
  <!-- 退出消息 -->
  <div class="system-notification" ng-switch-when="bye">系统:byebye,{{info.text}}</div>
  <!-- 普通消息 -->
  <div class="normal-message" ng-switch-when="normal" ng-class="{others:self!==info.from,self:self===info.from}">
    <div class="name-wrapper">{{info.from}} @ {{time | date: 'HH:mm:ss' }}</div>
    <div class="content-wrapper">{{info.text}}<span class="avatar"></span></div>
  </div>
</div>

模板中我们用ng-switch指令监听info.type变量的值,根据其值的不同显示不同内容。比如,当info.type值为”welcome”时,创建第一个dom节点,删除下方另外两个div。
另外,普通消息下,为了在UI上区分自己发出去的和收到的消息,需要给他们应用不同的样式,这里用ng-class指令实现。

复制代码 代码如下:
ng-class="{others:self!==info.from,self:self===info.from}"

当’self===info.from’返回true时,应用’self’类,否则,应用’others’类。
在此指令中,我们创建了独立作用域,并绑定了三个属性,绑定完后还必须在父作用域的HTML标签上添加相应属性。

scope:{
    info:"=",
    self:"=",
    scrolltothis:"&"
}

<message self="nickname" scrolltothis="scrollToBottom()" info="message" ng-repeat="message in messages"></message>

在link函数中,执行一个动作:每当一个message被加到页面上时,将聊天记录滚动到最下方,一开始我是这样写的:

复制代码 代码如下:
link:function(scope, elem, attrs){ scope.scrolltothis();}

结果发生了一个很奇怪的现象,总是滚动到上一条位置,而不是最新这条。调试之后发现是因为’scrolltothis’函数执行的时候,DOM还没渲染,所以在函数内部获取scrollHeight的时候获得的总是添加DOM节点之前的状态。这时候,可以把代码放到$timeout里延迟0秒执行,延迟0秒并不意味着会立即执行,因为js的单线程特性,代码实际会等到dom渲染完再执行。

复制代码 代码如下:
$timeout(scope.scrolltothis);

完整代码可以戳我的GitHub→ChatRoom-AngularJS,DEMO可以戳→chat room

有任何不妥之处或错误欢迎各位指出,不胜感激~

您可能感兴趣的文章:

  • js实现简易聊天对话框
  • javascript和jQuery实现网页实时聊天的ajax长轮询
  • nodejs实现的一个简单聊天室功能分享
  • 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
  • nw.js实现类似微信的聊天软件
  • Vue.js仿微信聊天窗口展示组件功能
  • JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序
  • js编写简单的聊天室功能
  • nodejs基于WS模块实现WebSocket聊天功能的方法
  • JavaScript实现简易QQ聊天界面
张贴在3