元素、组件、实例和节点

React 中的元素、组件、实例和节点,是React中关系密切的4个概念,也是很容易让React 初学者迷惑的4个概念。现在,老干部就来详细地介绍这4个概念,以及它们之间的联系和区别,满足喜欢咬文嚼字、刨根问底的同学(老干部就是其中一员)的好奇心。 元素 (Element) React 元素其实就是一个简单JavaScript对象,一个React 元素和界面上的一部分DOM对应,描述了这部分DOM的结构及渲染效果。一般我们通过JSX语法创建React 元素,例如: const element = <h1 className='greeting'>Hello, world</h1>; element是一个React 元素。在编译环节,JSX 语法会被编译成对React.createElement()的调用,从这个函数名上也可以看出,JSX语法返回的是一个React 元素。上面的例子编译后的结果为: const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' ); 最终,element的值是类似下面的一个简单JavaScript对象: const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } } React 元素可以分为两类:DOM类型的元素和组件类型的元素。DOM类型的元素使用像h1、div、p等DOM节点创建React 元素,前面的例子就是一个DOM类型的元素;组件类型的元素使用React 组件创建React 元素,例如: const buttonElement = <Button color='red'>OK</Button>; buttonElement就是一个组件类型的元素,它的值是: const buttonElement = { type: 'Button', props: { color: 'red', children: 'OK' } } 对于DOM类型的元素,因为和页面的DOM节点直接对应,所以React知道如何进行渲染。但是对于组件类型的元素,如buttonElement,React是无法直接知道应该把buttonElement渲染成哪种结构的页面DOM,这时就需要组件自身提供React能够识别的DOM节点信息,具体实现方式在介绍组件时会详细介绍。 有了React 元素,我们应该如何使用它呢?其实,绝大多数情况下,我们都不会直接使用React 元素,React 内部会自动根据React 元素,渲染出最终的页面DOM。更确切地说,React元素描述的是React虚拟DOM的结构,React会根据虚拟DOM渲染出页面的真实DOM。 组件 (Component) React 组件,应该是大家最熟悉的React中的概念。React通过组件的思想,将界面拆分成一个个可以复用的模块,每一个模块就是一个React 组件。一个React 应用由若干组件组合而成,一个复杂组件也可以由若干简单组件组合而成。 React组件和React元素关系密切,React组件最核心的作用是返回React元素。这里你也许会有疑问:React元素不应该是由React.createElement() 返回的吗?但React.createElement()的调用本身也是需要有“人”负责的,React组件正是这个“责任人”。React组件负责调用React.createElement(),返回React元素,供React内部将其渲染成最终的页面DOM。 既然组件的核心作用是返回React元素,那么最简单的组件就是一个返回React元素的函数: function Welcome(props) { return <h1>Hello, {props.name}</h1>; } Welcome是一个用函数定义的组件。如果使用类(class)定义组件,返回React元素的工作具体就由组件的render方法承担,例如: ...

December 17, 2024

浏览器渲染过程

渲染流程 首先要了解的概念: 渲染引擎:它是浏览器最核心的部分是 “Rendering Engine”,不过我们一般习惯将之称为 “浏览器内核” 渲染引擎主要包括的线程: 各个线程主要职责: GUI渲染线程:GUI 渲染线程负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。当界面需要重绘(Repaint)或由于某种操作引发回流(Reflow)时,该线程就会执行。 JavaScript引擎线程: JavaScript 引擎线程主要负责解析 JavaScript 脚本并运行相关代码。 JavaScript 引擎在一个Tab页(Renderer 进程)中无论什么时候都只有一个 JavaScript 线程在运行 JavaScript 程序。需要提起一点就是,GUI线程与JavaScript引擎线程是互斥的,这也是就是为什么JavaScript操作时间过长,会造成页面渲染不连贯,导致页面出现阻塞的原理。 事件触发线程:当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待 JavaScript 引擎的处理。 通常JavaScript引擎是单线程的,所以这些事件都会排队等待JS执行。 定时器触发器: 我们日常使用的setInterval 和 setTimeout 就在该线程中,原因可能就是:由于JS引擎是单线程的,如果处于阻塞线程状态就会影响记时的准确,所以需要通过单独的线程来记时并触发响应的事件这样子更为合理。 Http请求线程: 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求,这个线程就Http请求线程,它 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript 引擎的处理队列中等待处理。 有了上述的概念,对接下我们讲渲染流水线会有所帮助 简略版的渲染机制 很久之前就把浏览器工作原理读完了,看了很多博客,文章,当时简简单单的梳理一些内容,如下👇 简略版渲染机制一般分为以下几个步骤 处理 HTML 并构建 DOM 树。 处理 CSS 构建 CSSOM 树。 将 DOM 与 CSSOM 合并成一个渲染树。 根据渲染树来布局,计算每个节点的位置。 调用 GPU 绘制,合成图层,显示在屏幕上。 接下来大概就是这么说: 在构建 CSSOM 树时,会阻塞渲染,直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选择器,执行速度越慢。 ...

December 17, 2024

JSX

时下虽然接入 JSX 语法的框架越来越多,但与之缘分最深的毫无疑问仍然是 React。 2013 年,当 React 带着 JSX 横空出世时,社区曾对 JSX 有过不少的争议,但如今,越来越多的人面对 JSX 都要说上一句“真香”!我们就来一起认识下这个“真香”的 JSX,聊一聊“JSX 代码是如何‘摇身一变’成为 DOM 的”。 开始之前请先思考几个问题: JSX 的本质是什么,它和 JS 之间到底是什么关系? 为什么要用 JSX?不用会有什么后果? JSX 背后的功能模块是什么,这个功能模块都做了哪些事情? 面对以上问题,如果无法形成清晰且系统的思路,那么很可能是把 JSX 想得过于简单了。大多数人只是简单地把它理解为模板语法的一种,但事实上,JSX 作为 React 框架的一大特色,它与 React 本身的运作机制之间存在着千丝万缕的联系,上述 3 个问题的答案,就恰恰隐藏在这层“联系”中。 JSX 的本质:JavaScript 的语法扩展 JSX 到底是什么?看看 React 官网给出的一段定义: JSX 是 JavaScript 的一种语法扩展,它和模板语言很接近,但是它充分具备 JavaScript 的能力。 “语法扩展”这一点在理解上几乎不会产生歧义,不过“它充分具备 JavaScript 的能力”这句,却总让人摸不着头脑,JSX 和 JS 怎么看也不像是“一路人”啊?这就引出了“JSX 语法是如何在 JavaScript 中生效的”这个问题。 JSX 语法是如何在 JavaScript 中生效的:认识 Babel Facebook 公司给 JSX 的定位是 JavaScript 的“扩展”,而非 JavaScript 的“某个版本”,这就直接决定了浏览器并不会像天然支持 JavaScript 一样地支持 JSX。那么,JSX 的语法是如何在 JavaScript 中生效的呢?React 官网其实早已给过我们线索: ...

December 17, 2024

中间人攻击

一句话总结:中间人攻击的关键在于获取公钥。 一、我和小美传纸条 我和隔壁班的小美互相喜欢,经常互相传纸条。但我懒得动,一般让老王帮我顺路带过去,我信任老王,所以就是简单把纸对折一下就交给老王了。 二、带锁的盒子 有一天我发现,老王居然偷看我的纸条! 我很生气,于是买了一个带锁的盒子,并配了两把钥匙🔑,我留一把,另一把让老王交给小美。我心想这下子老王没钥匙,看不了我们的纸条了。 三、一个需要两把钥匙的盒子 又过了几天,我发现老王还是会偷看,为什么呢?原来这老小子当初传递钥匙的时候,自己去复刻了一把! 于是我又想了一个办法,换了一个更高级的盒子,这个盒子必须用一对钥匙才能使用,使用公钥上锁,必须使用私钥才能打开。我委托老王把我的公钥交给小美,把小美的公钥拿给我。 以后我们都用对方的公钥来进行加密,对方用自己的私钥就能解密。而且就算老王把公钥拿去复刻一把也没关系,没有私钥他就打不开箱子,完美! 四、班主任 过了几天,我发现老王还是能偷看我们的纸条,为什么呢?????? 我想了好几天终于想明白了!原来老王当初传递钥匙的时候,他把我俩的公钥自己留下了,这老小子把自己的公钥给了我们俩。他现在有手里有四把钥匙,想看什么看什么! 这次我们终于意识到问题的关键,不管什么方案,让老王传钥匙就得坏事!于是我和小美商量好,这次不通过老王,而是通过我的班主任传递公钥,终于可以愉快的聊天了! 五、网络中的加密知识 对称加密 对称加密使用同一个密钥进行加密和解密。它的优点是速度快,它的问题是密钥传播过程中一旦泄露,就功亏一篑了。 非对称加密 非对称加密使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。它的优点是密钥分发问题得到解决,公钥可以公开传播。缺点是速度较慢,通常用于加密小数据量或密钥交换。常见做法是通过非对称加密建立链接,交换对称加密密钥,然后使用对称加密的方式进行消息传递。 证书 数字证书是由认证机构(CA)签发的,包含公钥及其持有者身份信息的电子文档。它通过 CA 的数字签名验证其真实性,确保通信双方的身份和公钥的可信性。(证书就是上面例子中的班主任,是一个可信任的获取对方公钥的机构。) 六、中间人攻击 中间人攻击的关键在于攻击者成功获取并提供可信公钥,欺骗用户使其认为其公钥是合法服务器的公钥。这可以通过伪造证书或利用受损的 CA 来实现。(用上面例子来说,就是老王把自己的公钥伪装成小美的公钥给了我) 作为普通用户防御措施很简单,当访问一个网站时,如果浏览器弹出“证书不可信”告警的时候,不要点“我信任”。 常见考点 1. 中间人攻击的基本概念 问题: 什么是中间人攻击?请用通俗的语言解释。 中间人攻击有哪些典型的攻击方式? 被动攻击(如窃听)。 主动攻击(如数据篡改)。 中间人攻击的危害有哪些? 关键点: 中间人攻击是一种攻击者拦截并篡改通信内容的攻击。 危害包括:窃取敏感数据(如密码)、篡改通信内容、伪装身份等。 2. 中间人攻击的原理 问题: 中间人攻击是如何实现的?请简要描述其工作流程。 在 HTTP 中,为什么容易发生中间人攻击? HTTPS 是否完全能防止中间人攻击?为什么? DNS 劫持和 ARP 欺骗是如何帮助实现中间人攻击的? 关键点: 工作流程: 攻击者充当通信双方之间的“中间人”。 拦截通信数据,可能进行监听或篡改。 常见技术: ARP 欺骗:伪装网关。 DNS 劫持:将域名解析到攻击者控制的服务器。 Wi-Fi 劫持:在公共网络中拦截通信数据。 3. 防御中间人攻击的技术措施 问题: HTTPS 如何防御中间人攻击?它的安全机制是什么? 什么是证书信任链?如何防止伪造的证书? 什么是 HSTS(HTTP Strict Transport Security)?它如何防御中间人攻击? 什么是双向 SSL/TLS?它如何进一步提高安全性? 如何防止公共 Wi-Fi 中的中间人攻击? 关键点: ...

December 4, 2024

新变化

CSS 发展史 上图是20 世纪 90 年万维网刚出现时,由于当时并没有可以装饰网页的方法,原始的 Web 页面呈现的效果,随着 CSS(层叠样式表,Cascading Style Sheets)的诞生与发展,Web页面的样式有了翻天覆地的变化。 CSS的发布过程 CSS1.0 19912月W3C发布了第一个有关样式的标准CSS1.0。这个版本中,已经包含了的相关font的相关属性、颜色与背景的相关属性、文字的相关属性、box的相关属性等。 CSS2.0 1985年5月,CSS2.0正式推出。这个版本推荐的是内容和表现效果分离的方式,并开始使用样式表结构。 CSS2.1 2004年2月,CSS2.1正式推出。它在CSS2.0的基础上略微做了改动,删除了许多不被浏览器支持的属性 CSS3 从2011年开始CSS被分为多个模块单独升级。这些模块统称为CSS3 包含有: CSS 选择器level3 CSS 媒体查询level3 CSS color level3 CSS4 设计中 CSS 标准的制定大概有下面几个步骤 下面主要介绍的是与我们日常工作有关联的一些新特性,其中一些已经在主流浏览器中得到了支持,还有一些特性还在草案阶段,可能还会有一些变化。 CSS 伪类选择器 is()和where() 在编写css时,有时会需要使用很长的选择器列表来定位具有相同样式的子元素,比如对所有H元素下的span设置为block,之前会这么写: 这样写选择器看起来很长,可读性差。 此时,可以使用is()来提高易读性,同时避免使用长选择器 浏览器支持: :is() Chrome 88/ Firefox 78/ Edge 88 /Safari 14 :where() Chrome 88/ Firefox 78/ Edge 88 /Safari 14 注意: is()和where()在使用方法上和其他的伪类选择器一样,可以任意组合排列。 is()和where()的功能大体上是一样的,他们的差异性体现在选择器的权重上 where()选择器没有权重,也就是权重是0 is()选择器的权重由它的选择器列表中的最搞权重决定 规则示例: ...

November 9, 2024

移动端适配

导读 移动端适配,是我们在开发中经常会遇到的,这里面可能会遇到非常多的问题: 1px问题 UI图完美适配方案 iPhoneX适配方案 横屏适配 高清屏图片模糊问题 … 上面这些问题可能我们在开发中已经知道如何解决,但是问题产生的原理,以及解决方案的原理可能会模糊不清。在解决这些问题的过程中,我们往往会遇到非常多的概念:像素、分辨率、PPI、DPI、DP、DIP、DPR、视口等等,你真的能分清这些概念的意义吗? 本文将从移动端适配的基础概念出发,探究移动端适配各种问题的解决方案和实现原理。 一、英寸 一般用英寸描述屏幕的物理大小,如电脑显示器的17、22,手机显示器的4.8、5.7等使用的单位都是英寸。 需要注意,上面的尺寸都是屏幕对角线的长度: 英寸(inch,缩写为in)在荷兰语中的本意是大拇指,一英寸就是指甲底部普通人拇指的宽度。 英寸和厘米的换算:1英寸 = 2.54 厘米 二、分辨率 2.1 像素 像素即一个小方块,它具有特定的位置和颜色。 图片、电子屏幕(手机、电脑)就是由无数个具有特定颜色和特定位置的小方块拼接而成。 像素可以作为图片或电子屏幕的最小组成单位。 下面我们使用sketch打开一张图片: 将这些图片放大即可看到这些像素点: 通常我们所说的分辨率有两种,屏幕分辨率和图像分辨率。 2.2 屏幕分辨率 屏幕分辨率指一个屏幕具体由多少个像素点组成。 下面是apple的官网上对手机分辨率的描述: iPhone XS Max 和 iPhone SE的分辨率分别为2688 x 1242和1136 x 640。这表示手机分别在垂直和水平上所具有的像素点数。 当然分辨率高不代表屏幕就清晰,屏幕的清晰程度还与尺寸有关。 2.3 图像分辨率 我们通常说的图片分辨率其实是指图片含有的像素数,比如一张图片的分辨率为800 x 400。这表示图片分别在垂直和水平上所具有的像素点数为800和400。 同一尺寸的图片,分辨率越高,图片越清晰。 2.4 PPI PPI(Pixel Per Inch):每英寸包括的像素数。 PPI可以用于描述屏幕的清晰度以及一张图片的质量。 使用PPI描述图片时,PPI越高,图片质量越高,使用PPI描述屏幕时,PPI越高,屏幕越清晰。 在上面描述手机分辨率的图片中,我们可以看到:iPhone XS Max 和 iPhone SE的PPI分别为458和326,这足以证明前者的屏幕更清晰。 由于手机尺寸为手机对角线的长度,我们通常使用如下的方法计算PPI: iPhone 6的PPI为 ...

November 9, 2024

原子化CSS

1. 什么是原子化CSS 1.1 基本概念 原子化CSS(Atomic CSS) 近年来热度逐渐增加,与原子化CSS相关的库在Github上也收获上万的Star。那么什么是原子化CSS呢,引用文章 Let’s Define Exactly What Atomic CSS is 中定义:“原子化CSS是一种CSS架构方式,其支持小型、单一用途的类,其名称基于视觉功能。” 更加通俗的来讲,原子化CSS是一种新的CSS编程思路,它倾向于创建小巧且单一用途的class,并且以视觉效果进行命名。举个简单的例子: <!-- 原子化类定义 --> <style> .text-white { color: white; } .bg-black { background-color: black; } .text-center { text-align: center; } </style> <!-- 原子化类使用 --> <div class="text-white bg-black text-center">hello Atomic CSS</div> 1.2 VS 行内样式 看到以上的示例,你可能很快就想到,直接使用行内样式不是更好吗,还省去了原子类的定义。这个问题可以从样式编写、一致性、功能、和缓存四个方面来回答。 在样式编写层面,CSS预处理和后处理器很大程度上依赖单独的样式表,原子化CSS可以充分利用Sass、Less等CSS预处理器功能进行样式的编写,同时可以借助PostCSS进一步增强CSS的功能。而对于行内样式,虽然在技术上支持使用预处理和后处理器对其进行处理,但很少有成熟的工具对此提供支持和维护。 在一致性层面,原子化CSS框架一般有预定义的设计系统,开发者仅能在设计系统中选择要设置的值。而对于行内样式或者传统CSS类定义来说,可设置的值是没有任何限制的。对于行内样式或者传统的CSS类设置来说,一个标签的字体大小可能是14px或0.875rem,当产品(or 客户)说需要调小一点时,开发者A可能调整为13px,开发者B可能调整为12px。但对于原子化CSS框架来说,调小一点意味着设置的类从text-sm变为text-xs。 以下为部分采用传统CSS类编写的网站样式统计数据(统计来源): 掘金官网:283种背景颜色 471种字体颜色 264种字体大小 GitLab:1199种背景颜色 1351种字体颜色 450种字体大小 CSDN:585种背景颜色 1190种字体颜色 504种字体大小 在功能方面,原子化CSS本质上还是CSS类,因此支持媒体查询功能,也支持对元素的悬停、聚焦等状态进行处理,而内联样式缺少这部分的能力。 在打包方面,内联样式包含在JS文件中,样式的修改会导致整个bundle的改变,原子化CSS样式定义和JS逻辑分离,修改元素的class属性可能并不影响(在没有新CSS类的情况下)最终打包输出样式文件。 2. 谁在使用原子化CSS 截至目前已经有部分网站借鉴或者使用原子化CSS的思想重构了自己的web网站,比较知名的网站有Facebook、Twitter、Github、swipperjs等。根据网上公开的信息,Facebook在使用原子化CSS思想重构之后,仅登录页面的413KB样式文件,减少为整个站点的74KB。 Facebook ...

November 9, 2024

BFC

BFC 是前端面试中经常会被问到的一个知识点,今天就来带大家深入了解下什么是 BFC 以及它的作用。 文档流 在介绍BFC之前,需要先给大家介绍一下文档流。 我们常说的文档流其实分为定位流、浮动流、普通流三种。 绝对定位(Absolute positioning) 如果元素的属性 position 为 absolute 或 fixed,它就是一个绝对定位元素。 在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。 它的定位相对于它的包含块,相关CSS属性:top、bottom、left、right; 对于 position: absolute,元素定位将相对于上级元素中最近的一个relative、fixed、absolute,如果没有则相对于body; 对于 position:fixed,正常来说是相对于浏览器窗口定位的,但是当元素祖先的 transform 属性非 none 时,会相对于该祖先进行定位。 浮动 (float) 在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。 普通流 (normal flow) 普通流其实就是指BFC中的FC。FC(Formatting Context),直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。 在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行。块级元素则会被渲染为完整的一个新行。 除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。 BFC 概念 先看下MDN上关于BFC的定义: 块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。 具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。 通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。 除了 BFC,还有: IFC(行级格式化上下文)- inline 内联 GFC(网格布局格式化上下文)- display: grid FFC(自适应格式化上下文)- display: flex或display: inline-flex 注意:同一个元素不能同时存在于两个 BFC 中。 ...

November 9, 2024

z-index

大家可能觉得,z-index 是一个很简单的属性,你给它设置哪个值,元素就会位于 y 轴的哪个位置。但它实际上并没有我们想象的这么简单,这个属性背后是一系列决定元素所在层级的规则。 在进行今天的介绍前,我们先列出三个问题,如果你能一眼看出它们的解决方案,那么恭喜你掌握了z-index,也就不需要阅读本文了;如果不行,那么耐心看完本文,相信能找到答案。 三个自测问题 问题一:为什么z-index 数值更大,但 Content 没有在 Box 2 之上? <div id="box1"> Box 1 </div> <div id="content"> Content <br/> z-index: 2; </div> <div id="box2"> Box 2 <br/> z-index: 1; </div> div { padding: 25px; font-size: larger; } #box1 { background-color: chocolate; width: 200px; height: 100px; margin-bottom: -50px; } #content { background-color: gold; width: 300px; height: 200px; z-index: 2; } #box2 { background-color: cyan; width: 200px; height: 100px; margin-top: -50px; z-index: 1; } 问题二:明明 z-index 数值更小,为什么 Content 这次反而在Box 2 之上了? <div id="box1"> Box 1 </div> <div id="content"> Content <br/> transform: rotate(90deg); <br/> z-index: 1; </div> <div id="box2"> <br/> Box 2 <br/> z-index: 2; </div> div { padding: 25px; font-size: larger; } #box1 { background-color: chocolate; width: 200px; height: 100px; margin-bottom: -10px; } #content { background-color: gold; width: 250px; height: 200px; z-index: 1; transform: rotate(90deg); } #box2 { background-color: cyan; width: 200px; height: 100px; margin-top: -10px; z-index: 2; } ...

November 9, 2024

position: sticky

如果问,CSS 中 position 属性的取值有几个?大部分人的回答大概是 static、relative、absolute、fixed,实际上MDN上还有一个 sticky。 今天我们就来给大家介绍这个容易被忽视的position属性值 sticky。 先来看看MDN上对于 sticky 的介绍: 粘性定位元素(stickily positioned element)是计算后位置属性为 sticky 的元素。 粘性定位可以被认为是相对定位和固定定位的混合。 什么是结合两种定位功能于一体呢? 元素在跨越特定阈值前为相对定位,之后为固定定位。 也就是元素先按照普通文档流定位,然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。 元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。 这个特定阈值指的是 top、right、bottom 或 left 之一,换言之,指定 top、right、bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。 示例 上面的文字描述估计还是很难理解,看看下面这张 GIF 图,想想要实现的话,使用 JS + CSS 的方式该如何做: 按照常规做法,大概是监听页面 scroll 事件,判断每一区块距离视口顶部距离,超过了则设定该区块 position:fixed,反之去掉。 而使用 position:sticky ,则可以非常方便的实现: <div class="container"> <div class="sticky-box">内容1</div> <div class="sticky-box">内容2</div> <div class="sticky-box">内容3</div> <div class="sticky-box">内容4</div> </div> .container { background: #eee; width: 600px; height: 1000px; margin: 0 auto; } .sticky-box { position: sticky; height: 60px; margin-bottom: 30px; background: #ff7300; top: 0px; } div { font-size: 30px; text-align: center; color: #fff; line-height: 60px; } 看看上面的 CSS 代码,只是给每个内容区块加上 ...

November 9, 2024