Нулевая реализация персонализированного чата node+express

Node.js внешний интерфейс Express
Нулевая реализация персонализированного чата node+express

В этой статье используется node+express+jquery для создания персонализированного чата, давайте вместе~ (адрес источника см. в конце статьи)

визуализация

Структура проекта

реализовать функцию

  • Обнаружение входа
  • Система автоматически подсказывает статус пользователя (вход/выход)
  • показать онлайн пользователей
  • Поддержка отправки и получения сообщений
  • пользовательский цвет шрифта
  • Поддержка отправки смайликов, картинок, дрожания окон

Далее будет объяснено, как достичь

Предварительная подготовка

узел и среда npm,express,socket.io

Выполнение

1. Разверните чат на сервере

Сначала создайте сервер с узлом, разверните его на порту localhost:3000, сначала попробуйте отправить «hello world» в браузер и создайте новый файл server.js.

var app = require('express')();  // 引入express模块
var http = require('http').Server(app);

app.get('/', function(req, res){  // 路由为localhost:3000时向客户端响应“hello world”
  res.send('<h1>Hello world</h1>');  // 发送数据
});

http.listen(3000, function(){  // 监听3000端口
  console.log('listening on *:3000'); 
}); 

Откройте браузер и введите URL-адрес: localhost:3000 выглядит следующим образом.

Узловой сервер успешно построен.

Затем используйте экспресс, чтобы вернуть html-страницу в браузер.

#安装express模块
npm install --save express

Измените код server.js на:

var express = require('express');
var app = express();
var http = require('http').Server(app); 

// 路由为/默认www静态文件夹
app.use('/', express.static(__dirname + '/www'));

express.static(__dirname + '/www'); предназначен для размещения папки www в качестве статического ресурса, что означает, что файлы (html, css, js) в этой папке могут использовать относительные пути друг к другу. Добавьте файл index.html и соответствующий css в папку www (соответствующий код css не будет опубликован, подробности см. в исходном коде), как показано ниже, на странице используется маленький значок с потрясающим шрифтом.

<!doctype html>
<html>
  <head>        
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>chat</title>
    <link rel="stylesheet" href="style/index.css">
    <link rel="stylesheet" href="style/font-awesome-4.7.0/css/font-awesome.min.css">
  </head>
  <body>
    <div class="all">
      <div class="name">
        <!-- <h2>请输入你的昵称</h2> -->
        <input type="text" id="name" placeholder="请输入昵称..." autocomplete="off"> 
        <button id="nameBtn">确  定</button>
      </div>
      <div class="main">
        <div class="header">
          <img src="image/logo.jpg">
          happy聊天室
        </div>
        <div id="container">
          <div class="conversation">
              <ul id="messages"></ul>
              <form action="">
                  <div class="edit"> 
                    <input type="color" id="color" value="#000000">
                    <i title="双击取消选择" class="fa fa-smile-o" id="smile">
                    </i><i title="双击取消选择" class="fa fa-picture-o" id="img"></i>
                    <div class="selectBox"> 
                      <div class="smile"> 
                      </div>
                      <div class="img"> 
                      </div>
                    </div>
                  </div>
                  <!-- autocomplete禁用自动完成功能 -->
                  <textarea id="m"></textarea>
                  <button class="btn rBtn" id="sub">发送</button>
                  <button class="btn" id="clear">关闭</button>
              </form>
          </div>
          <div class="contacts">
            <h1>在线人员(<span id="num">0</span>)</h1>
            <ul id="users"></ul>
            <p>当前无人在线哟~</p>
          </div>
        </div>
      </div> 
    </div> 
  </body>
</html>

Откройте localhost:3000 и вы увидите следующее:

Чат успешно развернут на сервере.

2. Обнаружить логин

Socket.io требуется для передачи сообщений между клиентом и сервером.

#安装socket.io模块
npm install --save socket.io

Измените server.js следующим образом:

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

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

io.on('connection', function(socket){ // 用户连接时触发
  console.log('a user connected');
});

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

При открытии localhost:3000 будет инициировано событие подключения серверного ввода-вывода, и на сервере будет напечатано «пользователь подключен», но мы хотим подсчитать количество пользователей, подключенных к серверу. пользовательское соединение, напечатайте "n пользователей подключено", n - количество пользователей, что мне делать?

Установите глобальный массив как пользователь в server.js. Всякий раз, когда пользователь успешно подключается, вставьте псевдоним пользователя в user в событии подключения и напечатайте user.length, чтобы узнать количество пользователей, которые успешно подключились.

Подождите минуту.

Когда пользователь подключается, чтобы ввести псевдоним для входа в систему, мы должны проверить, существует ли уже псевдоним пользователя, чтобы избежать того же псевдонима.Сервер прослушивает событие входа в систему, чтобы оценить ситуацию.Поскольку все происходит после подключения пользователя, событие срабатывает.Должно быть записано в функции обратного вызова события соединения.

io.on('connection', (socket)=> {
    // 渲染在线人员
    io.emit('disUser', usersInfo);

    // 登录,检测用户名
    socket.on('login', (user)=> {
        if(users.indexOf(user.name) > -1) { // 昵称是否存在
            socket.emit('loginError'); // 触发客户端的登录失败事件
        } else {
            users.push(user.name); //储存用户的昵称
            usersInfo.push(user); // 储存用户的昵称和头像
            socket.emit('loginSuc'); // 触发客户端的登录成功事件
            socket.nickname = user.name;
            io.emit('system', {  // 向所有用户广播该用户进入房间
                name: user.name,
                status: '进入'
            });
            io.emit('disUser', usersInfo);  // 渲染右侧在线人员信息
            console.log(users.length + ' user connect.'); // 打印连接人数
        }
    });

Сначала будут проигнорированы события system и disUser, которые будут обсуждаться позже. Различают io.emit(foo), socket.emit(foo), socket.broadcast.emit(foo)

io.emit(foo); //会触发所有客户端用户的foo事件
socket.emit(foo); //只触发当前客户端用户的foo事件
socket.broadcast.emit(foo); //触发除了当前客户端用户的其他用户的foo事件

Далее код клиента chat-client.js

$(function() {
    // io-client
    // 连接成功会触发服务器端的connection事件
    var socket = io(); 

    // 点击输入昵称
    $('#nameBtn').click(()=> {  
      var imgN = Math.floor(Math.random()*4)+1; // 随机分配头像
      if($('#name').val().trim()!=='')
          socket.emit('login', {  // 触发服务器端登录事件
            name: $('#name').val(),
            img: 'image/user' + imgN + '.jpg'
          }); 
      return false;  
    });
    // 登录成功,隐藏登录层
    socket.on('loginSuc', ()=> { 
      $('.name').hide(); 
    })
    socket.on('loginError', ()=> {
      alert('用户名已存在,请重新输入!');
      $('#name').val('');
    }); 
});

Если авторизация прошла успешно, вы увидите следующую страницу:

Определение входа завершено.

3. Система автоматически подсказывает статус пользователя (вход/выход)

Эта функция предназначена для реализации системного приглашения «XXX входит в комнату чата», как показано на рисунке выше, инициирования системного события при успешном входе в систему и передачи информации всем пользователям.Обратите внимание, что вместо сокета используется io.emit. испускать в это время, и код клиента показывает, как показано ниже

// 系统提示消息
socket.on('system', (user)=> { 
  var data = new Date().toTimeString().substr(0, 8);
  $('#messages').append(`<p class='system'><span>${data}</span><br /><span>${user.name}  ${user.status}了聊天室<span></p>`);
  // 滚动条总是在最底部
  $('#messages').scrollTop($('#messages')[0].scrollHeight);
});

4. Показать онлайн-пользователей

Клиент прослушивает событие disUser, которое отображает онлайн-пользователей, а сервер запускает событие для повторного рендеринга один раз в следующие три периода времени.

  • Когда программа запускается
  • всякий раз, когда пользователь входит в комнату
  • всякий раз, когда пользователь выходит из комнаты
// chat-client.js
// 显示在线人员
socket.on('disUser', (usersInfo)=> {
  displayUser(usersInfo);
});
// 显示在线人员
function displayUser(users) {
  $('#users').text(''); // 每次都要重新渲染
  if(!users.length) {
    $('.contacts p').show();
  } else {
    $('.contacts p').hide();
  }
  $('#num').text(users.length);
  for(var i = 0; i < users.length; i++) {
    var $html = `<li>
      <img src="${users[i].img}">
      <span>${users[i].name}</span>
    </li>`;
    $('#users').append($html);
  }
}

5. Поддержка отправки и получения сообщений

Когда пользователь отправляет сообщение, на стороне сервера запускается событие sendMsg, а содержимое сообщения используется в качестве параметра. .излучать(фу)

 // server.js
    // 发送消息事件
    socket.on('sendMsg', (data)=> {
        var img = '';
        for(var i = 0; i < usersInfo.length; i++) {
            if(usersInfo[i].name == socket.nickname) {
                img = usersInfo[i].img;
            }
        }
        socket.broadcast.emit('receiveMsg', {  // 向除了发送者之外的其他用户广播
            name: socket.nickname,
            img: img,
            msg: data.msg,
            color: data.color,
            side: 'left'
        });
        socket.emit('receiveMsg', {  // 向发送者发送消息,为什么分开发送?因为css样式不同
            name: socket.nickname,
            img: img,
            msg: data.msg,
            color: data.color,
            side: 'right'
        });
    });

После того, как сервер получит сообщение от пользователя, он вызовет событие ReceiveMsg клиента и передаст сообщение, отправленное пользователем, в качестве параметра. Это событие добавит содержимое чата на панель чата. Ниже приведен чат-клиент. .js-код

// 点击按钮或回车键发送消息
    $('#sub').click(sendMsg);
    $('#m').keyup((ev)=> {
      if(ev.which == 13) {
        sendMsg();
      }
    });

    // 接收消息
    socket.on('receiveMsg', (obj)=> { // 将接收到的消息渲染到面板上
      $('#messages').append(` 
         <li class='${obj.side}'>
          <img src="${obj.img}">
          <div>
            <span>${obj.name}</span>
            <p>${obj.msg}</p>
          </div>
        </li>
      `);
      // 滚动条总是在最底部
      $('#messages').scrollTop($('#messages')[0].scrollHeight);
    }); 


    // 发送消息
    function sendMsg() { 
      if($('#m').val() == '') {  // 输入消息为空
        alert('请输入内容!');
        return false;
      }
      socket.emit('sendMsg', {
        msg: $('#m').val()
      });
      $('#m').val(''); 
      return false; 
    }

6. Настройте цвет шрифта

Благодаря новой функции ввода html5 системную палитру можно вызывать через ввод, тип которого — цвет.

<!-- $('#color').val();为选中颜色,格式为#FFCCBB -->
<input type='color' id='color'>  

Клиент отображает стиль содержимого в соответствии с цветом, выбранным пользователем, а код прост для понимания, поэтому я не буду здесь вдаваться в подробности.

7. Поддержка отправки выражений

Отправить смайлик на самом деле очень просто: поместите изображение смайлика в li, и когда пользователь щелкнет li, серийный номер в src смайлика будет проанализирован и сохранен в окне чата в формате [смайлик + серийный номер смайлика ]. После нажатия кнопки «Отправить» он будет проанализирован как src. Это процесс парсинга и восстановления, во время которого наш серверный код остается неизменным, нужно изменить событие receiveMsg, отслеживаемое клиентом.

// chat-client.js

    // 显示表情选择面板
    $('#smile').click(()=> {
      $('.selectBox').css('display', "block");
    });
    $('#smile').dblclick((ev)=> { 
      $('.selectBox').css('display', "none");
    });  
    $('#m').click(()=> {
      $('.selectBox').css('display', "none");
    }); 

    // 用户点击发送表情
    $('.emoji li img').click((ev)=> {
        ev = ev || window.event;
        var src = ev.target.src;
        var emoji = src.replace(/\D*/g, '').substr(6, 8); // 提取序号
        var old = $('#m').val(); // 用户输入的其他内容
        $('#m').val(old+'[emoji'+emoji+']');
        $('.selectBox').css('display', "none");
    });

После того, как клиент его получает, он восстанавливает порядковый номер выражения в src, и изменения следующие:

// chat-client.js

    // 接收消息
    socket.on('receiveMsg', (obj)=> {  
      // 提取文字中的表情加以渲染
      var msg = obj.msg;
      var content = '';
      while(msg.indexOf('[') > -1) {  // 其实更建议用正则将[]中的内容提取出来
        var start = msg.indexOf('[');
        var end = msg.indexOf(']');

        content += '<span>'+msg.substr(0, start)+'</span>';
        content += '<img src="image/emoji/emoji%20('+msg.substr(start+6, end-start-6)+').png">';
        msg = msg.substr(end+1, msg.length);
      }
      content += '<span>'+msg+'</span>';
      
      $('#messages').append(`
        <li class='${obj.side}'>
          <img src="${obj.img}">
          <div>
            <span>${obj.name}</span>
            <p style="color: ${obj.color};">${content}</p>
          </div>
        </li>
      `);
      // 滚动条总是在最底部
      $('#messages').scrollTop($('#messages')[0].scrollHeight);
    });

Смайлик может быть успешно отправлен.

8. Поддержка отправки изображений

Во-первых, это стиль кнопки изображения, кнопка, которая отправляет изображение, является вводом типа файла. Вот небольшой трюк, чтобы изменить стиль, то есть установить непрозрачность ввода на 0, z-index на 5, поместить нужный стиль в div и установить z-index на 1, чтобы наложить ввод.

<input type="file" id="file">
<i class="fa fa-picture-o" id="img"></i>
css:

.edit #file {
    width: 32.36px;
    height: 29px;
    opacity: 0;
    z-index: 5;
}
.edit #img {
    z-index: 0;
    margin-left: -43px;
}

Идеально

Следующим шагом является нажатие кнопки для отправки изображения. Мы использовали объект fileReader. Вот хорошая статья, объясняющая fileReader. FileReader — это объект, который может выводить выбранный файл в 64-битном формате и сохранять результат в reader.result , После выбора изображения, reader.result сохраняет src изображения.

// chat-client.js

    // 用户发送图片
    $('#file').change(function() {
      var file = this.files[0];  // 上传单张图片
      var reader = new FileReader();

      //文件读取出错的时候触发
      reader.onerror = function(){
          console.log('读取文件失败,请重试!'); 
      };
      // 读取成功后
      reader.onload = function() {
        var src = reader.result;  // 读取结果
        var img = '<img class="sendImg" src="'+src+'">';
        socket.emit('sendMsg', {  // 发送
          msg: img,
          color: color,
          type: 'img'  // 发送类型为img
        }); 
      };
      reader.readAsDataURL(file); // 读取为64位
    });

Поскольку отправляются изображения, это неизбежно повлияет на макет страницы.Ради красоты страницы клиент сначала определит, отправляется ли текст или изображения при получении сообщений от других пользователей, и отобразит разные макеты в соответствии с разными результатами. Метод оценки заключается в передаче типа, когда клиент отправляет сообщение, и в соответствии со значением типа тип отправляемого контента действительно отправляется. Поэтому в коде отправки картинки выше срабатывает событие sendMsg, а входящий параметр имеет дополнительный атрибут типа.

В ответ мы должны изменить функцию прослушивания событий receiveMsg в chat-client.js, чтобы выполнять различные операции в зависимости от входящего типа.

chat-client.js
    // 接收消息
    socket.on('receiveMsg', (obj)=> { 
      // 发送为图片
      if(obj.type == 'img') {
        $('#messages').append(`
          <li class='${obj.side}'>
            <img src="${obj.img}">
            <div>
              <span>${obj.name}</span>
              <p style="padding: 0;">${obj.msg}</p>
            </div>
          </li>
        `); 
        $('#messages').scrollTop($('#messages')[0].scrollHeight);
        return;
      }

      // 提取文字中的表情加以渲染
      // 下面不变
    }); 

Теперь мы можем отправлять фотографии

7. Отправить дрожание окна

Когда пользователь нажимает кнопку встряхивания, событие встряхивания сервера будет отправлено, и сервер будет транслировать событие, так что каждый клиент будет встряхивать окно.

// chat-client.js
    // 用户发送抖动
    $('.edit #shake').click(function() {
        socket.emit('shake');
    });
    
// server.js
   // 发送窗口抖动
    socket.on('shake', ()=> {
        socket.emit('shake', {
            name: '您'
        });
        socket.broadcast.emit('shake', {
            name: socket.nickname
        });
    });

Реализовать анимацию css3 для дрожания окна

.edit .selectBox { 
    position: absolute;
    bottom: 34px;
    left: 0px; 
}  
.shaking {
    animation: run 0.2s infinite;
}
@keyframes run {
    0% {
        left: 0;
    }
    25% {
        left: -7px;
    }
    50% {
        left: 7px;
    }
    100% {
        left: 0;
    }
}

Полностью завершите полнофункциональный чат!

Адрес источника:windlany/happy-chat,Эта статья писалась от случая к случаю два дня.На самом деле писать статьи более утомительно,чем набирать код...На самом деле написать чат не сложно.Это стартовая работа ноды. Если вы заинтересованы, вы можете раскошелиться и изменить его в соответствии с вашими потребностями.Если вы чувствуете себя хорошо, пожалуйста, дайте мне звезду.

Ссылка на ссылку