当前位置: 首页 > news >正文

【Nginx23】Nginx学习:响应头与Map变量操作

Nginx学习:响应头与Map变量操作

响应头是非常重要的内容,浏览器或者客户端有很多东西可能都是根据响应头来进行判断操作的,比如说最典型的 Content-Type ,之前我们也演示过,直接设置一个空的 types 然后指定默认的数据类型的值,所有的请求浏览器都会直接下载。另外,我们现在在做前后分离的开发时,也经常会通过头信息来传递一些标志参数,那么自定义响应头的作用就更加重要了。另外一个 Map 部分则是 Nginx 中的一种变量设置方式,话不多说,直接开始吧。

今天学习的内容响应头部分都是可以设置在 http、server、location 中的,有特殊情况的我会单独说。而 Map 部分则都是只能在 http 中进行配置。

响应头

在 Nginx 中,响应头模块就是 ngx_http_headers_module 模块。总共就三个配置指令,其实并不复杂。而且相信其中两个指令大家都至少是见过的。除了可以添加自定义的响应头之外,在这个模块中还有一个非常重要的内容就是 HTTP 的 Expire 缓存设置。在最后,我们将会统一进行一个测试,先来看看响应头模块中的三个配置指令。

add_header

如果响应代码等于 200、201 (1.3.10)、204、206、301、302、303、304、307 (1.1.16、1.0.13) 或 308 (1.13),则将指定字段添加到响应标头。

add_header name value [always];

默认值没有,但是 Nginx 会默认帮我们添加一些响应头,比如说 Server 显示 Nginx 版本号的,还有 Content-Type 这个标准响应头。它的参数值可以包含变量,最后的 always 表示忽略上面的那些状态码,任何响应都返回这个响应头。

我们可以定义多个响应头,如果当前的作用域中没有定义,那么会从上一级继承。

如果是空的内容,这个响应头不会返回。

add_trailer

如果响应代码等于 200、201、206、301、302、303、307 或 308,则将指定字段添加到响应的末尾。

add_trailer name value [always];

它的用法和 add_header 是一样的,但是不好测,据说是用在分段响应上的。不过我们之前在 Nginx学习:HTTP核心模块(十二)内嵌变量https://mp.weixin.qq.com/s/0ks7GgfcvJpQp7mA1IgQcA 中讲过一个 $sent_trailer_[name] 变量,大家还记得吧?它可以获取到响应尾所添加的内容,然后我们就可以输出到日志中。当时已经做过测试啦,这里就不再重复说了。

expires

如果响应代码等于 200、201 (1.3.10)、204、206、301、302、303、304、307 (1.1.1),则启用或禁用添加或修改“Expires”和“Cache-Control”响应头字段。

expires [modified] time;
expires epoch | max | off;

默认值是 off ,也就是关闭的,任何响应都不会返回 Expire 和 Cache-Control 响应头。这个呀,其实就是 HTTP 中的 Expire 和 Cache-Control 的基础知识相关的配置。比如我们查看一些网站的请求时,会有一些静态资源像是 js 文件、图片之类的,会返回 200 响应,但是后面还会跟着一个 from memory cache 或者 from disk cache 。这种就是使用了 Expire 或 Cache-Control 缓存,在缓存有效时间之内,都会直接从本地读取缓存,不会发送请求。

和 Last-Modified 以及 Etag 的区别就是,这两个以文件的修改为主,真的会发一个请求到服务器,服务器判断没修改之后再返回 304 。而 Expire 和 Cache-Control 连请求都不会发,必须强制刷新或者让浏览器不使用缓存。而且直接请求 URL 看不到效果,需要是静态页面中通过 src 加载的内容才会走这个缓存。Expire 比较老一些,新的是 Cache-Control ,所以两个同时存在时会走 Cache-Control 。不过 Nginx 中这个配置指令会一起设置。

好了,点到为止,还不太清楚的小伙伴可以继续查阅相关资料哦。

正常来说,这个 time 是要过期的时间长度,比如 10 秒后过期写 10s 就好了。没错,是当前时间加上 expires 设置的时间。如果使用 modified ,则是当前访问路径的文件的修改时间加上 expires 的时间。注意,服务端和客户端的时间要一致,比如我之前测试时,服务端虚拟机的时间比我的电脑慢了3分钟,设置 10s 的缓存就一直都不会生效。

我们也可以通过 @ 符号指定一个时间。

expires @15h30m;

这样就是指定当天的 15 点 30 分过期。

expires 还会影响到 Cache-Control 的值。

  • 如果设置一个负数的话,Cache-Control 会设置 no-cache ;

  • 如果设置为非负数,包括 0 的话,Cache-Control 的 max-age 会等于这个数值;

而真正的 Expire 响应头,则是具体的 GMT 时间值,也就是当前时间加上 expires 指定后的具体时间。

设置为 epoch 参数,则表示永远不缓存,对应的头信息为 “Expires” 设置成 “Thu, 01 Jan 1970 00:00:01 GMT” 而 “Cache-Control” 会设置成 “no-cache” ;设置为 max 参数则表示永远不过期,“Expires” 设置成 “Thu, 31 Dec 2037 23:55:55 GMT” 而 “Cache-Control” 会设置成 10 年。

最后一个参数的值,可以是一个变量。

响应头测试

好了,就这三个配置指令,不多吧。但是,如你对 HTTP 的基础知识真的都不清楚的话,那就没别的办法了,先自己测试一下,明白是什么意思,然后赶紧去恶补一下吧。

我们先写个 location 方便测试。

location /headers/ {alias html/;add_header PPOP abc$uri;add_header GET_VALUE $arg_a;add_trailer op def$uri;access_log logs/params2.log vvv;expires 10s;add_header Cache-Control public;
}

通过 alias 还是指向了 html 这个根目录,主要是我比较懒,不想多建目录啦。然后 add_header 的大家自己测试一下吧,看看响应头会不会返回数据。注意第二个,我们是接收的 $arg_[name] 这种形式的变量参数哦,如果不传变量看看会不会有响应头返回回来。

然后就是 add_trailer 的测试,上回我们只是大概说了下,这回还是再简单的看一下。在 location 中,我们将访问日志 access_log 配置为一个新的日志目录文件了,并且指定了日志格式是 vvv 。然后我们需要再到 http 中添加一个配置。

// http 下
log_format vvv op_trailer=$sent_trailer_op;

这个配置指令后面我们学习日志模块时会详细地再学习,现在先这么配就好了。然后访问请求之后,就可以在日志文件中看到信息了。

// params2.log
………………
op_trailer=def/headers/index.html
………………

好了,最后的重点,就是对于 expires 的测试了。我们需要先创建一个静态文件,然后加载一张图片。注意,图片路径我也是走的上面配置的 headers 这个 location ,直接走 /img/ 目录是不行的哦,因为我们的 expires 是配置在这个 location 当中了。

// cache1.html
222111
<img src="/headers/img/1.jpeg" width="200px"/>

然后开始请求访问,并多次刷新。我们测试的 10s ,需要注意测试机与当前主机的时间同步问题。另外,还添加了一个 Cache-Control 头设置为 public ,这个有啥用大家也可以自己查下哦,都是基础知识。不用设置它也可以。

489dbade732064ec7da0d691e8dc14a2.png

注意看,第一次是 200 正常响应,然后中间几次也是 200 ,但后面有了一个 memory cache 的标志了。查看 Nginx 的 access_log ,也不会看到这些请求,说明真的是没有发请求。然后 10s 后,再请求一次,会发现返回了一个 304 ,这是 Last-Modified 在起作用。同时,Expire 也被更新了。之后的请求又开始 memory cache 了。

看到了吧,这就是静态资源的多级缓存。在架构设计中,缓存前推中最重要的就是 HTTP 的这两块缓存,是非常重要的理论知识,而且也是非常容易就通过配置能够实现的理论实践,大家可以赶紧应用在自己的项目中哦。好处嘛,减少流量带宽占用,毕竟现在流量费也挺贵的,好吧,你不担心流量费,但至少 access_log 文件还能小点是不是。

ps.去看看京东、淘宝、网易、新浪这些大网站是怎么设置过期时间的哦,大部分图片可能都是 max ,而 js、css 之类的则可能会比较短哦。

Map变量

之前我们学过的都是 Nginx 提供的系统变量,这一次,我们要自己设置变量啦。在 Nginx 中,目前可知的设置变量的方法有三种,分别是 set 指令、map 指令和正则方式。正则就是匹配之后那个 $1 这种。

set 指令我们后面再说,今天先来看看 map 模块相关的指令。

map

Map 模块 ngx_http_map_module ,它可以创建变量,但是,它的值是取决于另外一个变量的。什么意思呢?我们先来看看这个指令的介绍。

map string $variable { ... }

这参数有点怪呀,第一个 string 表明要进行判断的值。第二个参数就是我们要创建的变量名称。后面花括号中的内容是对于那个 string 的匹配结果。来看一个例子。

map $arg_a $a {default 0;aaa 1;~.*aaa 2;aaa* 3;bbb 1;ccc 2;
}server {listen 8088;root html;location / {if ($a = 1) {return 200 aaa$a;}if ($a = 2) {return 200 bbb$a;}return 200 $a;
}

注意,map 要放在 http 下面哦,不能在 server 或 location 中。

在 map 中,我们设置了第一个参数是 $arg_[name] 这个变量,这样我们就可以通过 GET 参数 a 来传递值。第二个参数是赋值之后的变量名。

花括号中的内容是匹配规则,可以看到 default 表示默认值,aaa 是普通匹配,~.*aaa 是正则匹配。意思就是,请求中有一个 GET 参数是 a ,并且参数的值是 aaa ,那么 $a 的结果就是 1 ;如果是 xaaa ,那么 $a 就是 2 ;如果是 aaa* 结果值就是 3 ,注意,这个 * 没有特别含义的,目前状态下是不能进行通配的;其它两个不用说了吧;如果不匹配,或者没有这个 GET 参数的话,返回 0 。

然后在下面的 location 中,如果 $a 的值是 1 ,那么返回的结果前面加上 aaa ,如果是 2,结果前面加上 bbb ,其它情况直接返回 $a 的值。

来测试一下吧。

[root@localhost ~]# curl http://127.0.0.1:8088/
0
[root@localhost ~]# curl http://127.0.0.1:8088/?a=aaa
aaa1
[root@localhost ~]# curl http://127.0.0.1:8088/?a=waaa
bbb2
[root@localhost ~]# curl http://127.0.0.1:8088/?a=ccc
bbb2
[root@localhost ~]# curl http://127.0.0.1:8088/?a=ddd
0

看出效果了吧,是不是感觉似曾相识?没错,不要怀疑自己,这就是编程语言中的 switch 。

第一个参数是一个 string ,你也可以写一个固定的字符串,但是那样就没意义了。因此,map 通常都会配合系统提供的变量来进行操作,比如官网的例子。

map $http_host $name {hostnames;default       0;example.com   1;*.example.com 1;example.org   2;*.example.org 2;.example.net  3;wap.*         4;
}map $http_user_agent $mobile {default       0;"~Opera Mini" 1;
}

第一个例子是对 Host 请求头进行匹配,返回 $name 值。注意,这里的 * 是可以通配的,因为这是针对主机名的匹配,其实走的是主机掩码,就是域名那一套,比如泛解析的掩码通配。可以加上一个 hostnames 参数,就可以实现对主机名的通配,这个 hostnames 需要放在最上面。

第二个例子可以用于判断浏览器类型,比如说现在最常用的判断是否移动端,或者判断是否是微信客户端,然后通过这个变量就可以配合 if 指令进行跳转,高大上吧!

花括号中,除了匹配规则、default 和 hostnames 之外 ,还有两个特殊的参数,include 和 volatile ,前者可以包含一个带有值的文件。可以有多个。后者可以表示该变量不可缓存。

另外,如果正则、hostnames、还有普通匹配同时匹配到了怎么办呢?那就是优先顺序的问题了嘛。

  • 普通字符串值最高

  • 前面带 * 通配掩码的,比如:*.example.com

  • 后面带 * 通配掩码的,比如:mail.*

  • 第一个匹配的正则表达式(在配置文件中的出现顺序)

  • 默认 default 的值

map_hash_bucket_size

设置映射变量哈希表的存储桶大小。默认值取决于处理器的缓存线大小。

map_hash_bucket_size size;

默认值根据系统情况而定,默认值是 32 或 64 或 128 。

map_hash_max_size

设置映射变量哈希表的最大大小。

map_hash_max_size size;

默认值是 2048。

设置哈希表

之前很多内容中其实都提到过哈希表这个东西,今天就放到这里一起说明一下吧,因为 Map 模块后面的两个配置指令也和这个东西有关,以下是官方文档的解释。

为了快速处理静态的数据集合,诸如虚拟主机名、 map指令的值、 MIME类型和请求头的字段名,Nginx 使用了哈希表。在 Nginx 启动和更新配置的过程中,它会尽可能为哈希表选择最小的容量, 同时使每个哈希桶的长度不超过设置的配置参数。这些桶用于保存键和对应的哈希值。整个哈希表的容量以哈希桶的数量来定义。Nginx不断调整哈希表直到哈希表容量超过配置的最大值。大部分哈希表都有对应的指令,允许修改这些配置参数。比如,针对虚拟主机名的哈希表,有server_names_hash_max_size 和 server_names_hash_bucket_size 两条指令。

哈希桶大小的参数会对齐到处理器缓存线长度的整数倍。这将加速哈希表中的键查找,因为在现代的处理器上,这可以减少内存访问的次数。如果哈希桶大小等于处理器的缓存线长度,那么在最坏情况下,键查找时的内存访问次数是两次—— 第一次是计算哈希桶的地址,第二次是在哈希桶内进行键查找。因此,如果nginx提示需要增大哈希表容量或者哈希桶大小时,应优先增大前者。

说实话,我也不懂是啥意思,但看得出来:

  • 一是数据结构方面的问题,哈希是空间换时间的一种策略,因此,占用的内存空间也不能无限大,会有一个限制

  • 二是哈希表在 Nginx 启动时就把所有键值对确定了,之后不能再添加修改(开放地址法,键的数量大于可能的值的数量,不需要进行线性探测),而且尽量选择最小值,但是会通过哈希桶的数量来调整容量直到达到最大值

  • 三是有计算机原理中内存对齐的概念,哈希表可以快速访问,通过对齐能够减少内存访问次数(CPU缓存)

  • 四是如果 Nginx 日志中提示需要增大哈希表的话,优先调整 xxxx_bucket_size 之类的指令大小,也就是增大容量

其它的嘛?哥们实在是无能为力了 ,只能帮到这里了。希望各位大佬有时间并且不小心看到这篇文章的话,能够不吝赐教。

总结

今天的内容中,add_header 确实是用过,但是其它的,说实话,真的从来没接触过。没错,你没看错,干了这么些年,直到现在我也没完全搞清楚 HTTP 中缓存的这些东西。但是,通过学习今天的内容,并且在写文章时不断地查阅资料,这下真的算是彻底搞明白了 Expire 和 Last-Modified 这些东西到底是干嘛了。这下面试的时候总算不慌了,当然是前提别人能给 35+ 快 40 的老码农一个能面试的机会。Cry....

另外的 Map 模块,其实也从来都没用过,甚至之前都不知道有这个功能。毕竟在 Nginx 中,如果需要定义变量的话,set 指令真的很方便,不过通过了今天的学习,貌似 map 还是一个可以挖掘的宝藏功能哦,而且它真的非常像 switch 的作用,更加地灵活方便。

参考文档:

http://nginx.org/en/docs/http/ngx_http_headers_module.html

http://nginx.org/en/docs/http/ngx_http_map_module.html

相关文章:

【Nginx23】Nginx学习:响应头与Map变量操作

Nginx学习&#xff1a;响应头与Map变量操作 响应头是非常重要的内容&#xff0c;浏览器或者客户端有很多东西可能都是根据响应头来进行判断操作的&#xff0c;比如说最典型的 Content-Type &#xff0c;之前我们也演示过&#xff0c;直接设置一个空的 types 然后指定默认的数据…...

前端代理报错Error occured while trying to proxy to: localhost:端口

webpack配置进行前端代理时&#xff0c; 报错信息如下&#xff1a;(DEPTH_ZERO_SELF_SIGNED_CERT) 需设置&#xff1a;secure为false即可解决此报错 // webpack配置前端代理config["/test"]{target: https://xxxx.com,changeOrigin: true,secure: false // 这个配置…...

QT DAY6

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);socket new QTcpSocket(this);//如果连接服务器成功&#xff0c;该客户端就会发射一个connected的信号。//我们…...

Slint学习文档

Slint学习文档 Slint Learn如何学习本文档学习顺序标志说明 Slint With VSCodeSlint With Rust依赖&#x1f44e;定义宏 Slint与Rust分离1.添加编译依赖&#xff08;slint-build&#xff09;2.编写slint文件3.编写build.rs4.编写main.rs 普通组件主窗体Windowexample 文本Texte…...

【最新!七麦下载量analysis参数】逆向分析与Python实现加密算法

文章目录 1. 写在前面2. 请求分析3. 加密分析4. 算法实现 1. 写在前面 之前出过一个关于榜单analysis的分析&#xff0c;有兴趣的可以查看这篇文章&#xff1a;七麦榜单analysis加密分析 最近运营团队那边有同事找到我们&#xff0c;说工作中偶尔需要统计分析一下某APP在一些主…...

蓝桥杯练习题(3的倍数)

问题描述 小蓝对 3 的倍数很感兴趣。现在他手头有三个不同的数 a,b,c, 他想知道, 这三个数中是不是有两个数的和是 3 的倍数。 例如, 当 a3,b4,c6 时, 可以找到 a 和 c 的和是 3 的倍数。 例如, 当 a3,b4,c7 时, 没办法找到两个数的和是 3 的倍数。 输入格式 输入三行, 每行…...

安装Qe-7.2细节

编译 直接编译报错&#xff0c;发现要使用gpu加速。 检查linux的GPU: nvidia-smi lspci |grep -i nvidia module load cuda ./configure make all 安装curl mkdir build cd build …/configure --prefix/home/bin/local/curl make make install 加入路径&#xff1a; expor…...

3.运行项目

克隆项目 使用安装的git克隆vue2版本的若依项目&#xff0c;博主使用的版本是3.8.6. git clone https://gitee.com/y_project/RuoYi-Vue.git目录结构如下图所示&#xff0c;其中ruoyi-ui是前端的内容&#xff0c;其它均为后端的内容。 配置mysql数据库 在数据库里新建一个…...

【算法题】2651. 计算列车到站时间

题目&#xff1a; 给你一个正整数 arrivalTime 表示列车正点到站的时间&#xff08;单位&#xff1a;小时&#xff09;&#xff0c;另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意&#xff0c;该问题中的时间采用 24 小时制。 示例 1…...

Mybatis传递实体对象只能直接获取,不能使用对象.属性方式获取

mybatis的自动识别参数功能很强大&#xff0c;pojo实体类可以直接写进mapper接口里面&#xff0c;不需要在mapper.xml文件中添加paramType,但是加了可以提高mybatis的效率 不加Param注解&#xff0c;取值的时候直接写属性 //这里是单参数&#xff0c;可以不加param&#xff01…...

flink 写入数据到 kafka 后,数据过一段时间自动删除

版本 flink 1.16.0kafka 2.3 流程描述&#xff1a; flink利用KafkaSource&#xff0c;读取kafka的数据&#xff0c;然后经过一系列的处理&#xff0c;通过KafkaSink&#xff0c;采用 EXACTLY_ONCE 的模式&#xff0c;将处理后的数据再写入到新的topic中。 问题描述&#xff1…...

golong基础相关操作--一

package main//go语言以包作为管理单位&#xff0c;每个文件必须先声明包 //程序必须有一个main包 // 导入包&#xff0c;必须要要使用 // 变量声明了&#xff0c;必须要使用 import ("fmt" )/* * 包内部的变量 */ var aa 3var ss "kkk"var bb truevar …...

【深度学习】基于卷积神经网络的铁路信号灯识别方法

基于卷积神经网络的铁路信号灯识别方法 摘 要&#xff1a;1 引言2 卷积神经网络模型2.1 卷积神经网络结构2.2.1 卷积层2.2.2 池化层2.2.3 全连接层 3 卷积神经网络算法实现3.1 数据集制作3.2 卷积神经网络的训练过程3.2.1 前向传播过程 4 实验5 结语 摘 要&#xff1a; 目前中…...

DR IP-SoC China 2023 Day演讲预告 | 龙智Perforce专家解析芯片开发中的数字资产管理

2023年9月6日&#xff08;周三&#xff09;&#xff0c;龙智即将亮相于上海举行的D&R IP-SoC China 2023 Day&#xff0c;呈现集成了Perforce与Atlassian产品的芯片开发解决方案&#xff0c;助力企业更好、更快地进行芯片开发。 D&R IP-SoC China 2023 Day 是中国首个…...

解决github连接不上的问题

改 hosts 我们在浏览器输入 GitHub 的网址时&#xff0c;会向 DNS 服务器发送一个请求&#xff0c;获取到 GitHub 网站所在的服务器 IP 地址&#xff0c;从而进行访问。 就像你是一名快递员&#xff0c;在送快递前要先找中间人询问收件人的地址。而 DNS 就是这个告诉你目标地址…...

# DevOps名词定义梳理

DevOps名词定义梳理 极限编程座右铭&#xff1a;如果它令你很受伤&#xff0c;那么就做更多的练习&#xff08;If it hurts, do it more often&#xff09; 经常人们会把这些名词用错&#xff1a; 构建&#xff1a;就是把源代码制成成品的过程&#xff0c;这个过程一般会有单元…...

Redis Cluster

文章目录 一、集群搭建1 节点规划2 集群启动 二、配置一致性1 基本分工2 更新规则 三、Sharding1 数据分片分片实现分片特点 2 slot迁移迁移原因迁移支持集群扩容迁移错误背景现象问题分析验证猜想 集群缩容 3. 请求路由client端server端migrating节点的读写importing节点的读写…...

Pandas常用指令

astype astype的作用是转换数据类型&#xff0c;astype是没办法直接在原df上进行修改的&#xff0c;只能通过赋值的形式将原有的df进行覆盖&#xff0c;即df df.astype(dtype) astype的基本语法 DataFrame.astype(dtype, copyTrue, errorsraise) dtype参数指定将数据类型转换…...

FPGA实战小项目3

基于FPGA的波形发生器 基于FPGA的波形发生器 基于FPGA的beep音乐播放器设计 基于FPGA的beep音乐播放器设计 基于FPGA的cordic算法实现DDS sin和cosine波形的产生 基于FPGA的cordic算法实现DDS sin和cosine波形的产生...

mysql创建用户

创建用户 创建 -- 创建用户 itcast , localhost只能够在当前主机localhost访问, 密码123456; create user test01localhost identified by 123456;使用命令show databases;命令&#xff0c;只显示一个数据库&#xff0c;因为没有权限 -- 创建用户 test02, 可以在任意主机访问…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...

React核心概念:State是什么?如何用useState管理组件自己的数据?

系列回顾&#xff1a; 在上一篇《React入门第一步》中&#xff0c;我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目&#xff0c;并修改了App.jsx组件&#xff0c;让页面显示出我们想要的文字。但是&#xff0c;那个页面是“死”的&#xff0c;它只是静态…...