For most people, choosing the right city, major, and industry is crucial. Picking the right city ensures that you won’t struggle to find a job, choosing the right major can propel you into the middle class, and selecting the right industry can elevate you two whole social classes.
选城市,选专业,选行业
选城市,选专业,选行业,对普通人来说非常重要,选对一个至少不愁找工作,选对两个就能进入中产阶级,要是三个都选对就可以提升两个阶级。
A Discussion on Logical Deletion (Soft Deletion): Whether It’s Necessary and How to Implement It
In the real world, some documents become obsolete and are immediately shredded, while others need to be preserved in archives for future reference.
Consider an order, which references many other pieces of information, such as seller details, buyer details, and product details. When a product is removed from the catalog, we can’t directly delete the product information; doing so would render the associated order information incomplete.
For tables that require logical deletion (referred to as “collections” in MongoDB), there are two methods:
- Method 1: Add fields like
is_deleted
oris_active
to indicate whether a row has been logically deleted. - Method 2: Create a corresponding archive table (recycle bin table) for each table that needs logical deletion. First, insert the rows to be deleted into the archive table (including additional fields like deletion time, ID of the person who deleted it, etc.), and then delete the rows from the source table.
Many experts have already pointed out the drawbacks of Method 1.
Method 2 is easier to implement, non-intrusive to the source table, but it comes at the cost of increased disk space usage.
When designing the database, we should analyze the specific application scenario:
1. Based on the Business Requirements
If the business requirement is to back up data, the solution should be database backups, not logical deletions.
If the business requirement is to archive data, the solution should be archiving data, i.e., moving data into an archive table.
If the goal is simply to “freeze” data, an inactive
flag should be used. This provides perfect semantic meaning and ensures consistency. It’s important to note that “freezing” is not the same as “deleting.” “Freezing” means that if you need to use the data again, you can simply “unfreeze” it. “Deleting” means the data is gone, and if you need it again, you must recreate it.
2. Based on the Database System
Some database systems already implement archival features for you. For example, SQL Server has a history table feature that automatically logs deleted records into a history table, and updates are stored with their previous values. In such cases, there’s no need to create an archive table or implement archival logic at the code level.
3. Based on the Data Type in the Table
For tables such as menu tables (dictionary tables) or log tables, logical deletion is unnecessary and physical deletion is sufficient.
Only tables that store critical data, such as account tables or balance tables, should implement logical deletion. In such cases, using an archive table may be the better approach.
For further reading:
(Note: Currently, Zhihu requires login to view the original content. Without logging in, it will show random text as part of their anti-scraping measures against AI models.)
关于逻辑删除(假删除)是否要做,该怎么做的探讨
在现实世界中,有些文档用不到了、过期了,我们直接把它放入碎纸机碎掉,而有些文档需要保存到档案室,供以后查询。
一条订单,引用了很多其他信息,例如卖家信息、买家信息、商品信息等,当某种商品被下架时,我们也不能直接物理删除商品信息,否则引用它的订单的信息就不完整了。
对于要做假删除的那些表(在MongoDB中叫作“集合”):
- 方法一,可以增加一个is_deleted、is_active等字段来标识这行数据是否被假删除了。
- 方法二,可以专门为要做假删除的每张表建立一张对应的归档表(回收站表),把要删除的数据行先插入到归档表(包含删除时间、删除人ID、删除人姓名等额外字段),再在源表里删除。
方法一的缺点很多大神已经讲清楚了:
方法二更容易实现,对源表没有侵入性破坏,缺点只是增加了磁盘空间的开销。
我们设计数据库时,要视具体应用场景具体分析:
一、视具体业务的需求而定
如果业务问题是要备份数据,那应该做的是数据库备份,不应该是假删除。
如果业务问题是要归档数据,那应该做的是归档数据,也就是把数据移到归档表里。
如果业务问题只是想冻结数据,应该做inactive标记,这样在语义上非常完美,一致性约束同样没有问题。注意,“冻结”不是“删除”,“冻结”的意思是是这条数据如果你要再次用到,解冻它即可;而“删除”的意思是是这条数据已经被删除了,如果你要再次用到它,只能重新创建一条数据。
二、视数据库软件系统的类型而定
有些数据库软件系统已经帮你实现了归档数据的功能,例如SQL Server有历史表的功能,删除的记录自动记录到历史表里,更新操作也会把更新前的记录保存到历史表里。那么我们就无需自己创建归档表并在代码层面实现归档逻辑了。
三、视表中的数据类型而定
对于菜单表(字典表)、流水表(例如日志表),就无需做假删除了,因为没有必要,直接物理删除即可。
只有一些存储了重要数据的表,例如账户表、余额表,才要做假删除,也许使用回收站表的做法更好。
参考
https://www.zhihu.com/question/39967106/answer/121674339 注意,知乎现在需要登录才能查看到原文,否则显示的是一段随机文本,这是知乎应对AI大模型的爬虫的反爬措施。
人的利用价值和使用价值
人的利用价值,比如说你博士学历,很好利用的样子。但是你高分低能,一点小事都做不好,你的使用价值就很低。
Vue的渲染机制
Vue的视图模板被编译为一个render函数,render函数返回一棵虚拟DOM树,虚拟DOM树挂载(mount)为实际的DOM树。render函数会跟踪Vue的视图模板的依赖(即响应式状态),当响应式状态发生变化时,会执行其副作用,重新编译出一个render函数,返回一棵新的虚拟DOM树,然后与旧的虚拟DOM树进行节点之间的比对,找出更新的节点,然后只需把这些更新的节点更新(patch)到实际的DOM树的对应节点即可。这与替换整棵实际DOM树这种更新方法比起来,无疑性能更高,并且Vue还使用了静态提升、更新类型标记、树结构打平等优化手段来使这一过程更加高效!
参考
Flexbox交互式指南
本文翻译自《An Interactive Guide to Flexbox》。
Flexbox(弹性框)是一种非常强大的布局模式。当我们真正理解它的工作原理时,我们可以构建自动响应的动态布局,并根据需要重新排列。
例如,看看这个:
(译者注:案例请看原文)
此案例很大程度上受到Adam Argyle的出色的“4种布局,1种价格”的启发。它不使用媒体/容器查询。它没有设置任意断点,而是使用流畅的原则来创建无缝流动的布局。 以下是此案例的CSS:
form {
display: flex;
align-items: flex-end;
flex-wrap: wrap;
gap: 16px;
}
.name {
flex-grow: 1;
flex-basis: 160px;
}
.email {
flex-grow: 3;
flex-basis: 200px;
}
button {
flex-grow: 1;
flex-basis: 80px;
}
我记得我曾经遇到过这样的演示,当时完全不知所措。我知道 Flexbox 的基础知识,但这似乎是绝对的魔法!
在这篇博文中,我想完善您对 Flexbox 的心理模型。我们将通过了解每个属性来建立对 Flexbox 算法如何工作的直觉。无论您是 CSS 初学者,还是已经使用 Flexbox 多年,我敢打赌您都会学到很多东西!
让我们开始吧!
内容警告
我在本教程后面会做一个与食物相关的比喻。
Flexbox简介
CSS由许多不同的布局算法组成,布局算法的正式名称是“布局模式(layout mode)”。每种布局模式都是CSS中的一种小语言。默认布局模式是流式布局(Flow layout),但我们可以通过更改父容器上的display属性来选择使用Flexbox布局模式:
(译者注:案例请看原文)
当我们将display属性的值设置为flex时,我们会创建一个“flex格式化上下文”。这意味着,所有子元素都将根据Flexbox布局算法进行定位。
每种布局算法都旨在解决特定问题。默认的“流式”布局旨在创建数字文档,它本质上是Microsoft Word的布局算法。标题和段落以块的形式垂直堆叠,而文本、链接和图像等内容则不显眼地位于这些块内。
那么,Flexbox解决了什么问题?Flexbox就是将一组条目(元素)排列成一行或一列,并赋予我们对这些项目的分布和对齐方式的极大控制权。顾名思义,Flexbox就是“灵活性”。我们可以控制条目是增大还是缩小,如何分配额外的空间等等。
它仍然有意义吗?
你可能想知道:既然CSS Grid在现代浏览器中得到了很好的支持,那么Flexbox不是过时了吗?
CSS Grid是一种很棒的布局模式,但它解决的问题与Flexbox不同。我们应该学习这两种布局模式,并使用正确的工具来完成工作。
当涉及到以垂直或水平列表排列项目的动态、流畅的UI时,Flexbox仍然占据主导地位。我们将在本指南中看到一个示例,即解构的煎饼,这无法通过CSS Grid轻松实现。
老实说,作为一个熟悉CSS Grid和Flexbox的人,我仍然发现自己经常使用Flexbox!
Flex方向
如上所述,Flexbox主要是控制行或列中元素的分布。默认情况下,条目将并排堆叠在一行中,但我们可以使用flex-direction属性翻转到一列:
(译者注:案例请看原文)
使用flex-direction: row时,主轴水平运行,从左到右。当我们翻转为flex-direction: column时,主轴垂直运行,从上到下。
在Flexbox中,一切都基于主轴。算法不关心垂直或水平,甚至行或列。所有规则都围绕此主轴和垂直延伸的横轴构建。
这非常酷。当我们学习Flexbox的规则时,我们可以无缝地从水平布局切换到垂直布局。所有规则都会自动适应。此功能是Flexbox布局模式所独有的。
默认情况下,子元素将根据以下2条规则进行定位:
- 主轴(primary axis):子元素将聚集在容器的起始处。
- 交叉轴(cross axis):子元素将伸展以填满整个容器。
以下是这些规则的快速可视化:
在Flexbox中,我们决定主轴是水平还是垂直。这是所有Flexbox计算的根源。
“主轴”和“交叉轴”也可以称它们为“主轴”和“副轴”。
对齐
我们可以使用justify-content属性来改变子元素沿主轴的分布方式:
(译者注:案例请看原文)
当谈到主轴时,我们通常不会考虑对齐单个子项元素。相反,我们关心的是整个(子项元素)组的分布。
我们可以将所有项目集中在一个特定位置(使用flex-start、center和flex-end),也可以将它们分开(使用space-between、space-around和space-evenly)。
对于副轴,情况略有不同。我们使用align-items属性:
(译者注:案例请看原文)
有趣的是…使用align-items,我们有一些与justify-content相同的选项,但并没有完美的重叠。
为什么它们不共享相同的选项?我们很快就会解开这个谜团,但首先,我需要分享另一个对齐属性:align-self。
与justify-content和align-items不同,align-self应用于子元素,而不是容器。它允许我们沿副轴更改特定子元素的对齐方式:
(译者注:案例请看原文)
align-self具有与align-items相同的所有值。事实上,它们改变的是完全相同的东西。align-items是一种语法糖,是一种方便的简写,可以自动同时设置所有子元素的在副轴上的对齐方式。
没有justify-self属性。要理解为什么没有,我们需要深入研究Flexbox算法。
内容 vs 条目(子元素)
因此,根据我们目前所学的知识,Flexbox可能看起来相当随意。为什么名字是justify-content和align-items,而不是justify-items或align-content?
还有上文那个问题,为什么有align-items属性,而没有justify-self属性?
这些问题涉及到Flexbox最重要的和最容易被误解的事情之一。为了帮助解释,我想用一个比喻来说明。
在Flexbox中,条目(子元素)沿主轴分布。默认情况下,它们并排整齐排列。我可以画一条水平直线,将所有子元素串起来,就像烤肉串一样:
但是,交叉轴(副轴)有所不同。垂直直线只会与其中一个子项相交。它不像烤肉串,而更像一组鸡尾酒香肠:
这里有一个显著的区别。对于鸡尾酒香肠,每条都可以沿着签子移动,而不会干扰任何其他香肠:
相比之下,由于我们的主轴将每个子元素串在一起,因此单个元素无法沿着轴移动,而不会碰到其兄弟元素!尝试将中间部分左右拖动:
这是主轴和副轴之间的根本区别。当我们谈论副轴上的对齐时,每个条目都可以做任何它想做的事情。然而,在主轴上,我们只能考虑如何整组分配。
这就是为什么没有justify-self属性。中间部分设置justify-self: flex-start意味着什么?那个位置已经有另一个条目了!
考虑到所有这些知识背景,让我们对讨论的所有4个术语进行适当的定义:
- justify — 沿主轴定位某物。
- align — 沿交叉轴(副轴)定位某物。
- content — 一组可以排列的“东西”。
- items — 可以单独设置位置的单个条目。
因此:我们有justify-content属性来控制组沿主轴的排列,我们有align-items属性来沿副轴单独定位每个条目。这是我们用来管理Flexbox布局的两个主要属性。
没有justify-items属性的原因与没有justify-self属性的原因相同;当谈到主轴时,我们必须将所有条目(子元素)视为一个组。
那么align-content属性呢?实际上,它确实存在于Flexbox中!稍后我们将在讨论flex-wrap属性时介绍它。
假尺寸(hypothetical size)
让我们来谈谈我对Flexbox最令人大开眼界的认识之一。假设我有以下 CSS:
.item {
width: 2000px;
}
一个理性的人看到这个可能会说:“好吧,所以我们会得到一个宽度为2000像素的项目”。但这总是正确的吗?让我们测试一下:
(译者注:案例请看原文)
这很有趣,不是吗?两个条目应用了完全相同的CSS。它们各自的宽度都是:2000px。然而,第一个条目比第二个条目宽得多!
不同之处在于布局模式。第一个条目使用流式布局进行渲染,在流式布局中,宽度是一个硬性约束。当我们设置宽度:2000px时,我们将得到一个2000像素宽的元素,即使它必须冲破视口的一侧。
然而,在Flexbox中,width属性的实现方式不同。它更像是一种建议,而不是硬性约束。规范对此有一个名称:假设尺寸。它是元素在完美的乌托邦世界中的尺寸,当没有任何阻碍时。
唉,事情很少这么简单。在这种情况下,限制因素是父元素没有空间容纳2000px宽的子元素。因此,子元素的尺寸会缩小以适应它。
这是Flexbox理念的核心部分。事物是流动的、弹性的,可以适应世界的限制。
算法的输入
我们倾向于将CSS语言视为属性的集合,但我认为这是错误的思维模型(mental model)。正如我们所见,width属性的行为会根据所使用的布局模式而有所不同!
相反,我喜欢将CSS视为布局模式的集合。每种布局模式都是一个可以实现或重新定义每个CSS属性的算法。我们通过CSS声明(键/值对)提供一个算法,然后该算法决定如何使用它们。
换句话说,我们编写的CSS是这些算法的输入,就像传递给函数的参数一样。如果我们想真正熟悉CSS,仅仅学习CSS属性是不够的;我们必须了解算法如何使用这些属性。(译者注:这就是很多CSS新手说“CSS很难学”、“CSS属性的功能不正交”的原因了,因为学习和使用CSS的思维模式不正确)
增长与收缩
因此,我们已经看到Flexbox算法具有一些内建的弹性,具有假尺寸。但要真正了解Flexbox的弹性,我们需要讨论3个属性:flex-grow、flex-shrink和flex-basis。 让我们看看这些属性。
flex-basis
我承认:很长一段时间以来,我都不太明白flex-basis到底是什么。
简单来说:在Flex行中,flex-basis的作用与width相同。在Flex列中,flex-basis的作用与height相同。
我们已经知道,Flexbox中的所有内容都与主轴和副轴挂钩。例如,justify-content将沿主轴分布子元素,无论主轴是水平还是垂直,其工作方式都完全相同。
但是 width和height不遵循这条规则!width总是会影响水平尺寸。当我们将flex-direction从row翻转为column时,它不会突然变成height。
因此,Flexbox的作者创建了一个通用的“尺寸”属性,称为flex-basis。它类似于width或height,但与其他所有东西一样与主轴挂钩。它允许我们在主轴方向上设置元素的假尺寸,无论主轴方向是水平还是垂直。
在这里尝试一下。每个子元素都被赋予了flex-basis: 50px,但你可以调整第一个子元素:
(译者注:案例请看原文)
就像我们在width方面看到的一样,flex-basis更多的是一种建议尺寸,而不是硬性约束。在某个时候,空间不足以让所有元素都按照指定的大小放置,因此它们必须做出妥协,以避免溢出。
不完全一样
通常,我们可以在Flex行(Flex row)中互换使用width和flex-basis,但也有一些例外。例如,width属性对图像等替换元素的影响与flex-basis不同。此外,width可以将元素缩小到其最小尺寸以下,而flex-basis则不能。
这远远超出了这篇博文的范围,但我想提一下,因为你可能偶尔会遇到两个属性具有不同效果的边界情况。
flex-grow
默认情况下,Flex上下文中的元素将沿主轴缩小到其最小舒适尺寸。这通常会产生容器元素的额外的空间。
我们可以使用flex-grow属性来指定如何使用该空间:
(译者注:案例请看原文)
flex-grow的默认值是0,这意味着flex-grow是可选的。如果我们想让某个子元素占用容器中的所有额外空间,我们需要明确地告诉它。
如果多个子元素设置了flex-grow会怎么样?在这种情况下,额外空间会根据子元素的flex-grow的值按比例分配给它们。
我认为用可视化方式解释会更容易。尝试增加/减少每个子元素的flex-grow的值:
(译者注:案例请看原文)
例如,第一个子元素想要4个单位的额外空间,而第二个子元素想要1个单位。这意味着单位总数是5 (=4 + 1)。每个子元素都会按比例获得该额外空间的份额(第一个子元素获得4/5的额外空间,第二个子元素获得1/5的额外空间)。
flex-shrink
在目前我们看到的大多数示例中,我们都有额外的空间可供使用。但如果我们的子元素对于容器来说太大了怎么办?
让我们测试一下。尝试缩小容器的宽度以查看会发生什么:
(译者注:案例请看原文)
很有趣,对吧?两个子元素都会缩小,但它们会按比例缩小。第一个子元素的宽度始终是第二个子元素的2倍。
温馨提醒,flex-basis的作用与width相同。我们将使用flex-basis,因为它是常规用法,但如果使用width,我们也会得到完全相同的结果!
flex-basis和width设定元素的假设尺寸。Flexbox算法可能会将元素缩小到低于它所需尺寸,但默认情况下,它们将始终一起缩放,从而保持两个元素之间的比例。
现在,如果我们不想让元素按比例缩小怎么办?这就是flex-shrink属性的作用所在。
花几分钟看看这个演示。看看你是否能弄清楚这里发生了什么。我们将在下面进行探索。
(译者注:案例请看原文)
我们有两个子元素,每个元素的假设尺寸为250px。容器的宽度至少需要500px,才能容纳假设尺寸的这些子元素。
假设我们将容器缩小到400px。好吧,我们无法将价值500px的内容塞进400px的袋子里!我们缺口是100px。我们的元素将需要放弃总共100px,才能适合。
flex-shrink属性让我们决定如何支付这笔差额。
和flex-grow一样,它是一个比例。默认情况下,两个子元素都有flex-shrink: 1,因此每个子元素都支付缺口的1/2。它们各自放弃50px,其实际尺寸从250px缩小到200px。
现在,假设我们将第一个子元素的flex-shrink设置为3:
我们总共缺口100px。通常情况下,每个子元素都会支付1/2,但是由于我们对flex-shrink进行了调整,第一个元素最终支付3/4(75px),第二个元素支付1/4(25px)。
请注意,绝对值并不重要,重要的是比率。如果两个子元素都具有flex-shrink: 1,则每个子元素将支付总缺口的1/2。如果两个子元素都设置为flex-shrink: 1000,则每个子元素将支付总缺口的1000/2000。无论哪种方式,结果都是一样的。
收缩和比例
在我们查看的示例中,两个Flex子元素具有相同的假设尺寸(250px)。在确定如何收缩它们时,我们可以使用flex-shrink进行专门计算。
不过,正如我们之前所看到的,收缩算法也会尝试保持兄弟元素之间的比例。如果第一个子元素的大小是第二个的2倍,那么第一个子元素的收缩幅度会更大。
因此,完整的计算涉及每个子元素的flex-shrink值和相对大小。
不久前,我对flex-shrink有了新的认识:我们可以将其视为flex-grow的“反面”。它们是同一枚硬币的两面:
- flex-grow控制当子元素小于其容器时如何分配额外空间。
- flex-shrink控制当子元素大于其容器时如何移除空间。
这意味着同一时刻,这两个属性中只有一个可以处于激活的状态。如果有多余的空间,flex-shrink不会产生任何效果,因为子元素不需要缩小。如果子元素对于其容器来说太大,flex-grow不会产生任何效果,因为没有多余的空间可以分配。
我喜欢把它想象成两个不同的世界。你要么在地球上,要么在相反的世界。每个世界都有自己的规则。
防止收缩
有时,我们不希望某些Flex子元素收缩。
我经常在SVG图标和形状中发现这种情况。让我们看一个简化的示例:
(译者注:案例请看原文)
当容器变窄时,我们的两个圆圈会被挤压成椭圆形。如果我们想让它们保持圆形怎么办?
我们可以通过设置flex-shrink: 0来实现这一点:
(译者注:案例请看原文)
当我们将flex-shrink设置为0时,基本上完全“选择退出”收缩过程。Flexbox算法会将flex-basis(或width或height)视为硬性最小限制。
如果你感兴趣,以下是此演示的完整代码:
(译者注:代码请看原文)
更简单的方法?
有时,有人会想知道为什么我们有更简单的方法可以使用,却要费尽心思使用flex-shrink:
.item.ball {
min-width: 32px;
}
几年前,我会同意这一点。如果我们设置最小宽度,子元素将无法缩小到该点以下!我们添加了一个硬约束,而不是width / flex-basis的软约束。
我认为这是很容易将“熟悉”与“简单”混淆的情形之一。你可能对min-width比flex-shrink更熟悉,但这并不意味着flex-shrink更复杂!
经过几年的实践,我实际上觉得设置flex-shrink: 0是解决这个特定问题的更直接的方法。不过,min-width在Flexbox算法中仍然发挥着重要作用!我们接下来会讨论这一点。
最小尺寸陷阱
这里还有一件事需要讨论,而且非常重要。这可能是整篇文章中最有帮助的事情!
假设我们正在为一家电子商务商店网页构建一个流畅的搜索表单:
(译者注:案例请看原文)
当容器收缩到某个点以下时,内容就会溢出!
但为什么呢?flex-shrink的默认值是1,而我们并没有把它设置为0(阻止收缩),所以搜索输入框应该能够根据需要收缩!为什么它拒绝收缩呢?
情况是这样的:除了假设尺寸之外,Flexbox算法还关心另一个重要尺寸:最小尺寸(the minimum size)。
Flexbox算法拒绝将子元素缩小到其最小尺寸以下。无论我们将flex-shrink调到多高,内容都会溢出,而不是进一步缩小!
文本输入框的默认最小尺寸为170px-200px(不同浏览器会有所不同)。这就是我们上面遇到的限制。
在其他情况下,限制因素可能是元素的内容。例如,尝试调整此容器的大小:
(译者注:案例请看原文)
对于包含文本的元素,最小宽度是最长的不可断开的单词字符串的长度。 好消息是:我们可以使用min-width属性重新定义最小尺寸。
(译者注:案例请看原文)
通过直接在Flex子元素上设置min-width: 0px(译者注:在Flex容器的直接子元素上设置min-width: 0px,如果在孙元素上设置min-width: 0px是没有效果的),我们告诉Flexbox算法覆盖内置(默认)最小宽度。因为我们将其设置为0px,所以元素可以根据需要缩小。
相同的技巧可以在具有min-height属性的Flex列中发挥作用(尽管这个问题似乎并不经常出现)。
注意事项
值得注意的是,内置的最小尺寸确实有其用途。它起到护栏的作用,防止发生更糟糕的事情。
例如:当我们将min-width: 0px应用于包含文本的Flex子元素时,情况会变得更糟:
(译者注:案例请看原文)
能力越大,责任越大,对于Flexbox来说,min-width 一个特别强大的属性。它不止一次让我摆脱困境,但我总是小心翼翼,确保不会让事情变得更糟!
间隙
近年来提升Flexbox开发体验的最大的改进之一是gap属性:
(译者注:案例请看原文)
gap允许我们在每个Flex子元素之间创建间隙。这对于水平导航栏的标题子元素等场景非常有用:
(译者注:案例请看原文)
gap是Flexbox布局中一个相对较新的功能,但自2021年初以来,它已在所有现代浏览器中实现。
自动边距(Auto margins)
我还想分享一个与间距相关的技巧。这个技巧早在Flexbox早期就出现了,但相对来说不太为人所知,当我第一次发现它时,我感到非常震惊。
margin属性用于在特定元素周围添加空间。在某些布局模式(如Flow和Positioned)中,它甚至可以使用margin: auto将元素居中。
Flexbox中的自动边距更加有趣:
(译者注:案例请看原文)
之前,我们看到了flex-grow属性如何吞噬任何额外的空间,并将其应用于子元素。
自动边距将占用额外空间,并将其应用于元素的边距(margin)。它使我们能够精确控制在何处分配额外空间。
常见的顶部水平导航栏的布局是一侧显示logo,另一侧显示一些导航链接。以下是使用自动边距构建此布局的方法:
(译者注:案例请看原文)
Corpatech logo是列表中的第一个列表项。通过为其指定margin-right: auto,我们收集了所有额外空间,并将其强制置于第1个和第2个列表项之间。
我们可以使用浏览器devtools查看这里发生的情况:
有很多其他方法可以解决这个问题:我们可以将导航链接分组到它们自己的Flex容器中,或者我们可以使用flex-grow来扩展第一个列表项的宽度。但就我个人而言,我喜欢自动边距这个解决方案。我们将额外的空间视为资源,并决定它应该放在哪里。
换行(Wrapping)
到目前为止,我们已经讲了很多内容。我还想分享一个重要的收获。
到目前为止,我们所有的项目都并排放在一行/一列中。flex-wrap属性允许我们改变这种情况。看看吧:
(译者注:案例请看原文)
大多数时候,当我们在二维空间中工作时,我们会想要使用CSS Grid布局,但Flexbox + flex-wrap绝对有其用途!这个特殊的例子展示了“解构煎饼(deconstructed pancake)”布局,其中3个子元素在中等尺寸的屏幕上堆叠成倒金字塔形状。
当我们设置flex-wrap: wrap时,子元素不会缩小到其假设尺寸以下。至少,当可以选择换行到下一行或列时就不会缩小!
但是等一下!flex-wrap: wrap对我们上文的烤肉串/鸡尾酒香肠的比喻有什么影响?
使用flex-wrap: wrap,我们不再需要一条主轴线来串起每个子条目。实际上,每行都充当自己的迷你弹性盒容器。每行都有自己的一串,而不是所有行共用一串:
在这个缩小的范围内,我们到目前为止学到的所有规则仍然适用。例如,justify-content会在每根签子上分布两个子块。
但是align-items属性又怎么工作呢,现在我们有了多行的情况下?副轴现在可以与多个子条目相交了!
花点时间考虑一下。你认为当我们改变这个属性时会发生什么?一旦你有了答案(或至少有一个想法),看看它是否正确:
(译者注:案例请看原文)
每一行都是它自己的迷你Flexbox环境。align-items将在环绕每一行的隐形框内将每个子条目向上或向下移动。
但是如果我们想让整行(包括所有换行)本身对齐呢?我们可以使用align-content属性来实现: (译者注:案例请看原文)
总结一下以上案例发生的事情:
- flex-wrap: wrap给我们两行条目
- 在每一行中,align-items可以让我们向上或向下滑动每个单独的子条目
- 然而这两行在一个Flex上下文中!交叉轴(副轴)现在将与这两行相交,而不是一行。因此,我们不能单独移动其中一行,我们需要将它们作为一个组进行布局。
- 使用上面的定义,我们处理的是内容,而不是条目。但我们仍然在谈论副轴!因此,我们想要的属性是align-content。
你做到了!
所以我想承认一件事:这是一个很长的教程。我们已经陷入了困境,除非你已经是Flexbox的专业人士,否则我预计你的头会有点晕。
与CSS中的许多内容一样,Flexbox在你刚开始使用时可能看起来很简单,但当你学完基础知识时,复杂性会迅速增加。
因此,我们中的许多人在CSS方面都达到了早期的平稳期。我们有足够的知识来完成事情,但这是一场持续的斗争。CSS语言给人一种摇摇欲坠、难以捉摸的感觉,就像一座古老的绳桥,随时都可能断裂。当它断裂时,我们会向问题抛出随机的StackOverflow代码片段,希望能有所帮助。
这不好玩。这很糟糕,因为CSS是大多数前端开发工作中相当大的一部分! 事实上,CSS是一种非常健壮和一致的语言。问题是,我们的大多数心理模型都是不完整和不准确的。当我们花时间为CSS语言建立一个正确的直觉时,事情开始发生变化,它将成为一种绝对的乐趣。
Vue响应式系统
一句话总结Vue响应式系统的核心行为:在状态被访问时追踪其依赖,在状态被改变时执行其副作用。