
freeCodeCamp 课程挑战深度解析用ul与li创建无序列表【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp导读本文以 freeCodeCamp 开源课程中 Basic HTML 与 HTML5 模块的经典挑战「Create a Bulleted Unordered List」为主线逐层拆解无序列表ul/li的 HTML 语法、该挑战在课程体系中的位置、其 Markdown 源文件的完整结构以及挑战内置的自动化测试与判定逻辑。读完本文你不仅能掌握在 freeCodeCamp 课程中编写、提交与通过这类 HTML 练习的完整方法还能了解这些挑战文件在 curriculum 目录中的组织方式与校验机制为进一步参与课程建设打下基础。挑战在课程中的定位Basic HTML 与 HTML5 模块本挑战的源文件位于课程树中curriculum/challenges/english/blocks/basic-html-and-html5/bad87fee1348bd9aedf08827.md文件名中的bad87fee1348bd9aedf08827是该挑战的唯一id贯穿课程的排序、测试与用户学习进度记录。从课程的「块结构清单」curriculum/structure/blocks/basic-html-and-html5.json 可以看到本挑战在整个模块的 28 个挑战中排在第 15 位索引 14紧跟「Turn an Image into a Link」之后下一个挑战正是「Create an Ordered List」。id: bad87fee1348bd9aedf08827 title: Create a Bulleted Unordered List challengeType: 0 dashedName: create-a-bulleted-unordered-list这一位置并非偶然学习者此前已掌握h2标题、p段落、img图片、a链接等基础元素本挑战开始引入「列表」这类承载多行内容的结构化语义元素。此前的所有练习都在 CatPhotoApp 这个小猫照片应用页面中进行通过不断追加页面元素让学习者体会真实 HTML 文档的渐进式搭建过程。核心知识点无序列表的基本语法挑战的--description--部分即学习者在页面上看到的概念讲解给出了无序列表的权威定义HTML 提供专门用于创建无序列表dfnunordered lists/dfn即项目符号式列表的元素无序列表以起始标签ul开头随后跟随任意数量的列表项li元素最后以/ul闭合。原文档给出了最精简的示例ul limilk/li licheese/li /ul这段代码会在浏览器中渲染出带项目符号的两行内容milk与cheese。其语义非常明确ulUnordered List表达「一组彼此并列、顺序无关紧要的项目」而liList Item则是其中单个条目。正因如此无序列表非常适合表示购物清单、特性列表、菜单导航这类内容。值得深入理解的是默认渲染规则每个li默认独占一行浏览器自动在其前方渲染实心圆点项目符号disc列表项可以包含任意合法的内联或块级内容如文本、链接、图片项目符号会自动附着在每个li块之前若需要为嵌套列表表达层级可在li内部再次书写完整的ul或ol浏览器会自动切换符号样式并缩进列表属于块级语义结构与p段落一样参与文档流布局。挑战任务与起始代码Seed--instructions--对本挑战提出的任务只有一句话删除页面底部的最后两个p元素并在页面底部创建一个包含三项「猫咪喜爱之物」的无序列表。对应地--seed--中给出了一个不完整的 CatPhotoApp 页面作为编辑起点挑战中的「起始代码」h2CatPhotoApp/h2 main pClick here to view more a href#cat photos/a./p a href#img srchttps://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg altA cute orange cat lying on its back./a pKitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff./p pPurr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched./p /main任务的两个动作分别考查两种能力删除元素移除最后两个大段绕口令式p段落。这是对此前「Delete HTML Elements」挑战所学的巩固新增结构化元素在/main之前补上ul及其三个li考查对本次新知识的即时运用。需要注意任务细节——起始页面已经使用了mainHTML5 语义化标签新列表要放在main内、位于整页最底部以符合「at the bottom of the page」的要求。内置自动化测试逐条解读Hints每个 freeCodeCamp 挑战都会在--hints--中声明多条测试浏览器端实时运行并判定答案是否通过。本挑战共有 5 条 hint分别从结构存在性、数量、标签闭合三个维度验证非常适合用来理解课程的判定思路。1. 必须创建一个ul元素assert.isNotEmpty(document.querySelectorAll(ul));使用document.querySelectorAll(ul)抓取文档中全部ul元素assert.isNotEmpty要求结果非空即页面中至少出现一个无序列表。2.ul中必须有三个liassert.lengthOf(document.querySelectorAll(ul li), 3);querySelectorAll(ul li)选取所有「祖先为ul的li」。注意这里的后代选择器写法排除了嵌套在ol等其它列表容器内的li精确匹配题目对三个列表项的要求。3.ul必须成对闭合assert.match(code,/\/ul/gi); assert.match(code,/ul/gi); assert.strictEqual(code.match(/\/ul/gi).length,code.match(/ul/gi).length);这条 hint 直接对学习者的源代码字符串code变量做正则匹配既要求存在/ul又要求ul与/ul的数量严格相等。/gi中的g表示全局搜索i忽略大小写。由于match在无匹配时返回null前两个断言保证了数量至少为 1第三个断言则防止出现漏写闭合标签的情况。4. 每个li都必须闭合assert.match(code,/\/li/gi); assert.match(code,/li[\s]/gi); assert.strictEqual(code.match(/\/li/gi).length,code.match(/li[\s]/gi).length);li[\s]中的字符组[\s]是关键细节它只匹配「li后紧跟空白或」的写法避免误将li误写成li...something之外的拼接形式同时跳过link这类同样以li开头的标签。此 hint 与上一条配合共同强制学习者养成「开闭标签成对」的严谨习惯。5.li内容不得为空或纯空白assert.isEmpty([...document.querySelectorAll(ul li)].filter((item) item.textContent.trim() ));先筛选出所有文本内容trim()后为空的ul li再断言其集合为空。这阻止了用「空标签凑数量」的偷懒解法确保每个li都承载真实文字内容如 milk、cheese、catnip 等。从源码层面看这种「tests数组中texttestString」的结构正是课程体系对每个挑战的硬性要求。校验该结构的 Joi 模式定义在 curriculum/schema/challenge-schema.jstests: Joi.array() .items( Joi.object().keys({ id: Joi.string().allow(), text: Joi.string().required(), testString: Joi.string().allow().required() }), ... ) .required(),参考答案解析Solution本挑战在--solutions--中提供了官方标准答案h2CatPhotoApp/h2 main pClick here to view more a href#cat photos/a./p a href#img srchttps://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg altA cute orange cat lying on its back./a ul limilk/li limice/li licatnip/li /ul /main该解法的要点在于删除了两个填充文本段落而保留了首段的「cat photos」链接、img图片与main容器——被删的是「最后两个p」不是所有p在main内部末尾新增ul内含三个非空li内容选择了猫咪喜爱的典型事物牛奶、老鼠、猫薄荷与 CatPhotoApp 的主题保持一致所有开闭标签严格成对完全满足 5 条 hint 的判定条件。在源文件中--solutions--是可选的Joi 模式定义solutions: Joi.array().items(...).min(1)可选但为 HTML/CSS 类挑战提供官方解方便学习者在卡关时对照也为课程翻译与版本维护保留权威参照。挑战类型与运行机制从挑战文件到在线编辑器本挑战 frontmatter 中的challengeType: 0并非随意数字。在 packages/shared/src/config/challenge-types.ts 中html类型被定义为0const html 0;同一文件里还定义了该类型对应的视图与提交流程export const viewTypes { [html]: classic, ... }; export const submitTypes { [html]: tests, ... };也就是说challengeType: 0的挑战会以「经典classic」双栏界面呈现左侧是说明面板右侧是内置浏览器与可编辑的 HTML 源码区提交时走tests流程——即学习者点击运行按钮后浏览器加载其页面并执行--hints--中声明的全部测试实时反馈通过或失败状态。课程侧的验收脚本位于 curriculum/src/test/test-challenges.js其中可以看到测试字符串被集中提取、交付给独立的代码求值器执行的关键调用链const testStrings tests.map(test test.testString); const results await evaluator.evaluate(testStrings, 5000);5000表示单个测试的执行超时上限毫秒这从实现层面解释了为什么每条 hint 都应保持轻量、仅做 DOM 断言而不进行耗时计算。对ul与li这类标签的正确性检查正是在「页面在内存浏览器中渲染完成后再对 DOM 与源码字符串执行断言」的机制下完成的。延伸与衔接紧随其后的有序列表挑战本挑战的后续练习是「Create an Ordered List」curriculum/challenges/english/blocks/basic-html-and-html5/bad87fee1348bd9aedf08828.md它把无序列表延伸为有序列表ol liGarfield/li liSylvester/li /ol该挑战要求学习者在同一页面中同时维护一个Things cats love:无序列表与一个Top 3 things cats hate:有序列表其 hint 中包含了「同一类列表只能有一个」的校验assert.lengthOf(document.querySelectorAll(ul), 1); assert.lengthOf(document.querySelectorAll(ol), 1);对比两个相邻挑战可以看到课程编排的匠心同一个li列表项语法通过更换容器标签ul/ol实现「项目符号」与「序号」两种截然不同的视觉与语义效果帮助学习者举一反三。若想系统性回顾本模块前后的 HTML 知识点可浏览同目录下的其它挑战文件如删除元素、添加图片、锚点链接、表单与按钮等或对照 curriculum/structure/blocks/basic-html-and-html5.json 中的完整challengeOrder列表了解全貌。给学习者的通关要点与给课程贡献者的参考对学习者的实操建议可归纳为三步检查法先删后增严格按指令删除「最后两个p」不要误删其他内容也不要忘记在/main之前追加内容成对书写ul与每个li都务必书写闭合标签这是 hint 中最容易被正则拦下的失分点填充真实内容每个li都要有可见文本避免提交空条目。而对希望为课程贡献新挑战的开发者而言本文件是理解「经典 HTML 挑战」作者格式的最佳样例frontmatter 提供元数据id、title、challengeType、dashedName等随后依次是--description--概念讲解、--instructions--任务描述、--hints--text加testString的断言数组、--seed--起始代码与可选的--solutions--官方答案。复制本文件并替换其中各部分内容再配合 curriculum/schema/challenge-schema.js 中的字段约束自检即可生成一份格式合法、能被课程工具链识别的新挑战。本挑战中的所有要求都能在--hints--中找到可直接运行的验证代码这种「文档即数据、测试即约束」的组织方式正是 freeCodeCamp 课程体系能够支撑大规模多语言协作维护的基石。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考