Rumah hujung hadapan web tutorial js AngularJS Node.js melaksanakan bilik sembang dalam talian_AngularJS

AngularJS Node.js melaksanakan bilik sembang dalam talian_AngularJS

May 16, 2016 pm 03:41 PM
angularjs node.js bilik sembang dalam talian

Saya harus mengatakan bahawa bermula dengan AngularJS adalah lebih sukar daripada yang saya fikirkan Selepas membaca contoh PhoneCat yang disediakan di tapak web rasmi, saya pergi ke MOOC dan membaca Siri Praktikal AngularJS Da Mo Qiongqiu masih banyak soalan yang tidak jelas tentang penggunaan asas, jadi saya memutuskan untuk membuat ruang sembang dalam talian untuk membantu memahami. DEMO boleh diklik →ruang sembang, dan kod boleh diklik→ChatRoom-AngularJS.

Anda boleh cop gambar yang jelas http://files.jb51.net/file_images/article/201508/201508281040051.gif

Fungsi

Sebelum memulakan pembangunan, jelaskan dahulu fungsi yang perlu dilaksanakan:

Pengguna baharu log masuk dan menyiarkan untuk memberitahu pengguna lain
Pengguna pergi ke luar talian dan menyiarkan untuk memberitahu pengguna lain
Boleh memaparkan bilangan orang dalam talian dan senarai
Sembang kumpulan dan pemesejan peribadi tersedia
Jika pengguna menghantar mesej kumpulan, siaran akan memberitahu semua pengguna lain
Jika pengguna menghantar mesej peribadi, antara muka penerima akan dimaklumkan secara berasingan

Oleh kerana saya seorang yang estetik, saya bergantung sepenuhnya pada bootstrap Selain itu, saya juga meniru reka bentuk gelembung dalam sejarah sembang WeChat.

Antara muka dibahagikan kepada dua bahagian: kiri dan kanan, yang digunakan untuk memaparkan senarai dalam talian dan kandungan sembang masing-masing.

Dalam senarai dalam talian di sebelah kiri, klik pada item yang berbeza untuk menukar rakan kongsi sembang di bahagian kanan.

Rekod perbualan dengan rakan kongsi sembang semasa dipaparkan di sebelah kanan, tetapi hanya 30 yang terbaharu dipaparkan. Kandungan setiap rekod sembang termasuk nama panggilan dan avatar penghantar, masa penghantaran dan kandungan mesej. Mengenai avatar, kami akan melakukan proses mudah di sini dan menggantikannya dengan petak yang diisi dengan warna rawak. Selain itu, gaya mesej yang anda hantar dan mesej yang anda terima secara semula jadi perlu direka bentuk secara berbeza. Semua kesan boleh dilihat dalam gambar di bawah.

Anda boleh cop gambar yang jelas http://files.jb51.net/file_images/article/201508/201508281040052.png

Pelayan

Kami menggunakan Node.js dan campurkan express dan socket.io untuk membangunkan pelayan Buka terminal dalam direktori akar program dan laksanakan:

Salin kod Kod adalah seperti berikut:
npm init

Ikuti gesaan dan jana fail package.json. Buka dan konfigurasikan kebergantungan:

 "dependencies": {
  "express": "^4.13.3",
  "socket.io": "^1.3.6"
 }
Salin selepas log masuk

Kemudian laksanakan pemasangan npm untuk memasang modul bergantung.

Seterusnya, kami mencipta app.js baharu dalam direktori akar dan menulis kod sebelah pelayan di dalamnya. Buat folder awam baharu untuk menyimpan kod klien.

Kandungan utama dalam app.js adalah seperti berikut:

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');
});
Salin selepas log masuk

Dalam kod di atas, kami menambah pendengar untuk acara berikut:

-addUser, pengguna baharu memasuki bilik sembang

Acara ini dicetuskan oleh pelanggan memasukkan nama panggilan Selepas menerimanya, pelayan akan menilai sama ada nama panggilan itu sudah wujud, maklumkan kepada pelanggan bahawa nama panggilan itu tidak sah:

Salin kod Kod adalah seperti berikut:
socket.emit('userAddingResult',{result:false});

Sebaliknya, maklumkan kepada pelanggan bahawa nama panggilan itu sah dan semua maklumat pengguna yang disambungkan pada masa ini, dan siarkan maklumat pengguna baharu kepada pengguna lain yang disambungkan:

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

Anda perlu memberi perhatian kepada perbezaan antara 'socket.emit' dan 'socket.broadcast.emit' Anda boleh menyemak catatan blog ini Penjelasan beberapa penggunaan 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");

Salin selepas log masuk

-addMessage, pengguna menghantar mesej baharu

Dalam pemantauan acara ini, dua jenis situasi perlu dikendalikan:

1. Mesej peribadi

Jika mesej dihantar kepada pengguna tertentu A, maka anda perlu mendapatkan contoh soket yang sepadan dengan A dan kemudian memanggil kaedah emitnya. Jadi setiap kali pelanggan menyambung ke pelayan, kami perlu menyimpan contoh soketnya untuk keperluan berikutnya.

Salin kod Kod adalah seperti berikut:
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>
Salin selepas log masuk

我们并不立即深入逻辑细节,把框架搭好先。
首先,在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){}]);
Salin selepas log masuk

注意这里,我们用内联注入添加了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);//返回一个随机色
    }
  };
});
Salin selepas log masuk

注意socket服务中连接的语句“var socket = io();”,我们并没有传入任何url,是因为其默认连接部署这个网站的服务器。

考虑到聊天记录以及在线人员列表都是一个个逻辑及结构重复的条目,且html结构较复杂,为了其复用性,我们把它们封装成两个指令:

app.directive('message', ['$timeout',function($timeout) {}])
  .directive('user', ['$timeout',function($timeout) {}]);
Salin selepas log masuk

注意这里两个指令都注入了'$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 -->
Salin selepas log masuk

JS部分

 $scope.login = function() { //登录
   socket.emit("addUser", {...});
 }

 //收到登录结果
 socket.on('userAddingResult', function(data) {
   if (data.result) {
     $scope.hasLogined = true;
   } else { //昵称被占用
     $scope.hasLogined = false;
   }
 });
Salin selepas log masuk

这里监听了socket连接上的'userAddingResult'事件,接收服务端的通知,确认是否登录成功。

socket连接监听

成功登录以后,我们还监听socket连接上的其他事件:

复制代码 代码如下:

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

接收到事件以后,做相应的刷新动作,这里的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);
    }
  };
}])
Salin selepas log masuk

以及其模板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>
Salin selepas log masuk

模板中我们用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>
Salin selepas log masuk

在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

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

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial Java
1663
14
Tutorial PHP
1266
29
Tutorial C#
1239
24
Penjelasan grafik terperinci tentang memori dan GC enjin Node V8 Penjelasan grafik terperinci tentang memori dan GC enjin Node V8 Mar 29, 2023 pm 06:02 PM

Artikel ini akan memberi anda pemahaman yang mendalam tentang memori dan pengumpul sampah (GC) enjin NodeJS V8 saya harap ia akan membantu anda!

Artikel tentang kawalan memori dalam Node Artikel tentang kawalan memori dalam Node Apr 26, 2023 pm 05:37 PM

Perkhidmatan Node yang dibina berdasarkan bukan sekatan dan dipacu peristiwa mempunyai kelebihan penggunaan memori yang rendah dan sangat sesuai untuk mengendalikan permintaan rangkaian besar-besaran. Di bawah premis permintaan besar-besaran, isu yang berkaitan dengan "kawalan memori" perlu dipertimbangkan. 1. Mekanisme kutipan sampah V8 dan had ingatan Js dikawal oleh mesin kutipan sampah

Mari kita bincangkan tentang cara memilih imej Node.js Docker terbaik? Mari kita bincangkan tentang cara memilih imej Node.js Docker terbaik? Dec 13, 2022 pm 08:00 PM

Memilih imej Docker untuk Node mungkin kelihatan seperti perkara remeh, tetapi saiz dan potensi kelemahan imej itu boleh memberi kesan yang ketara pada proses dan keselamatan CI/CD anda. Jadi bagaimana kita memilih imej Node.js Docker yang terbaik?

Cara melaksanakan bilik sembang dalam talian menggunakan bahasa Go dan Redis Cara melaksanakan bilik sembang dalam talian menggunakan bahasa Go dan Redis Oct 27, 2023 pm 03:28 PM

Cara melaksanakan ruang sembang dalam talian menggunakan bahasa Go dan Redis Pengenalan: Dengan perkembangan pesat Internet, rangkaian sosial telah menjadi bahagian yang amat diperlukan dalam kehidupan seharian orang ramai. Sebagai bahagian penting rangkaian sosial, bilik sembang dalam talian popular di kalangan orang untuk kemudahan, masa nyata dan interaktiviti yang kuat. Artikel ini berdasarkan bahasa Go dan Redis dan memperkenalkan cara menggunakan kedua-dua alatan ini untuk melaksanakan ruang sembang dalam talian yang ringkas. 1. Pengenalan kepada bahasa Go: Bahasa Go ialah bahasa pengaturcaraan sistem sumber terbuka untuk sistem pengendalian moden.

Mari bercakap secara mendalam tentang modul Fail dalam Node Mari bercakap secara mendalam tentang modul Fail dalam Node Apr 24, 2023 pm 05:49 PM

Modul fail ialah enkapsulasi operasi fail asas, seperti membaca/menulis/membuka/menutup/memadam fail, dsb. Ciri terbesar modul fail ialah semua kaedah menyediakan dua versi **segerak** dan ** asynchronous**, dengan Kaedah dengan akhiran penyegerakan adalah semua kaedah penyegerakan, dan kaedah yang tidak semuanya adalah kaedah heterogen.

Mari kita bincangkan tentang gelung acara dalam Node Mari kita bincangkan tentang gelung acara dalam Node Apr 11, 2023 pm 07:08 PM

Gelung peristiwa ialah bahagian asas Node.js dan mendayakan pengaturcaraan tak segerak dengan memastikan bahawa utas utama tidak disekat Memahami gelung peristiwa adalah penting untuk membina aplikasi yang cekap. Artikel berikut akan memberi anda pemahaman yang mendalam tentang gelung acara dalam Node.

Mari kita bincangkan tentang cara menggunakan pkg untuk membungkus projek Node.js ke dalam fail boleh laku. Mari kita bincangkan tentang cara menggunakan pkg untuk membungkus projek Node.js ke dalam fail boleh laku. Dec 02, 2022 pm 09:06 PM

Bagaimana untuk membungkus fail boleh laku nodejs dengan pkg? Artikel berikut akan memperkenalkan kepada anda cara menggunakan pkg untuk membungkus projek Node ke dalam fail boleh laku. Saya harap ia akan membantu anda!

Apakah yang perlu saya lakukan jika nod tidak boleh menggunakan arahan npm? Apakah yang perlu saya lakukan jika nod tidak boleh menggunakan arahan npm? Feb 08, 2023 am 10:09 AM

Sebab mengapa nod tidak boleh menggunakan arahan npm adalah kerana pembolehubah persekitaran tidak dikonfigurasikan dengan betul Penyelesaiannya ialah: 1. Buka "Sistem Sifat"; 2. Cari "Pembolehubah Persekitaran" -> "Pembolehubah Sistem", dan kemudian edit persekitaran. pembolehubah; 3. Cari lokasi folder nodejs;

See all articles