websocket 学习--简单使用,nodejs搭建websocket服务器,到模拟股票,到实现聊天室

websocket简介:

WebSocket协议是 HTML5 开始提供的一种基于TCP的一种新的全双工通讯的网络通讯协议。它允许服务器主动发送信息给客户端

 

 

和http协议的不同??

HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。而这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。

简单的说,WebSocket协议之前,实现双工通信就是通过不停发送HTTP请求(长轮询,使用 Ajax 轮询技术,轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求),从服务器拉取更新来实现,这导致了效率低下,浪费带宽资源,WebSocket解决了这个问题。

WebSocket 就是这样发明的。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。

 

 

websocket如何工作??

 

在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为"握手" 。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输相传送。

 

 

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

 

以下 API 用于创建 WebSocket 对象。第一个参数 url, 指定连接的 URL。而URL参数需要以WS://或者WSS://开头,例如:ws://www.websocket.org,如果URL有语法错误,构造函数会抛出异常。第二个参数 protocol 是可选的,指定了可接受的子协议。议的参数例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定义协议。  第二个参数是协议名称,是可选的,服务端和客服端使用的协议必须一致,这样收发消息彼此才能理解,你可以定义一个或多个客户端使用的协议,服务端会选择一个来使用,一个客服端和一个服务端之间只能有一个协议

var Socket = new WebSocket(url, [protocol] );

注意:基于多线程或多进程的服务器无法适用于 WebSockets,因为它旨在打开连接,尽可能快地处理请求,然后关闭连接。任何实际的 WebSockets 服务器端实现都需要一个异步服务器。

目前大部分浏览器支持 WebSocket() 接口,如 Chrome, Mozilla, Opera 和 Safari。

 

 

WS和WSS的区别??

注意:WebSocket协议定义了两种URL方案,WS和WSS分别代表了客户端和服务端之间未加密和加密的通信。WS(WebSocket)类似于Http URL,而WSS(WebSocket Security)URL 表示连接是基于安全传输层(TLS/SSL)和https的连接是同样的安全机制。

 

 

 

websocket的属性、事件、方法

属性描述
Socket.readyState

只读属性 readyState 表示连接状态,可以是以下值:

0 - 表示连接尚未建立。

1 - 表示连接已建立,可以进行通信。

2 - 表示连接正在进行关闭。

3 - 表示连接已经关闭或者连接不能打开。

Socket.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

注意:上述readyState 属性用于表示链接状态!

 

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发

 

方法描述
Socket.send()

使用连接发送数据

Socket.close()

关闭连接

 

 

 

websocket+nodejs简单实例应用

WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

WebSocket API是纯事件驱动,一旦建立全双工连接,当服务端给客户端发送数据或者资源,它能自动发送状态改变的数据和通知。所以你不需要为了状态的更新而去轮训Server,在客户端监听即可。

 

websocket客户端:

<!DOCTYPE HTML>
<html><head><meta charset="utf-8"><title>websocket测试(runoob.com)</title><script type="text/javascript">function WebSocketTest(){if ("WebSocket" in window){alert("您的浏览器支持 WebSocket!");// 初始化一个 WebSocket 对象,参数指明urlvar ws = new WebSocket("ws://localhost:9999");// WebSocket 连接时候触发ws.onopen = function(){//使用 send() 方法发送数据ws.send("客户端发送的数据");alert("数据发送中...");};// 接收服务端数据时触发ws.onmessage = function (evt) { var received_msg = evt.data;console.log(received_msg);alert("数据已接收...");};//断开 web socket 连接成功触发事件ws.onclose = function(){ // 关闭 websocketalert("连接已关闭..."); };}else{// 浏览器不支持 WebSocketalert("您的浏览器不支持 WebSocket!");}}</script></head><body><div id="sse"><a href="javascript:WebSocketTest()">运行 WebSocket</a></div></body>
</html>

 

websocket服务端:

WebSocket 在服务端的实现非常丰富。Node.js、Java、C++、Python 等多种语言都有自己的解决方案。这里主要记录nodejs作为websocket服务端的解决方案。

Node 实现有以下三种。

  • µWebSockets
  • Socket.IO
  • WebSocket-Node

 

这里主要记录使用nodejs搭建websocket服务器的方案

ws 是nodejs的一个WebSocket库,可以用来创建服务。使用cnpm install ws 命令行进行安装

下面是server.js的文件内容,cmd转到文件目录运行 node server.js  命令行

 

var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ port: 9999 });
wss.on('connection', function (ws) {console.log('client connected');ws.on('message', function (message) {console.log(message);ws.send("服务端接收到请求后,发送给客户端的数据");});});

效果如下:

 

 

 

进阶:websocket+nodejs模拟股票实例

上面的例子很简单,只是为了演示如何运用nodejs的ws创建一个WebSocket服务器。且可以接受客户端的消息。那么下面这个例子演示股票的实时更新。客服端只需要连接一次,服务器端会不断地发送新数据,客户端收数据后更新UI.页面如下,有五只股票,开始和停止按钮测试连接和关闭。

注意:一定要先在项目文件夹下运行 cnpm install ws  安装wwebsocket依赖包,不然会报以下错误

 

 

服务端server.js文件内容如下:

//引入websocket 的ws模块
var WebSocketServer = require('ws').Server,//初始化websocket对象
wss = new WebSocketServer({ port: 8181 });//初始数据对象
var stocks = {"AAPL": 95.0,"MSFT": 50.0,"AMZN": 300.0,"GOOG": 550.0,"YHOO": 35.0
}//获取随机数据的函数
function randomInterval(min, max) {return Math.floor(Math.random() * (max - min + 1) + min);
}//定时器返回的句柄
var stockUpdater;
var randomStockUpdater=function(){for (var symbol in stocks) {  //遍历对象属性进行随机增加浮动数值if(stocks.hasOwnProperty(symbol)) {   //遍历对象非继承属性var randomizedChange = randomInterval(-150, 150);var floatChange = randomizedChange / 100;stocks[symbol] += floatChange;}}//随机时间间隔,获取一个数据区间中的随机数值var randomMSTime = randomInterval(500, 2500);  stockUpdater = setTimeout(function() {   //模拟股票数据变化,随机更改对象属性值randomStockUpdater();}, randomMSTime);}//执行模拟数据变化更新
randomStockUpdater();//声明clientStocks接收客户端数据
var clientStocks = [];//连接建立后
wss.on('connection', function (ws) {//定义数据更新函数var sendStockUpdates = function (ws) {if (ws.readyState == 1) {  //readyState为1表示已经建立连接var stocksObj = {};for (var i = 0; i < clientStocks.length; i++) {var symbol = clientStocks[i];stocksObj[symbol] = stocks[symbol];}if (stocksObj.length !== 0) {  //数据包内容不为空时将数据响应给客户端ws.send(JSON.stringify(stocksObj));//需要将对象转成字符串。WebSocket只支持文本和二进制数据console.log("更新", JSON.stringify(stocksObj));}}}//服务器端定时更新响应数据var clientStockUpdater = setInterval(function () {sendStockUpdates(ws);}, 1000);//服务器端接收到客户端发送过来的数据,根据请求的数据更新响应数据ws.on('message', function (message) {var stockRequest = JSON.parse(message);console.log("服务器收到的消息:", stockRequest);clientStocks = stockRequest['stocks'];sendStockUpdates(ws);});});

 

客户端client.html 文件如下,界面使用了和jquery和bootstrape框架

<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>WebSocket  Demo</title><meta name="viewport" content="width=device-width, initial-scale=1"/><link href="../bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" /><script src="../js/jquery-1.12.3.min.js"></script><script src="../bootstrap-3.3.5/js/bootstrap.min.js"></script>
</head><body>
<div class="vertical-center"><div class="container"><h1>Stock Chart over WebSocket</h1><button class="btn btn-primary">开始</button><button class="btn btn-danger">停止</button><table class="table" id="stockTable"><thead><tr><th>Symbol</th><th>Price</th></tr></thead><tbody id="stockRows"><tr><td><h3>AAPL</h3></td><td id="AAPL"><h3><span class="label label-default">95.00</span></h3></td></tr><tr><td><h3>MSFT</h3></td><td id="MSFT"><h3><span class="label label-default">50.00</span></h3></td></tr><tr><td><h3>AMZN</h3></td><td id="AMZN"><h3><span class="label label-default">300.00</span></h3></td></tr><tr><td><h3>GOOG</h3></td><td id="GOOG"><h3><span class="label label-default">550.00</span></h3></td></tr><tr><td><h3>YHOO</h3></td><td id="YHOO"><h3><span class="label label-default">35.00</span></h3></td></tr></tbody></table></div>
</div><script>//客户端初始化websocket对象var ws = new WebSocket("ws://localhost:9999");//客户端发送的请求对象var stock_request = { "stocks": ["AAPL", "MSFT", "AMZN", "GOOG", "YHOO"] };var isClose = false; //通讯连接是否被关闭//界面的初始化数据对象var stocks = {"AAPL": 0, "MSFT": 0, "AMZN": 0, "GOOG": 0, "YHOO": 0};//定义更新UI界面的函数function updataUI() {//websocket连接上时触发ws.onopen = function (e) {console.log('Connection to server opened');isClose = false;ws.send(JSON.stringify(stock_request));console.log("sened a mesg");}// UI update functionvar changeStockEntry = function (symbol, originalValue, newValue) {var valElem = $('#' + symbol + ' span');valElem.html(newValue.toFixed(2)); //toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。if (newValue < originalValue) {valElem.addClass('label-danger');valElem.removeClass('label-success');} else if (newValue > originalValue) {valElem.addClass('label-success');valElem.removeClass('label-danger');}}// websocket接收到服务端数据时触发ws.onmessage = function (e) {var stocksData = JSON.parse(e.data);  //字符串转JSON对象console.log(stocksData);for (var symbol in stocksData) {  //遍历对象属性,更改客户端界面数据if (stocksData.hasOwnProperty(symbol)) {changeStockEntry(symbol, stocks[symbol], stocksData[symbol]);stocks[symbol] = stocksData[symbol];}}};}updataUI();  //更新UI界面$(".btn-primary").click(function() {  //开始按钮点击可以在断开后重连websocketif (isClose) {ws = new WebSocket("ws://localhost:9999");}updataUI();  //重连后更新UI界面});$(".btn-danger").click(function() {  //断开按钮可以关闭websocket连接ws.close();});//触发websocket连接关闭事件ws.onclose = function (e) {console.log("Connection closed", e);isClose = true;};</script>
</body>
</html>

源码见文章底部链接,效果如下:

 

 

 

进阶:websocket+nodejs模拟聊天室实例

 

上面的例子是连接建立之后,服务端不断给客户端发送数据。接下来例子是一个简单的聊天室类的例子。可以建立多个连接。

1.安装node-uuid模块,用来给每个连接一个唯一号。

2、客户端代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>WebSocket Echo Demo</title><meta name="viewport" content="width=device-width, initial-scale=1"/><link href="../bootstrap-3.3.5/css/bootstrap.min.css" rel="stylesheet" /><script src="../js/jquery-1.12.3.min.js"></script><script src="../js/jquery-1.12.3.min.js"></script><script src="../bootstrap-3.3.5/js/bootstrap.min.js"></script><script>//建立连接var ws = new WebSocket("ws://localhost:8181");var nickname = "";ws.onopen = function (e) {console.log('Connection to server opened');}//显示函数,根据客户端接收到的数据类型进行ui界面显示function appendLog(type, nickname, message) {if (typeof message == "undefined") return;var messages = document.getElementById('messages');var messageElem = document.createElement("li");var preface_label;if (type === 'notification') {preface_label = "<span class=\"label label-info\">*</span>";} else if (type == 'nick_update') {preface_label = "<span class=\"label label-warning\">*</span>";} else {preface_label = "<span class=\"label label-success\">"+ nickname + "</span>";}var message_text = "<h2>" + preface_label + "&nbsp;&nbsp;"+ message + "</h2>";messageElem.innerHTML = message_text;messages.appendChild(messageElem);}//收到消息处理ws.onmessage = function (e) {var data = JSON.parse(e.data);nickname = data.nickname;appendLog(data.type, data.nickname, data.message);console.log("ID: [%s] = %s", data.id, data.message);}ws.onclose = function (e) {appendLog("Connection closed");console.log("Connection closed");}//发送消息function sendMessage() {var messageField = document.getElementById('message');if (ws.readyState === WebSocket.OPEN) {ws.send(messageField.value);}messageField.value = '';messageField.focus();}//修改名称function changName() {var name = $("#name").val();if (ws.readyState === WebSocket.OPEN) {ws.send("/nick " + name);}}function disconnect() {ws.close();}</script>
</head><body ><div class="vertical-center"><div class="container"><ul id="messages" class="list-unstyled"></ul><hr/><form role="form" id="chat_form" onsubmit="sendMessage(); return false;"><div class="form-group"><input class="form-control" type="text" id="message" name="message"placeholder="Type text to echo in here" value="" autofocus/></div><button type="button" id="send" class="btn btn-primary"onclick="sendMessage();">Send Message</button></form><div class="form-group"><span>nikename:</span><input id="name" type="text" /> <button class="btn btn-sm btn-info" onclick="changName();">change</button></div></div></div>
</body>
</html>

 

3、服务端代码如下:

//引入ws模块,初始化websocket服务端
var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server,
wss = new WebSocketServer({ port: 8181 });//引入node-uuid模块,唯一标识
var uuid = require('node-uuid');//客户端数组
var clients = [];//遍历所有客户端连接,依次下发数据
function wsSend(type, client_uuid, nickname, message) {for (var i = 0; i < clients.length; i++) {var clientSocket = clients[i].ws;if (clientSocket.readyState === WebSocket.OPEN) {clientSocket.send(JSON.stringify({ //websocket传递JSONA字符串格式"type": type,"id": client_uuid,"nickname": nickname,"message": message}));}}
}var clientIndex = 1;//每一个客户端和服务端建立连接时触发
wss.on('connection', function(ws) {var client_uuid = uuid.v4();  //获取随机唯一标识var nickname = "AnonymousUser" + clientIndex;clientIndex += 1;clients.push({ "id": client_uuid, "ws": ws, "nickname": nickname });console.log('client [%s] connected', client_uuid);var connect_message = nickname + " has connected";wsSend("notification", client_uuid, nickname, connect_message);console.log('client [%s] connected', client_uuid);ws.on('message', function(message) {if (message.indexOf('/nick') === 0) { //json字符串数据包含修改昵称的数据时var nickname_array = message.split(' ');if (nickname_array.length >= 2) {var old_nickname = nickname;nickname = nickname_array[1];var nickname_message = "Client " + old_nickname + " changed to " + nickname;wsSend("nick_update", client_uuid, nickname, nickname_message);}} else {wsSend("message", client_uuid, nickname, message);}});//断开指定uuid的连接var closeSocket = function(customMessage) {for (var i = 0; i < clients.length; i++) {if (clients[i].id == client_uuid) {var disconnect_message;if (customMessage) {disconnect_message = customMessage;} else {disconnect_message = nickname + " has disconnected";}wsSend("notification", client_uuid, nickname, disconnect_message);clients.splice(i, 1);}}};//某个客户端连接断开时触发ws.on('close', function () {closeSocket();});//SIGINT这个信号是系统默认信号,代表信号中断,就是ctrl+cprocess.on('SIGINT', function () {console.log("Closing things");closeSocket('Server has disconnected');process.exit();});
});

效果如下:

源码见文章尾部

 

上述代码实现了一个服务器下的多个客户端连接,单并没有实现客户端的及时通讯,比如微信和QQ的单聊和群聊效果,可以参考以下demo

参考网址:https://blog.csdn.net/CJXBShowZhouyujuan/article/details/77816944

 

 

 

node-uuid是什么??

 

nodejs生成UID(唯一标识符)——node-uuid模块

unique identifier 惟一标识符        -->> uid

在项目开发中我们常需要给某些数据定义一个唯一标识符,便于寻找,关联。node-uuid模块很好的提供了这个功能。

 

使用起来很简单,两种:

1、uuid.v1(); -->基于时间戳生成  (time-based)

2、uuid.v4(); -->随机生成  (random)

 

通常我们使用基于时间戳  v1()  生成的UID,随机生成  v4()  还是有一定几率重复的。

    var UUID = require('uuid');var ID = UUID.v1();

 

 

websocket 和 socket 的区别??

软件通信有七层结构,下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做不同的工作,上层协议依赖与下层协议。基于这个通信结构的概念。

Socket 其实并不是一个协议,是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。当两台主机通信时,让 Socket 去组织数据,以符合指定的协议。TCP 连接则更依靠于底层的 IP 协议,IP 协议的连接则依赖于链路层等更低层次。

WebSocket 则是一个典型的应用层协议。

总的来说:Socket 是传输控制层协议,WebSocket 是应用层协议。

 

 源码:http://pan.baidu.com/s/1c2FfKbA

或 百度链接:https://pan.baidu.com/s/1cabjJKikHC3xBW-qUtP-3g   提取码:yb4u 
 

参考网址:

https://www.cnblogs.com/stoneniqiu/p/5402311.html

http://www.runoob.com/html/html5-websocket.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

红队打靶练习:DIGITALWORLD.LOCAL: FALL

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto 5、whatweb 6、小结 目录探测 1、gobuster 2、dirsearch WEB 80端口 /test.php 文件包含漏洞 SSH登录 提权 get root and flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interfa…

vue全局安装jquery,vue使用bootstrap框架,vue中封装websocket通讯,vue引入element-ui 组件库,引入highcharts图表插件

vue安装jquery&#xff1a; 1、使用vue-cli创建好vue项目后&#xff0c;在项目文件夹下&#xff0c;使用命令npm install jquery --save-dev 引入jquery。 2、修改项目文件 build/webpack.base.conf.js&#xff0c;添加如下内容&#xff1a; var webpackrequire(webpack) mo…

flex弹性布局笔记

学习自菜鸟教程的flex布局笔记 布局的传统解决方案&#xff0c;基于盒装模型&#xff0c;依赖 display 属性 position 属性 float 属性。它对于那些特殊布局非常不方便&#xff0c;比如&#xff0c;垂直居中就不容易实现。 简介&#xff1a; W3C提出了一种新的方案—-Flex布…

css宽高自适应布局,实现Sticky Footer的三种布局方式

宽度自适应布局&#xff1a; 1、使用场景&#xff1a; 一侧&#xff08;左侧或者右侧&#xff09;为固定的导航或者菜单栏&#xff0c;另一侧将会随着浏览器的缩放而自适应改变其大小。这种布局结构可用于顶层布局结构亦可用于某个局部功能块&#xff0c;常见于各种web系统&am…

vue学习:事件传递(冒泡和捕获),事件委托,jquery中的事件委托,$event 获取元素,vue事件修饰符

事件传递 ----冒泡和捕获 DOM事件标准定义了两种事件流&#xff0c;这两种事件流分别是捕获和冒泡。 和许多Web技 术一样&#xff0c;在它们成为标准之前&#xff0c;Netscape和微软各自不同地实现了它们。Netscape选择实现了捕获事件流&#xff0c;微软则实现了冒泡事件流。…

vue中路径的配置使用

绝对路径使用&#xff1a; 在项目中build文件夹下的webpack.base.conf.js的 使用如下&#xff1a; import mock from /mock/mock.js; html 相对路径使用 1. 当需要引用 同一目录下的文件&#xff0c;直接输入文档, 如下 <img src”bg.jpg” /> 2、当需要引用下一级目录…

常用MIME类型,解决IIS布署后字体文件、mp4视频文件等not found 的错误

前言&#xff1a;项目在本地运行正常&#xff0c;但部署在IIS服务器后使用浏览器访问项目会报&#xff1a;404 not found 错误&#xff0c;包括mp4视频文件和woff文件找不到。。如下 原因&#xff1a;在IIS中没有将 .mp4和 .woff 后缀的相应的MIME类型&#xff0c;使得 .mp4等格…

浏览器兼容video视频播放的多种方法

前言&#xff1a; 在 HTML 中播放视频并不容易&#xff01;因为直到现在&#xff0c;仍然不存在一项旨在网页上显示视频的标准。今天&#xff0c;大多数视频是通过插件&#xff08;比如 Flash&#xff09;来显示的。然而&#xff0c;并非所有浏览器都拥有同样的插件。 比如win…

pdf文件加密解密,pdf忘记密码解密的办法

1、pdf文件加密 步骤&#xff1a;wps》菜单“保护”》文档加密&#xff0c;设置编辑及页面密码&#xff0c;如下 2、pdf解密 在解密窗口取消选择“设置编辑及页面密码”&#xff0c;如下 注意&#xff1a;当忘记pdf密码时&#xff0c;可以使用pdf解密软件解密&#xff0c;如下…

伪类::selection自定义文本选中时的样式(CSS3样式),CSS3的word-break单次换行

1、::selection CSS3伪类自定义文本选中时的样式 有的人在浏览网页时&#xff0c;喜欢一边选中文本一边阅读。在windows环境下&#xff0c;正常的文本选中应该是深蓝色背景白色文本的样式。那么想要修改文本选中样式&#xff0c;可以通过css中有这样的一个伪类::selection用于自…

修改elementUI组件样式无效的多种解决方式

前言&#xff1a;vueelementUI项目开发中&#xff0c;经常遇到修改elementUI组件样式无效的问题&#xff0c; 原因&#xff1a;在vue组件中我们经常需要给style添加scoped来使得当前样式只作用于当前组件的节点。添加scoped之后&#xff0c;工作原理是将当前组件的节点添加一个…

CSS3 @media媒体查询 适配不同尺寸设备的响应式布局(清晰详解)

随着宽屏的不断普及&#xff0c;CSS3出现了media媒体查询技术 一、了解Media 相关知识 1、了解Media Queries Media Queries能在不同的条件下使用不同的样式&#xff0c;使页面在不同在终端设备下达到不同的渲染效果。其原理就是允许添加表达式用以媒体查询&#xff08;包括媒…

windows下mysql8.0-64的安装、完全卸载及注意事项(亲测),MySQL和SQL Server的简单区别

Windows 上安装 MySQL 1、现在zip安装包&#xff1a; 点击链接 https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.11-winx64.zip 下载 zip 包。最新版本可以在 MySQL 下载 中下载中查看。 点击 Download 按钮进入下载页面&#xff0c;点击下图中的 No thanks, just star…

ChatGPT/GPT4+AI绘图+论文写作+编程结合到底有多强大?带你详细了解

ChatGPT在论文写作与编程方面具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的支持…

vue-cli项目布署问题解决:空白页、静态资源文件404错误、refrenceError:promise未定义(部分浏览器不支持ES6语法)

&#xff08;前言&#xff1a;文章记录vue-cli项目打包使用IIS布署遇到的几个错误及解决方式&#xff09; 首先简单理解webpack打包&#xff1a; 个人理解&#xff1a;项目开发中我们构建 "低耦合高内聚" 的组件/模块来代码重用、降低项目复杂性&#xff0c;提升开发…

简单地使用webpack进行打包,一些常见打包错误

本质上&#xff0c;webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时&#xff0c;它会递归地构建一个依赖关系图(dependency graph)&#xff0c;其中包含应用程序需要的每个模块&#xff0c;然后将所有这些模块打包成一个或…

Vue-cli 项目优化归纳(打包、源码、用户体验)

前言&#xff1a;vue-cli项目开发打包部署后&#xff0c;存在问题有首次首页加载过慢&#xff0c;包括加载缓慢问题&#xff0c;需要进行vue项目优化。下面是对vue性能优化方法进行归纳&#xff0c;后面会对方法进行亲测。 主要包括&#xff1a;代码包打包优化、编码优化、用户…

JS中的prototype、__proto__与constructor,原型和原型链

理解原型的几个关键点&#xff1a; 1、所有的引用类型&#xff08;数组、函数、对象&#xff09;可以自由扩展属性&#xff08;除null以外&#xff09;; 2、所有的引用类型&#xff08;对象&#xff09;都有一个’_ _ proto_ _属性(也叫隐式原型&#xff0c;它是一个普通的对…

彻底理解cookie,session,token

转载自&#xff1a;https://www.cnblogs.com/moyand/p/9047978.html 发展史 1、很久很久以前&#xff0c;Web 基本上就是文档的浏览而已&#xff0c; 既然是浏览&#xff0c;作为服务器&#xff0c; 不需要记录谁在某一段时间里都浏览了什么文档&#xff0c;每次请求都是一个新…

硬盘基本知识(磁头、磁道、扇区、柱面),格式化容量计算

计算差&#xff1a; 在购买硬盘之后&#xff0c;细心的人会发现&#xff0c;在操作系统当中硬盘的容量与官方标称的容量不符&#xff0c;都要少于标称容量&#xff0c;容量越大则这个差异越大。标称40GB的硬盘&#xff0c;在操作系统中显示只有38GB&#xff1b;80GB的硬盘只有7…