Web技巧(16)

3,818 阅读26分钟

上个周末因为自己要写PPT而没来得急整理,所以又错过了一期。在这一期中,大部分内容将围绕着@Bill Mei的《Top 10 most deadly CSS mistakes made by new and experienced developers》文章中提到观点来展开。这里面的一些观点虽然不完全对,但还是有相应的参考价值,取舍由大家自己来决定。如果你在这方面也有相关的经验,也欢迎在下面的评论中分享。另外在后面会简单的整理几个最近觉得有意思的新东西。感兴趣的同学,请继续往下阅读。

10个最致命的CSS错误

多年来,很多工程师在使用CSS时容易犯一些常见的错误,不管是老司机还是新手。而CSS一直又是简单但不容易的语言(不直观和难以使用),真正探究的并不多,而很多常见的错误又往往会阻碍项目的开发进程。如果我们在编写CSS的时候就能避免这些错误,是不是在实际开发的时候能事半功倍。

以下是编写CSS中常见的10个错误,也是最致命的错误。

接下来的10条内容来自于@Bill Mei的《Top 10 most deadly CSS mistakes made by new and experienced developers》一文。

编写选择器时太过遵循DOM结构

有一些开发人员喜欢追求一种极简主义的风格,他们试图着不在HTML中有大量的类名(class),通过使用DOM结构来作为CSS的选择器,这样他们的选择器就会遵循DOM树的结构。比如有这么一个DOM结构:

<body>
    <div class="container">
        <div class="main-content">
            <div class="blog-row">
                <div class="blog-col">
                    <section>
                        <article>
                            <a href="#">This link is not bold</a>
                            <p><a href="#" class="bold">This link is bold</a></p>
                        </article>
                    </section>
                    <section>
                        <a href="#">This link is not bold</a>
                    </section>
                </div>
            </div>
        </div>
    </div>
</body>

有些同学在给a链接添加样式的时候,会这样的操作:

body .container .main-content .blog-row .blog-col section article p a {
    font-weight: bold;
}

就算是在使用CSS处理器的时候也无限级的嵌套,经如:

body {
    .container{
        .main-content{
            .blog-row{
                .blog-col{
                    section{
                        article{
                            p{
                                a{
                                    font-weight: bold;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

特别是在CSS的处理器中,不要说是新手,很多老司机也会出现类似上面这样的错误。

虽然在编写HTML结构的时候,很多司机也提倡DOM结构能简洁就尽量的简洁,但并不是提倡这种无约束的极简主义。因为这种极简主义虽然保持了HTML的干净,但会让CSS变得混乱,使其更难理解、调试和更改。就如上面的示例所示,CSS会变得不灵活,因为长组合的CSS选择器承担了复制HTML结构的任务,但这有背于CSS应该做的事情。

CSS的任务是提供样式;HTML的任务是提供结构。这也是Web构建中最基本的原则之一。如果仅仅追求DOM简洁干净,而忽略CSS,不考虑与CSS相互结合,这是错误的一种做法。另外这种编写CSS的方式强度依赖于HTML的DOM结构树,也会造成很多致命性的错误,比如说,你的HTML结构做出调整,那么CSS选择器也将做调整,而这种长链条的组合是最易于出错的。这种做法也在无形中增加很多不必要的工作。

相反,我更建议CSS的类和HTML的DOM更应该合理的结合起来。如果你需要从页面中选择一个特定的元素,应该在该元素上添加一个类名来完成:

.bold {
    font-weight: bold;
}

就算是你要使用这种长组合的方式来定位到DOM元素,我也强烈建议:

CSS的选择器不超过三级

幸运的是,现在有很多方式可以帮助我们避免这种方式,比如借助StyleLint来监控你的CSS代码,让选择器不超三级嵌套。也可以使用CSS-in-JS和CSS Modules方式来维护你的CSS代码。特别今天(截至2019年),这种方式更被广泛的采用。

如果你对CSS-in-JS和CSS Modules感兴趣的话,我建议你花点时间阅读下面的相关文章:

话说回来,我们在项目中应该避免目标过于明确或指定过多的选择器,并且要避免使用!importantCSS权重的对比让我们更直观地了解为什么选择器器权重过大是不好的。如果选择器权重过大,它会更易被采用,如果我们想要通过另一个选择器来覆盖它,就需要一个权重更大的选择器。这也是令很多同学在覆盖样式时感到痛苦之处。

CSS选择器权重的争夺战是一直存在你的CSS中,这也是令很多老司机和新手痛苦之处。如果你是新手,那么掌握CSS选择器权重是的计算是非常有必要的

说到CSS选择器权重之争,我又要上@Elijah Manor

如果上图还无法让你整明白CSS选择器权重的计算,那么下面这个计算器就可以帮助你更好的理解

编写HTML时忽略SEO

搜索引擎优化(SEO)不仅仅是你完成编码后交给营销团队来处理。我们在编码的时候就需要考虑到SEO的内容,特别是因为一些影响SEO的因素。因为影响SEO因素一旦产生,那么后续要优化的难度就会更大。比如网站的URL Scheme或服务体系结构。

众所周知,HTML的语义化标签是影响SEO的因素之一,因为标签的选择会影响搜索引擎对内容的理解和排名。如果你想显示在搜索结果的顶部附近,那么就得选择正确的标签。

假设你正在写一篇关于CSS教程的文章。你可以把所有内容都放在一个<div>中,然而<div>是一个通用的非语义的标签,它不包含内容中的任何内在的含义。相反,你应该选择一个更具体的语义标签,例如<article>来包含文章的内容,<nav>来包含到跳转到其他文章的链接。

选择更具体的语义标签而不是一般非语义标签的好处是,你可以向搜索引擎提供关于你的网站更多的信息,这样一来,搜索引擎的爬虫能更好的理解和交付与读者的搜索查询相关的内容。

例如,用于文章标题的HTML标签,它有六个潜在的标题标签,按最重要的标题到最不重要的标题的顺序排列h1~h6(数值越小,表示越重要)。<h1>是你最重要的标题,因为它是一个特殊的信号,搜索引擎会把这个理解为你内容的标题或者页面的标题(<title>,大多数搜索引擎两者都会考虑)。此外,如果你的用户视力受损,并且使用屏幕阅读器,大多数屏幕阅读器都知道要立即大声的朗读<h1>中的内容,因为它会先假定这是你的内容的标题。

这也意味着,如果你使用<h1>来处理任何不是标题的内容,或者你在一个页面上有多个<h1>,搜索引擎就会被混淆,你的“真实”标题(想要第一时间让搜索引擎识别的标题)可能不会出现在搜索结果中。另外的一个情况是,在不同的部分嵌套多个<h1>,比如:

<article>
    <h1>My cool blog post</h1>
    <p>This blog is so cool!</p>
</article>
<footer>
    <h1>Contact Us</h1>
    <p>Tel: 867-5309</p>
</footer>

尽管这个页面上有两个<h1>标签,但第一个是在<article>中,而另一个是在<footer>标签中。由于搜索引擎理解<article>的内容要比<footer>的内容更重要,更有趣;所以它会使用<article>中的<h1>,而不是<footer>中的<h1>当作标题。所以在某种意义上,你的父母是谁,决定了你有多重要。现实生活中也是如此,有个好爹是多么的重要。

有关于HTML正确的打开姿势,@Daniel Tonon的《How to Section Your HTML》一文就做过这方面深入的探讨:

有关于HTML标签和SEO之间的关系,更多的内容可以阅读下面的文章:

随着JavaScript框架的崛起,比如VueReact等。很多同学平时在使用这些JavaScritp框开发页面的时候,可能也不太关注什么SEO相关的事情。事实上在国外有关于Vue,React开发页面时对SEO方面的讨论还是蛮多的,感兴趣可以阅读:

另外在Reddit和知乎上也有相关的讨论:

最后在给大家推荐一个工具Prerendering,号称是最好的SEO解决方案:

The best SEO solution, and SSR replacement for JavaScript websites. It’s like SSR with no need of coding.

使用px单位

使用px单位并不是一个错误,但要看使用的场景。真正的错误是使用绝对单位而不是相对单位

有关于CSS单位更多的介绍,可以阅读《图解CSS:CSS 的值和单位》一文或点击这里了解更多的内容

我们更喜欢使用相对测量方法,比如em%rem和其他可能的方法。之确保了网站的缩放比例能根据font-size进行缩放。

// 不好的用法
p {
    font-size: 16px;
    line-height: 20px;
    margin-bottom: 8px;
}

// 好的用法
body {
    font-size: 16px;
}
p {
    font-size: 1rem;
    line-height: 1.25;
    margin-bottom: 0.5em;
}

比如下图,就是使用em单位好的缩影:

时至今日,使用px这种绝对单位的问题是无法较好的适配于不同终端,特别是在移动终端上,面对的场景更为复杂。如果使用px单位不能让你的Web页面或Web应用程序在任何地方都保持相同的比例,所以你必须尝试将你的元素放在相对项中,而不是绝对项中。否则,屏幕上的可用空间不能适当地缩放到每个窗口大小。相对单位使用这种简单的px锁定你的设计到特定的缩放级别,使你的设计难以缩放到不同的设备。

在移动端的天下,我更建议使用视窗单位来做测量单位,更易于让你的设计能在不同的设备终端达到缩放效果。如果你对这方面感兴趣,建议您花点时间阅读:

试图实现“像素级”的完美设计

更普遍地说,在编写CSS时,“像素级”的完美设计并不是一个好的目标。

现代Web页面或Web应用程序必须跨多种设备(移动设备、桌面设备、平板电脑、TV大屏和手表)运行,其中有多样的屏幕大小、屏幕分辨率、操作系统、用户设置和JavaScript引擎,这些都会干扰渲染“像素级”完美设计的能力。

在我看来,一味地追求“像素级”完美的设计将需要更多额外的代码来处理,这些额外的代码将带来更大的复杂性和潜在的风险。可以说是“付出与收益不成正比”。

不过有一点需要特别提出,不要将“像素级”的完美设计和优秀的设计混淆。真正伟大的设计是给用户留下持久的情感影响。这是当他们打开你的产品时所得到的快乐,也是他们从你的Web应用中得到的快乐。而这一切并不是你选择16pt字号而不是15pt字号的崇拜

中断文档流

CSS的棘手之处在于使用不同的CSS代码可以实现相同的视觉效果。例如,要将页面上的元素水平垂直居中,可以有很多种方式,使用任何一处都可以让你的用户看到相同的效果。

@Amos整理了相关的技巧,可达23种方式来实现垂直居中

虽然实现同一效果有很多种方式,但我建议我们在实现效果的时候应该尽量的避免中断文档流。因为过于频繁地中断文档流(例如,过度使用float)会增加对内存的占用,而且让别的小伙伴甚至是你自己更难理解。

当有多个方案实现相同的视觉效果时,我更喜欢使用中用内存空间更小的技术。

不将设计和布局分离

CSS的任务是提供样式,HTML的任务是提供结构。通常,你应该首先以捕获页面信息结构层次的方式编写HTML。即:

在编写HTML的时候,应该忽略任何设计关注点

然后,添加CSS,让视觉上看起来很好。

虽然HTML提供了结构,但它不能总是将元素定位在你希望它在页面上出现的准确位置。因此,可以使用CSS构建页面的正确布局,以便元素出现在正确的位置。一旦一个元素被放置在页面的正确位置,就可以很容易地修饰它,使它看起来很漂亮,而不用担心它的位置。因此:

CSS布局(Layout CSS)和CSS美化(Lipstick CSS)是做着不同的事情

简单的看两示例:

// 不好的示例
.article {
    display: inline-block;
    width: 50%;
    margin-bottom: 1em;
    font-family: sans-serif;
    border-radius: 1rem;
    box-shadow: 12px 12px 2px 1px rgba(0, 0, 0, .2);
}
.sidebar {
    width: 25%;
    margin-left: 5px;
}

<div class="article"></div>
<div class="article sidebar"></div>

// 好的示例
/* Layout */
.article, .sidebar {
    display: inline-block;
}
.article {
    width: 50%;
    margin-bottom: 1em;
}
.sidebar {
    width: 25%;
    margin-left: 5px;
}

/* Lipstick */
.card {
    font-family: sans-serif;
    border-radius: 1rem;
    box-shadow: 12px 12px 2px 1px rgba(0, 0, 0, .2);
}

<div class="article card"></div>
<div class="sidebar card"></div>

CSS布局(Layout CSS)和CSS美化(Lipstick CSS)工作的分开也被称为关注点分离(Separation of Concerns),这是软件工程的一个通用原则,有助于保持代码的可维护性和易于理解

我们希望使用合适的工具来完成这项工作,因为以这种方式分离CSS可以很容易地将一个元素移动到页面的另一部分,而不会弄脏Lipstick CSS,还可以很容易的更改Lipstick,而不会破坏Layout。每次我们添加一个新特性时,混合使用之两种方法都会迫使我们同时做这两项工作。

移动先行

随着移动终端的普及率的提高,移动网站(或应用)成为主流。很多人开始提“移动第一”,在提这个理念的时候也意味着桌面(PC端)是二等公民。相反,“移动优先”的拥护者则表现出相反的行为,他们首先为桌面编写代码,然后试图将网站塞进移动端。他们使用@media来处理移动端设备上的异常,但实际情况是桌面端才应该是异常

在这个移动端的时代,你的用户首先通过他们的手机找到你,然后他们要是足够喜欢你的产品,才会到桌面端去体验。但在你的设计师、开发者和产品经理看来,手机真的是第一位吗?你是否先编写移动端的代码,然后再构建桌面端?你的设计师是先为手机创建线框图和模型,然后再为台式机创建线框和模型吗?在测试桌面版本之前,你是否在移动端版本上执行A/B测试,并征求用户的反馈?

//不好的做法
.container {
    width: 980px;
    padding: 1em;
}

@media (max-width: 979px) {
    .container {
        width: 100%;
        padding: 0.5em;
    }
}

// 好的做法
.container {
    width: 100%;
    max-width: 980px;
    padding: 0.5em;
}

@media (min-width: 980px) {
    .container {
        padding: 1em;
    }
}

另外一个主要的原因是,从移动端上往大屏幕上扩展会更容易;但要从大屏幕上删除元素使其适合较小屏幕,就会比较棘手。

没有使用命名方案

Namespaces are one honking great idea – let’s do more of those! — PEP 20: The Zen of Python

在CSS中给元素命名总是很烦人的,如果让你不要考虑命名方案就直接写代码,你一定会很兴奋。例如你给一个<img>元素添加类名的时候,你可能会将它命名为.img.image.blog-img.img-blog等。如果你将它命名为.blog-img,那之后你还会接受.ad-img.thumbnail-img的命名?

给元素命什么样的名,虽然看起来是一件很小的事情,但是CSS要比其他语言更难重构,因为我们目前没有任何用于CSS的静态分析工具来执行自动重构或重命名。CSS类可以使用JavaScript动态地添加、删除和构造,因此不可能找到“未声明”的CSS选择器 —— 仅仅因为CSS片段没有在一个页面的一个状态中使用,并不意味着它从示使用过。

另外,如果你的团队不能就是否将其命名为.center.centre.centered.text-center.align-center达成一致,那么BEM也就无法解决之个问题。

在一些JavaScript框架中,使用CSS-in-JS可以部分地解决这个问题,因为这些框架删除了CSS的全局作用域,并鼓励你将样式与其关联的组件放在一起。然而,CSS-in-JS还没有被广泛采用,而且这方面的争议也很多。

还有一个主要原因是,开发人员在删除任何可能破坏网站的内容时总是会犹豫不决。因此大家宁可谨慎行事,也可愿增加垃圾代码,也不敢去冒险。更糟糕的是,除非你很努力的推广和清晰地沟通你的设计系统,否则它可能会被忽视,因为你的同事会避免阅读你的文档,继续他们的老习惯。

不阅读文档

这看起来似乎很简单。比如说使用Bootstrap,很多同学认为只要安装了就可以了。不幸的是,如果你不真正理解CSS框架(CSS Framework),并且不小心违背了它的原则,那么它常常会导致比引用它来解决问题更多的问题出现。无论你使用的是Bootstrap、Material Design、Foundation等开源设计系统,还是你自己团队开发的设计系统。

因此,在使用任何一个框架或系统之前,很有必要花一定的时间去阅读相关的文档。

认真阅读文档是很重要的,因为许多框架要求你取消从以前的框架中提取的肌肉记忆,而且只有阅读了整个手册,你才能知道其缺陷在哪里。例如,组件继承是较老的前端框架中的一种常见模式。然而,React这样的新框架在使用组合而不是继承时工作是最好的。如果跳过文档的阅读,你很可能就不会意识到这一点,你可能就会默认使用你习惯的继承模式。

更普遍地说,你被从旧技术发展而来的肌肉记忆所困住是很危险的,这会导致我们犯最后一个致命的错误。

没有按照计划系统地学习CSS

技术是不断革新的,保持相关性的唯一方法是遵循一个持续学习和改进的计划

从教条中死记硬背知识是很危险的。一些有经验的开发人员一听到“内联样式(Inline Style)”就有着一种本能的反感,因为在他们的职业生涯的早期就被教导**“样式和结构的分离;永远不要使用内联样式”**。

事实上,“永远不要使用内联样式”是很久以前的最佳实践。那是当时的背景下会使HTML难以阅读、调试和更新。然而,这项技术的进展缓慢,最终颠覆了导致这些“最佳实践”的假设。新的假设导至新的最佳实践

内联样式只有在行内写样式才是真正的痛苦,但如果使用CSS-in-JS的库来管理你的内联样式时,这些所谓的缺点就消失了,而你的优势也就只剩下代码模块化,自动化测试和简单的管理工作等。

如果你固守着“永远不要使用内联样式”的教条,那么当最初的假设发生变化时,你就不会有好奇心去探究它意味着什么。使用系统的,结构化的计划从头开始学习CSS是很重要的,而不是仅仅搜索来寻找一些只关注表面实践的教程。

不幸的是,我尝试着寻找免费的在线资源来帮助你结构化、系统化的学习CSS,但并没有找到任何好的资源。现有的CSS资源要么过于技术化,并且假设你已经了解了浏览器渲染原理,要么它们只提供一些简单的技巧,而没有教给你一些有关于CSS的基本原理。

因为没有好的资源可以让你对CSS从心里就有一个可靠的心理模型,所以很多时候碰到问题都是依赖搜索,然后复制和粘贴来解决。这使得很多人对CSS的知识都是东拼西凑的,只知道解决出现的特定的Bug就足够了,但是当面对一个看起来需要花费数小时才能修复的,又难以理解的Bug时,会立马感到完全无助。

而且一直以来,在整个前端社区有一种不成文的理解。

CSS非常的简单,正因为其简单,才觉得很容易。了解它的属性就会使用

也正因这样的误导,大家觉得CSS很容易,没有任何学习成本。甚至有一些同学会认为,CSS就是手到擒来的东西。

而我想再次表达一个不同的观点是:CSS是简单,但绝不容易

Unlike a programming language that requires knowledge of loops, variables, and other concepts, CSS is pretty easy to pick up. Maybe it’s because of this that it has gained the reputation of being simple. It is simple in the sense of “not complex”, but that doesn’t mean it’s easy. Mistaking “simple” for “easy” will only lead to heartache.

上面罗列的一些观点不一定全对,但还是蛮有参考价值的。虽然不是什么技巧,但可以帮助我学习更多的技巧。

使用backdrop-filter实现磨砂玻璃效果

See the Pen Frosted glass effect by Facundo Corradini (@facundocorradini) on CodePen.

磨砂玻璃的效果最早来自于苹果手机设备上的效果。

早在2015年的《CSS3 Filter的十种特效》和《高级CSS filters》介绍滤镜使用的时候就知道background-filter这个属性。那个时候仅在Safari上才能看到效果,但从Chrome 76开始也能看到background-filter带来的磨砂玻璃效果。

HTML的output元素

或许很多人听过input元素,但对于output元素听说过的应该很少吧。

其实在W3C的HTML5工作草案12(2019年02月)就添加了output元素。在此工作草案之前,它在HTML5中被引用,直接是Web Forms 2.0中的定义

从HTML规范中的原始定义到现在,output的一些细节已经发生了变化,但是元素始终在表单元素的家族中。现在对output的定义从“output元素表示计算结果”到“output元素表示应用程序执行的计算结果或用户操作的结果”转变。

来看一个简单的使用用例:

<form oninput="added.value=parseInt(i1.value)+parseInt(i2.value)">
    <input type="number" min="0" name="i1" value="0"> +
    <input type="number" min="0" name="i2" value="0"> =
    <output name="added">0</output>
</form>

有关于output元素更多的介绍可以阅读:

你所不知道的:not()

在《初探CSS 选择器Level 4》一文中有详细介绍过:not()这个函数伪类的使用。

否定伪类:not()是一个函数伪类,以选择器列表做为参数,它表示的元素不是由其参数表示的。:not()选择器可以用来做为判断的一个选择器,好比JavaScript中的非。其主要作用就是将符合规则的元素剔除,将样式规则应用于其他元素上。事实上,在CSS Selector Level 3就有:not()的身影,只不过当初的功能比较弱,比如:not(p)用来选择不是<p>的元素。但在新版本的中,其功能变得更为强大,可以应用更为复杂的规则,但是同样地不允许嵌套使用,比如:not(:not(...))

我们平时开发项目的时候,时常会碰到列表这样的效果,列表项之间有一个margin-bottom,而往往想在最后一项中不设置margin-bottom。比如像下图这样的效果:

如果要避免多个类的时候,可以将它们连接起来,因为:not()没有逻辑组合符的操作,所以我们可以这样做:

body:not(.home):not(.away):not(.page-50) {

}

前几天@张鑫旭老师在《CSS :not伪类可能错误的认识》一文中也详细阐述了我们对:not()使用时容易搞错的几个点。比如,搞不清楚其优先级、不支持复杂选择器、容易搞不清楚的否定逻辑关系等。

从字符串中删除最后一个字符

JavaScript中从字符串中删除最后一个字符的两种方法:

// 使用`slice`
let input = "w3cplus.com"

function removeLastCharacter(str){
    let charcter_arr = str.split('');
    return charcter_arr.slice(0, charcter_arr.length - 1).join('');
}

let output = removeLastCharacter(input);
console.log(`Output is ${output}`);  // => Output is w3cplus.co

// 使用substring方法
let input = "w3cplus.com"

function removeLastCharacter(str){
    return str.substring(0, str.length - 1);
}

let output = removeLastCharacter(input);
console.log(`Output is ${output}`); // => Output is w3cplus.co

几张动图帮你更好的理解CSS Grid中的几个属性

这两年有关于CSS Grid Layout的相关讨论在社区中非常的火爆。强大到只需要添加一行代码就可以实现响应式的布局(一些特定场景)。

这一行代码就是:

grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));

代码中用到了repeat()auto-fitminmax()fr。接下来用@Per 文章中的几张GIF图来向大家展示他们的作用:

<!-- HTML -->
<div class="container">  
    <div>1</div>  
    <div>2</div>  
    <div>3</div>  
    <div>4</div>  
    <div>5</div>  
    <div>6</div>  
</div>

// CSS
.container {  
    display: grid;  
    grid-template-columns: 100px 100px 100px;  
    grid-template-rows: 50px 50px;  
}

看到的效果如下:

100px换上1fr

.container {  
    display: grid;  
    grid-template-columns: 1fr 1fr 1fr;  
    grid-template-rows: 50px 50px;  
}

效果如下:

使用repeat()可以让代码更干净:

.container {  
    display: grid;  
    grid-template-columns: repeat(3, 100px);  
    grid-template-rows: repeat(2, 50px);  
}

使用auto-fit做自动填充:

.container {  
    display: grid;  
    grid-gap: 5px;  
    grid-template-columns: repeat(auto-fit, 100px);
    grid-template-rows: repeat(2, 100px);  
}

加上minmax()用一行代码在一些场景中就可以达到响应式效果:

.container {  
    display: grid;  
    grid-gap: 5px;  
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    grid-template-rows: repeat(2, 100px);  
}

有关于repeat()auto-fitminmax()fr更多的介绍,可以阅读:

小结

文章围绕@Bill Mei的《Top 10 most deadly CSS mistakes made by new and experienced developers》进行展开。在Chrome78开始可以使用backdrop-filter实现磨砂玻璃的效果,HTML新增的output元素可以用来表示应用程序执行的计算结果或用户操作的结果;CSS的:not()虽然没有逻辑符来,但可以通过多操作符来组合,达到类似逻辑组合的效果。最后使用@Per制作的几张Gif图简单粗暴的告诉大家如何使用CSS Grid Layout中的repeat()frauto-fitminmax(),从而使用一行代码达到响应式的效果。常用于列表布局的场景中。

最后,希望这一期的内容大家会喜欢。如果你有更好的建议或相关的积累,欢迎在下面的评论中与我们一起分享。