APP中RN页面热更新流程-ReactNative源码分析

平时使用WebStorm或VSCode对RN工程中的文件修改后,在键盘上按一下快捷cmd+s进行文件保存,此时当前调试的RN页面就会自动进行刷新,这是RN开发相比于原生开发一个很大的优点:热更新。 那么,从按一下快捷cmd+s到RN页面展示出最新的JS页面,这个过程是怎样发生的呢?下面根据时间顺序来梳理一下。 这里约定后面说的原生部分是指iOS端,ReactNative源码分析指的是iOS端集成的RN框架分析。   原生APP中RN页面的热更新简要流程 React Native应用包含两部分:原生代码和JavaScript代码。JavaScript和原生代码通信的桥梁是Bridge,而Bridge的实现又依赖于JSThread的runloop。 当JS有消息要传递给原生时,它会把消息封装成事件放入到JSThread的runloop的事件队列中,而JSThread的runloop会监听消息队列中的事件,一旦有事件需要处理,就会将其交给Bridge处理,从而实现JavaScript和原生代码的相互调用和数据传输。   基于JavaScript和原生代码的消息传递机制,RN热更新步骤如下: 1.在iOS原生中的RN页面触发热更新时,首先是JS环境中的websocket收到了Metro服务器的通知,在这个通知中包含了需要更新的JS bundle的URL地址,然后js将这个通知事件放到了JSThread的runloop中传到了RCTCxxBridge。 2.RCTCxxBridge收到热更新事件后,调用JavaScriptCore框架中的方法来执行一个JavaScript脚本,这个脚本会告诉JavaScript环境去下载新的JS bundle并执行它。事件又回到了JS。 3.JavaScript环境调用下载命令向远程服务器请求新的JS bundle,事件又被转回到了原生侧。 4.原生侧下载最新的bundle.js,下载完成后调用加载,执行js方法。 5.重新设置RN页面的根组件。   热更新触发条件 React Native在调试模式下有两种热更新方式:Hot Reloading和Live Reload。Hot Reloading可以实现代码的增量更新,而Live Reload技术则是全量更新。 下面以在index.js中新增一个组件注册语句为例。 在RN项目中index.js是ReactNative项目的入口文件,RN启动时首先会执行这个文件,把组件注册到AppRegistry中,这里在index.js的文件底部顺序添加一个组件注册,然后按快捷键cmd+s保存修改
AppRegistry.registerComponent('FlatListDemo', () => FlatListDemo);
这时本地的Packager服务会监听本地文件系统的变化,当有文件修改并保存时,Packager会运行RN命令行工具,自动生成一个新的bundle文件
react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/main.jsbundle --assets-dest ios
然后将生成的bundle文件上传至服务器,接着Metro 服务器通过 WebSocket 链接发送消息给APP应用程序。

 

触发热更新

在APP中RN框架启动时,会在APP的JS运行上下文中创建一个websocket链接并与js服务器建立连接,它用于监听Metro服务器发来的bundle.js更新通知。 当Packger打了新的bundle.js并上传到js服务器后,Metor服务器就会向与它链接的websocket发送更新通知,js引擎收到服务器的通知后,就会做后续的事件处理。 具体js建立websocket的代码如下: 在iOS端ReactNative框架中,RCTCxxBridge文件中的+ (void)runRunLoop方法内负责创建并运行JS引擎对应的jsThread的runloop。它在APP启动时被创建,用来处理js引擎的任务和事件,并保证了_jsThread的常驻,不被销毁。 runloop被注册时机在RN框架启动时: js引擎收到服务器的通知后,被包成一个原生runloop的事件源放入到事件队列中,然后jsThread的runloop开始处理事件。 然后把事件加入到RCTMessageThread中进行异步处理 RCTCxxBridge调用js脚本,让js处理与最新bundle.js下载相关的事件。把事件传入到js事件队列中 js引擎处理完JS层面的事件后,将事件转回给原生,让原生代码执行实际的下载工作 原生侧的RCTDevSettings模块的reloadWithReason:方法进行处理。调用ReloadCommand监听的触发器,进行触发reloadCommand命令 RCTReloadCommand发送didReceiveReloadCommand收到下载指令 接着调用RCTBridge中的didReceiveReloadCommand方法,RCTBridge中销毁之前的js缓存,调用setUp进行js环境重置,js资源下载 js资源下载完成后,执行js代码 js资源reload完成后,调用js引擎,展示目标组件 当js文件加载成功后,APP会重新创建一个RCTRootContentView, 并将旧的移除,把新的添加上去。新的RCTRootContentView.reactTag使用规则递增
- (void)bundleFinishedLoading:(RCTBridge *)bridge
{
  RCTAssert(bridge != nil, @"Bridge cannot be nil");
  if (!bridge.valid) {
    return;
  }
  
  [_contentView removeFromSuperview];
  _contentView = [[RCTRootContentView alloc] initWithFrame:self.bounds
                                                    bridge:bridge
                                                  reactTag:self.reactTag
                                            sizeFlexiblity:_sizeFlexibility];
  [self runApplication:bridge];
  
  _contentView.passThroughTouches = _passThroughTouches;
  [self insertSubview:_contentView atIndex:0];
  
  if (_sizeFlexibility == RCTRootViewSizeFlexibilityNone) {
    self.intrinsicContentSize = self.bounds.size;
  }
}
  
- (void)runApplication:(RCTBridge *)bridge
{
  NSString *moduleName = _moduleName ?: @"";
  NSDictionary *appParameters = @{
    @"rootTag" : _contentView.reactTag,
    @"initialProps" : _appProperties ?: @{},
  };
  
  RCTLogInfo(@"Running application %@ (%@)", moduleName, appParameters);
  [bridge enqueueJSCall:@"AppRegistry" method:@"runApplication" args:@[ moduleName, appParameters ] completion:NULL];
}
  

至此,APP中RN页面的热更新主要流程结束。

 
本文转载于网络 如有侵权请联系删除

相关文章

  • 拆分列转明细还有这种神操作?真是666

    这两天在群里又有大神祭出PowerQuery神杀鸡! 事情是这样的……群友问:如下图,像这种将混在一个单元格里的内容,怎么拆分出来变成明细表?马上有群友想到,先拆分列,然后逆透视…… 这个6,鼠标点点,一气呵成……不过,这有个小问题,拆分列的时候,PowerQuery会按照拆分出来的最大列数给出固定的列名,比如这个动画例子里的客户经理,现在数据里最多的只有3个,那么拆分出来最多3列,列名被固定为“客户经理.1”、“客户经理.2”、“客户经理.3”,所以,如果后面有新的数据进来,客户经理更多了,就得不到完整的结果了……那么,怎么办呢?我首先想到的是:用函数Text.Split将内容拆分成List,然后对List进行展开,这样,就能够确保后续在数据增加的情况下,仍然得到完整的结果,如下所示:这个66,不过这有点儿太麻烦了,又要增加自定义列,又要函数,还要展开数据……终于,大神“莫言”抛下一图,还好没有“绝尘而去”……不然我都来不及说个“牛”字!这个真是666!原来在拆分列的高级选项里就直接有拆分到行的功能!

  • 扒一扒那些叫欧拉的定理们(十一)——欧拉数论定理

    早点关注我,精彩不错过!转眼欧拉系列已经写了10篇,进入尾声的同时也是渐入佳境。前面我们聊到的是立体和平面几何,图论,复数领域的欧拉定理,相关内容请戳: 扒一扒那些叫欧拉的定理们(十)——群论观点下的欧拉公式进阶 扒一扒那些叫欧拉的定理们(九)——群论观点下的欧拉公式初步 扒一扒那些叫欧拉的定理们(八)——欧拉公式和自然对数的底e 扒一扒那些叫欧拉的定理们(七)——欧拉线定理的证明 扒一扒那些叫欧拉的定理们(六)——九点圆定理的证明 扒一扒那些叫欧拉的定理们(五)——平面几何欧拉定理的证明 扒一扒那些叫欧拉的定理们(四)——平面几何欧拉定理美学鉴赏 扒一扒那些叫欧拉的定理们(三)——简单多面体欧拉定理的抽象形式 扒一扒那些叫欧拉的定理们(二)——简单多面体欧拉定理的证明 扒一扒那些叫欧拉的定理们(一)——基本介绍和简单多面体欧拉定理而今天要介绍的,是谈到欧拉所不得不提的一个重要成就,那就是欧拉数论定理。如果说数学是科学的皇后,那数论就是数学的掌上明珠,关于数论的研究仿佛就像探究宇宙的真理一般,奥妙无穷。数论欧拉定理无疑是璀璨的数论星河里最亮的一颗,今天,我们尝试着用不同层级的角度来理解

  • redis 持久化

    文章目录1.前言2.RDB2.1.手动触发2.2.自动触发2.3.RDB执行流程2.4.RDB的优点2.5.RDB的缺点3.AOF3.1.如何开启AOF3.2.AOF整体的执行流程3.3.命令写入3.4.文件同步3.5.文件重写机制3.6.AOF的优点3.7.AOF的缺点4.AOF和RDB的区别5.重启加载6.性能问题与解决方案7.总结前言Redis目前已经成为主流的内存数据库了,但是大部分人仅仅是停留在会用的阶段,你真的了解Redis内部的工作原理吗?今天这篇文章将为大家介绍Redis持久化的两种方案,文章将会从以下五个方面介绍:什么是RDB,RDB如何实现持久化?什么是AOF,AOF如何实现持久化?AOF和RDB的区别。如何重启恢复数据?持久化性能问题和解决方案RDBRDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。RDB完成后会自动生成一个文件,保存在dir配置的指定目录下,文件名是dbfileName指定。Redis默认会采用LZF算法对生成的RDB文件做压缩处理,压缩后的文件远远小于内存大小,默认开启。手动触发手动触发的命令有s

  • ​LeetCode刷题实战46:全排列

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选!今天和大家聊的问题叫做全排列,我们先来看题面:https://leetcode-cn.com/problems/permutations/Givenacollectionofdistinctintegers,returnallpossiblepermutations. 题意给定一个没有重复数字的序列,返回其所有可能的全排列样例输入:[1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]复制解题 来源:https://www.cnblogs.com/techflow/p/12636563.html回溯法我们在之前的文章当中分析过,全排列问题,可以看成是搜索问题,从而近似成八皇后问题。在八皇后问题当中,我们枚举的是棋盘的每一行当中的皇后放置的位置,而全排列其实也一样,我们要枚举每一个元素放置的位置。不过八皇后当中要求皇后除了不

  • Prometheus监控神器-服务发现篇(一)

    本章节主要讲自动发现使用场景介绍与Prometheus基于文件、DNS的自动发现配置当我们使用各类exporter分别对系统、数据库和HTTP服务进行监控指标采集,对于所有监控指标对应的Target的运行状态和资源使用情况,都是用Prometheus的静态配置功能static_configs来手动添加主机IP和端口,然后重载服务让Prometheus发现。对于一组比较少的服务器的测试环境中,这种手动方式添加配置信息是最简单的方法。但是实际生产环境中,对于成百上千的节点组成的大型集群又或者Kubernetes这样的大型集群,很明显,手动方式捉襟见肘了。为此,Prometheus提前已经设计了一套服务发现功能。Prometheus服务发现能够自动检测分类,并且能够识别新节点和变更节点。也就是说,可以在容器或者云平台中,自动发现并监控节点或更新节点,动态的进行数据采集和处理。目前Prometheus已经支持了很多常见的自动发现服务,比如consulec2gceserverset_sd_configopenStackkubernetes等等。我们常用的就是sd_config、DNS、kuber

  • 为什么建议你使用枚举?

    枚举是JDK1.5新增的数据类型,使用枚举我们可以很好的描述一些特定的业务场景,比如一年中的春、夏、秋、冬,还有每周的周一到周天,还有各种颜色,以及可以用它来描述一些状态信息,比如错误码等。枚举类型不止存在在Java语言中,在其它语言中也都能找到它的身影,例如C#和Python等,但我发现在实际的项目中使用枚举的人很少,所以本文就来聊一聊枚举的相关内容,好让朋友们对枚举有一个大概的印象,这样在编程时起码还能想到有“枚举”这样一个类型。本文的结构目录如下:枚举的7种使用方法很多人不使用枚举的一个重要的原因是对枚举不够熟悉,那么我们就先从枚举的7种使用方法说起。用法一:常量在JDK1.5之前,我们定义常量都是publicstaticfinal...,但有了枚举,我们就可以把这些常量定义成一个枚举类了,实现代码如下:publicenumColorEnum{ RED,GREEN,BLANK,YELLOW }复制用法二:switch将枚举用在switch判断中,使得代码可读性更高了,实现代码如下:enumColorEnum{ GREEN,YELLOW,RED } publicclassColor

  • Spring Boot 集成 Ehcache 缓存,三步搞定!

    作者:谭朝红www.ramostear.com/articles/spring_boot_ehcache.html本次内容主要介绍基于Ehcache3.0来快速实现SpringBoot应用程序的数据缓存功能。在SpringBoot应用程序中,我们可以通过SpringCaching来快速搞定数据缓存。接下来我们将介绍如何在三步之内搞定SpringBoot缓存。 1.创建一个SpringBoot工程你所创建的SpringBoot应用程序的maven依赖文件至少应该是下面的样子:<?xmlversion="1.0"encoding="UTF-8"?> <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven

  • Spring Boot 面试,一个问题就干趴下了!

    随着SpringBoot使用越来越广泛,SpringBoot已经成为Java程序员面试的知识点,很多同学对SpringBoot理解不是那么深刻,经常就会被几个连环跑给干趴下了!比如下面这一段的SpringBoot问答:问:你觉得SpringBoot最大的优势是什么呢?答:SpringBoot的最大的优势是“约定优于配置“。“约定优于配置“是一种软件设计范式,开发人员按照约定的方式来进行编程,可以减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。问:SpringBoot中“约定优于配置“的具体产品体现在哪里。答:SpringBootStarter、SpringBootJpa都是“约定优于配置“的一种体现。都是通过“约定优于配置“的设计思路来设计的,SpringBootStarter在启动的过程中会根据约定的信息对资源进行初始化;SpringBootJpa通过约定的方式来自动生成Sql,避免大量无效代码编写。问:SpringBootStarter的工作原理是什么?答:SpringBoot在启动的时候会干这几件事情:SpringBoot在启动时会去依赖的Starter包中寻找r

  • 如何给Centos系统的虚拟机更改主机名

    有的小伙伴们发现Centos系统中主机名很长,想着更改主机名,换个简单的主机名,但是又不知道怎么做。其实这个问题的解决方案很简单的,默认情况下,虚拟机的主机名为localhost。在Centos中,关于主机名的文件存放在/etc/hostname文件下,具体的操作流程如下。1、打开虚拟机电源,输入账号和密码,输入命令:vi/etc/hostname,进入文件,如下图所示。2、发现主机名默认为localhost.localdomain,老长的一个名字。。。看着眼睛都花了。如果英语不好的话,打死都记不住~~~在vi模式下,点击键盘insert即可开始对文件进行修改,在这里大家可以随意修改主机名。比方说小编把这台虚拟机拟命名为slave2,那么将localhost.localdomain替换为slave2即可。修改完之后按下Esc,再输入:wq!,以保存退出。如果不确定是否已经修改成功,可以通过cat/etc/hostname进行查看,如下图所示。3、除了上面的那种方法之外,也有的伙伴通过更改/etc/hosts文件来更改主机名,详情如下。输入命令:vi/etc/hosts,进入文件。源文件

  • MacOS 下使用 intellij IDEA 将git上传项目到 Github

    1、用IDEA打开项目,创建一个本地git仓库,默认路径就是项目文件夹。这时项目目录中的文件名会变成红色,表示文件为提交到本地git。2、右击工程文件->git->add,这时文件名会变成绿色。3、右击工程文件->git->commit,提交到本地git。至此,本地git已commit完毕。image.pngimage.png4、接下来开始将本地git项目上传到github上事先新建好的repository中。进入工程文件夹所在目录,右击文件夹->gitbashhere,依次输入以下命令:代表上传文件夹中的所有文件 若出现以下界面,则表示上传成功

  • 一周AI看点 | 迪拜新任命的人工智能国家部长仅27岁,吴恩达招实习生没上过Coursera课的不要

    本期一周AI看点包括行业资讯、投融资、业界观点、技术前沿以及应用等方面。 行业百度或分拆国际化事业部,进一步聚焦人工智能战略《财经》近日报道称,百度国际化事业部将大概率面临分拆。《财经》引述接近百度国际化事业部人士称,分拆将分为三部分,其中包括:移动产品矩阵和海外移动广告平台独立分拆,将在日本收购的原生广告平台popIn与百度人工智能团队整合,出售在巴西收购的团购网站PeixeUrbano。其中前两部分在分拆后,分别由百度国际化事业部副总经理胡勇和百度日本分公司总经理张成焕继续负责。阿里达摩院火速挖人!微软、谷歌著名AI专家入职阿里人工智能实验室阿里巴巴近日宣布,微软亚洲研究院首席研究员聂再清博士、谷歌Tango和DayDream项目技术主管李名杨博士入职阿里巴巴人工智能实验室(以下简称AILabs)。其中聂再清将担任AILabs北京研发中心总负责人,李名杨任AILabs机器视觉杰出科学家。华为Mate10发布,起售价近5500,没用上人脸识别MagicLive人工智能系统并未出现在华为Mate10上,而且搭载了华为首款AI芯片麒麟970的华为也没有用上人脸识别,而是依然选择了指纹解锁

  • 腾讯云版权登记费用发票类问题

    版权登记申请怎么收费?对于版权服务,我们提供一次性购买的模式。n一次性购买模式:用户仅需要按量一次性购买后即可使用。一次性购买的产品中包含了版权登记规费以及服务费。更多详情请参见购买指南。版权登记付款后怎么申请发票?您购买版权产品,待发货成功后,您可在发票管理申请发票,由腾讯云为您开具发票。具体产品发货节点如下:若您购买的是版权登记普通办理类型的产品,待材料申报至版权局并受理成功(以版权局下发受理通知书为准),即为发货成功。若您购买的是版权登记加急办理类型的产品,待材料申报至版权局并完成审查(以版权下发审查结果通知书为准),即为发货成功。如何填写腾讯云版权服务的发票内容?腾讯云版权服务开具的发票内容为信息技术服务云服务费(目前不支持更改其他发票类目)。更多发票问题可参见发票常见问题。

  • python 用 matplotlib 在 3D 空间绘制散点,体验不同视角 实例详解

    图形预览:       说明: 在3维空间绘制点(0,0,0),(1,1,1),(2,2,2)及其在三个坐标平面的投影。   0、import importnumpyasnpfrommatplotlibimportpyplotasplt frommpl_toolkits.mplot3dimportAxes3D复制   1、单一方位角 #创建画布 fig=plt.figure(figsize=(12,8), facecolor='lightyellow' ) #创建3D坐标系 ax=fig.gca(fc='whitesmoke', projection='3d' ) #定义数据 x=np.array([0,1,2]) y=np.array([0,1,2]) z=np.array([0,1,2]) #绘制3D散点 points=ax.scatter(xs=x,#x轴坐标 ys=y,#y轴坐标 zs=z,#z轴坐标 zdir='z',# c='r',#color s=70,#size ) #点在3个坐标平面上的投影 ax.

  • Opencv4新属性-二维码识别

    intmain() { Matimg=imread("C:\\Users\\24731\\Desktop\\000\\001.jpg"); if(img.empty()) { cout<<"请确认图像文件名称是否正确"<<endl; return-1; } Matgray,qrcode_bin; cvtColor(img,gray,COLOR_BGR2GRAY); QRCodeDetectorqrcodedetector; vector<Point>points; stringinformation; boolisQRcode; isQRcode=qrcodedetector.detect(gray,points);//识别二维码 if(isQRcode) { //解码二维码 information=qrcodedetector.decode(gray,points,qrcode_bin); cout<<points<<endl;//输出二维码四个顶点的坐标 } else { cout<<"无法识别二维码,请确认图

  • .net core使用MQTT

    废话不多说,我们来直接实践…… 一、搭建mqtt控制台服务端 新建一个.netcore控制台项目,然后使用Nuget添加MQTTnet包,我这里使用2.4版本,注意不同版本,代码写法不相同,如下图 编写代码,详见注释 启动试一下,发现启动成功了 二、搭建第一个客户端client1 同样使用控制台来展示客户端 具体代码如下图 三、搭建客户端client2 注意,客户端2和客户端1代码大致相同,只是为了演示,他们的主题不同,发送的内容不同 四、运行起来看看效果 右键解决方案=》属性,把三个项目都改为启动项,应用并确定后执行CTRL+F5,见下图   服务器、客户端1、客户端2都成功接收和发布了消息,成功。 五、使用带有dashboard的EMQX来代替自写服务端 下载地址:https://www.emqx.io/downloads/broker/v3.1.1/ windows版本可选择前两个,下载后解压,注意路径不要带有中文,否则会出错 进入解压后的文件夹,在地址栏输入cmd或者打开控制台进入文件夹路径,执行命令如图 启动成功,打开浏览器,输入

  • PI Errors and possible solutions

    引自:https://wiki.scn.sap.com/wiki/display/ERPHCM/PI+Errors+and+possible+solutions 转至元数据起始   404-NotFounderror Targethost:transaction-engine.tax.service.gov.uk"andport443,itgives"404-NotFound"ontestconnection? TheconfigurationchangescanbebrokendownintothefollowingtworequirementsfortheinterfaceHR_GB_EFO_RESP_OUT. 1.Ifnotalreadypresentinyoursystem,addanewconfiguration fortheSUBMISSIONwiththecondition/p1:GovTalkMessage/p1:Header/p1:MessageDetails/p1:Function=delete 2.Youprobablyalreadyhave

  • CCF CSP 201412-3 集合竞价

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCFCSP201412-3集合竞价 问题描述   某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量。  该程序的输入由很多行构成,每一行为一条记录,记录可能有以下几种:  1.buyps表示一个购买股票的买单,每手出价为p,购买股数为s。  2.sellps表示一个出售股票的卖单,每手出价为p,出售股数为s。  3.canceli表示撤销第i行的记录。  如果开盘价为p0,则系统可以将所有出价至少为p0的买单和所有出价至多为p0的卖单进行匹配。因此,此时的开盘成交量为出价至少为p0的买单的总股数和所有出价至多为p0的卖单的总股数之间的较小值。  你的程序需要确定一个开盘价,使得开盘成交量尽可能地大。如果有多个符合条件的开盘价,你的程序应当输出最高的那一个。 输入格式   输入数据有任意多行,每一行是一条记录。保证输入合法。股数为不超过108的正整数,出价为精确到恰好小数点后两位的正实数,且不超过10000.00。 输出格式   你需要输出一行,包含两个数,

  • tarjan全家桶

    tarjan全家桶 关于tarjan它太强了CCCOrz dfs树&low dfs树:在图上做不重复经过同一点的dfs,经过的边与点形成一棵树。于是图上所有点都被这棵树包含,一部分边被包含。称被包含的点叫树边,其他边叫回边。整个图就是dfs树,由于是由dfs得到。所以dfs树有非常强的性质,所有回边一定是从一点开始,到它的一个祖先,也就是说两棵没有交集的子树之间一定没有边相连。 dfn:dfn[now]表示now点的dfn序。 low:在做tarjan算法时通常需要开一个low数组,low的定义在处理不同问题时可能略有区别。大体为low[rt]表示以rt为根的子树中经过树边和一条回边能到达的dfn最小的点的dfn。 其实理解tarjan的最好办法就是感性 强连通分量 voidtarjan(intnow) { dfn[now]=low[now]=++tot; s.push(now);in[now]=1; for(inti=head[now];i;i=nxt[i]) { if(!dfn[to[i]]) tarjan(to[i]),low[now]

  • 很全很全的前端本地存储讲解

    三种本地存储方式 cookie 前言 网络早期最大的问题之一是如何管理状态。简而言之,服务器无法知道两个请求是否来自同一个浏览器。当时最简单的方法是在请求时,在页面中插入一些参数,并在下一个请求中传回参数。这需要使用包含参数的隐藏的表单,或者作为URL参数的一部分传递。这两个解决方案都手动操作,容易出错。cookie出现来解决这个问题。 作用 cookie是纯文本,没有可执行代码。存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来向访问者电脑上存储数据,或者某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 如何工作 当网页要发http请求时,浏览器会先检查是否有相应的cookie,有则自动添加在requestheader中的cookie字段中。这些是浏览器自动帮我们做的,而且每一次http请求浏览器都会自动帮我们做。这个特点很重要,因为这关系到“什么样的数据适合存储在cookie中”。 存储在cookie中的数据,每次都会被浏览器自动放在http请求中,如果这些数据并不是每个请求都需要发给服务端的数据,浏览器这设置自动

  • WSL2的Ubuntu中安装Docker

    1、配置WSL2和安装Ubuntu,过程略 2、Ubuntu中安装依赖库 sudoaptupdate&&sudoaptupgrade sudoaptinstallapt-transport-httpsca-certificatescurlgnupg2software-properties-common 复制  3、配置Docker的GPG公钥 curl-fsSLhttps://download.docker.com/linux/ubuntu/gpg|sudoapt-keyadd- 复制  4、添加amd64的Docker的清华软件仓库源 sudoadd-apt-repository\ "deb[arch=amd64]https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu\ $(lsb_release-cs)stable" 复制  5、安装Docker sudoaptupdate sudoaptinstalldocker-ce 复制  6、配置国内镜像加

  • 第一章:建设 Flutter 开发环境 (windows)

    Flutter官方网站:https://flutter.dev/docs/get-started/install 根据官方手册引导,将FlutterSDK包解压放到自已喜欢的目录上,不要放需要管理员权限的目录即可 无需安装DartSDK因为下载FlutterSDK就已经附带了,接下来就是直接将解压后的目录路径添加到系统环境变量PATH上,这样Terminal(终端)就可以运行flutter和dart命令了。 接下来安装AndroidStudio目的是为了安装AndroidSDK,所以安装时请将SDK的选项全部选中,之后运行flutterdoctor去检测开发环境是否完成。 在第3步,常见的问题: 运行flutterdoctor等半天没有反应,这是因为网络的原因,此时我们需要配置清华提供的镜像地址在系统环境变量上 根据清华TUNA网站这个文章去设置:https://mirrors-i.tuna.tsinghua.edu.cn/help/flutter/ windows就像这样,Mac、Linux就跟TUNA文章做法一致: 2.提示AndroidSDK需要去accept

相关推荐

推荐阅读