<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ 技术 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ 技术 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 04 Jun 2026 20:19:26 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/tag/tech/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 28关学会HTML与HTML5基础 ]]>
                </title>
                <description>
                    <![CDATA[ 「经历」 我自学前端已经有 6 年多了，自问当时学前端是没有系统化学习的。一开始边看文档，连滚带爬学 HTML 和 CSS 排版，然后深入研究 JavaScript，因为当时最火的就是 JQuery，所以用了很长一段时间的 JQ。 到了后面遇到有一个项目需要我做 APP 开发，但是不可能去学 IOS 开发和安卓开发，因为项目时间也不可能给我们这么充裕的学习时间。所以当时的我深入分析了几个混合 APP 开发的框架。分析对象包括当时基于 AngularJs 的 Ionic 框架和 React Native。综合考虑最后选择了 Ionic，然后自学了 Angular2。（过程也是踩过成千上万的坑学会的） APP 开发的这个过程让我深入感觉到那时候前端的革命性变化。庞大的前端知识扑面而来，也没有想到前端已经发展到这样一个地步。这段时间让我深刻领会到前端的博大精深，并且被前端这个技术领域深深的吸引住了。 到了后面 Vue 突然开始火了，各大技术公司都开始使用 Vue+Cli 脚手架搭建前端应用。越来越多的企业要求使用 Vue 开发前端应用和 WebAPP。热爱前端的我从来不畏惧需要学更多的 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/28-html-html5-challenges/</link>
                <guid isPermaLink="false">5f114ddadb4be8080eb7126b</guid>
                
                    <category>
                        <![CDATA[ Web ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 技术 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 自学编程 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ 三钻 ]]>
                </dc:creator>
                <pubDate>Thu, 29 Jul 2021 09:20:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2020/07/banner.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h1 id="">「经历」</h1>
<p>我自学前端已经有 6 年多了，自问当时学前端是没有系统化学习的。一开始边看文档，连滚带爬学 HTML 和 CSS 排版，然后深入研究 JavaScript，因为当时最火的就是 JQuery，所以用了很长一段时间的 JQ。</p>
<p>到了后面遇到有一个项目需要我做 APP 开发，但是不可能去学 IOS 开发和安卓开发，因为项目时间也不可能给我们这么充裕的学习时间。所以当时的我深入分析了几个混合 APP 开发的框架。分析对象包括当时基于 AngularJs 的 Ionic 框架和 React Native。综合考虑最后选择了 Ionic，然后自学了 Angular2。（过程也是踩过成千上万的坑学会的）</p>
<p>APP 开发的这个过程让我深入感觉到那时候前端的革命性变化。庞大的前端知识扑面而来，也没有想到前端已经发展到这样一个地步。这段时间让我深刻领会到前端的博大精深，并且被前端这个技术领域深深的吸引住了。</p>
<p>到了后面 Vue 突然开始火了，各大技术公司都开始使用 Vue+Cli 脚手架搭建前端应用。越来越多的企业要求使用 Vue 开发前端应用和 WebAPP。热爱前端的我从来不畏惧需要学更多的知识，既然 Vue 来势汹汹，我也开始深入研究和学习 Vue 开发前端。经过一番折腾 Vue 也上手了。</p>
<p>至今我依然在不停的学习前端无边无际的知识和技术。</p>
<p>最近我发现，现在学习技术容易了很多。有各种技术文章、手摸手教学、线上培训课程和视频，甚至还有全免费的线上学习课程和练习。相比以前从看文档，连滚带爬的在项目中试错式的学习真的是容易多了。</p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「前言」</h1>
<p>我们都深刻知道，如果想在前端走的更远更久，基础知识必须是要牢固的。最近发现一个免费学习编程的网站 <code>freeCodeCamp(🔥)</code> - <a href="https://www.freecodecamp.org"><code>官方版（英文）</code></a> ｜ <a href="https://www.freecodecamp.one"><code>中文社区版</code></a> 。我好学的性格牵动着我的灵魂，忍不住就去研究了一下。我发现里面的课程确实很全面，而且还有实时和实战编程练习。就算是对于零基础的童鞋，也是可以开始学习编程的。</p>
<p>在一个夜深人静的夜晚，我看着电脑思考人生的时候，我灵机一动，要不我开始写一个系列的文章和大家一起闯关进攻前端全方位知识点。没有闯过这些关卡的童鞋，无论前端能力如何，这个可以锻炼我们自己，也可以深入知道我们自己的前端水平和差距。想学习前端的童鞋可以从零开始学习，一起排除困难共同打开前端大门！</p>
<p>使用这个免费网站学习编程，每一个知识学习完成后会给大家发放一个证书，然后每一个关键学习点之后，还有项目实战。自从 2014 年，有超过 4 万个<code>freeCodeCamp</code>毕业的童鞋获得了大企业工作机会。（里面有提到谷歌，苹果，微软，亚马逊，Spotify 等公司）</p>
<p>还有看到一些学员的评价：</p>
<blockquote>
<ul>
<li>“我在实习的时候，导师就叮嘱我在 freeCodeCamp 上做题闯关。技术的精进不仅给了我强大的自信，也让我得以进入大厂 ThoughtWorks。” --- 姜玉珍</li>
<li>“对于还没有形成编程思维的新人，即使是 leetcode 上面 easy 级别的算法题目都感到非常有难度，而 freeCodeCamp 的算法题恰好是一个良好的过渡。” --- 魏朝欣</li>
</ul>
</blockquote>
<p>无论这些证书是否对我们在中国的企业有一定的价值。但是能获得多一个证书，没有什么不好的呀。废话不多说了，我们这里就开始勇闯第一课《基础 HTML 与 HTML5 入门》！</p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「规则」如何一起闯关</h1>
<p>在开始这个闯关的系列之前，讲一下我们具体怎么一起闯关。</p>
<blockquote>
<p><strong>首先</strong>，如果我是单纯在这里给大家发布答案，我觉得这些文章就没有太大意义了。所以我希望在闯关的过程中一起学习到更多的知识，弄懂更深层的技术和用我的相关经验讲说这些知识在工作中的使用场景和小技巧。</p>
<hr>
<p>个人觉得英文版本的操作和体验都更好，加上英文版本的课题会更新。所以我会在英文版中与大家一起闯关。但是喜欢用中文社区版本也是可以的哦。酸甜苦辣各有所爱，但是效果和课题基本都是一样的哈。</p>
</blockquote>
<p><strong>每一篇文章的大概内容：</strong></p>
<ol>
<li>首先我们每一篇文章会尽量包含一个大知识点中的 N 个关卡。每一个知识点的关卡数量不一，所以有时候可能会拆分成几篇文章来讲说。</li>
<li>每一个关卡当中的知识点在 freeCodeCamp 中有一定的知识材料。但是在一起闯关的文章当中也会做一些详细的知识补充和一些有趣的理解方式。</li>
<li>每一个较难的关卡，都会在文章当中做详细的思路，多种实现方式等等的讲说，让我们在每一个关卡中能带走更多深层的知识点。</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h2 id="freecodecamp">freeCodeCamp 使用教程</h2>
<hr>
<h3 id="">课程内容</h3>
<p>FCC 一共有 6 大课程，一共大约 1800 个小时的内容和练习。如果是新人，推荐从第一个开始一个一个闯关学习。如果是老司机，是来这里学习你需要的知识，那可以随意选择你需要的课程开始学习。</p>
<ul>
<li>响应式 Web 设计（300 个小时）</li>
<li>算法和数据结构（300 个小时）</li>
<li>前端库和框架（300 个小时）</li>
<li>数据可视化（300 个小时）</li>
<li>API 和微服务（300 个小时）</li>
<li>信息安全和质量保证（300 个小时）</li>
</ul>
<p>最后还有一个是数千个小时的面试题可以提供给我们使劲的刷哦！</p>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="600" height="400" loading="lazy"></p>
<h3 id="">进入关卡</h3>
<p>首先我们展开第一课看一下：</p>
<p><img src="https://img-blog.csdnimg.cn/20200508151501995.png" alt="20200508151501995" width="2108" height="814" loading="lazy"></p>
<ol>
<li>第 1 点这里是基础知识的文章，可以点击查看。看完基础知识之后可以点击下方的<code>回到第一小节</code>开始闯关！</li>
<li>第 2 点这里下面所有的都是练习题，一个一个顺着闯关即可。</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h3 id="">关卡教程</h3>
<blockquote>
<p>⚠️ 注意：<br>
大家闯关之前，推荐大家都先使用 GitHub 登陆，到时候颁发的证书和闯关进度才能得到保存和跟踪哦！！！</p>
</blockquote>
<p>我们先从左边 👈 部分的内容开始说明：</p>
<ol>
<li>简单讲说了这个关卡涉及的知识点</li>
<li>描述关卡的挑战内容</li>
<li>本关卡的所有目标，点击测试代码的时候，完成的会出现 ✅，没有全部 ✅ 那就是还有部分我们没有实现哦。所有 ✅ 才能通关。</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504234332698.png" alt="20200504234332698" width="1358" height="1596" loading="lazy"></p>
<p>接下来就是说明中间的代码区：</p>
<ol>
<li>代码区，用于编写我们这个关卡的代码。</li>
<li>错误输出区域，当我们点击<code>测试代码</code>后，如果有错误就会显示在这里。</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504234641496.png" alt="20200504234641496" width="1386" height="1600" loading="lazy"></p>
<p>最后，最右边的部分是代码被编译后的效果，也就是我们在代码去编写的代码最终会在浏览器呈现出来的效果哦。（这里的效果会在我们编写代码的同时触发变化哦！）</p>
<p><img src="https://img-blog.csdnimg.cn/2020050423175522.png" alt="2020050423175522" width="950" height="350" loading="lazy"></p>
<p>提交代码/测试成功后：</p>
<p><img src="https://img-blog.csdnimg.cn/20200504234802981.png" alt="20200504234802981" width="1816" height="1258" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「知识」闯关基础知识点</h1>
<blockquote>
<p><strong>HTML 是什么？</strong><br>
HTML 的全称是 HyperText Markup Language（超文本标签语言），它是一种用来描述网页结构的标签语言。<br>
它采用一种特殊的语法或符号来组织网页的内容，元素通常都有开始标签和结束标签，例如标题、段落、列表。</p>
</blockquote>
<h2 id="html">更好的理解 HTML</h2>
<p>对于没有计算机基础的童鞋（就算是有）都会觉得有点抽象，不太好理解。我们换一个说法来理解一下：</p>
<blockquote>
<p>HTML 就等同于我们人体里面的骨架，一块一块骨头（标签）组装起来建立起一个人的骨架和结构。比如说经常可以见到的<code>head</code>，<code>body</code>，<code>footer</code>等标签，就等同于一个人的<code>头</code>，<code>身体</code>和<code>脚</code>。那其他的标签比如<code>h1</code>，<code>h2</code>，<code>div</code>，<code>section</code>和<code>ul</code>，<code>li</code>等标签就是用来组建我们人体每一个部位的小骨头。</p>
</blockquote>
<center><img src="https://img-blog.csdnimg.cn/2020050417151024.png" width="614" height="1384" alt="2020050417151024" loading="lazy"></center>
<p>如果 HTML 加上了 JavaScript（人体中的大脑和肌肉）就可以操控整个人的动作，让一个人活起来了。但是只有骨头和肌肉，这个也太难看了吧？想想都觉得吓人。所以我们会有皮肤来把这些不太好看的东西藏起来，这个时候就需要在 HTML 中使用 CSS（人体的皮肤）。这样子我们有好的皮肤加上衣服和化妆品的打扮，这样才可以貌美如花嘛对吧？</p>
<center><img src="https://img-blog.csdnimg.cn/20200504165855630.png" width="940" height="572" alt="20200504165855630" loading="lazy"></center>
<p>如果我们上面说的骨头和骨架，在代码中又是什么样子的呢？我们一起来看看：</p>
<pre><code class="language-html">&lt;h1&gt;Top level heading: Maybe a page title&lt;/h1&gt;

&lt;p&gt;
  A paragraph of text. Some information we would like to communicate to the viewer. This can be as
  long or short as we would like.
&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Number one on the list&lt;/li&gt;
  &lt;li&gt;Number two&lt;/li&gt;
  &lt;li&gt;A third item&lt;/li&gt;
&lt;/ol&gt;
</code></pre>
<p>这段代码被编译后就会在浏览器呈现出这个样子：</p>
<p><img src="https://img-blog.csdnimg.cn/20200504180352518.png" alt="20200504180352518" width="1736" height="468" loading="lazy"></p>
<h2 id="html5">HTML5 又是什么？</h2>
<p>HTML 这种超文本源自于 Web 早期和最初的用例。当时页面都是静态文档，并且文档中也有连接和引用到其他的文档。通过浏览器中的 hypertext links（超文本链接）在文档之中跳转与导航。这样用户就可以自由的在文档之中翱翔，不用在文档直接搜索查看。</p>
<p>后期 web 页面和 web 应用渐渐变得越来越复杂，W3C 更新了 HTML 的规范来让所有的浏览器更加兼容彼此。为什么呢？大家应该都知道市面上有五花八门的各种浏览器，如果每一个浏览器都对 HTML 有不同的写法，不同的规范，那我们做前端开发的，有多少的浏览器规范我们就需要学会多少种写法。不用后浪推上来，已经累死在沙滩上了。</p>
<p>那 HTML5 其实就是第五版的 HTML 规范，也是目前最新的版本。</p>
<p>基础知识弄懂了，我们马上就来开始闯关吧！GO GO GO！</p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html">「第一关」用 HTML 元素与世界问好</h1>
<blockquote>
<p>关卡名：<code>Say Hello to HTML Elements</code></p>
</blockquote>
<p>身在技术领域的童鞋们都知道，入门任何语言的开头都是先与世界问个好（所谓的输出一个"Hello World"）。所以第一关当然是用 HTML 元素与世界问好啦！😂</p>
<h5 id="">知识点</h5>
<ul>
<li>这一关我们看到代码区域有<code>&lt;h1&gt;hello&lt;/h1&gt;</code>这一段代码，这个就是所谓的 HTML 元素了！也就是人体中的一小块骨头 🦴！。</li>
<li>HTML 中每一个标签都需要开始与结束标签：<code>&lt;h1&gt;</code> 为开始，<code>&lt;/h1&gt;</code> 为结束。</li>
<li>开始与结束标签的区别，就是结束标签多了<code>/</code>（斜杠）。</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>修改开始标签<code>&lt;h1&gt;</code>与关闭标签<code>&lt;/h1&gt;</code>之间的内容。</li>
<li>把内容从<code>Hello</code>改为<code>Hello World</code>。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>HTML 中的开始与结束标签的格式与规范</li>
<li>标签的内容是什么</li>
<li>如何修改标签内容</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232647107.png" alt="20200508232647107" width="1492" height="368" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="h2">「第二关」使用 H2 元素加入副标题</h1>
<blockquote>
<p>关卡名：<code>Headline with the h2 Element</code></p>
</blockquote>
<p>接下来的几个关卡中，我们会慢慢的一步一步的搭建一个 HTML5 的 <strong>“猫星人图片的网页应用”</strong>。</p>
<h5 id="">知识点</h5>
<ul>
<li><code>h2</code>元素是常用的副标题，其实就是比<code>h1</code>字体要小的标题，用过<code>WPS</code>或者<code>word</code>文档的童鞋应该秒懂了。</li>
<li>这些标题标签会告诉浏览器去显示一些默认的标题样式</li>
<li><code>h1</code>一般用于网页大标题，而<code>h2</code>就是用于副标题。</li>
<li>其实在 HTML 当中还有很多自带的标题元素，例如<code>h3</code>，<code>h4</code>，<code>h5</code>和<code>h6</code>，每一个代码一个等级的副标题，这里数字越大，标题的大小就越小哦。</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>在<code>h1</code>标签后面（第二行）加入一个<code>h2</code>标签。</li>
<li>并且在<code>h2</code>元素中加入<code>CatPhotoApp</code>的文字内容。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>创建一个<code>h2</code>元素</li>
<li><code>h2</code>元素必须有一个结束标签</li>
<li><code>h2</code>元素必须含有"<strong>CatPhotoApp</strong>"的文字内容</li>
<li><code>h1</code>元素必须含有"<strong>Hello World</strong>"的文字内容</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>什么是副标题</li>
<li>HTML 有哪些副标题</li>
<li>如何加入副标题</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232620883.png" alt="20200508232620883" width="1492" height="406" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第三关」段落元素加入信息内容</h1>
<blockquote>
<p>关卡名：<code>Inform with the Paragraph Element</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li><code>p</code>是<code>paragragh</code>（段落）的缩写，就是我们在写文章中的段落一样，一般都是用来放信息内容的。</li>
<li>我们可以用<code>&lt;p&gt;我是一个p标签&lt;/p&gt;</code>，这样的方式来加入段落元素。</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>在我们的<code>h2</code>元素下方加入<code>p</code>元素。</li>
<li>在<code>p</code>元素的内容中加入文字"<strong>Hello Paragraph</strong>"。</li>
<li>注意：HTML 的规范中说明，<strong>所有标签的英文字母都必须使用小写！</strong></li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>代码中必须有一个规范的<code>p</code>元素。</li>
<li><code>p</code>元素中必须含有文字"<strong>Hello Paragraph</strong>"。</li>
<li><code>p</code>元素必须有一个结束标签。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li><code>p</code>元素是什么</li>
<li>如何加入信息内容段落</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232551519.png" alt="20200508232551519" width="1492" height="444" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第四关」加入“占位”文字</h1>
<blockquote>
<p>关卡名：<code>Fill in the Blank with Placeholder Text</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>开发者们用一个传统，就是在没有内容的时候，排版时都会用统一的占位文字“<strong>lorem ipsum text</strong>”。很多人很好奇，为什么都用这个？</li>
</ul>
<blockquote>
<p>Lorem ipsum 从 15 世纪开始就被广泛地使用在西方的印刷、设计领域中，在电脑排版盛行之后，这段被传统印刷产业使用几百年的无意义文字又再度流行。由于这段文字以“Lorem ipsum”起头，并且常被用于标题的测试中，所以一般称为 Lorem ipsum，简称为 Lipsum。</p>
<hr>
<p>原先大家以为这段拉丁文只是没有意义的组合，目的是让阅读者不要被文章内容所影响，而只专注于观察字型或版型，并借此填满空间。但根据美国拉丁学者 Richard McClintock 的研究，Lorem ipsum 原来起源于西赛罗《善恶之尽》（De finibus bonorum et malorum）第一章（Liber Primus）的 32、33 两节。</p>
</blockquote>
<ul>
<li>这段占位文字用了 5 个世纪也是够长情的了，既然我们这些关卡是在搭建一个“猫星人”的应用，那么我们改为“<strong>kitty ipsum text</strong>”。😁</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>把<code>p</code>元素的内容替换成这一段占位文字：“<strong>Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.</strong>”</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>p</code>元素需要含有“<strong>kitty ipsum text</strong>”的首几个单词。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>什么是“<strong>lorem ipsum text</strong>”</li>
<li>为什么“<strong>lorem ipsum text</strong>”经常用于设计和排版的占位文案</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232456551.png" alt="20200508232456551" width="2048" height="558" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html">「第五关」清除 HTML 代码注释</h1>
<blockquote>
<p>关卡名：<code>Uncomment HTML</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>代码注释是为了在代码中留下备注的一种常用写法。通常为了给自己和其他开发者留下有意义的备注，让大家可以更容易的懂得代码的作用或者含义。代码注释是不会影响代码的运行，或者是显示出来给到用户看到的。</li>
<li>代码注释还有一个非常使用的目的，就是屏蔽代码。被注释的代码就不会被编译器运行，这样被注释的代码就不会生效了。</li>
<li>不同语言有不同的注释写法，HTML 的注释写法开始是<code>&lt;!--</code>，结束使用<code>--&gt;</code>。例如：<code>&lt;!-- &lt;p&gt; abc &lt;/p&gt; --&gt;</code>。</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>此关卡的代码都被注释掉了，所以所有的代码都没有生效。（预览区可以看到是空白的）</li>
<li>我们需要清除掉这里的注释，让<code>h1</code>，<code>h2</code>和<code>p</code>元素生效。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>页面预览区需要可以看到<code>h1</code>元素内容</li>
<li>页面预览区需要可以看到<code>h2</code>元素内容</li>
<li>页面预览区需要可以看到<code>p</code>元素内容</li>
<li>页面中没有遗漏结束注释标签<code>--&gt;</code></li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>什么是代码注释</li>
<li>代码注释有什么作用</li>
<li>如何清除代码注释</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232414817.png" alt="20200508232414817" width="2048" height="558" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html">「第六关」局部 HTML 代码注释</h1>
<blockquote>
<p>关卡名：<code>Comment out HTML</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>上一关我们看到可以把整个代码注释掉，但是其实很多时候我们可能需要注释掉局部的代码，或者是多段代码。</li>
<li>使用方式也是一样的，在想开始注释的地方加入<code>&lt;!---</code>，然后结束的地方加入<code>--&gt;</code>。</li>
</ul>
<blockquote>
<p>⚠️ 注意：<br>
在注释代码的时候要注意的一个点，HTML 的元素都是有开始与结束标签的，注释的过程中如果我们注释掉半个元素，那代码就会有结束没有开头了。这样是会报错的哦。同等概念，后面我们会学到，HTML 元素是可以加入属性的，属性也是无法单独注释的。</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>注释掉整个<code>h1</code>元素和<code>p</code>元素，<code>h2</code>元素要生效。（也可以说页面上只能看到<code>h2</code>这个元素的效果）</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>h1</code>元素应该被注释掉，页面看不到该元素效果</li>
<li><code>p</code>元素应该被注释掉，页面看不到该元素效果</li>
<li>页面预览区需要可以看到<code>h2</code>元素内容</li>
<li>每一段注释都应该有结束注释标签<code>--&gt;</code></li>
<li><code>h1</code>，<code>h2</code>和<code>p</code>元素在代码中的顺序不能变</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何局部注释代码</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232349471.png" alt="20200508232349471" width="2048" height="634" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html">「第七关」删除 HTML 元素</h1>
<blockquote>
<p>关卡名：<code>Delete HTML Elements</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>场景：因为手机的屏幕高度可呈现的空间不多，所以我们要把<code>h1</code>元素删除掉。</li>
</ul>
<blockquote>
<p>⚠️ 注意：<br>
删除代码和注释代码都有一个一样的原则。就是开始与结束的标签不能缺了其中之一，要不代码就会报错。所以删除元素的时候也要注意元素的开始与结束标签的完整性。</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>删除掉代码中的<code>h1</code>元素，让我们的页面更加整洁和更有空间感。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>h1</code>元素应该被完整的被删除</li>
<li>页面预览区需要可以看到<code>h2</code>元素内容</li>
<li>页面预览区需要可以看到<code>p</code>元素内容</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何正确的删除元素</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232309358.png" alt="20200508232309358" width="2048" height="482" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html5">「第八关」HTML5 元素</h1>
<blockquote>
<p>关卡名：<code>Introduction to HTML5 Elements</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>HTML5 给我们带来了更多具备丰富代表性的 HTML 标签。这些标签包括<code>main</code>（主要内容）、<code>header</code>（头部）、<code>footer</code>（脚步）、<code>nav</code>（导航）、<code>video</code>（视频）、<code>article</code>（文章）、<code>section</code>（区域/分段内容）和更多。</li>
<li>这些标签给 HTML 的结构带来了更多可描述性的意义。就好像人体也有很多代表性的结构与区域名称，比如说：肱骨、股骨、腕骨、肩胛和不规则骨等等。</li>
<li>人体的骨头要分类，也是为了让医生更好的在大量的骨头中找到或者描述到具体的那种骨头。那 HTML5 中的这些丰富的标签也是一样的。他们可以更好的帮助<code>搜索引擎</code>找到对应的内容，加入这些标签也让我们的网页做到更好的<strong>搜索引擎优化（SEO）</strong>。</li>
</ul>
<blockquote>
<p><strong>什么是搜素引擎？</strong><br>
我们可以把搜索引擎看作是一本很大很大的书中的目录。我们想想在现代的互联网中，全世界有多少个网站或者网页应用？如果没有一个目录让我们可以搜索，我们怎么可以找到我们想看的内容或者网站？可以说基本是不可能的！</p>
<hr>
<p><strong>搜索引擎怎么运作？</strong><br>
那搜索引擎的目录是怎么生成的呢？这个世界有一种很厉害的虫，那就是"爬虫"。每天搜索引擎的公司会派出成千上万的爬虫军队出去，在互联网上到处找网站，然后进入每一个网站中阅读里面的内容。然后收集回来的内容会经过做过滤和分析，然后建立关键词等等，最后生成一个搜索目录。我们经常用的搜索引擎包括：百度搜索，谷歌搜索，搜狗搜素，360 搜素等等。</p>
</blockquote>
<p>用其中一个标签来举例，一个<code>main</code>元素中嵌套了两个子元素：</p>
<pre><code class="language-html">&lt;main&gt;
  &lt;h1&gt;Hello World&lt;/h1&gt;
  &lt;p&gt;Hello Paragraph&lt;/p&gt;
&lt;/main&gt;
</code></pre>
<blockquote>
<p>小贴士：这些 HTML5 的标签的作用和适用性会在后面的“Applied Accessibility（应用无障碍）”的课程中详细讲说。</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>在原有的<code>p</code>元素下方添加一个新的<code>p</code>元素，并且加入这段内容<code>Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.</code></li>
<li>然后用一个<code>main</code>元素两个<code>p</code>元素包裹起来。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>应该有 2 个<code>p</code>元素，每个都有文字内容</li>
<li>每个<code>p</code>元素都有结束标签</li>
<li>第二个<code>p</code>元素的内容含有“Purr jump eat...”这段文字</li>
<li>代码中必须含有<code>main</code>元素</li>
<li><code>main</code>元素中必须含有两个<code>p</code>子元素</li>
<li><code>main</code>元素开始必须在第一个<code>p</code>元素之前</li>
<li><code>main</code>元素结束必须在第二个<code>p</code>元素之后</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>学到了更多丰富的 HTML5 标签</li>
<li>学会使用<code>main</code>元素</li>
<li>学会嵌套元素</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/2020050823222173.png" alt="2020050823222173" width="2048" height="634" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第九关」网站中插入图片</h1>
<blockquote>
<p>关卡名：<code>Add Images to Your Website</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>我们可以通过使用<code>img</code>元素为我们的网页插入图片，然后使用元素中的<code>src</code>属性来指定图片地址。</li>
</ul>
<blockquote>
<p>⚠️ 注意：<code>img</code>元素是不需要结束标签的，它是属于自动关闭型元素。</p>
</blockquote>
<ul>
<li>W3C 规范中，所有<code>img</code>必须填写<code>alt</code>属性（alt 是“<strong>Alternative</strong>”的缩写，就是“<strong>替代</strong>”的意思）。当一个图片无法加载或者显示时，<code>alt</code>属性的值就会替代这个图片显示出来。</li>
<li>另外<code>alt</code>对于搜索引擎优化是有一定的帮助的，因为这个属性是用来描述一个图片的。如果这个图片是一只猫，对于搜索引擎的爬虫会针对图片的 Alt 取得关于这个图片的描述。这样搜索引擎才能知道这个图片大概是什么。</li>
</ul>
<blockquote>
<p>⚠️ 注意：</p>
<ul>
<li>如果图片是单纯为了装饰的，那<code>alt</code>就留空：<code>alt=""</code></li>
<li>尽量不要在<code>alt</code>属性中加入特殊字符（或者符号），除非是必须的</li>
</ul>
</blockquote>
<p>一个完整的<code>img</code>元素例子如下：</p>
<pre><code class="language-html">&lt;img
  src="https://www.your-image-source.com/your-image.jpg"
  alt="Author standing on a beach with two thumbs up."
/&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>在<code>main</code>元素中的<code>p</code>元素之前添加<code>img</code>元素。</li>
<li><code>img</code>元素的<code>src</code>属性的值指向<code>https://bit.ly/fcc-relaxing-cat</code></li>
<li>给予<code>img</code>元素的<code>alt</code>属性一个合适的名字：比如“Kitty” (小猫咪的意思)</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>页面中必须有一个<code>img</code>元素。</li>
<li><code>img</code>元素中的<code>src</code>属性指向一个猫咪的图片地址。</li>
<li><code>img</code>元素中的<code>alt</code>属性值不能为空。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何使用<code>img</code>图片元素</li>
<li>懂得使用<code>src</code>属性</li>
<li>懂得使用<code>alt</code>属性</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232128378.png" alt="20200508232128378" width="2048" height="672" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十关」使用锚元素实现链接跳转</h1>
<blockquote>
<p>关卡名：<code>Link to External Pages with Anchor Elements</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>在 HTML 当中，<code>a</code> (锚) 元素是用于跳转页面，可以是内部页面或者是外部页面。（内部指的是本网站内的页面，外部指的是本网站以外的其他网站的页面。）</li>
<li><code>a</code> 元素需要一个网页地址的属性叫<code>href</code>。也需要一个 anchor text（锚文字）：</li>
</ul>
<blockquote>
<p>例如：<br>
<code>&lt;a href="https://freecodecamp.org"&gt;这个链接会跳转到 freecodecamp.org&lt;/a&gt;</code></p>
<ul>
<li>网页地址：<a href="https://freecodecamp.org">https://freecodecamp.org</a></li>
<li>锚文字（其实就是跳转链接的文案）：这个链接会跳转到 freecodecamp.org</li>
</ul>
</blockquote>
<ul>
<li>使用以上例子，在浏览器中就会显示一段文字链接 “这个链接会跳转到 freecodecamp.org”，点击该链接就会跳转到<strong><a href="https://www.freecodecamp.org">https://www.freecodecamp.org</a></strong>这个网址。</li>
</ul>
<blockquote>
<p>额外知识点：<br>
以上例子讲说的是跳转外部链接，如果我想跳转当前网址的子页面呢？(所谓的内部跳转，但是其实还可以做到当前页面的位置跳转，这个下一个关卡就会学到咯！)</p>
<ul>
<li>比如现在我们当前的页面是"www.freecodecamp.org"，我们的链接想跳转到“www.freecodecamp.org/learn”。</li>
<li>这个时候我们的<code>a</code>元素的<code>href</code>属性可以这么写</li>
</ul>
</blockquote>
<pre><code class="language-html">&lt;a href="/learn"&gt;这个链接会跳转到 freecodecamp.org/learn&lt;/a&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>创建一个<code>a</code>元素，链接文案为“cat photos”，并且指定跳转到<code>http://freecatphotoapp.com</code></li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>a</code>元素的链接文案必须含有“cat photos”</li>
<li><code>a</code>元素的跳转地址必须是<code>http://freecatphotoapp.com</code>。</li>
<li><code>a</code>元素必须有结束标签。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何在网页中添加链接</li>
<li>懂得使用<code>href</code>属性</li>
<li>懂得如何添加链接文案</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508232040589.png" alt="20200508232040589" width="2048" height="748" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十一关」使用锚元素跳转内部页面区域</h1>
<blockquote>
<p>关卡名：<code>Link to Internal Sections of a Page with Anchor Elements</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li><code>a</code>（锚）元素还可以用于跳转页面内部的特定区域。</li>
<li>创建一个内部跳转链接，首先我们需要在<code>href</code>属性的值中绑定一个哈希符号<code>#</code>和一个唯一<code>id</code>属性。</li>
<li><code>id</code>属性是在 HTML 中任何一个元素都可以绑定的唯一标识。<code>id</code>属性可以给予一个元素一个唯一的识别名，让这个元素可以在 HTML 中被选择到。</li>
</ul>
<p>以下是一个内部跳转链接的例子，其中的<code>...</code>代表被省略的一段代码。</p>
<pre><code class="language-html">&lt;a href="#contacts-header"&gt;Contacts&lt;/a&gt;
...
&lt;h2 id="contacts-header"&gt;Contacts&lt;/h2&gt;
</code></pre>
<blockquote>
<p><strong>我们来分析一下这个例子：</strong></p>
<ul>
<li>这里的<code>h2</code>元素被绑定了一个<code>id</code>属性，名字为“contacts-header”。</li>
<li>我们的<code>a</code>元素链接的指定<code>href</code>跳转地址为<code>#contacts-header</code>。</li>
<li>我们可以看到<code>#</code>后面的名字与<code>h2</code>的<code>id</code>值一致，就是这样点击这个链接的时候，页面就会移动到绑定了同一个名字的元素的位置。</li>
<li>我们要注意的是<code>id</code>属性的值，在当前页面中必须是唯一的。</li>
</ul>
</blockquote>
<blockquote>
<p>知识点：<br>
在这个例子里面，我们可以看到<code>a</code>元素多了一个<code>target</code>属性。这个属性在链接中是非常常用的。我们经常用的各大电商平台，我们点击一个商品的链接都会打开一个新窗口，但是有一些链接就不会。这种就是用<code>target</code>属性控制的。</p>
<hr>
<p><code>target</code>属性的常用值有：</p>
<ul>
<li><strong>_blank</strong>：在新窗口中打开被链接文档。</li>
<li><strong>_self</strong>：默认。在相同的框架中打开被链接文档。</li>
<li><strong>_parent</strong>：在父框架集中打开被链接文档。</li>
<li><strong>_top</strong>：在整个窗口中打开被链接文档。</li>
<li><em>framename</em>：在指定的框架中打开被链接文档。</li>
</ul>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>修改我们的外部跳转链接的<code>href</code>属性为<code>#footer</code>，并且把链接的文案“cat photos”改为"Jump to Bottom"。</li>
<li>移除<code>target="_blank"</code>属性，因为这个属性会让我们的链接在全新的窗口打开这个跳转链接。</li>
<li>最后在页面最底部的<code>footer</code>元素中添加<code>id</code>属性，属性值为"<strong>footer</strong>"。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>页面中必须含有一个锚元素</li>
<li>页面中只有一个 footer 标签</li>
<li><code>a</code>元素的<code>href</code>属性值必须是<code>#footer</code></li>
<li><code>a</code>元素必须没有<code>target</code>属性</li>
<li><code>a</code>元素的链接文章应该是“Jump to Bottom”</li>
<li><code>footer</code>元素的<code>id</code>属性值必须是"footer"</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何在网页中添加内部链接</li>
<li>懂得使用<code>id</code>属性</li>
<li>懂得使用哈希符号链接跳转</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231953144.png" alt="20200508231953144" width="2048" height="1318" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十二关」文章中嵌套锚元素</h1>
<blockquote>
<p>关卡名：<code>Nest an Anchor Element within a Paragraph</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>我们可以在文字中添加链接：</li>
</ul>
<pre><code class="language-html">&lt;p&gt;
  Here's a
  &lt;a target="_blank" href="http://freecodecamp.org"&gt;link to freecodecamp.org&lt;/a&gt;
  for you to follow.
&lt;/p&gt;
</code></pre>
<blockquote>
<p><strong>分析一下这个例子的实现原理：</strong></p>
<ul>
<li>首先我们有一个文字段落<code>&lt;p&gt;Here's a ... for you to follow.&lt;/p&gt;</code></li>
<li>在这个文字段落中"<strong>...</strong>"的部分我们加入<code>a</code> (锚) 元素：<code>&lt;a href="http://freecodecamp.org"&gt; ... &lt;/a&gt;</code>，这里我们用<code>a</code>元素包裹了"<strong>...</strong>"这个文字内容，这样这个文字内容就会变成一个链接，并且可点击跳转网页。（记住这里需要我们有开始<code>&lt;a&gt;</code>与结束<code>&lt;/a&gt;</code>标签，这样才能指定这个链接的开始与结束区域）</li>
<li>这里<code>a</code>元素中加入<code>target="_blank"</code>可以让链接在新窗口打开，<code>href</code>属性指定了跳转链接。</li>
<li>最后"..."的内容在这个例子里面就是" link to freecodecamp.org"，也就是链接的文案（锚文字）。</li>
</ul>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>首先在<code>main</code>元素中加入一个新的<code>p</code>元素。</li>
<li><code>p</code>元素中的文案写入"View more cat photos"。</li>
<li>使用我们原来的<code>a</code>元素替换这段文案中的“cat photos”，从而把这段文案中的"cat photos"改为一个链接。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>a</code>元素的链接需要指定跳转"<a href="http://freecatphotoapp.com">http://freecatphotoapp.com</a>"</li>
<li><code>a</code>元素的链接文案应该是“cat photos”</li>
<li><code>a</code>元素需要被<code>p</code>元素包裹着，然后<code>main</code>元素中需要一共有 3 个<code>p</code>元素</li>
<li><code>a</code>元素需要被新的<code>p</code>元素包裹着，不能是其他的<code>p</code>元素</li>
<li><code>p</code>元素中必须含有“View more ” （more 后面需要含有一个空格）</li>
<li><code>a</code>元素中不能含有“View more”等文字</li>
<li>所有<code>p</code>元素必须有结束标签</li>
<li>所有<code>a</code>元素必须有结束标签</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>在文章段落中添加链接</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231849358.png" alt="20200508231849358" width="2048" height="786" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十三关」使用哈希符号创建死链接</h1>
<blockquote>
<p>关卡名：<code>Make Dead Links Using the Hash Symbol</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>有时候我们需要添加一个死链接（顾名思义，就是一个点击后无效的链接，不会触发页面跳转）</li>
<li>这种链接有几个用途，第一种在排版的过程中还不知道需要链接哪里，第二种就是后面这个链接交给 JavaScript 处理。（后面的 JavaScript 关卡中会讲到哦）</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;a href="#"&gt;死链接&lt;/a&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>当前的<code>a</code>元素中的<code>href</code>是指向一个链接地址"<a href="http://freecatphotoapp.com">http://freecatphotoapp.com</a>"</li>
<li>把<code>href</code>属性值改为<code>#</code>，就可以把这个锚元素变成一个死链接</li>
<li>这里还需要把<code>target</code>属性移除掉，要不还是会跳转页面的</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>a</code>元素的<code>href</code>属性值是<code>#</code>，是一个死链接</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>用哈希符号创建死链接</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231802953.png" alt="20200508231802953" width="2048" height="748" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十四关」把图片变成链接</h1>
<blockquote>
<p>关卡名：<code>Turn an Image into a Link</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>我们可以通过用<code>a</code>元素包裹一个元素，让这个元素变成一个链接</li>
<li>比较常用的一个例子就是使用<code>a</code>元素包裹一个<code>img</code>元素，这样就可以把一个图片变成一个链接。（也就是说，点击这个图片就可以跳转页面了）</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;a href="#"&gt;
  &lt;img src="https://bit.ly/fcc-running-cats" alt="Three kittens running towards the camera." /&gt;
&lt;/a&gt;
</code></pre>
<blockquote>
<p>这个例子中，我们希望这个图片的链接是一个"死链接"，所以<code>href</code>属性的值需要使用<code>#</code>。</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>用<code>a</code>元素包裹页面中的<code>img</code>元素</li>
<li>改变后，我们在最右边的预览区把鼠标放到图片上方，我们可以看到我们的鼠标从一个“<strong>普通鼠标志</strong>”变成一个“<strong>点击手指的标志</strong>”</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>img</code>元素需要包裹在<code>a</code>元素之中</li>
<li>图片的链接必须是一个死链接</li>
<li>所有的<code>a</code>元素必须有结束标签</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>给图片添加链接</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231725267.png" alt="20200508231725267" width="2048" height="824" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十五关」创建无序列表</h1>
<blockquote>
<p>关卡名：<code>Create a Bulleted Unordered List</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>HTML 当中有特殊的元素用于创建无序列表。</li>
<li>无序列表需要使用<code>ul</code>元素包裹着多个<code>li</code>元素，开始标签为<code>&lt;ul&gt;</code>，结束标签为<code>&lt;/ul&gt;</code>。</li>
</ul>
<p>*代码例子：**</p>
<pre><code class="language-html">&lt;ul&gt;
  &lt;li&gt;牛奶&lt;/li&gt;
  &lt;li&gt;芝士&lt;/li&gt;
&lt;/ul&gt;
</code></pre>
<p>这段代码就会创建一个无序列表，列表内容有“牛奶”与“芝士”。</p>
<h5 id="">过关目标</h5>
<ul>
<li>移除代码中最后两个<code>p</code>元素。</li>
<li>然后添加一个<strong>无序列表</strong>，列出 3 个喵咪喜爱的东西。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>创建一个<code>ul</code>元素</li>
<li><code>ul</code>元素应该包裹着 3 个<code>li</code>元素</li>
<li><code>ul</code>元素必须有结束标签</li>
<li>所有<code>li</code>元素必须有结束标签</li>
<li><code>li</code>元素中必须有内容，也不能是只有空格</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>ul</code>元素</li>
<li>使用<code>li</code>元素</li>
<li>创建无序列表</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231648984.png" alt="20200508231648984" width="1952" height="786" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十六关」创建有序列表</h1>
<blockquote>
<p>关卡名：<code>Create an Ordered List</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>HTML 当中还有一种叫有序列表（就是前面会按照 1，2，3，4... 以此类推）</li>
<li>需要使用<code>ol</code>元素包裹着多个<code>li</code>元素，开始标签为<code>&lt;ol&gt;</code>，结束标签为<code>&lt;/ol&gt;</code></li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;ol&gt;
  &lt;li&gt;肥猪&lt;/li&gt;
  &lt;li&gt;肥牛&lt;/li&gt;
&lt;/ol&gt;
</code></pre>
<p>以上这段代码会创建一个有序列表，有序的列出“肥猪”和“肥牛”。</p>
<h5 id="">过关目标</h5>
<ul>
<li>在“<strong>Top 3 things cat hate:</strong>”的<code>p</code>元素下方加入一个有序列表</li>
<li>有序列表中列出 3 样喵咪讨厌的东西</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>有一个有序列表列出 3 样喵咪讨厌的东西</li>
<li>有一个无序列表列出 3 样喵咪喜欢的东西</li>
<li>只有一个<code>ul</code>元素</li>
<li>只有一个<code>ol</code>元素</li>
<li><code>ul</code>元素中有 3 个<code>li</code>元素</li>
<li><code>ol</code>元素中有 3 个<code>li</code>元素</li>
<li>所有<code>li</code>元素必须有结束标签</li>
<li>所有<code>li</code>元素的内容不能为空或者只有空格</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>ol</code>元素</li>
<li>创建有序列表</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231613451.png" alt="20200508231613451" width="1952" height="1052" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十七关」创建文本输入框</h1>
<blockquote>
<p>关卡名：<code>Create a Text Field</code></p>
</blockquote>
<h5 id="">知识点</h5>
<p>接下来的几个关卡，我们一起来创建一个表单。</p>
<blockquote>
<p><strong>什么是表单？</strong></p>
<p>表单就是一个网页端的表格，让用户在其中填写信息提交给我们保存起来。在办理事情的时候，我们经常会需要填写表格，然后提交给工作人员。在网络上填写表格也是一样的。用户在表单中填写表格，然后提交给我们保存起来，工作人员在后台管理系统就可以对这些表格进行处理了。</p>
</blockquote>
<ul>
<li>一个表单就必定会有文字填写的地方，在 HTML 中我们会使用<code>input</code>元素来创建一个文本输入框，给到用户填写文字。</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;input type="text" /&gt;
</code></pre>
<blockquote>
<p>知识点：</p>
<ul>
<li><code>input</code>元素是一个自我关闭型标签，所以不需要结束标签的。</li>
<li><code>input</code>元素中有一个<code>type</code>属性，这个是用来定义这个输入框的类型，这里因为我们需要文本类型，所以就是<code>text</code>。那其他类型有什么呢？其他的类型在后面的关卡中会讲到哦。</li>
<li><code>input</code>元素中的<code>name</code>属性也是非常重要的，后端接受表单的输入框数据时，用的就是<code>name</code>属性值来获取数据的。</li>
</ul>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>在有序列表的<code>ol</code>元素下方创建一个<code>input</code>元素，<code>type</code>元素值使用“<strong>text</strong>”</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>需要有一个<code>input</code>元素，<code>type</code>属性值为<code>text</code></li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>input</code>元素创建文本输入框</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="600" height="400" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/2020050823152167.png" alt="2020050823152167" width="1952" height="1090" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十八关」文本输入框中添加占位文本</h1>
<blockquote>
<p>关卡名：<code>Add Placeholder Text to a Text Field</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>占位文本（Placeholder）也叫输入框提示语，这段文字会在用户为输入前在输入框中显示。</li>
</ul>
<p><strong>我们可以用以下方式加入占位文本：</strong></p>
<pre><code class="language-html">&lt;input type="text" placeholder="这个是占位文本/提示语" /&gt;
</code></pre>
<blockquote>
<p>⚠️ 记住：</p>
<p><code>input</code>元素是自我结束型元素，不需要结束标签哦！</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li>在<code>input</code>元素当中添加<code>placeholder</code>属性，属性值为"cat photo URL"</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>input</code>元素中有<code>placeholder</code>属性</li>
<li><code>placeholder</code>的属性值必须为“<strong>cat photo URL</strong>”</li>
<li><code>input</code>元素不需要有结束标签</li>
<li><code>input</code>元素语法不能有误</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>在<code>input</code>元素中添加<code>placeholder</code>属性</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/2020050823143732.png" alt="2020050823143732" width="1952" height="1090" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第十九关」创建一个表单元素</h1>
<blockquote>
<p>关卡名：<code>Create a Form Element</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>我们知道在现实生活中，提交一个表单/表格，只需要填写好后递交给一个人就可以了。但是在网页中的表单是怎么提交让我们保存起来的呢？</li>
<li>其实也很简单，我们首先创建一个<code>form</code>元素来建立一个表单，然后在<code>form</code>元素中添加一个<code>action</code>属性，并且给他一个提交的地址即可。</li>
</ul>
<blockquote>
<p><strong>小知识：</strong></p>
<p>我们知道现实中我们会把表格提交给工作人员，那在网页中我们提交给谁呢？我们用一个简单接地气的例子来理解一下：</p>
<ul>
<li>首先表格的内容都是电子化数据不是纸质的，那肯定是要提交给一个电子化储存的地方</li>
<li>电子化储存的地方就是服务器，也就是一台电脑</li>
<li>但是总要有一个<code>人</code>这样的东西接收我们的表单吧？是的，操控这个服务器的就是<code>后端</code></li>
<li>所以表单的<code>action</code>顾名思义是一个提交动作，表单需要指定给一个“人”来接收，在网络上就是“服务器地址或者后端地址”</li>
<li>我们再想想现实中，工作人员拿到我们的表格，会存放到文件仓库对吧？那在网络应用中电子表单的数据放哪里呢？</li>
<li>表单数据提交给到后端之后，后端会拿着这个数据储存到<code>数据库</code>中，数据库也就是文件库了</li>
</ul>
<p>通过这个例子大家应该可以能理解表单数据提交和储存的概念了。也更能懂得这个<code>action</code>背后的基本逻辑是什么了。</p>
</blockquote>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;form action="/url-where-you-want-to-submit-form-data"&gt;
  ...
&lt;/form&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>把我们的<code>input</code>元素包裹在<code>form</code>元素之中，然后在<code>form</code>元素中加入<code>action</code>属性值“<strong>/submit-cat-photo</strong>”</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>文本输入框应该包裹在<code>form</code>元素之中</li>
<li><code>form</code>元素需要有<code>action</code>属性值为“/submit-cat-photo”</li>
<li><code>form</code>元素需要有完整的开始与结束标签</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何完成使用表单</li>
<li>使用表单<code>form</code>元素</li>
<li>懂得<code>action</code>属性的意义和用法</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231340182.png" alt="20200508231340182" width="1952" height="1166" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第二十关」添加表单提交按钮</h1>
<blockquote>
<p>关卡名：<code>Add a Submit Button to a Form</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>用户输入了表单中的信息，但是没有一个提交的按钮，这个信息是不会自动提交到服务端的</li>
<li>所以我们需要在表单中加入<code>button</code>元素（按钮元素），并且给它的<code>type</code>属性一个“<code>submit</code>（提交动作）”的类型</li>
<li>用户点击这个按钮就会提交表格中所有输入框内的信息</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>在<code>form</code>元素中的最后添加<code>button</code>元素，类型为<code>submit</code></li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>表单元素中必须含有一个按钮</li>
<li><code>button</code>元素必须有一个<code>type</code>属性值为<code>submit</code></li>
<li><code>button</code>元素中的文字内容必须是"Submit"</li>
<li><code>button</code>元素必须有结束标签</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>button</code>元素</li>
<li>如果添加提交表单按钮</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231256383.png" alt="20200508231256383" width="1952" height="1204" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第二十一关」设置一个输入框为必填 ​</h1>
<blockquote>
<p>关卡名：<code>Use HTML5 to Require a Field</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>我们可以让表单中某个特定的输入框变成必填，如果用户没有填写是无法提交表单的</li>
<li>举例，现在我们需要一个文本输入框变成必填项，我们只需要在<code>input</code>元素中添加一个<code>require</code>属性</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;input type="text" required /&gt;
</code></pre>
<blockquote>
<p>⚠️ 注意：<code>input</code>元素中的<code>require</code>属性是不需要填写属性值的，只要加入这个属性就起效了。</p>
</blockquote>
<h5 id="">过关目标</h5>
<ul>
<li><code>input</code>元素加入<code>required</code>属性，把输入框变成一个必填项，用户如果没有填写内容将无法提交表单</li>
<li>加入后尝试在输入框中没有填写内容时点击"Submit"按钮，看看 HTML5 时如何提醒我们必填内容未完成的。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li><code>input</code>元素应该有一个<code>required</code>属性</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>input</code>元素中的<code>required</code>属性</li>
<li>给表单加入必填输入框</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231219256.png" alt="20200508231219256" width="1952" height="1204" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第二十二关」添加一组单选按钮</h1>
<blockquote>
<p>关卡名：<code>Create a Set of Radio Buttons</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>当我们在表单中询问用户一个问题，并且希望用户只给出多选一的答案。这个时候我们就可以使用<em>单选按钮</em>。</li>
<li>单选按钮是<code>input</code>元素中其中一种类型。</li>
<li>要使用单选按钮，我们需要把每一个单选的<code>input</code>元素包裹在一个<code>label</code>元素中。这时<code>label</code>元素就会与<code>input</code>元素绑定上。意思就是<code>label</code>中的任何文字，在点击的时候都可以选中这个选项。</li>
<li>所有相关的单选项需要有同一个<code>name</code>属性值才能把这些单选项组成一组选项。</li>
<li>单选项被列为一组后，才能选择这组其中一个单选项时，才会自动去除选中其他这组里面的选项。</li>
</ul>
<p><strong>单选按钮的例子：</strong></p>
<pre><code class="language-html">&lt;label&gt;
  &lt;input type="radio" name="indoor-outdoor" /&gt;
  内门
&lt;/label&gt;
</code></pre>
<ul>
<li>最佳实践是在<code>label</code>元素上设置一个<code>for</code>属性，其值与输入元素的<code>id</code>属性值相匹配。这允许辅助技术在标签和子<code>input</code>元素之间创建链接关系。例如:</li>
</ul>
<pre><code class="language-html">&lt;label for="indoor"&gt;
  &lt;input id="indoor" type="radio" name="indoor-outdoor" /&gt;
  Indoor
&lt;/label&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>添加一对<code>radio</code>单选按钮到我们的表单中，每个需要有自己的<code>label</code>元素包裹着。</li>
<li>一个选项显示为<code>indoor</code>和另外一个选项显示<code>outdoor</code>。</li>
<li>两个选项的<code>name</code>属性值都必须是<code>indoor-outdoor</code>，从而把它们组成一组。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>需要有两个<code>radio</code>元素的单选按钮</li>
<li><code>radio</code>元素的单选按钮都需要有<code>name</code>属性值为<code>indoor-outdoor</code></li>
<li>两个<code>radio</code>元素的单选按钮都需要有自己的<code>label</code>元素包裹着</li>
<li>每个<code>radio</code>元素都有结束标签</li>
<li>一个单选为<code>indoor</code></li>
<li>一个单选为<code>outdoor</code></li>
<li>所有<code>radio</code>元素都必须在<code>form</code>元素之内</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>label</code>元素</li>
<li>使用<code>input</code>元素中的<code>radio</code>类型</li>
<li>如何组合一组单选项</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508231133820.png" alt="20200508231133820" width="1952" height="1432" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第二十三关」添加一组复选框</h1>
<blockquote>
<p>关卡名：<code>Create a Set of Checkboxes</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>表单中，通常用<code>checkbox</code>来建立复选框的表单问题。</li>
<li><code>checkbox</code>是<code>input</code>元素的其中一种类型。</li>
<li>要使用复选框，我们需要把每一个复选框的<code>input</code>元素包裹在一个<code>label</code>元素中。这时<code>label</code>元素就会与<code>input</code>元素绑定上。意思就是<code>label</code>中的任何文字，在点击的时候都可以选中这个选项。</li>
<li>所有相关的复选框需要有同一个<code>name</code>属性值才能把这些选项组成一组选项。</li>
<li>与单选的原理相同：最佳实践是在<code>label</code>元素上设置一个<code>for</code>属性，其值与输入元素的<code>id</code>属性值相匹配。这允许辅助技术在标签和子<code>input</code>元素之间创建链接关系</li>
</ul>
<p><strong>复选框例子：</strong></p>
<pre><code class="language-html">&lt;label for="loving"&gt;
  &lt;input id="loving" type="checkbox" name="personality" /&gt;
  Loving
&lt;/label&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>在<code>form</code>元素内添加一组 3 个<code>checkbox</code>类型的复选框。</li>
<li>每一个复选框的<code>input</code>都要有自己的<code>label</code>包裹着。</li>
<li>三个复选框都需要使用同一个<code>name</code>属性值为<code>personality</code>。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>需要有 3 个复选框元素。</li>
<li>每个复选框元素必须包裹着在自己的<code>label</code>元素内。</li>
<li>每一个<code>label</code>元素都需要有结束标签。</li>
<li>所有复选框都需要用同一个<code>name</code>属性值为<code>personality</code>。</li>
<li>所有复选框都需要添加在<code>form</code>元素之中。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>input</code>元素中的<code>checkbox</code>类型</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508230712438.png" alt="20200508230712438" width="2014" height="1546" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="value">「第二十四关」复选框与单选框中使用 value</h1>
<blockquote>
<p>关卡名：<code>Delete HTML Elements</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>当一个表单提交时，表单所有的数据会发送到服务端（后端），这里也包括我们选择的选择框数据。</li>
<li><code>checkbox</code>复选框和<code>radio</code>单选框的选中数据也是会一起提交到服务端，那后端怎么判定我们选中了那些呢？</li>
<li>无论是复选还是单选，后端接收到的都是选中的选项输入框<code>value</code>属性的值。</li>
<li>所有我们需要给每一个<code>checkbox</code>或者<code>radio</code>类型的输入框一个<code>value</code>属性。</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;label for="indoor"&gt;
  &lt;input id="indoor" value="indoor" type="radio" name="indoor-outdoor" /&gt;
  Indoor
&lt;/label&gt;
&lt;label for="outdoor"&gt;
  &lt;input id="outdoor" value="outdoor" type="radio" name="indoor-outdoor" /&gt;
  Outdoor
&lt;/label&gt;
</code></pre>
<p>以上例子中，我们有两个<code>radio</code>单选框类型的输入框。假设用户选中了"Outdoor"并且提交了表单，表单数据中会含有<code>indoor-outdoor=outdoor</code>这样的参数。<code>indoor-outdoor</code>这部分来源于这个输入框的<code>name</code>属性，然后<code>outdoor</code>就是用户选中的选项的<code>value</code>属性值。</p>
<p>如果我们没有填写<code>value</code>属性值，用户选中了任何一个选项然后提交表单。后端接收到的数据就是<code>indoor-outdoor=on</code>。这个数据里面只能告诉我们<code>indoor-outdoor</code>这个选项，用户有选中一个值，但是是什么，我们不知道。这样这个表单的数据就没有任何意义了。所以我们一定要给每一个选项<code>input</code>元素加入一个<code>value</code>属性值。</p>
<h5 id="">过关目标</h5>
<ul>
<li>给每一个<code>radio</code>和<code>checkbox</code>输入框类型的元素一个<code>value</code>属性值。</li>
<li>这里<code>value</code>属性值常规来说我们<strong>都是用英文的</strong>，在这个例子中因为我们的选项本身就是英文，所以我们直接用选项名作为<code>value</code>的值即可。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>其中一个<code>radio</code>的<code>value</code>属性值需要是”<strong>indoor</strong>“</li>
<li>其中一个<code>radio</code>的<code>value</code>属性值需要是”<strong>outdoor</strong>“</li>
<li>其中一个<code>checkbox</code>的<code>value</code>属性值需要是”<strong>loving</strong>“</li>
<li>其中一个<code>checkbox</code>的<code>value</code>属性值需要是”<strong>lazy</strong>“</li>
<li>其中一个<code>checkbox</code>的<code>value</code>属性值需要是”<strong>energetic</strong>“</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>value</code>属性</li>
<li>给<code>radio</code>或者<code>checkbox</code>加上<code>value</code>属性值</li>
<li>多选项或者单选项数据提交的原理</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508230558471.png" alt="20200508230558471" width="2014" height="1394" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「第二十五关」默认选中单选框/复选框</h1>
<blockquote>
<p>关卡名：<code>Check Radio Buttons and Checkboxes by Default</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>很多时候，表单当中都会有默认选中值。</li>
<li>如果我们想默认选中单选项中的其中一个，或者是默认选中复选项中的几个怎么实现呢？</li>
<li>想默认选中，我们只需要在<code>radio</code>或者<code>checkbox</code>的<code>input</code>元素中添加<code>checked</code>属性即可（这个也是一个不需要属性值的属性）</li>
</ul>
<p><strong>代码例子：</strong></p>
<pre><code class="language-html">&lt;input type="radio" name="test-name" checked /&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>把<code>radio</code>单选框组合的第一个单选项设置为默认选中。</li>
<li>把<code>checkbox</code>复选框组合的第一个复选项设置为默认选中。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>单选框组合的第一个单选项默认被选中</li>
<li>复选框组合的第一个复选项默认被选中</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>给<code>radio</code>单选项或者<code>checkbox</code>复选项添加默认选中属性<code>checked</code></li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508230402201.png" alt="20200508230402201" width="2014" height="1850" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="div">「第二十六关」将许多元素嵌套在单个 div 元素中</h1>
<blockquote>
<p>关卡名：<code>Nest Many Elements within a Single div Element</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li><code>div</code>元素，也称为分割元素，是其他元素的通用容器。</li>
<li><code>div</code>元素也是最常用的 HTML 元素之一。</li>
<li>与其他非自我结束元素一样，可以使用<code>div</code>元素来开始，然后在另一行使用<code>&lt;/div&gt;</code>来结束。</li>
</ul>
<h5 id="">过关目标</h5>
<ul>
<li>嵌套“Things cats love”和“Things cats hate”的两个列表到<code>div</code>元素之中</li>
</ul>
<blockquote>
<p>提示：把<code>&lt;div&gt;</code>开始标签放在"Things cats love"的<code>p</code>元素上方，然后<code>&lt;/div&gt;</code>结束标签在<code>&lt;/ol&gt;</code>的下方。最后整个<code>div</code>元素把所有内容包裹起来。</p>
</blockquote>
<h5 id="">过关条件</h5>
<ul>
<li><code>p</code>元素内容被包裹在<code>div</code>元素之中</li>
<li><code>ul</code>元素内容被包裹在<code>div</code>元素之中</li>
<li><code>ol</code>元素内容被包裹在<code>div</code>元素之中</li>
<li><code>div</code>元素必须有结束标签</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>使用<code>div</code>元素分割内容</li>
<li>使用<code>div</code>元素嵌套多个元素</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200508235036344.png" alt="20200508235036344" width="2048" height="1660" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="htmldoctype">「第二十七关」声明 HTML 文档的 Doctype</h1>
<blockquote>
<p>关卡名：<code>Declare the Doctype of an HTML Document</code></p>
</blockquote>
<h5 id="">知识点</h5>
<p>到目前为止，我们闯过的关卡当中包括了特定的 HTML 元素以及使用。但是那些都是一个完成 HTML 页面的其中一部分。其实还有一些元素是每一个 HTML 页面都需要存在的。</p>
<p>在文章的顶部我们需要告诉浏览器，我们需要使用哪一个版本的 HTML。HTML 这个语言一直在持续更新升级。各大浏览器基本都兼容最新的配置与版本（那就是 HTML5）。但是还有一些浏览器只兼容一些历史版本的 HTML（例如旧版本的 IE 浏览器）。</p>
<ul>
<li>要告诉浏览器我们需要使用那个版本的 HTML，我们需要在 HTML 文件的头部添加<code>&lt;!DOCTYPE ...&gt;</code>，这里的<code>...</code>可以写入 HTML 的某个版本。如果是 HTML5 的话，那就是<code>&lt;!DOCTYPE html&gt;</code>即可。</li>
<li>在这个声明的代码中<code>!</code>和<code>DOCTYPE</code>都是非常重要的，而<code>DOCTYPE</code>也是必须大写的。然后<code>html</code>这个就无大小写限制了。</li>
<li>跟着这段文件 HTML 版本声明就是<code>html</code>元素。所有我们网页的代码和元素都必须在<code>html</code>元素内编写。</li>
</ul>
<p><strong>HTML 代码例子：</strong></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;!-- Your HTML code goes here --&gt;
&lt;/html&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>在代码区域第一行，加入<code>DOCTYPE</code>声明，并且选择使用 HTML5 版本。</li>
<li>声明后加入<code>html</code>元素，并且在<code>html</code>元素内嵌套一个<code>h1</code>标题元素。</li>
<li><code>h1</code>标题元素内必须含有一个标题文案，文案可以随意填写。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>代码中必须含有<code>&lt;!DOCTYPE html&gt;</code>标签。</li>
<li>代码中必须含有<code>html</code>元素。</li>
<li><code>html</code>元素必须包裹着一个<code>h1</code>元素。</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>如何声明 HTML 版本</li>
<li>使用<code>html</code>标签</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200509000812981.png" alt="20200509000812981" width="1492" height="482" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="html">「第二十八关」定义 HTML 文档的头部和主体</h1>
<blockquote>
<p>关卡名：<code>Define the Head and Body of an HTML Document</code></p>
</blockquote>
<h5 id="">知识点</h5>
<ul>
<li>在标准的 HTML 文档结构中，我们需要丰富这个基础结构的分区。</li>
<li>所以在<code>html</code>元素中我们会分出<code>head</code>头部元素和<code>body</code>主体元素。</li>
<li>所有<strong>CSS 引用，字体引用，网页标题</strong>等等这些网页定义的内容都是放在<code>head</code>元素之内。</li>
<li>然后所有页面的布局元素都需要放在<code>body</code>元素之内。</li>
</ul>
<blockquote>
<p>小贴士：</p>
<p>我们用一个一个更好的理解方式，让我们更容易记住这个规则的原理。</p>
<ul>
<li>如果我们想一下，所有的知识，思想，印象等等就等同于 HTML 当中的"<strong>CSS 引用，字体引用，网页标题</strong>"，那东西是不是都应该在我们的脑袋里面呢？所以呀“<strong>CSS 引用，字体引用，网页标题</strong>”都应该放在<code>head</code>头部元素中！</li>
<li>我们的骨头和骨架是不是在我们身体内呢？所以剩下所有的页面布局代码就要放在<code>body</code>主体元素中！</li>
</ul>
</blockquote>
<p><strong>HTML 结构代码例子：</strong></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;!-- metadata elements --&gt;
    &lt;!-- CSS引用，字体引用，网页标题等等元素 --&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;!-- page contents --&gt;
    &lt;!--页面的布局元素 --&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h5 id="">过关目标</h5>
<ul>
<li>代码区域里面有<code>title</code>页面标题元素，<code>h1</code>文章标题元素和<code>p</code>文章段落元素。</li>
<li>把<code>title</code>元素嵌套到一个<code>head</code>元素中。</li>
<li>剩余的<code>h1</code>和<code>p</code>的内容都嵌套到一个<code>body</code>元素中。</li>
</ul>
<h5 id="">过关条件</h5>
<ul>
<li>只有一个<code>head</code>元素</li>
<li>只有一个<code>body</code>元素</li>
<li><code>head</code>元素需要被<code>html</code>元素包裹着</li>
<li><code>body</code>元素需要被<code>html</code>元素包裹着</li>
<li><code>title</code>元素需要被<code>head</code>元素包裹着</li>
<li><code>h1</code>和<code>p</code>元素都需要被<code>body</code>元素包裹着</li>
</ul>
<h5 id="">学会了什么？</h5>
<p>这关卡主要教会我们：</p>
<ol>
<li>建立完成的 HTML 文档结构</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20200504230328260.png" alt="20200504230328260" width="1920" height="100" loading="lazy"></p>
<h5 id="">答案</h5>
<p><img src="https://img-blog.csdnimg.cn/20200509002635302.png" alt="20200509002635302" width="2048" height="1052" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/2020050422480843.png" alt="2020050422480843" width="1920" height="250" loading="lazy"></p>
<h1 id="">「终」总结</h1>
<p><img src="https://img-blog.csdnimg.cn/20200509083941200.png" alt="20200509083941200" width="1714" height="658" loading="lazy"></p>
<p>恭喜大家一起闯过 28 关。我们学习到了 HTML 与 HTML5 的基础知识。虽然说这些都是很基础的知识，可以说闯过这 28 关，前端入门级别都还没有到。但是庞大与伟大的事业和建筑物都是从稳固的基础建立起来的。无论是多么简单还是无比困难的任务，我们都需要耐心和细心对待，把每一件小事都做到极致，才能逐步壮大，成功才会在远方等着我们。</p>
<p>下一期，我们开始第二课，深入浅出 CSS 基础。一起继续闯关打怪，打开前端技术大门。敬请期待哦！</p>
<blockquote>
<p>我是<font color="#60AAF8"><b>三钻</b></font>，一个在<font color="#60AAF8"><b>技术银河</b></font>中和你们一起来终身漂泊学习。<br>
想看更多技术知识文章关注个人微信公众号《<strong>技术银河</strong>》！<br>
有问题可以在公众号留言咨询哦！下期再见 👋！</p>
</blockquote>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Golang 依赖注入(Dependency Injection) ]]>
                </title>
                <description>
                    <![CDATA[  * Dependency Injection 🧪 * 工程意图     * 简化程序     * 初始化工程     * Test     * 运行测试     * 总结         1. Dependency Injection 🧪 依赖注入是目前很多优秀框架都在使用的一个设计模式。 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/golang-dependency-injection/</link>
                <guid isPermaLink="false">5d77122cfbfdee429dc5fbbc</guid>
                
                    <category>
                        <![CDATA[ 技术 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 开发者 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 自学编程 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ 谷中仁 ]]>
                </dc:creator>
                <pubDate>Tue, 10 Sep 2019 03:03:18 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2019/09/chalk-chalkboard-exam-459793--1--1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <ul>
<li><a href="#dependency-injection-%F0%9F%A7%AA">Dependency Injection 🧪</a>
<ul>
<li><a href="#%E5%B7%A5%E7%A8%8B%E6%84%8F%E5%9B%BE">工程意图</a></li>
<li><a href="#%E7%AE%80%E5%8C%96%E7%A8%8B%E5%BA%8F">简化程序</a></li>
<li><a href="#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A5%E7%A8%8B">初始化工程</a></li>
<li><a href="#test">Test</a></li>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%B5%8B%E8%AF%95">运行测试</a></li>
<li><a href="#%E6%80%BB%E7%BB%93">总结</a></li>
</ul>
</li>
</ul>
<!-- /TOC -->
<h1 id="1dependencyinjection">1. Dependency Injection 🧪</h1>
<p>依赖注入是目前很多优秀框架都在使用的一个设计模式。<br>
Dependency Injection 常常简称为：DI。它是实现控制反转（Inversion of Control – IoC）的一个模式。</p>
<p>在各种大工程中少不了各种测试，其中 TDD 就是非常流行的一种，在前端开发中用的比较多的 <a href="https://github.com/facebook/jest">Jest</a> 就是一种，在 Golang 开发命令行工具的时候也是需要 DI 这种模式来实现命令行测试的。因为传统的测试室获取不到命令行的输入输出的。</p>
<h2 id="11">1.1. 工程意图</h2>
<p>仓库：<a href="https://github.com/guzhongren/TDD/tree/master/10.dependency-injection">https://github.com/guzhongren/TDD/tree/master/10.dependency-injection</a><br>
编写一个命令行工具库，打包并运行程序，根据工具名称后面的名称来显示 <code>'Hello, + 名称'</code>。</p>
<h2 id="12">1.2. 简化程序</h2>
<p>我们知道 golang 打包后就是一个可执行程序，程序名称根据你指定的名称显示，那么要实现这个工具就是需要接收到程序名后面的参数并显示出来。但本次的重点是实现 DI, 所以我们将重点放在命令行的测试与实现上。<br>
我们只实现 Greet 函数的 DI 就可以了。</p>
<h2 id="13">1.3. 初始化工程</h2>
<pre><code class="language-shell">go mod init dependency-injection
</code></pre>
<p>按照惯例，测试的函数需要以 Test 开头，参数为 *testing.T 类型</p>
<h2 id="14test">1.4. Test</h2>
<ul>
<li>测试先行</li>
</ul>
<pre><code class="language-go">func TestGreet(t *testing.T) {
	// 申明 buffer，准备接受数据， 因为bytes.Buffer， 重点：bytes.Buffer实现了 io.Writer
	buffer := bytes.Buffer{}
	// 将buffer 传入，此时就是依赖注入的入口，
	Greet(&amp;buffer, "chris")
	// 获取程序运行的结果
	got := buffer.String()
	// 期望值
	want := "Hello, chris"
	// 测试判断
	if got != want {
		t.Errorf(`got %s, want %s`, got, want)
	}
}
</code></pre>
<ul>
<li>
<p>运行 <strong>go test</strong>, 程序会报错，因为没有实现 Greet 函数。</p>
</li>
<li>
<p>最小化的实现 Repeat</p>
</li>
</ul>
<pre><code class="language-go">// Greet 打印问候
func Greet(w io.Writer, name string) {
	fmt.Fprintf(w, "Hello, "+name)
}
</code></pre>
<p>重点说明，命令行的测试需要将结果打印在命令行窗口中，如果没有测试，我们可以用 fmt.Printf 等打印函数将结果打印出来，但是，<br>
测试需要拿到打印的内容，就需要将内容用标准输出；当然可以变相的先用其他打印函数将结果打印出来，然后再将结果 return 出去，<br>
在测试中，接受返回值，再比较；这样做不标准而已，学了今天内容其实就可以用 DI 来解决了。</p>
<h2 id="15">1.5. 运行测试</h2>
<ul>
<li>基本测试</li>
</ul>
<pre><code class="language-shell">$ go test
PASS
ok      dependency-injection    0.006s
</code></pre>
<h2 id="16">1.6. 总结</h2>
<p>基本测试很简单，不用解读了。作为开发者，我们应该用最直接的工具来保证我们程序的健壮性，而不一定要绕个弯来解决问题，如上面的打印结果的测试。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Golang 基准测试（Benchmark） ]]>
                </title>
                <description>
                    <![CDATA[ 简介 > 基准测试是对计算机系统的性能的测试。 在程序中，基准测试，是一种测试代码性能的方法；比如有一个问题你有多种不同的方案，你想选择一种性能最好的方案，那么你就需要基准测试。 > 基准测试主要是通过测试 CPU 和内存的效率问题，来评估被测试代码的性能，进而找到更好的解决方案。比如链接池的数量不是越多越好，那么哪个值才是最优值呢，这就需要配合基准测试不断调优了。 工程意图 仓库： https://github.com/guzhongren/TDD/tree/master/09.benchmar 根据输入的字符串和重复次数，输出重复次数后的字符串。 初始化工程 go mod init benchmark 测试的函数需要以 Test 开头，参数为 *testing.T 类型 Test  * 测试先行 # 测试 Repeat 函数 func TestRepeat(t *testing.T) { 	actual := Repeat(`a`, 6) 	expect := `aaaaaa` 	if actual != expect { 		t.Errorf(`expect ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/golang-benchmark/</link>
                <guid isPermaLink="false">5d69e90bfbfdee429dc5fa1f</guid>
                
                    <category>
                        <![CDATA[ 技术 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 开发者 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ 自学编程 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ 谷中仁 ]]>
                </dc:creator>
                <pubDate>Tue, 10 Sep 2019 02:58:37 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2019/09/chalk-chalkboard-exam-459793--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="">简介</h2>
<blockquote>
<p>基准测试是对计算机系统的性能的测试。</p>
</blockquote>
<p>在程序中，基准测试，是一种测试代码性能的方法；比如有一个问题你有多种不同的方案，你想选择一种性能最好的方案，那么你就需要基准测试。</p>
<blockquote>
<p>基准测试主要是通过测试 CPU 和内存的效率问题，来评估被测试代码的性能，进而找到更好的解决方案。比如链接池的数量不是越多越好，那么哪个值才是最优值呢，这就需要配合基准测试不断调优了。</p>
</blockquote>
<h2 id="">工程意图</h2>
<p>仓库： <a href="https://github.com/guzhongren/TDD/tree/master/09.benchmar">https://github.com/guzhongren/TDD/tree/master/09.benchmar</a></p>
<p>根据输入的字符串和重复次数，输出重复次数后的字符串。</p>
<h2 id="">初始化工程</h2>
<pre><code class="language-shell">go mod init benchmark
</code></pre>
<p>测试的函数需要以 Test 开头，参数为 *testing.T 类型</p>
<h2 id="test">Test</h2>
<ul>
<li>测试先行</li>
</ul>
<pre><code class="language-go"># 测试 Repeat 函数
func TestRepeat(t *testing.T) {
	actual := Repeat(`a`, 6)
	expect := `aaaaaa`
	if actual != expect {
		t.Errorf(`expect %s, but got %s`, expect, actual)
	}
}
</code></pre>
<ul>
<li>
<p>运行 <strong>go test</strong>, 程序会报错，因为没有实现 Repeat 函数。</p>
</li>
<li>
<p>最小化的实现 Repeat</p>
</li>
</ul>
<pre><code class="language-go">// Repeat return a string with same char
func Repeat(char string, count int) (result string) {
	for i := 0; i &lt; count; i++ {
		result += char
	}
	return
}
</code></pre>
<p>上面的函数中 return 并没有返回值，是因为，在 Repeat 函数的返回值部分有一个result，<br>
当返回值是函数体里面的值的时候，可以不用写返回值，go 程序自动将该值返回。但return 依旧不能省略。</p>
<h2 id="benchmark">Benchmark</h2>
<p>基准测试的函数名须以 Benchmark 开头， 参数须为 *testing.B；循环中的 b.N， go 会根据系统情况生成，不用用户设定。</p>
<pre><code class="language-go">func BenchmarkRepeat(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		Repeat(`b`, 5)
	}
}

</code></pre>
<h2 id="">运行测试</h2>
<ul>
<li>基本测试</li>
</ul>
<pre><code class="language-shell">$ go test
PASS
ok      benchmark       0.006s
</code></pre>
<p>基本测试很简单，不用解读了。</p>
<ul>
<li>基准测试</li>
</ul>
<pre><code class="language-shell">$ go test -bench=. -run=none
goos: darwin
goarch: amd64
pkg: benchmark
BenchmarkRepeat-12      10000000               116 ns/op
PASS
ok      benchmark       1.297s
</code></pre>
<p>运行基准测试也要使用go test命令，不过我们要加上-bench=标记，它接受一个表达式作为参数，匹配基准测试的函数，. 表示运行所有基准测试。</p>
<p>因为默认情况下 go test 会运行单元测试，为了防止单元测试的输出影响我们查看基准测试的结果，可以使用-run=匹配一个从来没有的单元测试方法，过滤掉单元测试的输出，我们这里使用none，因为我们基本上不会创建这个名字的单元测试方法。</p>
<p>下面着重解释下说出的结果，看到函数后面的-12了吗？这个表示运行时对应的 GOMAXPROCS 的值。接着的 10000000 表示运行 for 循环的次数，也就是调用被测试代码的次数，最后的 116 ns/op表示每次需要话费 116 纳秒。<br>
以上是测试时间默认是1秒，也就是1秒的时间，调用 10000000 次，每次调用花费 116 纳秒。如果想让测试运行的时间更长，可以通过 -lunchtime 指定，比如5秒。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
