【CSS in Depth 2 精译_059】9.2 把 CSS 模块组合成更大的结构
当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 【第九章 CSS 的模块化与作用域】 ✔️
- 9.1 模块的定义
- 9.1.1 模块和全局样式
- 9.1.2 一个简单的 CSS 模块
- 9.1.3 模块的变体
- 9.1.4 多元素模块
- 9.2 将模块组合为更大的结构 ✔️
- 9.2.1 模块中多个职责的拆分 ✔️
- 9.2.2 模块的命名 ✔️
- 9.3 CSS 的作用域
文章目录
- 9.2 把模块组合成更大的结构 Modules composed into larger structures
- 9.2.1 模块中多个职责的拆分 Dividing multiple responsibilities among modules
- 9.2.1.1 CSS 模块中的定位技巧 Positioning in a module
- 9.2.1.2 关于状态类 State classes
- 9.2.1.3 菜单模块 The menu module
- 9.2.2 模块的命名 Naming modules
《CSS in Depth》新版封面
译者按
继上一篇了解了 CSS 模块化的核心概念后,这一节重点介绍模块化 CSS 的具体用法。作者沿用第六章中的下拉菜单的示例,分两个模块(下拉与菜单)进行了详细演示,并对模块化 CSS 应用过程中的相关注意事项及考量因素做了深入浅出的讲解。当年我也是看了第一版中相关章节的介绍,才明白状态类究竟是怎么回事。新版中的第九章整合了上一版的第九、十两个章节,同时新增了容器查询作为新版第十章。让我们继续跟随作者的思路,彻底拿下看似神秘莫测的模块化 CSS!
9.2 把模块组合成更大的结构 Modules composed into larger structures
每个模块都应该各司其职。消息模块的职责是让消息提示醒目;媒体模块的职责是在一段文本中配置一张图片。我们可以简洁明了地概括出它们的目标:有的是为了版面布局,有的则是出于整体风格的考虑。当模块试图完成的核心任务不止一个时,就应该考虑将其拆分为更小的模块。
为此,本节将实现一个下拉菜单来演示说明(如图 9.5 所示)。该菜单与第六章(6.3.1 小节)里创建的版本类似。
【图 9.5 下拉菜单效果图】
创建模块之前应该先问问自己:“从更高的层面上看,这个模块的职责是什么?”对于本例,您的回答可能是这样的:“用按钮触发下拉菜单并让菜单项由上至下堆叠排列。”
就这个场景而言,这样的回答还算是个恰如其分的描述。但我有一个经验法则:“如果在描述模块职责时必须使用 和 这个词,那么当下很可能是在描述多项职责。”那它究竟是要触发菜单,还是要堆叠排列菜单项呢?
当我们需要用 和(and) 来描述模块职责时,不妨思考一下是否在描述两种(甚至更多的)职责;当然也有可能不是,毕竟这条经验并非放之四海而皆准的。但如果答案是肯定的,就需要为每个职责分别定义模块。这是模块封装的一个非常重要的原则,也叫做 单一职责原则(Single Responsibility Principle)。要尽可能把多种职责分配到不同的模块中,这样每个模块就可以确保小巧精炼、聚焦功能点并且易于理解。
9.2.1 模块中多个职责的拆分 Dividing multiple responsibilities among modules
本节演示通过两个不同的模块创建下拉菜单的方法。第一个模块可以叫作 下拉(dropdown) 模块,其中包含一个控制容器可见性的按钮元素。换言之,该模块负责显示与隐藏容器。我们也可以描述按钮外观以及指示操作行为的小三角形符号。阐明模块的细节虽然会用到 和(and) 的字眼,但它们都从属于首要职责,因此这么处理是没问题的。
第二个模块叫 菜单(menu) 模块,用于放置链接列表。将菜单模块的一个实例放入下拉模块的容器内,就可以构建出完整的页面了。
将代码清单 9.11 中的样式添加到页面中。这段代码主干是一个下拉模块,其中包含菜单模块。代码中还有一小段 JavaScript
脚本,用于在点击切换按钮时实现菜单的开关功能。
代码清单 9.11 用两个模块构造一个下拉菜单
<div class="dropdown"><button class="dropdown__toggle">Main Menu</button><!-- 下拉菜单的切换按钮 --><div class="dropdown__drawer"><!-- drawer 抽屉子元素作菜单容器 --><ul class="menu"><!-- 位于 drawer 元素内部的菜单模块 --><li><a href="/">Home</a></li><li><a href="/coffees">Coffees</a></li><li><a href="/brewers">Brewers</a></li><li><a href="/specials">Specials</a></li><li><a href="/about">About us</a></li></ul></div>
</div><script type="module">var toggle = document.querySelector('.dropdown__toggle');toggle.addEventListener('click', function (event) { // 点击切换按钮时切换 is-open 样式类event.preventDefault();var dropdown = event.target.parentNode;dropdown.classList.toggle('is-open');});
</script>
这里使用了双下划线标记来表明 toggle
和 drawer
同为下拉模块的子元素。点击切换按钮将显示或隐藏 drawer
抽屉元素。JavaScript
代码为下拉模块的主元素添加或移除 is-open
样式类,以此来实现下拉效果:按下切换按钮时变为 <div class="dropdown is-open">
;再次点击则恢复为 <div class="dropdown">
。
下拉模块的样式如代码清单 9.12 所示,将其添加到样式表中。这些样式跟第六章中的演示的版本类似,只是为了符合双下划线标记的类名约定更新了相关类名。这样就实现了下拉效果,只是其中的菜单项还没有指定样式。
代码清单 9.12 定义下拉模块样式
@layer modules {.dropdown {display: inline-block;position: relative; /* 为绝对定位的 drawer 抽屉元素建立一个包含块 */}.dropdown__toggle {padding: 0.5em 2em 0.5em 1.5em;border: 1px solid #ccc;font-size: 1rem;background-color: #eee;}.dropdown__toggle::after {content: "";position: absolute;right: 1em;top: 1em;border: 0.3em solid;border-color: black transparent transparent; /* 利用边框样式绘制三角形(详见第 6 章) */}.dropdown__drawer {display: none; /* 初始隐藏 drawer 元素,出现 is-open 类时再恢复显示 */position: absolute;left: 0;top: 2.1em;min-width: 100%;background-color: #eee;}.dropdown.is-open .dropdown__toggle::after {top: 0.7em;border-color: transparent transparent black; /* 下拉框打开时翻转三角形 */}.dropdown.is-open .dropdown__drawer {display: block; /* 初始隐藏 drawer 元素,出现 is-open 类时再恢复显示 */}
}
上述代码中,主元素设置了相对定位,由此为抽屉元素创建了一个包含块(containing block),接着在包含块内设置绝对定位。切换按钮也指定了一些样式,包括 ::after
伪元素中的三角形效果;添加 is-open
样式类后,抽屉元素又重新显示并同时翻转三角形标记。
这段代码共计 35 行,涉及不少内容,但还不至于在使用模块时毫无头绪。当后续需要修改模块时,就会发现模块越小越好,这样就能快速定位到问题所在。
9.2.1.1 CSS 模块中的定位技巧 Positioning in a module
该下拉模块是我们使用定位的首个 CSS 模块,其中创建了模块自己的包含块(即主元素上的 position: relative
声明)。绝对定位的元素(即 drawer
元素与 ::after
伪元素)就是基于同一模块内的位置来定位的。
我们应该尽量让需要定位的元素关联到同一模块内的其他元素,这样当把模块放到另一个设置了定位的容器内时,才不致于弄乱既定样式。
9.2.1.2 关于状态类 State classes
注意,样式类 is-open
在下拉模块中有特定的用途。我们在模块中使用 JavaScript
动态添加或移除这个类。它也是 状态类(state class) 的一个示例,因为它代表着模块在当前状态下的表现。
根据惯例,状态类一般是以 is-
或 has-
开头。这样状态类的目的就会比较明显,它们表示模块当前状态下的一些特征或者即将发生的变化。类似的例子还有 is-expanded
、is-loading
以及 has-error
等。这些状态类的具体表现取决于使用它们的模块。
重点
状态类的代码要和模块的其他代码放在一起。这样,在使用
JavaScript
动态变更模块效果时,就可以使用状态类来触发变更。
预处理器和模块化 CSS
所有的预处理器(如
Sass
或者Less
)都提供了将分散的 CSS 文件合并为一个单独文件的功能。这样就可以用多个文件和多个目录来组织样式,而最终提供给浏览器的只有一个样式文件,从而减少浏览器发起的网络请求数;同时也便于让开发者将代码文件拆分为易于维护的大小。我认为这是 CSS 预处理器具备的最有价值的一个特性。如果您正好在使用某种预处理器,那我强烈建议您将 CSS 里的每个模块都放到各自对应命名的文件里,并按实际需要将这些文件组织进不同的目录中。然后再创建一个主样式表,并引入所有的 CSS 模块。这样一来,想要修改某个模块时就不必到一个冗长的样式表里搜索了。因为很清楚在哪里能找到它。
您可以创建一个只包含
@use
语句的main.scss
主样式文件,如下所示:@use 'reset'; @use 'global'; @use 'message'; @use 'button'; @use 'media'; @use 'dropdown';
预处理器会从
reset.scss
和global.scss
中分别引用重置样式和全局样式,并从各自的文件中引入模块样式,然后输出一个包含所有样式的样式表文件。这样每个模块都单独拥有了一个便于维护的文件。有关预处理器的更多信息,请参阅本书附录 B,或者参考预处理器的文档,了解使用其导入指令的更多信息。
9.2.1.3 菜单模块 The menu module
实现了下拉模块,下面来处理菜单模块。我们无需关心下拉菜单的打开和关闭,相关功能已经在下拉模块中实现了。菜单模块只需要实现各菜单项的样式即可。
对应的样式如代码清单 9.13 所示。将其添加到您的样式表中。
代码清单 9.13 菜单模块的样式
@layer modules {.menu {margin-block: 0;padding-inline-start: 0;list-style-type: none; /* 移除浏览器默认的列表项样式 */border: 1px solid #999;}.menu > li + li {border-block-start: 1px solid #999; /* 在各列表项链接间添加一条边框 */}.menu > li > a { /* 扩大链接的可点击区域 */display: block;padding: 0.5em 1.5em;background-color: #eee;color: #369;text-decoration: none;}.menu > li > a:hover { /* 给鼠标悬停添加高亮效果 */background-color: #fff;}
}
这些样式与第六章中的下拉菜单相同,每个 <li>
都是模块的一个子元素,因此我觉得没必要为每个元素都添加一个双下划线形式的样式类,而是直接使用后代选择器 .menu > li
来实现目标。
菜单模块是完全独立的,并不依赖于下拉模块。这使得代码更加简单,因为大可不必为了理解一个模块而不得不先理解另一个模块,同时也有利于更加灵活地复用模块。
您也可以创建一个风格迥异的菜单(无论是以变体的形式还是完全独立的模块形式)并根据需求在拉下模块内部进行使用;甚至可以把菜单模块用到下拉模块以外的任意位置。我们无法预知页面后续的需求是什么,但有了可复用的样式模块,就可以确保在一定程度上提供前后一致的样式效果。
将代码组织成模块需要一定的实践经验。本例中将下拉模块与菜单模块分开实现也并没有什么不容置疑的理由——这两个模块确实是要协同工作的,并且在实际项目中估计也很少会遇到需要在下拉菜单中支持不同类型菜单的情况。
只是这样处理后,我发现它们在概念上很容易区分开。这样每个模块就变小了,而轻量小巧的模块往往更容易理解,将来也更容易修改。有时,模块也会自然而然地变大;如果拆分起来实在很困难,那就不要拆分,除非遇到特定需求再来考虑。
9.2.2 模块的命名 Naming modules
为模块命名是个很伤脑筋的问题。开发模块的时候我们可以用个临时的名称,但在您认为模块已经开发完毕之前,请务必注意规范命名。这也许算是模块化 CSS 开发中最难的部分了。
回想一下前面章节里介绍的媒体模块,我们曾用它来展示一张跑步者的图片以及跑步的小贴士,如图 9.6 所示。
【图 9.6 包含图片和跑步小贴士的 media 媒体模块效果图】
假设我们还没有为该模块命名,现在有个页面需要用到它,我们可能会叫它跑步提示模块(running-tip)。这样的命名很贴切,看上去也挺合适;但它也可能用于其他方面。如果使用同样的 UI 元素做别的事情,该如何处理?比如沿用跑步类网站的主题风格,可能需要用到一连串的模块来列出即将举办的赛事信息,这时候“跑步提示”的命名方式就显得格格不入了。
无论使用场景是什么,模块的命名都应该有意义。同时也要避免使用简单描述视觉效果的名称。
将该模块命名为“带图片的灰色盒子”(gray-box-with-image)看似通用,要是今后遇到要改成浅蓝色背景呢?或者需要重新设计网站呢?这样的命名方式显然就不好使了,到头来还得重新命名,然后再到 HTML 里所有用到它的地方进行更新替换。
我们应该换一种思路,思考模块代表的含义究竟是什么。但要真正做到这一点绝非易事。媒体模块的 media 这个命名就很恰当,它表示一种图文混排的版式,并给人以强烈的印象,同时也没有将模块局限于任何特定的场景或视觉效果。
模块要适用于各种不同的场景,因此命名应该简单好记为上。当网站有很多页面的时候,可能会多次用到某个模块。届时您可能会用这样的表述来和团队其他成员进行沟通:“这里就用 ‘媒体(media)’ 模块吧”,或者“这些 ‘板块(tiles)’ 都挤到一起了”。
至此,我们已经实现了消息模块、媒体模块、下拉模块以及菜单模块。一些比较值得推荐的模块命名包括面板(panel)、警告(alert)、可折叠部分(collapsible-section)、以及表单控件(form-control)等等。如果从一开始就对网站的整体设计有全面把控,无疑将更有利于模块的规范命名。例如,可能有两个 UI 元素都可以叫作 板块(tile),然而它们毫不相关,此时就应该分别给它们更明确的命名(比如分别叫作媒体板块(media-tile)和标题板块(headline-tile))。
有些人强制使用两个单词来命名每个模块,旨在避免模块指代不明;因为您也吃不准什么时候会需要另一个新的 tile 模块。如果现有的 tile 模块的命名较为明确,那么在命名新模块时就相对会容易些,不至于同前一个模块名混淆。
在给模块的变体类命名时,也应该遵循同样的原则。例如,如果已经有按钮模块(button module)了,就不宜使用 button--red
和 button--blue
来命名红色和蓝色的变体子类。网站设计在将来可能会改变,而您并不知道这些按钮的颜色是否会相应变化。推荐使用一些更有意义的名称,例如 button--danger
或 button--success
等。
使用 large
或 small
这样具有相对意味的词语来命名修饰符的做法并不可取,但也是可以接受的。没人说过网站重构时不能修改 button--large
的尺寸,只要它还是比标准按钮大一些就行。但一定要避免使用像 button--20px
这样的过于精确的修饰符类名。
关于 JavaScript 的替代方案 Alternate approaches in JavaScript
在大型团队中书写模块化样式,需要一些苛刻的约束条件来确保每个人遵守相同的类名约定。此外,也需要采取一些措施来防止大家新建的模块名称出现冲突。为了解决这些问题,一些 Web 开发社区开始尝试模块化 CSS 的替代方案。一番探索后,他们转向了
JavaScript
,并最终提出了一种现在被称为 CSS in JS 的解决方案。这种方案不再依赖样式类命名的口头约定,而是使用
JavaScript
来确保创建唯一的类名。为了实现这样的功能,业内已经出现了许多相关的JavaScript
库,其中最受欢迎的有Styled Components
和一个名为CSS Module
(命名易混淆)的库;其中许多工具库都与特定的JavaScript
框架或工具集绑定,例如React
和WebPack
。这种解决方案目前还存在争议,但是相关动态值得关注,尤其是当您在开发单页面应用(即 single page applications,简称 SPA)的时候。它只能在完全由
JavaScript
框架(如React
)渲染的项目里使用。采用这种方案需要做一些权衡,并且会限制使用特定的工具集。CSS in JS 虽然并非完美的解决方案,但在某些应用场景下经过验证确实是可行的。
关于《CSS in Depth》(中译本书名《深入解析 CSS》)
第 1 版 | 第 2 版 | |
---|---|---|
读者评分 | 原版:4.7(亚马逊);中文版:9.3(豆瓣) | 原版:5.0(亚马逊);中文版:暂无,待出版 |
出版时间 | 原版:2018 年 3 月;中文版:2020 年 4 月 | 原版:2024 年 7 月;中文版:暂无,待出版 |
原价 | 原版:$44.99;中文版:¥139.00 | 原版:$59.99;中文版:暂无,待出版 |
现价 | 原版:$36.49;中文版:¥52.54 起步 | 原版:$52.09;中文版:暂无,待出版 |
原版国内预订 | 起步价 ¥461.00 | 起步价 ¥750.00 |
本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!
目前已完结的章节(可进入本专栏查看详情,连载期间完全免费):
- 第一章 层叠、优先级与继承(已完结)
- 1.1 层叠
- 1.2 继承
- 1.3 特殊值
- 1.4 简写属性
- 1.5 CSS 渐进式增强技术
- 1.6 本章小结
- 第二章 相对单位(已完结)
- 2.1 相对单位的威力
- 2.2 em 与 rem
- 2.3 告别像素思维
- 2.4 视口的相对单位
- 2.5 无单位的数值与行高
- 2.6 自定义属性
- 2.7 本章小结
- 第三章 文档流与盒模型(已完结)
- 3.1 常规文档流
- 3.2 盒模型
- 3.3 元素的高度
- 3.4 负的外边距
- 3.5 外边距折叠
- 3.6 容器内的元素间距问题
- 3.7 本章小结
- 第四章 Flexbox 布局(已完结)
- 4.1 Flexbox 布局原理
- 4.2 弹性子元素的大小
- 4.3 弹性布局的方向
- 4.4 对齐、间距等细节处
- 4.5 本章小结
- 第五章 网格布局(已完结)
- 5.1 构建基础网格
- 5.2 网格结构剖析 (上)
- 5.2.1 网格线的编号(下)
- 5.2.2 网格与 Flexbox 配合(下)
- 5.3 两种替代语法
- 5.3.1 命名网格线
- 5.3.2 命名网格区域
- 5.4 显式网格与隐式网格(上)
- 5.4.1 添加变化 (中)
- 5.4.2 让网格元素填满网格轨道(下)
- 5.5 子网格(全新增补内容)
- 5.6 对齐相关的属性
- 5.7 本章小结
- 第六章 定位与堆叠上下文(已完结)
- 6.1 固定定位
- 6.1.1 创建一个固定定位的模态对话框
- 6.1.2 在模态对话框打开时防止屏幕滚动
- 6.1.3 控制定位元素的大小
- 6.2 绝对定位
- 6.2.1 关闭按钮的绝对定位
- 6.2.2 伪元素的定位问题
- 6.3 相对定位
- 6.3.1 创建下拉菜单(上)
- 6.3.2 创建 CSS 三角形(下)
- 6.4 堆叠上下文与 z-index
- 6.4.1 理解渲染过程与堆叠顺序(上)
- 6.4.2 用 z-index 控制堆叠顺序(上)
- 6.4.3 深入理解堆叠上下文(下)
- 6.5 粘性定位
- 6.6 本章小结
- 第七章 响应式设计(已完结)
- 7.1 移动端优先设计原则(上篇)
- 7.1.1 创建移动端菜单(下篇)
- 7.1.2 给视口添加 meta 标签(下篇)
- 7.2 媒体查询(上篇)
- 7.2.1 深入理解媒体查询的类型(上篇)
- 7.2.2 页面断点的添加(中篇)
- 7.2.3 响应式列的添加(下篇)
- 7.3 流式布局
- 7.4 响应式图片
- 7.5 本章小结
- 第八章 层叠图层及其嵌套
- 8.1 用 layer 图层来操控层叠规则(上篇)
- 8.1.1 图层的定义(上篇)
- 8.1.2 图层的顺序与优先级(下篇)
- 8.1.3 revert-layer 关键字(下篇)
- 8.2 层叠图层的推荐组织方案
- 8.3 伪类 :is() 和 :where() 的用法
- 8.4 CSS 嵌套的使用
- 8.4.1 嵌套选择器的使用
- 8.4.2 深入理解嵌套选择器
- 8.4.3 媒体查询及其他 @规则 的嵌套
- 8.5 本章小结
相关文章:
【CSS in Depth 2 精译_059】9.2 把 CSS 模块组合成更大的结构
当前内容所在位置(可进入专栏查看其他译好的章节内容) 【第九章 CSS 的模块化与作用域】 ✔️ 9.1 模块的定义 9.1.1 模块和全局样式9.1.2 一个简单的 CSS 模块9.1.3 模块的变体9.1.4 多元素模块 9.2 将模块组合为更大的结构 ✔️ 9.2.1 模块中多个职责的…...
uniapp+vue3+ts H5端使用Quill富文本插件以及解决上传图片反显的问题
uniappvue3ts H5端使用Quill富文本插件以及解决上传图片反显的问题 1.在项目中安装Quill npm i quill1.3.72.需要显示富文本的页面完整代码 <template><view><div ref"quillEditor" style"height: 65vh"></div></view> &…...
shell(二)
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
在使用PCA算法进行数据压缩降维时,如何确定最佳维度是一个关键问题?
一、PCA算法的基本原理 PCA算法的核心思想是通过正交变换,将一组可能相关的变量转换成一组线性不相关的变量,称为主成分。这组主成分能够以最小的信息损失来尽可能多地保留原始数据集的变异性。具体来说,PCA算法包括以下几个步骤:…...
学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P1 ~ P2)
概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南,对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...
#渗透测试#红蓝攻防#HW#SRC漏洞挖掘01之静态页面渗透
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…...
开源POC库推荐
声明 学习视频来自 B 站UP主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 ✍🏻作者简介:致…...
深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结ResNeXt基本介绍 1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数:定义损失函数&…...
用vite下载的react + TS的项目,组件会调用两次
解决方案: 去掉main.tsx文件中的StrictMode...
STM32F4----DCA数字量转换成模拟量
STM32F4----DCA数字量转换成模拟量 基本原理 上一节讲诉了ADC的具体原理与程序搭建https://blog.csdn.net/qq_35970934/article/details/143999874?spm1001.2014.3001.5501。这节讲DAC的原理和程序,在实际应用中,我们经常需要调节电压的输出大小&…...
springboot3如何集成knife4j 4.x版本及如何进行API注解
1. 什么是Knife4j knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案, 取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!knife4j的前身是swagger-bootstrap-ui,swagger-bootstrap-ui自1.9.6版本后,正式更名为knife4j为了契合微服务的架构发展,由于原来…...
【Linux网络 (二)】套接字编程
Linux: 网络 一、前言二、端口号 (port)1)port、套接字概念2)端口号 vs 进程id3)端口号和进程关系 三、认识TCP/Udp协议1)连接性解释2)可靠性解释3)面向数据报/字节流解释 四、网络字节序五、struct sockad…...
SQL 语句执行计划中的连接方式
SQL 语句执行计划中的连接方式 join操作 join操作基本分为3大类:外连接(细分为:左连接(Left outer join/ left join)、右连接(right outer join/ right join)、全连接(full outer …...
3、集线器、交换机、路由器、ip的关系。
集线器、交换机、路由器三者的关系 1、集线器2、交换机(每个交换机是不同的广播域,ip地址起到划分广播域的作用)3、 路由器4、ip地址 1、集线器 一开始两台电脑通信就需要网线就可以,但是三台或者更多主机通信时,就需…...
OpenCV相机标定与3D重建(3)校正鱼眼镜头畸变的函数calibrate()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::fisheye::calibrate 函数是 OpenCV 中用于校正鱼眼镜头畸变的一个重要函数。该函数通过一系列棋盘格标定板的图像来计算相机的内参矩阵和畸变…...
【论文笔记】LLaVA-KD: A Framework of Distilling Multimodal Large Language Models
Abstract 大语言模型(Large Language Models, LLM)的成功,使得研究者为了统一视觉和语言的理解去探索多模态大预言模型(Multimodal Large Language Models, MLLM)。 但是MLLM庞大的模型和复杂的计算使其很难应用在资源受限的环境,小型MLLM(s-MLLM)的表现…...
C++内存管理和模板
文章目录 1. C内存管理1.1 new1.1.1 内置类型1.1.2 自定义类型1.1.3 定位new表达式1.1.4 new的优势与不足1.1.5 new的原理 1.2 delete1.2.1 内置类型1.2.2 自定义类1.2.3 delete和free1.2.4 delete原理 1.3 new和delete的对应1.3.1 内置类型1.3.2 自定义类型 2. 模板2.1 函数模…...
Docker 容器化开发 应用
Docker 常用命令 存储 - 目录挂载 存储 卷映射 自定义网络 Docker Compose语法 Dockerfile - 制作镜像 镜像分层机制 完结...
element-plus教程:Input Number 数字输入框
一、基础用法 要使用Input Number数字输入框,只需要在<el-input-number>元素中使用v-model绑定变量即可。例如: <template><el-input-number v-model"value" /> </template><script lang"ts" setup>…...
【Go语言成长之路】编写web应用
文章目录 编写Web应用一、介绍二、创建项目2.1 创建wiki数据结构2.2 介绍net/http包(小插曲)2.3 使用 net/http 提供 wiki 页面2.4 编辑Pages2.5 html/template包2.6 处理不存在的页面2.7 保存页面2.8 错误处理2.9 模板缓存2.10 验证2.11 函数文字和闭包…...
Java 对象头、Mark Word、monitor与synchronized关联关系以及synchronized锁优化
1. 对象在内存中的布局分为三块区域: (1)对象头(Mark Word、元数据指针和数组长度) 对象头:在32位虚拟机中,1个机器码等于4字节,也就是32bit,在64位虚拟机中࿰…...
安宝特分享 | 如何利用AR技术革新医疗实践:从远程急救到多学科协作
AR技术在国内外医院的应用 在现代医疗环境中,患者面临的挑战依然严峻:看病难、看病远、看病急。这些问题不仅影响了患者的治疗效果,也让医务工作者倍感压力。幸运的是,随着增强现实(AR)技术的发展…...
小米note pro一代(leo)线刷、twrp、magisk、TODO: android源码编译
本文主要说android5 整体思路 android 5.1 twrp magisk Zygisk(Riru) Dreamland(xposed) Riru不支持android5.1, 因此只能选择Zygisk : 如果你正在使用 Android 5,你必须使用 Zygisk 因为 Riru 并不支持 Android 5. 基于magisk之上的xposed 其中提到的 作者…...
vue2-基础核心
vue简介 动态构建用户界面的渐进式 JavaScript 框架 vue的特点: 遵循MVVM模式 采用组件化模式,提高代码复用率,让代码更好维护 声明式编码,无需直接操作DOM,提高开发效率,编码简洁、体积小,运行效率高 本…...
使用 前端技术 创建 QR 码生成器 API1
前言 QR码(Quick Response Code)是一种二维码,于1994年开发。它能快速存储和识别数据,包含黑白方块图案,常用于扫描获取信息。QR码具有高容错性和快速读取的优点,广泛应用于广告、支付、物流等领域。通过扫…...
天云数据参编行业标准|《Maas模型服务协议要求》标准正式发布
随着各行业对大模型的应用需求日益增多,模型即服务(MaaS)发展迅速,MaaS将AI模型以服务的方式提供给用户,降低模型使用门槛。当前产业界已推出诸多MaaS产品,并集成和提供了大量模型服务,然而对于…...
观察者模式和订阅模式
观察者模式和订阅模式在概念上是相似的,它们都涉及到一个对象(通常称为“主题”或“发布者”)和多个依赖对象(称为“观察者”或“订阅者”)之间的关系。然而,尽管它们有相似之处,但在某些方面也…...
Mac设置java环境变量
Mac电脑中存在多个jdk版本,如何配置java环境变量为指定版本jdk? 一、查看所有已安装的 JDK 版本 /usr/libexec/java_home -V二、临时设置 export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)三、永久设置 如果需要永久使用指定版...
Sentinel服务保护
Sentinel是阿里巴巴开源的一款服务保护框架,目前已经加入SpringCloudAlibaba中。官方网站: home | Sentinel Sentinel 的使用可以分为两个部分: 核心库(Jar包):不依赖任何框架/库,能够运行于 Java 8 及以…...
Linux内核USB2.0驱动框架分析--USB包
一, 包的组成 每个包都由SOP(包起始域)、SYNC(同步域)、Packet Content(包内容)、EOP(包结束域)四部分组成,其中SOP、SYNC、EOP为所有包共有的域,…...
SpringCloud Gateway转发请求到同一个服务的不同端口
SpringCloud Gateway默认不支持将请求路由到一个服务的多个端口 本文将结合Gateway的处理流程,提供一些解决思路 需求背景 公司有一个IM项目,对外暴露了两个端口8081和8082,8081是springboot启动使用的端口,对外提供一些http接口…...
win10局域网加密共享设置
1、创建共享账户 我的电脑右键选择管理 选择本地用户和组 -> 用户 双击用户 在空白区域右键,新建用户 然后创建用户 点击创建后 2、设置网络 右下角网络右键...
论文阅读——Performance Evaluation of Passive Tag to Tag Communications(一)
文章目录 摘要一、互耦对监听器标签输入阻抗的影响A. 无限细偶极子互阻抗的理论研究B. 电细偶极子的情况:理论与模拟C. 印刷偶极子的情况:电磁模拟与测量 二、T2T 通信系统的性能评估总结 论文来源:https://ieeexplore.ieee.org/document/970…...
Docker Registry(镜像仓库)详解
Docker Registry(镜像仓库)详解 Docker Registry,即Docker镜像仓库,是Docker生态系统中一个至关重要的组件。它负责存储、管理和分发Docker镜像,为Docker容器提供镜像资源。本文将深入探讨Docker Registry的功能、结构…...
17. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--主币种设置
记账模块是我们项目的核心模块,也是用户使用最多的模块,因此这个模块的东西比较多,我们要分为多个部分编写代码。 一、需求 币种设置的需求涉及到了我们前面编写的代码,我们来具体看一下需求。 编号需求说明1主币种设置1. 用户…...
ChatPaper.ai:通过阅读文献高效学习英语的新思路
前言 作为一名学习者,我们常常会遇到这样的困境:想提高英语水平,但单纯背单词缺乏语境;想读专业文献,却被英语障碍所困扰。今天我要分享一个工具 ChatPaper.ai,它让我找到了将英语学习和专业阅读完美结合的…...
.NET9 - 新功能体验(二)
书接上回,我们继续来聊聊.NET9和C#13带来的新变化。 01、新的泛型约束 allows ref struct 这是在 C# 13 中,引入的一项新的泛型约束功能,允许对泛型类型参数应用 ref struct 约束。 可能这样说不够直观,简单来说就是Span、ReadO…...
探索Python PDF处理的奥秘:pdfrw库揭秘
文章目录 探索Python PDF处理的奥秘:pdfrw库揭秘1. 背景:为何选择pdfrw?2. pdfrw是什么?3. 如何安装pdfrw?4. 五个简单的库函数使用方法4.1 读取PDF信息4.2 修改PDF元数据4.3 旋转PDF页面4.4 提取PDF中的图片4.5 合并P…...
网络爬虫——爬虫项目案例
本节将全面讲解如何通过实战爬虫项目解决复杂问题。结合最新技术和实际开发需求,案例将涵盖完整开发流程,包括需求分析、实现代码、优化方法和常见问题解决。力求实现高效、可扩展的爬虫项目架构,帮助开发者提升实战能力。 案例 1:…...
JAVA中的Lamda表达式
JAVA中的Lamda表达式 Lambda 表达式的语法使用场景示例代码1.代替匿名内部类2. 带参数的 Lambda 表达式3. 与集合框架结合使用4. 使用 Stream 操作 总结 Java 的 Lambda 表达式是 Java 8 引入的一个新特性,用于简化代码,特别是在处理函数式编程时。Lambd…...
经典游戏:飞机大战游戏python设计与实现
《飞机大战》是一款经典的二维飞行射击游戏,其核心玩法是控制玩家飞机与敌机作战,通过击落敌机获取分数并尽量避免被敌机击中。根据提供的代码,飞机大战的设计和实现可以分为以下几个主要部分:游戏初始化、游戏界面设计、玩家控制…...
网络爬虫——常见问题与调试技巧
在开发网络爬虫的过程中,开发者常常会遇到各种问题,例如网页加载失败、数据提取错误、反爬机制限制等。以下内容将结合实际经验和技术方案,详细介绍解决常见错误的方法,以及如何高效调试和优化爬虫代码。 1. 爬虫过程中常见的错误…...
深入理解TensorFlow中的形状处理函数
摘要 在深度学习模型的构建过程中,张量(Tensor)的形状管理是一项至关重要的任务。特别是在使用TensorFlow等框架时,确保张量的形状符合预期是保证模型正确运行的基础。本文将详细介绍几个常用的形状处理函数,包括get_…...
macOS 无法安装第三方app,启用任何来源的方法
升级新版本 MacOS 后,安装下载的软件时,不能在 ”安全性与隐私” 中找不到 ”任何来源” 选项。 1. 允许展示任何来源 点击 启动器 (Launchpad) – 其他 (Other) – 终端 (Terminal): 打开终端后,输入以下代码回车: …...
Leetcode148. 排序链表(HOT100)
链接 我写的错误代码: class Solution { public:ListNode* sortList(ListNode* head) {if (!head || !head->next)return head;ListNode* fast head;ListNode* slow head;while (fast&&fast->next) {fast fast->next->next;slow slow->…...
Linux线程_线程互斥_线程同步
一.线程互斥 1.进程线程间的互斥相关概念 临界资源:多线程执行流共享的资源就叫做临界资源临界区:每个线程内部,访问临界资源的代码,就叫做临界区互斥:任何时刻,互斥保证有且只有一个执行流进入临界区&…...
【Spiffo】环境配置:VScode+Windows开发环境
摘要: 在Linux下直接开发有时候不习惯快捷键和操作逻辑,用Windows的话其插件和工具都更齐全、方便,所以配置一个Windows的开发环境能一定程度提升效率。 思路: 自己本地网络内远程连接自己的虚拟机(假定用的是虚拟机…...
DevExpress控件 基本使用
DevExpress控件 一、DevExpress简介 1、所有编辑器的公共功能 全部都可以绑定数据; 全部都可以独立使用或用于由 Developer Express 提供的容器控件 (XtraGrid、XtraVerticalGrid、XtraTreeList 和 XtraBars) 内的内置编辑; 全部都使用相同的样式、外…...
设计模式——装饰器模式
装饰器模式是结构型设计模式,在Python中有一个非常著名的装饰器wrapper,它的实现方法就是使用了该设计模式,装饰器可以修饰类也可以修饰函数。 从类的设计上说,他的本质是在不定义子类的情况下动态的给对象添加一些额外的功能。举…...
【编程题目】列表、元组及集合
一.列表的题目 题目1:列表反转与排序 描述:给定一个整数列表,首先反转该列表,然后对其进行升序排序。最后输出处理后的列表。输入:一个整数列表,例如 [3, 1, 4, 1, 5, 9]输出:处理后的列表,例如 [1, 1, 3, 4, 5, 9]示例:input_list = [3, 1, 4, 1, 5, 9] # 你的代码 …...