内容简介:├── package-lock.json├── package.json├── public
项目目录
├── package-lock.json
├── package.json
├── public
│ └── index.html
└── server
└── server.js
初始化
npm init
npm install --save express
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> </body> </html>
server.js
const path = require('path'); const express = require('express'); //获取路劲,有讲究 const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); app.use(express.static(publicPath)); app.listen(port, () => { console.log(`Server is up on ${port}`); });
package.json
{ "name": "node-chat-app", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { /* 启动脚本 */ "start": "node server/server.js", "test": "echo \"Error: no test specified\" && exit 1" }, /* node版本号 */ "engines": { "node": "10.13.0" }, "author": "", "license": "ISC", "dependencies": { "express": "^4.14.0" } }
部署hekuro
> heroku create > git push https://git.heroku.com/rocky-shore-24556.git
使用socket.io
安装:
npm install -save socket.io
socket.io可以让服务器与客户端相互连接并触发事件。下例测试连接与断开服务器
server.html:
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('connect', () => { console.log('Connected to server'); }); socket.on('disconnect', () => { console.log('Disconnected from server'); }); </script> </body> </html>
运行:打开localhost:3000即可运行,查看控制台输出的语句。
> node server/server.js
##项目目录重构
创建和触发自定义事件。
将客户端js代码分离出来:
|—— node_moudles
├── package-lock.json
├── package.json
├── public
│ ├── index.html
│ └── js
│ └── index.js
└── server
└── server.js
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="/js/index.js"></script> </body> </html>
index.js:
为了让浏览器识别,将匿名函数修改为function
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); socket.emit('createMessage', { from: 'Andrew', text: 'Yup, that works for me.' }); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); });
server.js:
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', { from: 'John', text: 'See you then', createdAt: 123123 }); socket.on('createMessage', (message) => { console.log('createMessage', message); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
运行:打开localhost:3000即可运行,查看控制台输出的语句。
> node server/server.js
广播
当客户端连接服务器之后,所有的节点即会触发newMessage事件,但是当前连接的客户端与其他客户端接受的信息不相同。
当前客户端接受:Welcome to the chat app
其他客户端接受:New user joined
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="/js/index.js"></script> </body> </html>
index.js:
为了让浏览器识别,将匿名函数修改为function
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); });
server.js:
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); // 当客户端连接之后,即会触发newMessage事件,但是当前连接的客户端与其他客户端接受的信息不相同。 // 只发送给当前连接的节点 socket.emit('newMessage', { from: 'Admin', text: 'Welcome to the chat app', createdAt: new Date().getTime() }); // 只发送给当前连接的节点发送给其他节点 socket.broadcast.emit('newMessage', { from: 'Admin', text: 'New user joined', createdAt: new Date().getTime() }); socket.on('createMessage', (message) => { console.log('createMessage', message); io.emit('newMessage', { from: message.from, text: message.text, createdAt: new Date().getTime() }); // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
测试
运行:
> node server/server.js
分别打开两个浏览器tabs,
打开localhost:3000查看控制台输出的语句。
封装产生信息
目录
├── package-lock.json
├── package.json
├── public
│ ├── index.html
│ └── js
│ └── index.js
└── server
├── server.js
└── utils
└── message.js
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="/js/index.js"></script> </body> </html>
index.js:
为了让浏览器识别,将匿名函数修改为function
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); });
message.js
var generateMessage = (from, text) => { return { from, text, createdAt: new Date().getTime() }; }; module.exports = {generateMessage};
server.js
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const {generateMessage} = require('./utils/message'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); socket.broadcast.emit('newMessage', generateMessage('Admin', 'New user joined')); socket.on('createMessage', (message) => { console.log('createMessage', message); io.emit('newMessage', generateMessage(message.from, message.text)); // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
测试
运行:
> node server/server.js
分别打开两个浏览器tabs,
打开localhost:3000查看控制台输出的语句。
信息反馈
当客户端发出一条消息,希望得到服务器的反馈,如果服务器发送成功个,会收到消息。
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="/js/index.js"></script> </body> </html>
index.js:
为了让浏览器识别,将匿名函数修改为function
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); }); socket.emit('createMessage', { from: 'Frank', text: 'Hi' }, function (data) {//回调函数 console.log('Got it', data); });
message.js
var generateMessage = (from, text) => { return { from, text, createdAt: new Date().getTime() }; }; module.exports = {generateMessage};
server.js
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const {generateMessage} = require('./utils/message'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); socket.broadcast.emit('newMessage', generateMessage('Admin', 'New user joined')); socket.on('createMessage', (message, callback) => { console.log('createMessage', message); io.emit('newMessage', generateMessage(message.from, message.text)); callback('This is from the server.'); //客户端执行回调函数 // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
测试
运行:
> node server/server.js
分别打开两个浏览器tabs,
打开localhost:3000查看控制台输出的语句。
## 简单聊天页面
index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <ol id="messages"></ol> <form id="message-form"> <input name="message" type="text" placeholder="Message"/> <button>Send</button> </form> <script src="/js/index.js"></script> </body> </html>
index.js:
为了让浏览器识别,将匿名函数修改为function
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); //新消息来了之后,添加到页面中 socket.on('newMessage', function (message) { console.log('newMessage', message); var li = jQuery('<li></li>'); li.text(`${message.from}: ${message.text}`); jQuery('#messages').append(li); }); //按钮提交事件 jQuery('#message-form').on('submit', function (e) { e.preventDefault(); socket.emit('createMessage', { from: 'User', text: jQuery('[name=message]').val() }, function () { }); });
message.js
var generateMessage = (from, text) => { return { from, text, createdAt: new Date().getTime() }; }; module.exports = {generateMessage};
server.js
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const {generateMessage} = require('./utils/message'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); socket.broadcast.emit('newMessage', generateMessage('Admin', 'New user joined')); socket.on('createMessage', (message, callback) => { console.log('createMessage', message); io.emit('newMessage', generateMessage(message.from, message.text)); callback('This is from the server.'); //客户端执行回调函数 // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
测试
运行:
> node server/server.js
分别打开两个浏览器tabs,
打开localhost:3000查看控制台输出的语句。
经纬度
index.js
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); var li = jQuery('<li></li>'); li.text(`${message.from}: ${message.text}`); jQuery('#messages').append(li); }); jQuery('#message-form').on('submit', function (e) { e.preventDefault(); socket.emit('createMessage', { from: 'User', text: jQuery('[name=message]').val() }, function () { }); }); var locationButton = jQuery('#send-location'); locationButton.on('click', function () { if (!navigator.geolocation) { return alert('Geolocation not supported by your browser.'); } navigator.geolocation.getCurrentPosition(function (position) { socket.emit('createLocationMessage', { latitude: position.coords.latitude, longitude: position.coords.longitude }); }, function () { alert('Unable to fetch location.'); }); });
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <ol id="messages"></ol> <form id="message-form"> <input name="message" type="text" placeholder="Message"/> <button>Send</button> </form> <button id="send-location">Send Location</button> <script src="/js/index.js"></script> </body> </html>
message.js
var generateMessage = (from, text) => { return { from, text, createdAt: new Date().getTime() }; }; module.exports = {generateMessage};
server.js
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const {generateMessage} = require('./utils/message'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); socket.broadcast.emit('newMessage', generateMessage('Admin', 'New user joined')); socket.on('createMessage', (message, callback) => { console.log('createMessage', message); io.emit('newMessage', generateMessage(message.from, message.text)); callback('This is from the server.'); // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('createLocationMessage', (coords) => { io.emit('newMessage', generateMessage('Admin', `${coords.latitude}, ${coords.longitude}`)); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
谷歌经纬度
index.js
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); var li = jQuery('<li></li>'); li.text(`${message.from}: ${message.text}`); jQuery('#messages').append(li); }); socket.on('newLocationMessage', function (message) { var li = jQuery('<li></li>'); var a = jQuery('<a target="_blank">My current location</a>'); li.text(`${message.from}: `); a.attr('href', message.url); li.append(a); jQuery('#messages').append(li); }); jQuery('#message-form').on('submit', function (e) { e.preventDefault(); socket.emit('createMessage', { from: 'User', text: jQuery('[name=message]').val() }, function () { }); }); var locationButton = jQuery('#send-location'); locationButton.on('click', function () { if (!navigator.geolocation) { return alert('Geolocation not supported by your browser.'); } navigator.geolocation.getCurrentPosition(function (position) { socket.emit('createLocationMessage', { latitude: position.coords.latitude, longitude: position.coords.longitude }); }, function () { alert('Unable to fetch location.'); }); });
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>Welcome to the chat app</p> <script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <ol id="messages"></ol> <form id="message-form"> <input name="message" type="text" placeholder="Message"/> <button>Send</button> </form> <button id="send-location">Send Location</button> <script src="/js/index.js"></script> </body> </html>
message.js
var generateMessage = (from, text) => { return { from, text, createdAt: new Date().getTime() }; }; var generateLocationMessage = (from, latitude, longitude) => { return { from, url: `https://www.google.com/maps?q=${latitude},${longitude}`, createdAt: new Date().getTime() }; }; module.exports = {generateMessage, generateLocationMessage};
server.js
const path = require('path'); const http = require('http'); const express = require('express'); const socketIO = require('socket.io'); const {generateMessage,generateLocationMessage} = require('./utils/message'); const publicPath = path.join(__dirname, '../public'); const port = process.env.PORT || 3000; var app = express(); var server = http.createServer(app); var io = socketIO(server); app.use(express.static(publicPath)); io.on('connection', (socket) => { console.log('New user connected'); socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); socket.broadcast.emit('newMessage', generateMessage('Admin', 'New user joined')); socket.on('createMessage', (message, callback) => { console.log('createMessage', message); io.emit('newMessage', generateMessage(message.from, message.text)); callback('This is from the server.'); // socket.broadcast.emit('newMessage', { // from: message.from, // text: message.text, // createdAt: new Date().getTime() // }); }); socket.on('createLocationMessage', (coords) => { io.emit('newLocationMessage', generateLocationMessage('Admin', coords.latitude, coords.longitude)); }); socket.on('disconnect', () => { console.log('User was disconnected'); }); }); server.listen(port, () => { console.log(`Server is up on ${port}`); });
页面优化
css/style.css:
button,button:hover{border:none;color:#fff;padding:10px}.chat__messages,.chat__sidebar ul{list-style-type:none}*{box-sizing:border-box;margin:0;padding:0;font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-weight:300;font-size:.95rem}li,ul{list-style-position:inside}h3{font-weight:600;text-align:center;font-size:1.5rem}button{background:#265f82;cursor:pointer;transition:background .3s ease}button:hover{background:#1F4C69}button:disabled{cursor:default;background:#698ea5}.centered-form{display:flex;align-items:center;height:100vh;width:100vw;justify-content:center;background:-moz-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-webkit-gradient(linear,left top,right bottom,color-stop(0,rgba(49,84,129,1)),color-stop(100%,rgba(39,107,130,1)));background:-webkit-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-o-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-ms-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:linear-gradient(325deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%)}.centered-form__form{background:rgba(250,250,250,.9);border:1px solid #e1e1e1;border-radius:5px;padding:0 20px;margin:20px;width:230px}.form-field{margin:20px 0}.form-field>*{width:100%}.form-field label{display:block;margin-bottom:7px}.form-field input,.form-field select{border:1px solid #e1e1e1;padding:10px}.chat{display:flex}.chat__sidebar{overflow-y:scroll;width:260px;height:100vh;background:-moz-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-webkit-gradient(linear,left top,right bottom,color-stop(0,rgba(49,84,129,1)),color-stop(100%,rgba(39,107,130,1)));background:-webkit-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-o-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-ms-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:linear-gradient(325deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%)}.chat__footer,.chat__sidebar li{background:#e6eaee;padding:10px}.chat__sidebar h3{color:#e6eaee;margin:10px 20px;text-align:left}.chat__sidebar li{border:1px solid #e1e1e1;border-radius:5px;margin:10px}.chat__main{display:flex;flex-direction:column;height:100vh;width:100%}.chat__messages{flex-grow:1;overflow-y:scroll;-webkit-overflow-scrolling:touch;padding:10px}.chat__footer{display:flex;flex-shrink:0}.chat__footer form{flex-grow:1;display:flex}.chat__footer form *{margin-right:10px}.chat__footer input{border:none;padding:10px;flex-grow:1}.message{padding:10px}.message__title{display:flex;margin-bottom:5px}.message__title h4{font-weight:600;margin-right:10px}.message__title span{color:#999}@media (max-width:600px){*{font-size:1rem}.chat__sidebar{display:none}.chat__footer{flex-direction:column}.chat__footer form{margin-bottom:10px}.chat__footer button{margin-right:0}}
index.js
var socket = io(); socket.on('connect', function () { console.log('Connected to server'); }); socket.on('disconnect', function () { console.log('Disconnected from server'); }); socket.on('newMessage', function (message) { console.log('newMessage', message); var li = jQuery('<li></li>'); li.text(`${message.from}: ${message.text}`); jQuery('#messages').append(li); }); socket.on('newLocationMessage', function (message) { var li = jQuery('<li></li>'); var a = jQuery('<a target="_blank">My current location</a>'); li.text(`${message.from}: `); a.attr('href', message.url); li.append(a); jQuery('#messages').append(li); }); jQuery('#message-form').on('submit', function (e) { e.preventDefault(); socket.emit('createMessage', { from: 'User', text: jQuery('[name=message]').val() }, function () { }); }); var locationButton = jQuery('#send-location'); locationButton.on('click', function () { if (!navigator.geolocation) { return alert('Geolocation not supported by your browser.'); } locationButton.attr('disabled', 'disabled').text('Sending location...'); navigator.geolocation.getCurrentPosition(function (position) { locationButton.removeAttr('disabled').text('Send location'); socket.emit('createLocationMessage', { latitude: position.coords.latitude, longitude: position.coords.longitude }); }, function () { locationButton.removeAttr('disabled').text('Send location'); alert('Unable to fetch location.'); }); });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web开发权威指南
[美] Chris Aquino,、[美] Todd Gandee / 奇舞团 / 人民邮电出版社 / 2017-9 / 99.00元
本书在知名培训机构Big Nerd Ranch 培训教材的基础上编写而成,囊括了JavaScript、HTML5、CSS3等现代前端开发人员急需的技术关键点,包括响应式UI、访问远程Web 服务、用Ember.js 构建应用,等等。此外,还会介绍如何使用前沿开发工具来调试和测试代码,并且充分利用Node.js 和各种开源的npm 模块的强大功能来进行开发。 全书分四部分,每部分独立完成一个项......一起来看看 《Web开发权威指南》 这本书的介绍吧!