├── .github └── workflows │ └── mkdocs.yml ├── .gitignore ├── README.md ├── docs ├── CNAME ├── ai-ml │ ├── NLP.md │ ├── adversarial-search.md │ ├── index.md │ ├── pytorch.md │ ├── 现代概率机器学习初步.md │ └── 神经网络.md ├── backend │ ├── crawler │ │ └── crawler.md │ ├── django │ │ └── django.md │ ├── expressjs │ │ └── express-js.md │ ├── go │ │ └── go.md │ └── index.md ├── basic │ ├── git.md │ ├── index.md │ ├── latex.md │ ├── linux.md │ ├── markdown.md │ ├── meet-problems.md │ ├── vscode.md │ └── web.md ├── courses │ └── index.md ├── frontend │ ├── android │ │ ├── components.md │ │ ├── extensions.md │ │ ├── index.md │ │ ├── resources.md │ │ ├── structure.md │ │ └── useful-things.md │ ├── index.md │ ├── react │ │ ├── basic.md │ │ ├── dataflow.md │ │ ├── extensions.md │ │ ├── function-component.md │ │ ├── index.md │ │ ├── lifecycle.md │ │ └── prepare.md │ ├── swiftui │ │ ├── build-views.md │ │ ├── data-flow.md │ │ ├── declaritive-mvvm.md │ │ ├── extensions.md │ │ ├── hello-world.md │ │ └── index.md │ ├── web │ └── web_foundation │ │ ├── Readme.md │ │ ├── css.md │ │ ├── foundation.md │ │ ├── html.md │ │ ├── hw.pdf │ │ └── javascript.md ├── hardware │ ├── cod.md │ └── index.md ├── index.md ├── languages │ ├── c-oop │ │ ├── behavioral-pattern.md │ │ ├── class-advanced.md │ │ ├── class-easy.md │ │ ├── combination-and-derivation.md │ │ ├── environment.md │ │ ├── function-object-and-smart-pointers.md │ │ ├── function.md │ │ ├── index.md │ │ ├── polymorphism-and-templates.md │ │ ├── reference-copy.md │ │ ├── stl-and-string.md │ │ ├── templates-and-intro-to-stl.md │ │ └── virtual-function.md │ ├── css │ │ ├── bootstrap.md │ │ ├── index.md │ │ └── mdui.md │ ├── html.md │ ├── index.md │ ├── java │ │ ├── advanced-language-feature.md │ │ ├── basic-language-structure.md │ │ ├── design-patterns.md │ │ ├── fundamental-oop.md │ │ ├── index.md │ │ └── introduction-and-installation.md │ ├── javascript │ │ ├── async.md │ │ ├── browser.md │ │ ├── control.md │ │ ├── function.md │ │ ├── index.md │ │ ├── oop-advance.md │ │ ├── oop.md │ │ └── variable.md │ ├── modern-cpp.md │ ├── node.js │ │ ├── index.md │ │ └── npm.md │ ├── python │ │ ├── crawler.md │ │ ├── index.md │ │ └── pip.md │ ├── rust │ │ ├── control.md │ │ ├── function.md │ │ ├── generics.md │ │ ├── index.md │ │ ├── matching.md │ │ ├── ownership.md │ │ ├── reference.md │ │ ├── start.md │ │ ├── struct.md │ │ ├── trait.md │ │ ├── variable.md │ │ └── whyrust.md │ ├── swift │ │ ├── basic.md │ │ ├── control-flow.md │ │ ├── extensions.md │ │ ├── generics.md │ │ ├── index.md │ │ ├── internal-types.md │ │ ├── types.md │ │ └── variable-function.md │ └── typescript │ │ ├── function.md │ │ ├── index.md │ │ ├── oop.md │ │ ├── type.md │ │ └── variable.md ├── notes │ ├── editor.md │ └── reader.md ├── source │ ├── basic-tutorial.md │ ├── book.md │ ├── index.md │ ├── lecture.md │ └── source.md └── static │ ├── ai-ml │ ├── adversarial-search │ │ ├── minmax.png │ │ └── montecarlo.png │ ├── nlp │ │ ├── 1-id.png │ │ ├── 10-bert.png │ │ ├── 11-gpt.png │ │ ├── 12-self.png │ │ ├── 13-cross.png │ │ ├── 14-special.png │ │ ├── 15-multihead.png │ │ ├── 16-groupquery.png │ │ ├── 17-encoder.png │ │ ├── 18-decoder.png │ │ ├── 19-lora.png │ │ ├── 2-embedding.png │ │ ├── 20-finetune.png │ │ ├── 3-cbow.png │ │ ├── 4-cnn.png │ │ ├── 5-rnn.png │ │ ├── 6-distance.png │ │ ├── 7-probs.png │ │ ├── 8-dotproduct.png │ │ └── 9-transformer.png │ └── nn │ │ ├── cnn.png │ │ ├── convolution.png │ │ ├── draw.drawio │ │ ├── fitting.svg │ │ ├── fitting2.png │ │ ├── graph.svg │ │ ├── icon.png │ │ ├── mlp.png │ │ ├── rnn.png │ │ └── wordvec.jpeg │ ├── backend │ ├── crawler │ │ ├── clear-network-log.png │ │ ├── end-of-answers.png │ │ ├── feeds-cursor.png │ │ ├── feeds-detail.png │ │ ├── filter-XHR.png │ │ ├── filter-feeds.png │ │ ├── get-url.png │ │ ├── get-with-cookie.png │ │ ├── get-without-cookie.png │ │ ├── last-page.png │ │ ├── login-XPath.png │ │ ├── login-changed.png │ │ ├── login-posi.png │ │ ├── login-window.png │ │ ├── scrapy-architecture.png │ │ ├── scrapy-startproject.png │ │ └── session-id-in-html.png │ └── django │ │ ├── django-admin-manage-model.png │ │ └── django-admin-panel.png │ ├── basic │ └── web │ │ ├── html1.png │ │ ├── html2.png │ │ ├── html3.png │ │ └── jd1.png │ ├── frontend │ ├── android │ │ ├── layout.png │ │ └── resources.png │ ├── react │ │ ├── lifecycle-flowchart.jpg │ │ ├── lifecycle-methods.png │ │ ├── recursive-render.png │ │ ├── src.zip │ │ └── useeffect-warning.png │ └── swiftui │ │ ├── build-views-button-1.webp │ │ ├── build-views-ex-1.webp │ │ ├── build-views-group-1.webp │ │ ├── build-views-hstack-1.webp │ │ ├── build-views-hstack-2.webp │ │ ├── build-views-image-1.webp │ │ ├── build-views-image-2.webp │ │ ├── build-views-image-3.webp │ │ ├── build-views-image-4.webp │ │ ├── build-views-image-5.webp │ │ ├── build-views-image-6.webp │ │ ├── build-views-image-ori.webp │ │ ├── build-views-label-1.webp │ │ ├── build-views-menu-1.webp │ │ ├── build-views-modifier-1.jpeg │ │ ├── build-views-modifier-2.jpeg │ │ ├── build-views-spacer-1.webp │ │ ├── build-views-text-1.webp │ │ ├── build-views-text-2.webp │ │ ├── build-views-text-3.webp │ │ ├── build-views-text-4.webp │ │ ├── build-views-vstack-1.webp │ │ ├── build-views-zstack-1.webp │ │ ├── build-views-zstack-2.webp │ │ ├── build-views-zstack-3.webp │ │ ├── data-flow-state-1.gif │ │ ├── hello-world-files.jpeg │ │ ├── hello-world-project.jpeg │ │ ├── mvvm-arch.svg │ │ └── mvvm-mv.svg │ └── languages │ ├── css │ ├── 0.html │ ├── 1-after.html │ ├── 1-before.html │ ├── 2.html │ ├── 3.html │ └── 4.html │ ├── html │ ├── 0.html │ ├── 1.html │ ├── 2.html │ ├── 3.html │ └── 4.html │ ├── java │ ├── compile-and-run.png │ └── create-new-project.png │ ├── javascript │ ├── dom-html.html │ ├── event-1.html │ ├── event-2.html │ ├── event-3.html │ ├── function-proto.png │ ├── proto-proto.png │ └── proto-triangle.png │ └── swift │ └── multiline-string.png ├── mkdocs.yml ├── requirements.txt └── theme ├── main.html └── partials └── comments.html /.github/workflows/mkdocs.yml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 13 | - uses: actions/setup-python@v2 14 | with: 15 | python-version: 3.x 16 | - run: pip install -r requirements.txt 17 | - run: mkdocs gh-deploy --force 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /site/* 2 | .venv 3 | .DS_Store 4 | /__pycache__/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sast-skill-docs 2 | 3 | ## Installation 4 | 5 | ```bash 6 | python3 -m venv .venv 7 | source .venv/bin/activate 8 | pip install -r requirements.txt 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.net9.org -------------------------------------------------------------------------------- /docs/ai-ml/index.md: -------------------------------------------------------------------------------- 1 | # 人工智能 & 机器学习 2 | 3 | 本部分主要介绍人工智能领域相关知识以及可能使用到的框架、工具。 4 | 5 | !!! caution "不完善的条目" 6 | 7 | 我们希望有更多的编写者为这一部分编写文档,尤其是 Pytorch 相关。 -------------------------------------------------------------------------------- /docs/backend/index.md: -------------------------------------------------------------------------------- 1 | # 后端框架 2 | 3 | 本部分主要介绍后端开发时可能使用到的各类框架。 4 | 5 | -------------------------------------------------------------------------------- /docs/basic/index.md: -------------------------------------------------------------------------------- 1 | # 基本技能 2 | 3 | 进入计算机领域的一些基本的学习技能和学习工具,从如何记笔记、码代码,到如何使用好你的电脑、如何管理你的代码,我们希望这里的文档能提供一些帮助。 4 | 5 | !!! caution "不完善的条目" 6 | 7 | 我们希望有更多的编写者为这一部分编写文档。 -------------------------------------------------------------------------------- /docs/basic/markdown.md: -------------------------------------------------------------------------------- 1 | # Markdown 入门 2 | 3 | !!! note "前言" 4 | 5 | Markdown 是一种学习成本较低的轻量级标记语言。它用简单的标记语法代替按钮,因此能省去频繁使用鼠标调整排版的麻烦,为文档编写者提供便利。用 Markdown 编写的内容可导出为 HTML、Word、PDF 等多种格式的文档。由于易读易写,它在 GitHub、简书等网站上也有广泛的应用。 6 | 7 | 通过阅读本文档,读者可以在五分钟内快速学习到常用的 Markdown 标记。更多的内容请移步菜鸟教程。 8 | 9 | 我们强烈建议计算机类的同学们在大一的春季学期学会 Markdown 或 LaTeX 二者中其中之一,因为这将是我们后续实验报告或大作业报告将利用的常用工具。 10 | 11 | 在开始学习 Markdown 语法之前,建议先通过 [Typora 官网](https://typora.io/) 安装好 Typora 编辑器。 12 | 13 | ## 语法 14 | 15 | ### 标题 16 | 17 | 共有 1-6 级标题,使用 `#` 标记。`#` 数量与标题级别对应。注意 `#` 与文字间的空格不可省略。 18 | 19 | ```markdown 20 | #### 四级标题 21 | ##### 五级标题 22 | ###### 六级标题 23 | ``` 24 | 25 | #### 四级标题 26 | ##### 五级标题 27 | ###### 六级标题 28 | 29 | ### 字体 30 | 31 | ```markdown 32 | *斜体* _斜体_ 33 | **粗体** __粗体__ 34 | ***粗斜体*** ___粗斜体___ 35 | ~~删除线~~ 36 | 下划线 37 | ``` 38 | 39 | *斜体* _斜体_ 40 | 41 | **粗体** __粗体__ 42 | 43 | ***粗斜体*** ___粗斜体___ 44 | 45 | ~~删除线~~ 46 | 47 | 下划线 48 | 49 | ### 列表 50 | 51 | 无序列表用 `*` 或 `+` 或 `-` 标识,有序列表用数字和 `.` 来标识,支持列表嵌套。 52 | 53 | ```markdown 54 | * 第一项 55 | + 第二项 56 | - 第三项 57 | 1. 子项一 58 | 1. 孙子项一 59 | * 重孙子项一 60 | ``` 61 | 62 | * 第一项 63 | + 第二项 64 | - 第三项 65 | 1. 子项一 66 | 1. 孙子项一 67 | * 重孙子项一 68 | 69 | ### 引用 70 | 71 | ```markdown 72 | > 这是一条无意义的引用。 73 | ``` 74 | 75 | > 这是一条无意义的引用。 76 | 77 | ### 代码 78 | 79 | ```markdown 80 | 加法操作由 `add()` 函数完成 81 | ``` 82 | 83 | 加法操作由 `add()` 函数完成 84 | 85 | ````markdown 86 | ```Python 87 | def add(a, b): 88 | return a + b 89 | ``` 90 | ```` 91 | 92 | ```Python 93 | def add(a, b): 94 | return a + b 95 | ``` 96 | 97 | ### 链接 98 | 99 | ```markdown 100 | [菜鸟教程](https://www.runoob.com/markdown/md-tutorial.html) 101 | 102 | ``` 103 | 104 | [菜鸟教程](https://www.runoob.com/markdown/md-tutorial.html) 105 | 106 | 107 | 108 | ### 图片 109 | 110 | 插入图片需依照 `` 格式。注意不要使用本地路径,可以将图片上传到清华云盘再获取图片链接。 111 | 112 | ```markdown 113 |  114 | ``` 115 | 116 |  117 | 118 | ## 其他 119 | 120 | Markdown 还有一些高级玩法,例如表格、公式、HTML 元素、画时序图、画流程图等等。由于不是很常用,这些都留给有兴趣的读者自行探索。 121 | 122 | 友情链接: 123 | 124 | + 菜鸟教程 125 | + **(推荐学习)**公式编辑教程 126 | + 绘制流程图、时序图、甘特图 127 | + CommonMark,一个常用的 Markdown 标准 128 | -------------------------------------------------------------------------------- /docs/basic/meet-problems.md: -------------------------------------------------------------------------------- 1 | # 当我遇到问题时,我该怎么做... 2 | 3 | > 科协水群里闲聊时,有人“暴言”:“在贵系有技术问题时,摇人比查文档更方便。”遇到问题时多和其他人交流、避免闷头苦干当然是支持的,但这并不意味着问问题前不需要付出努力(例如在搜索引擎上查找)、问问题时对方有义务替你解答...... 4 | > 5 | > —— 摘自 “酒井科协” 公众号 2022 年 3 月 25 日文章 6 | 7 | 学习过程中遇到问题是在所难免的,而如何面对遇到的问题,却是值得我们学习的话题。本篇文章我们从“如何使用搜索引擎”、“如何查阅官方文档”、“如何选择常用网站”、“如何有效地进行提问”这几种方式来阐述,“当我在学习过程中遇到问题时,我应该怎样做...” 8 | 9 | 10 | 11 | ## 如何使用搜索引擎 12 | 13 | ### 我应该怎样选用搜索引擎 14 | 15 | “百度一下,你就知道”诚然是大众的选择,而我们必须指出其在搜索结果呈现时的局限性。具体来说,由于一些商业性因素的限制,它大概率会返回一些与搜索结果不是最强相关的内容。我们在这里推荐两款搜索引擎:如果你因为中国大陆的限制无法访问互联网上的一部分内容,我们推荐你使用 **“Bing 国际版”**,而如果你可以访问到世界互联网上的内容,我们则推荐你使用 **“Google”**。我们接下来的讨论均以后者作为基础展开。 16 | 17 | ### 我应该如何使用搜索引擎 18 | 19 | 相信大家都掌握了搜索引擎的基本使用方法,也掌握了例如“搜索关键词”而不是“搜索整句话”的这种基本搜索技巧。接下来我们演示一些较为进阶的搜索方法。 20 | 21 | + 指定网站搜索 `site:web.site` 22 | + 精确匹配 `"Exact Match"` 23 | + 必须包含 `+` 与必须不包含 `-` 24 | + 任意匹配 `*` 25 | + 指定时间范围,例如只获取过去 1 年内的搜索结果,这样可以保证搜索结果的时效性 26 | 27 | 参考资料:[How to properly use a search engine](https://www.instructables.com/How-to-Properly-Use-a-Search-Engine/). 28 | 29 | 30 | 31 | ## 如何查阅官方文档 32 | 33 | 大部分你使用的工具或者库都会有自己的官网网站;有些即使没有官方网站也会有自己的 GitHub Repo 和配套的 Wiki。了解一个工具或者函数库最全面、也是最便利的方法,实际上是读它对应部分的说明文档。 34 | 35 | 比如,我们想了解怎么在 PyTorch 中实现叉乘,或许我们可以在百度中搜索 `pytorch 叉乘`,然后点开一个 CSDN 教程,但这远没有 Google 搜索 `pytorch cross product`,然后打开 pytorch.org 的官方文档进行阅读来的全面而透彻。 36 | 37 | 再比如,如果我想快速上手一个名叫 “Carla” 的模拟仿真工具,最合适的方式,应该是搜索 “carla doc”,然后打开[官方文档](https://carla.readthedocs.io/en/latest/)阅读其中 “Getting Started” 部分,这样能对这个软件有最基本的了解。之后再根据自己的需要阅读其他部分的内容。 38 | 39 | 40 | 41 | ## 如何选择常用网站 42 | 43 | 要想搜索不同的内容,我们一般会选择不同的网站。这里我们针对一些常见的问题,列出一些常用的网站: 44 | 45 | `Runtime Error / Compilation Error` 46 | 47 | 程序运行时遇到了我不了解的报错,即使查看了函数调用栈也不理解最终的报错信息;程序编译不过,其中用了我不理解的编译特性... **StackOverflow** 是这些问题的好帮手,可以替代 CSDN 作为你的搜索首选。事实上,CSDN 的部分内容是直接从 StackOverflow 上搬运而来,而这些搬运而来的内容在国内网站上又相互爬取、相互展示... 48 | 49 | 但这也不意味着中文内容都是差的,如果使用 Google 并且语言为中文,通常能查到一些中文个人博客的内容,这些内容一般不会是机器搬运的,可以作为参考。例如如果想要配置 `DN42` 实验网络,由于官方文档不详细,个人博客的内容也是非常重要的参考。 50 | 51 | `What is the original paper of XXX...` 52 | 53 | 我们想知道某篇学术论文的出处,或者是其引用格式。这时 **scholar.google.com** 就可以起到很好的作用。如果你知道这篇论文的全名,你可以直接进行搜索,然后便捷地获取引用格式与论文原文的 PDF 版本。 54 | 55 | `I want to know whether or not someone has implemented this...` 56 | 57 | 想找过往的轮子?好办,在 **GitHub** 中进行搜索,你可以看到规模庞大的开源代码...但是,在使用时请务必遵守其对应的 LICENSE。可以尝试使用 [GitHub Code Search](https://cs.github.com),能够更加精确、全面的搜索公开仓库的代码。 58 | 59 | 此外,在学习对应的内容时,我们推荐到对应的官方网站、教程、文档或 Wiki 上进行学习。在学习一些公开课程可能涉及到的知识时(如 CS231n),我们推荐先搜索课程主页,进而在 YouTube 上搜索对应的讲解视频,然后在 B 站与知乎等国内平台上进行检索。 60 | 61 | 62 | 63 | ## 如何有效地进行提问 64 | 65 | 在你尝试了如上内容无果之后,自己闷头苦干或许已经不能解决你的问题了。是时候进行提问了 —— 打开微信列表,翻出一个人的账号,然后敲下一句“在吗”,等待回复 —— 不,这并不是正确的提问方式,至少对方从一句“在吗”中并没有获得任何的信息增益。他/她可能认为你想邀他/她喝一杯下午茶,而不是帮你还有 24 个小时就到 DDL 的 DSA 编程作业 Debug。 66 | 67 | 要想有效地进行提问,我们强烈推荐你阅读一遍参考资料。当然,我们在这里列出几点重点: 68 | 69 | **在你提问之前** 70 | 71 | + 请确保你通过搜索引擎检索不到你想问的问题 72 | + 请确保你查阅了官方文档,其中并没有提及可以直接解决你的问题的答案 73 | + 请确保你自己做了充分的预实验 74 | + 比如 `这段程序的运行结果是什么?`,为什么不自己跑一下呢 75 | 76 | **你的提问内容** 77 | 78 | + 请提供充分的信息给回答者 79 | + 比如请不要发一个 `这段代码有 Bug [捂脸]` 的语句给对方,然后附上一个 ~300 行,以文本方式发送在微信聊天框的代码 80 | + 请至少提供充分的说明:哪段代码?出了什么问题?报错信息是什么?这段代码的目标功能是什么? 81 | + 如果有可能的话,请给出足够多的注释(不过是代码还是你的思考内容) 82 | + 请说出你做过了哪些努力 83 | + 比如按照某个论坛某条回复的方法进行了尝试 84 | 85 | 即使提问,也不代表问题的主动权放在了对方手里。问题毕竟是你自己的问题,对方没有义务帮助你必须解决掉这个问题,所以继续自行寻找答案也许是需要的... 86 | 87 | 参考资料:[How to ask the question the smart way](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way). -------------------------------------------------------------------------------- /docs/basic/web.md: -------------------------------------------------------------------------------- 1 | # Web 与 Web 应用基础 2 | 3 | ## 前言 4 | 5 | 当我们访问网站的时候,发生了些什么?网页实质上是文件。当我们通过浏览器访问网站时,浏览器会向服务器发送请求,服务器会将网页文件发送给浏览器,浏览器再将网页文件渲染成我们看到的网页。 6 | 7 | ## Web 页面 8 | 9 | ### HTML 10 | 11 | HTML (Hyper Text Markup Language, 超文本标记语言) 是一种用于描述网页文档的语言。HTML 定义了许多不同种类的标签, 它们被尖括号包围,起始标签和结束标签通常成对出现,标签自身则表示了内容的类型与格式,标签内含有具体的内容。例如,下面的代码表示 **加粗的** “你好” 12 | 13 | ```html 14 | 你好 15 | ``` 16 | 17 | 在 Word 中,我们通过手动在 Tab 栏里调整格式,文本的写作、结构和格式的调整相分离。而在 HTML 中,**内容的格式信息以标签的形式,作为纯文本存储在文件中**,便于生成、编辑、传输、渲染。 18 | 19 | 下面是一些常见的用来表征文本的 HTML 标签: 20 | 21 | |标签|描述| 22 | |---|---| 23 | |`` - ``|定义标题,从最高级别到最低级别| 24 | |``|定义段落| 25 | |``|定义无序列表| 26 | |``|定义有序列表| 27 | |``|定义列表项| 28 | |``|定义表格| 29 | |``|定义表格的行| 30 | |``|定义表格的单元格| 31 | |``|定义表格的表头单元格| 32 | |``|定义加粗的文本| 33 | |``|定义斜体的文本| 34 | |``|插入换行符| 35 | 36 | 作为“超文本标记语言”,HTML 标签还可以表征文本以外的内容,如图片、视频、超链接等能够在网页上显示的内容。此外,一些不在网页直接显示,但与网页有关的内容也可以用对应的标签在 HTML 中呈现。下面是另一些常用的标签: 37 | 38 | |标签|描述| 39 | |---|---| 40 | |``|定义HTML文档的根元素| 41 | |``|定义文档的头部区域| 42 | |``|定义文档的主体区域| 43 | |``|插入图像| 44 | |``|创建链接| 45 | |``|定义一个区块或容器| 46 | |``|标记或包装文本片段| 47 | |``|定义页眉部分| 48 | |`` 标签来定义样式,进行批量的格式调整。 80 | 81 | ```html 82 | 83 | 84 | 85 | 86 | Tab 栏标题 87 | 93 | 94 | 95 | 96 | 大标题 97 | 一个段落包含一部分加粗的文字 98 | 99 | 100 | 101 | ``` 102 | 103 | 现在的网页看起来像这样: 104 | 105 |  106 | 107 | 同一网站的不同页面往往具有统一的格式,在每个 HTML 文件中进行重复的修改是一件比较麻烦的事,因此可以将这些样式抽离出来,成为 CSS(Cascading Style Sheets) 文件。除了元素类型,CSS 还可以根据元素的类、id 等进行选择,以实现更多样的样式控制。之所以叫做 “层叠样式表”,是因为当有多个规则作用于同一个元素时,规则会按照一定顺序叠加,可以理解为不同的 CSS 具有不同的优先级,优先级高的(直接写在 HTML 中元素起始标签内的 "style")会覆盖优先级低的 (外部引用单独的 CSS 文件)。 108 | 109 | 除了呈现静态的网页界面外,我们希望通过点击网页中的内容来实现一些变化,这可以通过一种“简易”的脚本语言 JavaScript 来实现。JavaScript 语言可以在网页中直接嵌入,也可以单独写成文件,通过 `` 标签引入。在上面的 HTML 实例中再加入 JavaScript 代码: 110 | 111 | ```html 112 | 113 | 114 | 115 | 116 | ``` 117 | 118 | 这时我们点击网页上的图片就可以看到弹窗了: 119 | 120 |  121 | 122 | JavaScript 是一种脚本语言,它不需要编译,嵌入 HTML 后可以随时运行。JavaScript 是图灵完备的,可以实现任何逻辑,它的优势在于**可以方便地访问网络、操纵 HTML 文档内的元素**。 123 | 124 | > 最初的 JavaScript 名为 LiveScript,但是因为一个糟糕的营销策略而被重新命名,该策略企图利用 Sun Microsystem 的 Java 语言的流行性,将它的名字从最初的 LiveScript 更改为 JavaScript——尽管两者之间并没有什么共同点。这便是之后混淆产生的根源。—— [MDN Web Docs](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Language_overview) 125 | 126 | JavaScript 的语法与 C++ 类似,更多相关知识可以参考网上的教程进行自学。 127 | 128 | ### 页面调试 129 | 130 | Google Chrome (大部分现代浏览器都采用了 Chrominum 内核)浏览器提供了一个非常方便的调试工具,可以帮助我们调试网页。在 Chrome 浏览器中打开一个网页,按下 F12,就可以打开调试工具。调试工具中的选择、查找元素、查看网络请求等功能在页面调试,前端开发中非常有用。 131 | 132 | ## Web 通信 133 | 134 | > HTML, CSS, JavaScript 统称为“前端三件套”。如果把这些文件比作包裹,那么为了实现通信,我们还需要一个“快递员”——HTTP 协议。 135 | 136 | ### HTTP 137 | 138 | HTTP (Hyper Text Transfer Protocol) 协议是一种用于传输超文本的应用层协议,它是基于 TCP/IP 协议的。我们发送请求时可能希望获得一些文件,也可能需要主动发送一些信息,如用户名、密码等。HTTP 协议定义了一些请求方法,常见的有 GET, POST, PUT, DELETE 等。不同的请求方法具有不同的语义: 139 | - GET 方法用于获取资源 140 | - POST 方法用于发送信息(提交数据) 141 | - PUT 方法用于更新资源 142 | - DELETE 方法用于删除服务器端指定的资源 143 | 144 | ~~事实上,大部分请求方法都可以混用,但是这样不符合开发规范~~ 145 | 146 | 在发送请求时如何携带具体的信息呢? 147 | - 路径传参,例如用 GET 方法请求 148 | `http://info.com/score/2022010897/` 149 | - Query String(查询字符串),例如用 GET 方法请求 150 | `http://info.com/score?id=2022010897&semester=23fall` 151 | - 请求体传参,我们可以在请求的正文中传输任意格式的信息作为参数,例如 POST 请求 `http://info.com/score` 并携带以下 JSON 格式的信息 152 | ```json 153 | { 154 | "id": "2022010897", 155 | "semester": "23fall", 156 | "GPA": 4.0 157 | } 158 | ``` 159 | 160 | 我们通过客户端发送的请求被服务器接收后,服务器会进行处理并返回一个响应,响应中包含了状态码、响应头、响应体等信息。状态码用于表示请求的状态,常见的有 200 OK(请求成功), 400 Bad Request (请求有误), 404 Not Found(请求的资源不存在), 500 Internal Server Error(服务器内部错误)等。响应头用于表示响应的一些信息,如响应的时间、服务器的类型等。响应体则是服务器返回的具体内容。HTTP response 的正文中可以携带 HTML 文档、JSON 数据、图片、视频等任意格式的数据。 161 | 162 | Apifox / POSTMAN 是一款方便的 HTTP 请求调试工具,可以用于调试 HTTP 请求,模拟向服务器发送请求的过程,方便地向任意地址发送任意方法的信息,携带任意正文。 163 | 164 | ## Web 应用基础 165 | 166 | ### 静态网页 167 | 168 | 有些网站的内容是提前创建好、固定不变的,这些称为静态网页。例如 Hexo 等生成的个人博客。 169 | 170 | 对于静态网页,每一个地址对应的网页文件是固定的,服务端不需要对内容做逻辑上的处理,只需要将对应的文件发送给客户端即可。 171 | 172 | 由于没有具体业务逻辑,一个通用的服务端软件即可满足需求,例如 Nginx。准备好 HTML, CSS, JS 文件,放在服务器指定路径上,一个支持静态网页的网站就搭建好了。然而,有些网页的内容不得不动态地变化,内容需要实时更新,或者我们希望根据用户的身份显示不同的内容,这时,就需要动态网页。 173 | 174 | ### 动态网页 175 | 176 | 动态网页的内容是根据用户的请求动态生成的,网站内容会根据使用者的身份、后台数据库等因素动态生成,例如淘宝、京东。 177 | 178 | 传统模式的动态网页实现策略是,服务器在收到请求后,根据请求内容,从数据库中读取数据,将数据处理好后填入预先准备好的模板中,构成完整的 HTML 文件,再将文件发送给客户端。 179 | 180 | 然而,这种模式的缺点在于,对于每次请求服务器都需要发送完整的 HTML 文件,造成大量的网络流量并降低传输效率。实际上,把“动态”的网页数据和“静态”的网页模板分离开,并让客户端完成将数据填入模板的过程,这就是现代动态网页常见的实现方式——前后端分离开发模式 181 | 182 | ### 前后端分离开发模式 183 | 184 | 对于绝大部分动态网页而言,“动态”的是具体的数据,网页的框架、呈现给用户的界面是“静态”的。“前端”指的就是用户界面,“后端”指的就是数据与业务逻辑,两者可以完全分离。 185 | 186 | 以访问京东为例:客户端请求 jd.com, 返回了由 HTML, CSS, JS 文件构成的静态网页,此时我们可能看得到网页的大体框架,却看不到具体的商品。 187 | 188 |  189 | 190 | 网页上的 JS 脚本会向指定的后端服务器发起请求,获取商品信息,JS 脚本将获取到的信息填入网页,呈现出我们看到的内容。 191 | 192 | 前后端之间的通信也往往使用 HTTP 协议;内容的格式由开发者规定,称为 API (Application Programming Interface, 应用程序接口) 193 | 194 | ### 持久化存储 195 | 196 | 在网页中,我们经常需要存储一些数据,例如用户的登录状态、购物车中的商品等。这些数据需要在用户关闭网页后仍然存在,这就需要将数据存储在服务器上,以实现持久化存储。 197 | 198 | 考虑到存储的数据量可能很大,并且需要进行查询、修改、删除等操作,我们需要一个**数据库**来存储数据。数据库以表单形式持久化存储数据,可以方便地进行查询、修改、删除等操作。 -------------------------------------------------------------------------------- /docs/courses/index.md: -------------------------------------------------------------------------------- 1 | # 课程指引 2 | 3 | 本页面将根据清华大学计算机科学与技术系培养方案中的课程,指出各个课程学习过程中可以参考的引导文档。 4 | 5 | ## 大一年级 6 | 7 | ### 程序设计基础(秋季学期) 8 | 9 | - 基本技能 / Linux 入门 10 | - 基本技能 / VSCode 配置 11 | - 基本技能 / 如何使用搜索引擎 12 | - 编程语言 / C 语言基础 13 | - 编程语言 / 现代 C++ 语言 14 | 15 | ### 面向对象程序设计基础(春季学期) 16 | 17 | - 编程语言 / C 语言基础 18 | - 编程语言 / 现代 C++ 语言 19 | 20 | ### 程序设计训练(夏季学期) 21 | 22 | - 编程语言 / Python 语言基础 23 | - 编程语言 / Java 语言基础 24 | - 编程语言 / JavaScript 语言基础 25 | 26 | ## 大二年级 27 | 28 | ### 数据结构(秋季学期) 29 | 30 | - 外部链接 / OI-Wiki 31 | 32 | ### 人工智能导论(春季学期) 33 | 34 | - 人工智能 & 机器学习 / Pytorch 入门 35 | 36 | ### 软件工程(春季学期) 37 | 38 | - 编程语言 / JavaScript 语言基础 39 | - 编程语言 / TypeScript 语言基础 40 | 41 | ## 大三年级 42 | 43 | ### 虚拟现实技术(秋季学期) 44 | 45 | - 编程语言 / JavaScript 语言基础 46 | 47 | ### 操作系统(春季学期) 48 | 49 | - 编程语言 / Rust 语言基础 -------------------------------------------------------------------------------- /docs/frontend/android/extensions.md: -------------------------------------------------------------------------------- 1 | # 后续学习 2 | 3 | 到这里文档就算结束了,但是如果想更加深入的学习 Android 开发,可以参考下面的内容 4 | 5 | - [Android 开发者官网](https://developer.android.com/docs?hl=zh-cn):官方网站是最权威的学习资料,里面有很多教程和详尽的 API 文档,还有一些示例代码。除此之外,官网还有一些关于 Android 开发的最新动态,如新的 API 版本、新的开发工具等。 6 | - [Android Weekly](https://androidweekly.net/):每周更新,汇集了互联网上有关 Android 开发的技术文章、开源项目、工具等,截至文档完成时已经更新了接近 600 期。 7 | -------------------------------------------------------------------------------- /docs/frontend/android/index.md: -------------------------------------------------------------------------------- 1 | # Android 开发入门 2 | 3 | !!! info "说明" 4 | 5 | 本内容根据 [2023 年科协暑培朱煜章同学的 Java 课程讲义](https://summer23.net9.org/frontend/android/),和 [2024 年科协暑培熊泽恩同学的 Java 课程讲义](https://summer24.net9.org/frontend/android/prerequisites)整理。 6 | 7 | Android 是一个开源的、基于 Linux 开发的移动设备操作系统,编写一个 Android 应用可以使用的编程语言有 Java, Kotlin, C++ 等,本文档将以 Java 为例进行讲解。 8 | 9 | ## 前置知识 10 | 11 | - Java 语言基础知识,可以参考 [Java 语言基础](../../languages/java/index.md) 12 | 13 | ## 开发准备 14 | 15 | - Java 语言环境 16 | - 我们选择 Android Studio 作为开发平台,可以在 [Download Android Studio & App Tools - Android Developers (google.cn)](https://developer.android.google.cn/studio/) 下载。Android Studio 是一个基于 IntelliJ IDEA 的 Android 开发工具,为开发人员提供了广泛的功能和工具,用于设计、编写、调试和测试 Android 应用程序。开发中常用的功能有: 17 | - 布局编辑器:Android Studio 提供了一个可视化布局编辑器,用于设计应用程序的用户界面。开发人员可以直观地添加 UI 元素、调整布局和设置属性。 18 | - 调试工具:Android Studio 具有内置的调试工具,开发人员可以在代码中设置断点,跟踪变量的值,并执行逐行调试。 19 | - 虚拟设备管理器:Android Studio 包含一个虚拟设备管理器,用于创建和管理模拟的 Android 设备。这使开发人员能够在没有实际设备的情况下进行应用程序的测试和调试。 20 | - APK 构建工具:Android Studio 可以将应用程序打包为 Android 安装包(APK)。开发人员可以生成签名的 APK 文件,以便在设备上进行部署和分发。 21 | - SDK 管理器:Android Studio 包含一个 SDK(Software Development Kit)管理器,用于下载和管理 Android 平台的各种版本和附加组件。开发人员可以根据目标设备和最低支持版本来选择所需的 SDK 组件。 22 | 23 | ## 学习方法 24 | 25 | 单纯通过文档来学习 Android 开发是很痛苦的,因此我们强烈建议面向一些实际的代码,而不是文档中的样例代码,这样可以更容易了解 Android 的设计模式,而且在 IDE 中可以用你的 shift 键直接跳转到你需要浏览的地方,这比看文档看到不明白的地方再去百度/谷歌快太多了。本文末尾也会提供一个项目供大家参考。 26 | 27 | ## 后续拓展 28 | 29 | 本文档可以在以下课程帮助到你: 30 | 31 | - 程序设计训练(Java 课堂) 32 | - 其他存在 Android 开发需求的课程 33 | 34 | ## 资源链接 35 | 36 | - Android 开发者[官方文档](https://developer.android.google.cn/docs) 37 | - GitHub 上的一个 Android 包含教程、一些开源项目和工具库的合集:https://github.com/aritraroy/UltimateAndroidReference 38 | 39 | ## 相关链接 40 | 41 | - 2022 年科协暑培的 [Android 项目示例](https://github.com/xsun2001/simple-tree-hole-android)(Java 语言) 42 | - 2023 年科协暑培的 [Android 课程作业](https://github.com/sast-summer-training-2023/sast2023-java-and-android) 43 | - 2024 年科协暑培的 [Android 课程作业](https://github.com/sast-summer-training-2024/sast2024-android) 44 | -------------------------------------------------------------------------------- /docs/frontend/android/resources.md: -------------------------------------------------------------------------------- 1 | # Android 的资源库 2 | 3 | Android 的资源库存储着 APP 的本地资源,包括布局文件、图片、音频、字符串、颜色等内容,这些资源使用 XML 语法编写,被存储在项目文件的 res 目录下,在 APP 运行时可以被调用。 4 | 5 | 6 | 7 | 8 | 9 | ## 布局文件 10 | 11 | 布局文件一般被存储在 layout 目录下,你需要使用多种 `Layout` 将对应的部分插入到界面对应的位置并使用各种各样的 `View` 单独或嵌套在 `Layout` 内作为页面展示的元素。下面是一个示例: 12 | 13 | ```xml 14 | 15 | 23 | 24 | 28 | 29 | 34 | 35 | 39 | 40 | 51 | 52 | 63 | 64 | 65 | 73 | 74 | 75 | 76 | 80 | 81 | ``` 82 | 83 | 得到的布局如下图,如你所见,前后两个 View 是上下占位边框,中间的部分是一组横向线性排列,权重为 $2:1$;左边是两个文本框组成的,右边是一张图片。布局文件的编写还是比较直观的,更多地需要在实践中提高使用的熟练度,这里不再赘述。 84 | 85 | 86 | 87 | 88 | 89 | !!! tip "几点关于布局文件的 tip" 90 | 91 | 1. 布局文件只能有一个根元素。 92 | 2. 上图可视化布局文件的工具是 Android Studio 的布局编辑器,你也可以在布局编辑器中直接添加元素并调整相关参数,任何更改 Android Studio 都会帮你写入布局文件内,不过直接对布局文件进行修改是更推荐的做法。 93 | 94 | ## 其他资源类型 95 | 96 | 除了布局文件以外,Android 还有很多类型的资源,比如颜色列表状态资源,它一般存储在 values 目录下的 `colors.xml`。 97 | 98 | ```xml 99 | 100 | 101 | #FFBB86FC 102 | #FF6200EE 103 | #FF3700B3 104 | #FF03DAC5 105 | #FF018786 106 | #FF000000 107 | #FFFFFFFF 108 | #66CCFF 109 | #39C5BB 110 | #787a7a 111 | #FAFAFA 112 | 113 | ``` 114 | 115 | 还有菜单资源,一般存储在 menu 目录下。 116 | 117 | ```xml 118 | 119 | 120 | 124 | 128 | 132 | 133 | ``` 134 | 135 | Android 还有更多种资源类型,这里一一介绍并不现实,想要了解更多的可以跳转 [资源类型简介](https://developer.android.google.cn/guide/topics/resources/available-resources?hl=zh-cn)。 136 | -------------------------------------------------------------------------------- /docs/frontend/android/structure.md: -------------------------------------------------------------------------------- 1 | # Android 项目的构成 2 | 3 | ## Manifests 4 | 5 | 在 Android 应用中,`AndroidManifest.xml` 文件是必不可少的。它是 Android 应用的核心配置文件,它包含了应用的元数据和配置信息,用于描述应用的结构和行为。这个文件为系统提供了关于应用的各种关键信息,如应用的**包名**、**应用图标**、**版本信息**、**支持的 Android 版本**、**对外暴露的组件**(如 Activity、Service、BroadcastReceiver 等),以及其他系统需要知道的设置和权限。 6 | 7 | 以下是一个 `AndroidManifest.xml` 文件的示例: 8 | 9 | ```xml 10 | 11 | 13 | 14 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ``` 37 | 38 | ## Fragments/Activities/Services/Adapters/Intents 39 | 40 | 这些组件是 Android 应用的基本组成部分,位于 `app/src/main/java/` 文件夹里。 41 | 42 | - **Fragments**:可以看作是活动的一部分,用于管理用户界面的一部分。 43 | - **Activities**:是应用中的一个单独的屏幕,用户可以与之交互。 44 | - **Services**:用于在后台执行长时间运行的操作,而不会干扰用户界面。 45 | - **Adapters**:用于将数据绑定到视图组件,如列表视图或网格视图。 46 | - **Intents**:用于启动活动、服务或广播,还可以在应用之间传递数据。 47 | 48 | 其中,`MainActivity.java` 通常作为应用的主入口点,它是一个继承自 `Activity` 的类,用于定义应用的主界面和用户交互逻辑。 49 | 50 | ## Tests 51 | 52 | 测试是确保应用质量和稳定性的重要部分。测试文件通常位于以下两个目录: 53 | 54 | - `app/src/test/`:包含单元测试,这些测试在开发人员的机器上运行。 55 | - `app/src/androidTest/`:包含仪器测试,这些测试在设备或模拟器上运行。 56 | 57 | ## Resources 58 | 59 | 资源文件是应用的非代码部分,包括图像、字符串、颜色定义等。资源文件位于 `app/src/main/res/` 文件夹中,主要包括: 60 | 61 | - `drawable/`:存放图像资源。 62 | - `values/`:存放字符串、颜色定义、尺寸定义等。 63 | - `layout/`:存放应用的布局文件,如 XML 文件。 64 | 65 | ## Gradle Scripts 66 | 67 | Gradle 是 Android 应用的构建系统。Gradle Scripts 用于定义项目的构建过程和依赖关系。主要文件包括: 68 | 69 | - `gradle.properties`:定义全局配置,如最小 SDK 版本。 70 | - `gradle-wrapper.properties`:定义 Gradle 包装器的配置。 71 | - `settings.gradle.kts`:定义项目设置,如模块名称。 72 | - `build.gradle.kts`:定义模块的构建逻辑,包括依赖项和插件。 73 | -------------------------------------------------------------------------------- /docs/frontend/index.md: -------------------------------------------------------------------------------- 1 | # 前端框架 2 | 3 | 本部分主要介绍 Web、移动端前端开发可能使用到的各类框架。 -------------------------------------------------------------------------------- /docs/frontend/react/dataflow.md: -------------------------------------------------------------------------------- 1 | # 非常规数据流 2 | 3 | 我们先前介绍过 React 的瀑布数据流,也就是父组件向子组件传递数据的数据组织形式。但是有时我们会要求子组件的行为影响父组件,或者多个组件之间共享信息。本部分将会简要介绍如何实现这些非常规数据流。 4 | 5 | ## 反向数据流 6 | 7 | 反向数据流实际上是一个很常见的需求,比如说**分页器**。分页器在 UI 构成上而言,仅仅是一个网页的部分,但是它的状态却决定了整个网页应当显示的内容。从而我们必须构建从分页器向父组件的数据流,让分页器起到作用。 8 | 9 | 这里我们沿用先前的代码,考虑一个简化的反向数据流需求。比如说这里,我们希望让点击正方形这个事件,不仅仅改变正方形本身的颜色,还可以改变父组件 `App` 内部的计数器来显示点击次数。 10 | 11 | !!! note "删掉一些多余的代码" 12 | 13 | 这里我们不涉及生命周期,故可以删除掉 `Square` 组件内的计时器以及相关的生命周期代码。 14 | 15 | 首先我们需要在父组件 `App` 的状态中添加一个计数器,并且在构造函数中初始化。修改后的 `App` 组件为: 16 | 17 | ```typescript 18 | // Component 'App' 19 | interface AppState { 20 | readonly clickCnt: number; 21 | } 22 | 23 | class App extends React.Component, AppState> { 24 | constructor(props: Record) { 25 | super(props); 26 | this.state = { clickCnt: 0 }; 27 | } 28 | 29 | render(): ReactElement { 30 | return ( 31 | 32 | This is a square! 33 | We have click it for {this.state.clickCnt} time(s)! 34 | 35 | 36 | ); 37 | } 38 | } 39 | ``` 40 | 41 | ??? note "`Record` 是什么?" 42 | 43 | `Record` 可以理解为空对象 `{}` 的类型标注,这里仅仅是为了通过 TypeScript 的类型检查。 44 | 45 | 此外,我们还需要编写一个递增计数器的成员函数: 46 | 47 | ```typescript 48 | // Component 'App' 49 | increaseCnter(): void { 50 | this.setState((prev) => ({ 51 | ...prev, 52 | clickCnt: prev.clickCnt + 1, 53 | })); 54 | } 55 | ``` 56 | 57 | 现在我们需要思考的就是如何让子组件 `Square` 调用到这个函数。我们注意到在 TypeScript 语言之中,函数也是一种对象,所以我们完全可以通过组件属性将这个函数传递给子组件。那么我们需要在子组件属性接口上增添一个回调函数: 58 | 59 | ```typescript hl_lines="4" 60 | interface SquareProps { 61 | readonly size: number; 62 | readonly color: string; 63 | readonly increaseCnter: () => void; 64 | } 65 | ``` 66 | 67 | 之后通过组件属性将父组件成员函数向下传递: 68 | 69 | ```typescript 70 | // Component 'App', Function 'render' 71 | this.increaseCnter()} /> 72 | ``` 73 | 74 | 然后我们就可以在子组件内通过 `this.props.increaseCnter` 来调用这个函数了: 75 | 76 | ```typescript 77 | // Component 'Square', Function 'render' 78 | render(): ReactElement { 79 | return { 86 | this.switchColor(); 87 | this.props.increaseCnter(); 88 | }} 89 | />; 90 | } 91 | ``` 92 | 93 | 这样我们就可以通过记录点击正方形的次数了。 94 | 95 | !!! note "真的是反向数据流吗?" 96 | 97 | 我们通过传递回调函数实现了反向数据流,但实际上这样的操作并没有违反瀑布数据流的约定。父组件向下传递的,仅仅是子组件在约束下操作父组件状态的权限,实际上还是可以理解为父组件控制了子组件的行为边界。 98 | 99 | ## 组件间共享数据 100 | 101 | 我们注意到即使我们可以通过传递回调函数的方式实现反向数据流,但实际上这种反向数据流依然只能在父子之间传递。对于更大规模的前端,我们往往需要跨越文档树传递信息,乃至整个应用都需要共享某些信息。此时依然通过回调函数传递就显得极为局限,而现在的一种通用解决方案为 Redux。 102 | 103 | 但由于 Redux 一般用于较大型的工程,这里使用小正方形作为 DEMO 难以讲解。所以这里提供若干学习 Redux 的一些资料链接,希望读者在使用到 Redux 的时候可以参考: 104 | 105 | - Redux 官方文档 106 | - 阮一峰 Redux 教学文档 107 | 108 | !!! note "预留文档" 109 | 110 | 后续可能会编写 Redux 教学文档。 -------------------------------------------------------------------------------- /docs/frontend/react/extensions.md: -------------------------------------------------------------------------------- 1 | # 后续拓展 2 | 3 | 如果你已经学习完了这一篇文档,理解了我们讲述的所有概念,那么你就已经有足够的能力完成《软件工程》课程的大作业 Web 应用前端,乃至开发出一个真正可以上架的 Web 应用了!剩下的,仅仅是多多练习,在编程中理解这些概念,运用这些概念。 4 | 5 | 不过在真正踏上 Web 前端的道路之前,我们还有一些可以给出的资源链接。 6 | 7 | ## Ant Design 8 | 9 | Ant Design 是一个成熟的前端组件库,其作用在于免去调试一整天 CSS 样式表还调不出好看的 Layout 或灵活的交互的苦恼,让我们能更专注于设计前端和用户、后端、数据库的交互逻辑和前端性能。 10 | 11 | Ant Design 官方网址:。 -------------------------------------------------------------------------------- /docs/frontend/react/index.md: -------------------------------------------------------------------------------- 1 | # React 开发入门 2 | 3 | React 前端框架是当下常用的网页前端框架,基于 JavaScript 语言,并提供了对 TypeScript 语言的支持。 4 | 5 | ## 前置知识 6 | 7 | - 具有 JavaScript 以及 TypeScript 语言基础 8 | 9 | - 理解 HTML 标签语法和 CSS 语法 10 | 11 | - 有简单的状态机思维 12 | 13 | ## 后续拓展 14 | 15 | React 作为广泛运用的网页前端框架,基本上可以应对大部分常见的网页前端编写任务。 16 | 17 | --- 18 | 19 | 可以应用 React 相关知识的课程: 20 | 21 | - 软件工程 22 | - 【其他需要编写网页前端的课程】 23 | 24 | ## 资源链接 25 | 26 | - [2024 年酒井科协暑培讲义](https://summer24.net9.org/frontend/react/handout) 27 | - [2023 年酒井科协暑培讲义](https://summer23.net9.org/frontend/react/) 28 | - [React 官方中文文档](https://zh-hans.react.dev/) 29 | 30 | !!! note "官方文档与我们的文档" 31 | 32 | React 官方文档提供了两种学习路径,分别是: 33 | 34 | - 边做边学编写一个井字棋游戏 35 | - 讲解具体的 React 设计哲学与各种概念 36 | 37 | 本文档结合了这两条路径,提供了具体的示例也同时尝试着具体讲解各类概念。 38 | -------------------------------------------------------------------------------- /docs/frontend/react/lifecycle.md: -------------------------------------------------------------------------------- 1 | # 生命周期方法 2 | 3 | ## React 组件的生命周期 4 | 5 | 我们在实际的开发之中,前端需要显示的数据、显示数据的方式往往需要根据从后端、公开平台等处拉取的信息确定,那么我们就需要考虑应当何时发起网络请求拉取数据。 6 | 7 | 在叙述何时拉取数据之前,我们可以先了解一下 React 组件的生命周期,也就是一个 React 组件从构建到解构的全过程: 8 | 9 | - 准备挂载,这个时候属性会被传递到组件的构造函数之中,实例化一个组件,同时创设相应的 `state`。 10 | 11 | - 挂载组件,这个时候框架调用 `render` 函数,生成组件的展示方式并渲染,**挂载完毕之后会使用 `React.Component` 类之中定义的 `componentDidMount` 生命周期方法**,表示组件挂载完毕。 12 | 13 | - 监听组件的 `setState` 方法调用,一旦组件的状态改变,就代表着可能会导致组件的显示方式改变,此时框架会重新调用 `render` 函数进行重新渲染。 14 | 15 | - 卸载组件,当组件需要被移除的时候,**在卸载之前会调用 `React.Component` 类之中定义的 `componentWillUnmount` 生命周期方法**,表示即将卸载组件。 16 | 17 | 注意这里提到的 `componentDidMount` 和 `componentWillUnmount` 方法,这两个方法会在对应的生命周期时间点由 React 框架自动调用。前者调用时组件已经构建完毕且挂载到 DOM 树上,此时便可以从网络拉取数据并写入对应的成员变量或者调用 `this.setState` 根据获取的数据重新渲染组件。 18 | 19 | 而后者调用时意味着组件即将卸载,此时应当清除掉一些即将不使用的、在后台运行占用资源的计时器、事件监听器等对象,保证资源不浪费。 20 | 21 | ??? note "更完整的生命周期" 22 | 23 | **【注意】**这里可能包含过时乃至危险的编码方法,如果只需要学习生命周期方法的运用可以跳过,本部分仅用于深入了解 React 框架。 24 | 25 | 如果使用 VS Code 等带有代码提示的工具编写代码,我们可以看到还有很多其他的生命周期方法: 26 | 27 |  28 | 29 | 这些方法实际上描述了更为细致的 React 组件生命周期,现在我们逐步表述。 30 | 31 | - 组件挂载 32 | - 首先调用构造函数 `constructor()`,其接受的参数为组件属性,同时初始化组件状态。在 ES6 JavaScript 类语法糖出现之前,构造函数由 `getDefaultProps()` 和 `getInitialState()` 两个方法替代 33 | - 其次调用 `componentWillMount()` 方法,用户可以 override 该方法实现自定义功能 34 | - 然后调用 `render()` 方法获取组件的显示方式,渲染组件 35 | - 最后调用 `componentDidMount()` 方法,用户可以 override 该方法实现自定义功能 36 | - 组件更新 37 | - 如果是接受新的组件属性进行更新,调用 `componentWillReceiveProps()` 方法。该方法接受的参数为该组件的新属性 38 | - 首先调用 `shouldComponentUpdate()` 方法,该方法返回布尔值,表示组件此时是否需要更新。若得到 `false`,则组件停止更新,否则继续向下执行。该方法接受的参数为该组件的新属性和新状态 39 | - 其次调用 `componentWillUpdate()` 方法,用户可以 override 该方法实现自定义功能。该方法接受的参数为该组件的新属性和新状态 40 | - 然后调用 `render()` 方法获取组件显示方式,渲染组件 41 | - 最后调用 `componentDidUpdate()` 方法,表示组件更新完毕。该方法接受的参数为组件更新前的旧属性和旧状态 42 | - 组件卸载 43 | - 调用 `componentWillUnmount()` 方法,用户可以 override 该方法实现自定义功能 44 | - 组件错误处理 45 | - 调用 `componentDidCatch()` 方法,用户可以 override 该方法实现自定义功能。该方法接受的参数为错误信息 46 | - 组件监听的方法调用 47 | - `setState()` 方法发起组件更新的**请求**,会触发一次重新渲染,具体用法先前已经讲解 48 | - `forceUpdate()` 方法发起组件更新的**命令**,与 `setState()` 方法不同在其会无视 `componentShouldUpdate()` 的返回值,正常完成组件更新流程(包括调用 `componentDidUpdate()` 方法) 49 | 50 | 总体而言,React 组件的生命周期大致为下图(ES5 版本,不包括组件错误处理和方法监听): 51 | 52 |  53 | 54 | 图片来源:。 55 | 56 | !!! caution "不安全的生命周期方法" 57 | 58 | 我们可以注意到 `componentWillMount()` 等方法已经被标记为 Deprecated,这是因为这类方法往往可能会在组件未构建完毕或者更新完毕的时候修改组件,这是有数据竞争危险的。所以在 React 17/18 版本的过渡之中,这些方法会被废弃。这些生命周期方法包括: 59 | 60 | - `componentWillMount()` 61 | - `componentWillUpdate()` 62 | - `componentWillReceiveProps()` 63 | 64 | ## 实例——为组件挂载计时器 65 | 66 | 现在我们着重讲解如何利用 `componentDidMount` 和 `componentWillUnmount` 方法。这两个生命周期方法标记着组件生命周期的开始与终结,所以如果我们需要使用一个和组件同时构造、同时释放的对象,我们就需要在这两个生命周期方法内构建和释放这个对象。其中一个例子就是计时器。 67 | 68 | 我们现在考虑先前编写的小正方形,现在我们能够通过修改组件状态来控制它的颜色,但我们实际上还是要通过用户来触发我们修改颜色的函数。如果我想要将这个函数改为自动调用,不可避免地就需要引入计时器。 69 | 70 | 首先我们需要将计时器声明为类成员以符合 TypeScript 的检查: 71 | 72 | ```typescript 73 | class Square extends React.Component { 74 | timer: any; 75 | // ... 76 | } 77 | ``` 78 | 79 | 之后,我们需要在 `componentDidMount` 方法中,在组件刚挂载的时候构建计时器对象: 80 | 81 | ```typescript 82 | // Component 'Square' 83 | componentDidMount(): void { 84 | this.timer = setInterval(() => this.switchColor(), 1000); 85 | } 86 | ``` 87 | 88 | `setInterval` 方法设定一个周期计时器,上述计时器将会每间隔 1000 毫秒调用一次 `this.switchColor` 方法。 89 | 90 | 最后,我们需要在 `componentWillUnmount` 方法中,在组件即将卸载的时候删除计时器对象: 91 | 92 | ```typescript 93 | // Component 'Square' 94 | componentWillUnmount(): void { 95 | clearInterval(this.timer); 96 | } 97 | ``` 98 | 99 | 使用 `npm run start / yarn start` 命令即可运行应用,看到一个每隔一秒变色的正方形了。 100 | 101 | ## `setState` 方法与可能的循环渲染 102 | 103 | 初次使用 React 框架并尝试维护组件状态的时候,往往会遇到滥用 `setState` 方法导致组件崩溃的错误。 104 | 105 | 尝试在 `Square` 组件内写入这样的代码: 106 | 107 | ```typescript 108 | // Component 'Square' 109 | componentDidUpdate() { 110 | this.setState((o) => o); 111 | } 112 | ``` 113 | 114 | 再运行 React 应用,你应当能观察到 React 崩溃。请自行思考原因,如果没有思路,可以打开浏览器控制台查看报错原因或者展开下面的笔记框阅读我们给出的解释。 115 | 116 | ??? note "React 崩溃的原因" 117 | 118 | 如果你打开了浏览器的控制台,应当会看到类似下图的报错: 119 | 120 |  121 | 122 | 现在我们回顾调用 `setState` 时 React 框架的处理流程。如果调用后通过了 `shouldComponentUpdate` 的检查,则就会进入组件更新的处理流程,这期间会调用 `componentWillUpdate`、`componentDidUpdate`、`render` 等方法,如果这些方法内又一次调用了 `setState` 方法,则又会触发组件更新,从而导致循环渲染,这种死循环会导致 React 框架崩溃退出。 123 | 124 | 所以我们应当避免在 `componentWillUpdate`、`componentDidUpdate` 内调用 `setState`,即使需要调用,也仅能够在某个条件分支语句内使用,比如: 125 | 126 | ```typescript 127 | componentDidUpdate(prevProps) { 128 | if (prevProps.foo !== this.props.foo) { 129 | this.setState(/* SOMETHING */); 130 | } 131 | } 132 | ``` 133 | 134 | 这样至少不会导致最简单的死循环,但是这样还是有可能导致重复渲染,进而导致性能浪费。 -------------------------------------------------------------------------------- /docs/frontend/react/prepare.md: -------------------------------------------------------------------------------- 1 | # 环境配置 2 | 3 | ## 前置环境配置 4 | 5 | 在继续下面的环境配置之前,本文档默认了你已经安装了高于 v12 的 `node`,并且可以使用 `npm install`。 6 | 7 | 如果安装 Node.js 或者 npm 遇到困难,可以参考 [Node.js 的引导文档](/languages/node.js)。 8 | 9 | ## 使用 `yarn` 代替 `npm` 10 | 11 | 这是一个**可选项**,在实际工程之中两者并没有本质上的差别。与常用的 `npm` 相比,`yarn` 大多情况下具有更快的下载速度和更为清晰的命令行输出。所以我们更加推荐使用 `yarn`。 12 | 13 | 这里不具体叙述安装过程,可以参考 [官网](https://yarn.bootcss.com) 上给出的方式进行安装,也可以使用 `npm install yarn -g` 命令安装(后者可能不适用于 Linux 用户)。 14 | 15 | `yarn` 的命令和 `npm` 的命令大致具有以下对应关系,更细节的关系则可以参考 [npm 的引导文档](/languages/node.js/npm): 16 | 17 | | | `npm` | `yarn` | 18 | | ---------------- | ------------------------------ | ---------------------- | 19 | | 安装指定第三方库 | `npm install react --save` | `yarn add react` | 20 | | 移除指定第三方库 | `npm uninstall react --save` | `yarn remove react` | 21 | | 开发模式下安装 | `npm install react --save-dev` | `yarn add react --dev` | 22 | 23 | ## 安装 TypeScript 24 | 25 | TypeScript 是 JavaScript 的超集。简而言之,TypeScript 就是带有类型系统的 JavaScript。TypeScript 代码可以直接被编译为 JavaScript 代码并执行。 26 | 27 | 安装 TypeScript 是简单的: 28 | 29 | ```shell 30 | # yarn 31 | yarn global add typescript 32 | 33 | # npm 34 | npm install -g typescript 35 | ``` 36 | 37 | 安装后可以在某一目录下新建 `hello.ts` 文件,输入以下代码: 38 | 39 | ```typescript 40 | let a: string = "Hello world!"; 41 | console.log(a); 42 | ``` 43 | 44 | 并在这个目录下执行: 45 | 46 | ```shell 47 | tsc hello.ts 48 | ``` 49 | 50 | 如果安装顺利,这个目录下应当会出现编译生成的 `hello.js` 文件,使用命令 `node hello.js` 应当就可以看到命令行输出的问候语。 51 | 52 | ## 安装 React 框架 & 创建 React 应用 53 | 54 | React 框架的安装可以通过脚手架 `create-react-app` 完成,一般而言安装框架这一过程可以集成在创建应用的过程中完成。 55 | 56 | 进入到你想要创建应用的目录下,执行以下命令: 57 | 58 | ```shell 59 | # npm 5.2+ 60 | npm install create-react-app -g 61 | npx create-react-app --template typescript 62 | 63 | # yarn 0.25+ 64 | yarn global add create-react-app 65 | yarn create react-app --template typescript 66 | ``` 67 | 68 | 这里 `` 是你的应用的目录的路径。这些命令会创建一个使用 TypeScript 开发的 React 应用,并安装 React 框架。 69 | 70 | 如果安装顺利,使用命令: 71 | 72 | ```shell 73 | # npm 74 | npm run start 75 | 76 | # yarn 77 | yarn start 78 | ``` 79 | 80 | 即可编译整个应用,随后应当就可以通过本地 3000 端口访问到 React 的欢迎界面了。 81 | 82 | !!! note "使用我们提供的框架" 83 | 84 | 为了更好地阅读本文档,我们推荐下载我们提供的简化版 React 框架。我们提供的框架中仅保留了最基础、最必要的代码文件。 85 | 86 | 使用我们提供的框架之前,我们希望你已经通过上述步骤成功初始化了一个新的 React 应用并能够在 3000 端口访问到欢迎界面。如果已经确认初始化成功,可以通过 该链接 下载压缩包,请在解压后使用压缩包内的 `src` 文件夹替换你的 React 应用的 `src` 文件夹,并再次使用 `npm run start` 或者 `yarn start` 命令运行 React 应用。 87 | 88 | 如果你现在能够在 3000 端口访问到一个写有 `Hello, React!` 字样的页面,则已经完成了配置。 89 | 90 | ## 代码格式化 91 | 92 | 这是一个**可选项**,但是我们认为开发较大工程的时候,尤其是需要多人协作的时候,统一的码风是必要的。 93 | 94 | 即使每个人都可以有自己习惯的编写风格,但为了其他人阅读方便,在提交代码之前应该使用代码格式化工具统一码风。这里简单介绍两种常用的格式化工具。 95 | 96 | ### ESLint 97 | 98 | 在应用目录下执行下列命令,即可初步配置一个 ESLint: 99 | 100 | ```shell 101 | # npm 102 | npm install eslint --save-dev 103 | ./node_modules/.bin/eslint --init 104 | 105 | # yarn 106 | yarn add eslint --dev 107 | yarn eslint --init 108 | ``` 109 | 110 | 执行第二条命令后,ESLint 会询问你的配置。对于前几个问题我们建议选择“强制调整码风” “使用 JavaScript modules(import/export) ” “使用 React 框架” “使用 TypeScript ” “在浏览器上运行代码”。 111 | 112 | 后续则是对具体码风规则的配置,你可以回答具体问题或选择使用模板,也可以暂且不回答而选择后续手动配置 `.eslintrc` 文件中的码风规则。 113 | 114 | 下面我们希望能够一键调整码风,比如说终端执行 `yarn fix` 就可以修复所有源代码的码风。现在打开 `package.json` 文件,可以注意到这样的一段: 115 | 116 | ```json 117 | "scripts": { 118 | "start": "react-scripts start", 119 | "build": "react-scripts build", 120 | "test": "react-scripts test", 121 | "eject": "react-scripts eject" 122 | } 123 | ``` 124 | 125 | 在最后添加一行: 126 | 127 | ```json 128 | "scripts": { 129 | ... 130 | "fix": "./node_modules/.bin/eslint src --ext .js,.jsx,.ts,.tsx --fix" 131 | } 132 | ``` 133 | 134 | 这一行的意思是执行 `yarn fix` 的时候会使用 ESLint 将 `src` 目录下的所有扩展名为 `js / jsx / ts / tsx` 的文件修复码风。 135 | 136 | 不过要注意的是,自动修复能力有限,所以更多的时候还需要手动对文件进行一些调整。自动修复也有可能会出错,这个时候可以自己手动添加让 ESLint 忽略这一部分的注释。 137 | 138 | ### Prettier 139 | 140 | 在 Node.js 项目中添加 Prettier: 141 | 142 | ```bash 143 | yarn add -D prettier 144 | ``` 145 | 146 | 在 `package.json` 中添加: 147 | 148 | ```json 149 | { 150 | "scripts": { 151 | ... 152 | "fix": "prettier --write 'src/**/*{.js,.jsx,.ts,.tsx}'" 153 | } 154 | } 155 | ``` 156 | 157 | 这里的含义与 ESLint 相似,只不过这次是由 Prettier 尝试修复码风。 158 | 159 | !!! note "ESLint 和 Prettier 的区别" 160 | 161 | 需要注意的是,Prettier 仅仅尝试修复码风,它所进行的一切修改在语法上都是等价的,也即 Prettier 并不关心代码的正确性,甚至不会检查是否符合语法规范;同时 Prettier 可以配置的项目相当少,这是由于 Prettier 的开发者更希望能强制统一标准而非在具体 lint 配置上陷入无意义的争论。 162 | 163 | ESLint 在检查风格的同时也可以进行更多的语法检查,还可以通过插件来检查更加具体的错误,例如 React Hook 的不当使用等;相比于 Prettier,ESLint 还可以对代码风格进行更复杂的配置。 164 | -------------------------------------------------------------------------------- /docs/frontend/swiftui/data-flow.md: -------------------------------------------------------------------------------- 1 | 我们之前介绍的都是一些非常简单的情况:它们都不涉及变化的状态。然而,几乎所有的应用都需要依赖于变化的数据。我们需要一种方法,使得当数据更新时及时、正确地更新我们的 UI。我们将介绍 UI 与数据绑定过程中涉及的一些最基本的常见数据流。 2 | 3 | ## State 4 | 5 | 我们来看一个简单的例子。在我们的 View 中,需要记录用户点击的次数,并显示在屏幕上。你可能想要这样写:给 `ContentView` 加上一个变量 `count`,然后在 `Button` 中更改这个值: 6 | 7 | ```swift hl_lines="2 6" 8 | struct ContentView: View { 9 | var count: Int = 0 10 | 11 | var body: some View { 12 | HStack { 13 | Button("Click") { count += 1 } 14 | Text("\(count)") 15 | } 16 | } 17 | } 18 | ``` 19 | 20 | 但这样是不能正常工作的。 21 | 22 | 首先,这个代码并不能通过编译: 23 | 24 | ``` 25 | Left side of mutating operator isn't mutable: 'self' is immutable 26 | ``` 27 | 28 | 原因是,`struct` 是值类型,一般的函数不能够修改其变量的值。 29 | 30 | 而且,有一个更加深层的原因。我们改变了 `count`,并且希望 `Text("\(count)")` 能显示最新的值。但是,`ContentView` 并不知道当 `count` 更新时需要更新 UI。 31 | 32 | 修改的方法很简单,只需要在 `var count: Int = 0` 前加上 `@State`: 33 | 34 | ```swift 35 | @State var count: Int = 0 36 | ``` 37 | 38 | 这样,就能够通过编译,并且我们的界面会随着 `count` 的更新而更新了: 39 | 40 |  41 | 42 | **`@State` 是什么语法?为什么能够修改 `count`?** 43 | 44 | `@State` 涉及到一种叫 [property wrapper](https://docs.swift.org/swift-book/LanguageGuide/Properties.html#ID617) 的语法。简单来说,property wrapper 有如下特性: 45 | 46 | - 是一个包装后的类型,但对外的表现就像是被包装前的数据一样 47 | - 当被包装的值被设定或被读取时,执行特定的代码 48 | 49 | 因为我们实际上是修改 `@State` 所包装的值而非 `@State` 变量本身,所以是可以修改 `count` 的值的。 50 | 51 | **为什么更新 `count` 之后 UI 会自动更新?** 52 | 53 | 上面关于 property wrapper 的特性具体到 `@State`,即: 54 | 55 | - 我们可以直接取其所储存的值(如上面的 `Text("\(count)")`) 56 | - 它在被设定时会触发 View 重新计算 `body`(如上面的 `count += 1`) 57 | 58 | 于是,通过 `@State`,我们实现了 **UI 与数据的绑定**,只要 `count` 更新,整个 View 就会被重新计算。我们的 UI 在任何时刻都反映了数据最新的值,我们只需要修改数据,而无需手动地更新 UI。 59 | 60 | !!! note "React 中的类似方法" 61 | 62 | 如果你对 React 有所了解,`@State` 相当于: 63 | 64 | - 对于 `Component`:通过 `state` 获取值;调用 `setState` 更改值 65 | - 对于纯函数组件:`useState` 的两个返回值,分别对应获取和更改 66 | 67 | 实际上,View 和 React 中的纯函数组件概念上是一样的。SwiftUI 通过 Swift 的 property wrapper 语法,将获取值、设定值以及更新 UI 简化为一个变量的读取和设定,而 React 因为语言的限制,设定值以及更新 UI 只能采用调用函数的方法。 68 | 69 | ## Binding 70 | 71 | `@State` 解决了在**单个** View 中根据数据更新 View 的问题。但是,有时我们为了重用代码或保持代码的简洁,需要将一些 View 拆分出来,这就产生了一个问题:**如何在父 View 和子 View 中共享一个可由子 View 修改的值?**也就是说,数据如何从子视图流向父视图? 72 | 73 | 比如,我们希望把「点击一次使得值加 1」的按钮封装起来,以便重复使用,那么上面的 `Button` 不再在 `ContentView` 中定义,而是在另一个 View 中出现: 74 | 75 | ```swift 76 | struct IncrementButton: View { 77 | // TODO: Data 78 | var body: some View { 79 | Button("Increase") { 80 | // TODO: Increse data 81 | } 82 | } 83 | } 84 | ``` 85 | 86 | 如何在这两个 View 共享 `count` 使得 `IncrementButton` 可以修改呢?这就需要 `@Binding`。在 `IncrementButton` 中,添加一个成员 `@Binding var value: Int`,并在 `Button` 的 `action` 中将其值加 1: 87 | 88 | ```swift hl_lines="2" 89 | struct IncrementButton: View { 90 | @Binding var value: Int 91 | 92 | var body: some View { 93 | Button("Increase") { value += 1 } 94 | } 95 | } 96 | ``` 97 | 98 | 而在父 View 中,通过在 `@State` 变量名前加上一个 `$` 来传递 `Binding`: 99 | 100 | ```swift hl_lines="6" 101 | struct ContentView: View { 102 | @State var count: Int = 0 103 | 104 | var body: some View { 105 | HStack { 106 | IncrementButton(value: $count) 107 | Text("\(count)") 108 | } 109 | } 110 | } 111 | ``` 112 | 113 | 在 `IncrementButton` 中修改 `value`,`ContentView` 中的 `count` 就会同步变化。换而言之,我们实现了**父 View 和子 View 数据的绑定。** 114 | 115 | !!! note "关于 `$count`" 116 | 117 | 在变量名前加 `$` 并不是一种语法,而是编译器自动给 `ContentView` 加上了一个变量名为 `$count` 的成员变量,它的类型为 `Binding`。 118 | 119 | !!! note "更多的原生 View" 120 | 121 | 掌握了 `@Binding` 后,你可以使用更多的与数据相关的原生 View 了。比如,一个文本框: 122 | 123 | ```swift 124 | TextField("", text: $myText) 125 | ``` 126 | 127 | 当用户输入文本时,`TextField` 中的文本会同步到 `myText` 中。 128 | 129 | 你可以在文档中探索更多的原生 View。 130 | 131 | ??? note "`$count` 的实质" 132 | 133 | 在文档中,你可以看到 `Binding` 有这样一种构造函数: 134 | 135 | ```swift 136 | init(get: @escaping () -> Value, set: @escaping (Value) -> Void) 137 | ``` 138 | 139 | 第一个参数 `get` 用于返回 `Binding` 变量读取的值,第二个参数 `set` 是当 `Binding` 变量改变时所执行的操作。 140 | 141 | 因此,你完全可以用这种方法取代 `$count`: 142 | 143 | ```swift 144 | IncrementButton(value: 145 | Binding( 146 | get: { count }, 147 | set: { count = $0 } 148 | ) 149 | ) 150 | ``` 151 | 152 | 当 `IncrementButton` 获取 `value` 时,调用 `get` 获取当前的值;当 `IncrementButton` 改变 `value` 时,调用 `set` 更新 `count`。由 `@State` 生成的 `Binding` 变量无非就是实现这样的功能。 153 | 154 | ## UI 是状态的函数 155 | 156 | 通过上面的一些例子,你应该能总结出 SwiftUI 中 View 的一些特点。最明显的是:**View 唯一地由数据确定。**如果将 `@State`、`@Binding` 所代表的数据视作一种“状态”,那么我们可以写出这样一条式子: 157 | 158 | ``` 159 | View = f(state) 160 | ``` 161 | 162 | 其中的 `f`,其实就是 `View` 中的 `body`。每次 `state` 更新时,View 通过 `body` 的定义计算出新状态下的 UI,并进行更新。所以,这也是为什么 `body` 应当是一个**计算变量**,而不是储存变量——它本质上是一个函数。 163 | 164 | 这种性质一个很自然的结果是:**我们无法获得 View 的引用,也无法直接修改其 UI,所有对 UI 的修改都源自于数据的改变**。 165 | 166 | 我们在下一节中进行更深入的讨论。 167 | -------------------------------------------------------------------------------- /docs/frontend/swiftui/declaritive-mvvm.md: -------------------------------------------------------------------------------- 1 | 以上是对 SwiftUI 基础内容的介绍。在你将来学习更加高级的内容之前,有必要对 SwiftUI 的 UI 构建作一个概念上的总览。我们将讨论两个核心概念:声明式 UI,以及 MVVM 架构。 2 | 3 | ## 声明式 UI 4 | 5 | 我们先来看两段代码。 6 | 7 | 一段使用 SwiftUI: 8 | 9 | ```swift 10 | Text("Hello, world!") 11 | .font(.system(size: 20, weight: .bold)) 12 | .foregroundColor(.red) 13 | ``` 14 | 15 | 另一段使用 UIKit: 16 | 17 | ```swift 18 | let label = UILabel() 19 | label.text = "Hello, world!" 20 | label.font = .systemFont(ofSize: 20, weight: .bold) 21 | label.textColor = .systemRed 22 | ``` 23 | 24 | 它们都创建了一个带有一定样式的文本 UI。然而,它们的构建方式有着本质上的不同。对于 SwiftUI,我们**描述** Text 及其字体、颜色等各种样式,而对于 UIKit,我们通过**设定**属性值来更改。前者称为「声明式」(declarative),而后者称为「命令式」(imperative)。 25 | 26 | 你可以从这两个词中体会到两种不同代码的显著区别。在 SwiftUI 中,我们不会使用“命令”语句来告诉一个 View “怎么做”,而是通过“声明”一个 View 以及它的结构、特征来告诉这个 View “做成怎样”。 27 | 28 | 当 UI 的状态需要随着状态的变化而更新时,二者的优劣变得非常明显。**命令式 UI 构建需要在每次状态更新时都通过一定的逻辑更新所有关联的 UI,而声明式 UI 构建只需要在一开始将所有可能的 UI 状态描述出来,就可以形成状态到 UI 的一个映射。** 29 | 30 | 这两种方式的复杂程度差别有多大?作个简单的计算:假如我们的 UI 有 10 种可能的状态,那么命令式 UI 最多需要根据 $\dbinom{10}{2} = 45$ 种不同的状态**转移**定义来定义 UI 更新函数,而声明式 UI 最多不过需要定义 10 种不同状态下的 UI。更糟糕的是,一旦命令式 UI 的某一步 UI 更新出现问题,那么很可能接下来的更新都会导致错误的 UI。因此,当状态复杂到一定程度的时候,命令式 UI 的正确更新变得几乎不可能(回想一下你之前写过的命令式 UI,比如贵系同学们用 Qt 写过的大作业)。 31 | 32 | 声明式 UI 的这种特征决定了它有很多与命令式 UI 不同的性质: 33 | 34 | - 没有对 UI 的引用。声明式 UI 只是一种对“UI 是怎样的”的描述,它对 UI 本身没有掌控。 35 | - 由状态唯一确定,且只能通过修改状态更新 UI。 36 | - 只是对 UI 的描述,并不是真实的 UI。 37 | 38 | 实际上,SwiftUI 底层是 UIKit,SwiftUI 其实是通过某种方式将 UIKit 中复杂的的 UI 更新简化为状态到 UI 的简单映射。 39 | 40 | !!! note "关于 View 的计算与 UI 更新" 41 | 42 | 我们知道,每次状态更新时,View 中的 `body` 都会被重新计算以获得最新的 UI。你可能会对这种方式的性能问题产生担忧。实际上,SwiftUI 的 UI 更新是十分高效的。 43 | 44 | 请谨记,View 并不是真实的 UI,只是一种描述。SwiftUI 底层通过某种机制,能够比较更新前后两个描述的区别,然后只更新**描述中变化了**的 UI。 45 | 46 | ## MVVM 架构 47 | 48 | 我们之前通过 `@State` 和 `@Binding` 简单介绍了 SwiftUI 中数据和 UI 的交互。我们把 view 所依赖的数据及与数据相关的逻辑称为 model,那么: 49 | 50 | - 数据由 model 绑定到 view 51 | - view 拥有 model,并能进行修改 52 | 53 |  54 | 55 | 然而,现实情况远比我们在前一节中“记录点击次数”的情况复杂。比如,我们的数据储存在数据库中,需要复杂的操作取出来,而且取出来的数据并不一定是 view 能够**直接**使用的,可能要经过一定的转换。这时,如果继续使用上面的架构,view 的负担就过于沉重了,这与 view 的定位相违背:view 应该**只需要知道如何展示数据、与用户交互**。 56 | 57 | 而且,view 只能持有**仅与 UI 相关**的状态,不能持有外部数据。理由之一是:外部数据可能需要在不同 view 之间共享,而如果由值类型的 view 存储显然无法完成。 58 | 59 | 因此,我们需要在中间加上一层:view model。 60 | 61 |  62 | 63 | 其中,view model 负责: 64 | 65 | - 持有 model,根据 view 的命令修改 model 66 | - 监听 model 变化,在变化时通知 view 67 | - 将 model 的数据转化为 view 能够直接使用的数据 68 | 69 | View 负责: 70 | 71 | - 将“需要做什么”发送给 view model(如,用户输入信息后,让 view model 存入数据库) 72 | - 监听 view model 通知,并根据 view model 提供的数据更新界面 73 | 74 | 请注意,在这个架构中,数据是严格**单向流动**的。 75 | 76 | 在 SwiftUI 中,MVVM 架构通常通过 `ObservableObject` 和 `@ObservedObject` 完成。具体来说: 77 | 78 | - View model 为了能够将 model 已经变化了的消息“通知” view,需要继承 `ObservableObject` 类(因此必须是 `class`) 79 | - View model 的成员变量可以加上 `@Published`,表示这个变量变化时通知 view 80 | - View 中对 view model 加上 `@ObservedObject`,表示监听 view model 发出的信号 81 | 82 | 下面是一个最简单的例子: 83 | 84 | ```swift 85 | struct ContentView: View { 86 | @ObservedObject var viewModel = ViewModel() 87 | 88 | var body: some View { 89 | HStack { 90 | Button("Click") { 91 | viewModel.count += 1 92 | } 93 | Text("\(viewModel.count)") 94 | } 95 | } 96 | } 97 | 98 | class ViewModel: ObservableObject { 99 | @Published var count: Int = 0 100 | } 101 | ``` 102 | 103 | 限于篇幅,有关 MVVM 架构的实践请参考 [CS193p 课程有关 MVVM 的介绍](https://www.bilibili.com/video/BV1q64y1d7x5?p=3)。 104 | 105 | !!! note "再谈 `@State`" 106 | 107 | 前面提到,View 只能持有仅与 UI 相关的状态。也就是说,在 View 中,`@State` 包装的值不能与外部数据相关。 108 | 109 | 什么是仅与 UI 相关的状态?一个简单的例子是:`Button` 在用户按下时会有透明度的变化,这里记录按压的状态和透明度的值就属于“仅与 UI 相关的状态”。 110 | 111 | 实践中一个简单的判断方法是:如果一个 `@State` 不能标记成 `private`,即外部需要访问这个数据,那么它就不仅与 UI 相关,这时不能用 `@State` 来储存,需要借助 view model。 112 | -------------------------------------------------------------------------------- /docs/frontend/swiftui/extensions.md: -------------------------------------------------------------------------------- 1 | 本文仅对 SwiftUI 中一些最基本的知识作了介绍,而这远远不够。要想开发一个完整的应用,你还需要学习更多内容。 2 | 3 | 这是一些仅供参考的建议: 4 | 5 | - 经常探索[官方文档](https://developer.apple.com/documentation/swiftui),看看你能使用的工具有什么 6 | - 看看历年 [WWDC](https://developer.apple.com/videos/topics/) 有什么视频讲解的内容是你需要的,关注每年的 WWDC 7 | - 不要惧怕英文内容,阅读英文文档是开发的必经之路 8 | - 学会用英文搜索,**尽量不用中文搜索** 9 | 10 | ## 概念性知识 11 | 12 | 这些概念性知识能够帮助你理解 SwiftUI 是如何运行的,进而帮助你写出效率更高、更加正确的程序。SwiftUI 本身并不复杂,但其原理需要深入的学习才能理解,而对原理的理解往往会在很大程度上影响程序的质量。 13 | 14 | 这些话题非常重要: 15 | 16 | - [SwiftUI 生命周期](https://developer.apple.com/videos/play/wwdc2020/10037/):`App`、`Scene` 和 `View` 之间的关系 17 | - [SwiftUI 中的数据流](https://developer.apple.com/videos/play/wwdc2020/10040/):SwiftUI 中的数据流及其使用原则 18 | - [MVVM 架构](https://www.bilibili.com/video/BV1q64y1d7x5?p=3):虽然我们已经简单介绍过,但你仍应听一听 CS193p 的这节课 19 | - [View Identity](https://developer.apple.com/videos/play/wwdc2021/10022/):在底层,不同的 View 之间是如何区分的? 20 | 21 | ## 技术性知识 22 | 23 | 这些技术性的知识是一些“SwiftUI 能做什么”的集合,基本上是[官方文档](https://developer.apple.com/documentation/swiftui)中你能用的所有 SwiftUI 现成工具,可以需要时再查阅,也可以无聊时随便翻翻。遇到问题时,[Google](https://google.com)[、Stackoverflow](https://stackoverflow.com) 和 [WWDC 视频](https://developer.apple.com/videos/swiftui-ui-frameworks)是你可靠的助手。 24 | 25 | - [原生组件](https://developer.apple.com/documentation/swiftui/views-and-controls):文字、图片、按钮等组件 26 | - [排布](https://developer.apple.com/documentation/swiftui/view-layout-and-presentation):Stack、Grid、ScrollView、NavigationView 等 27 | - [数据流与状态](https://developer.apple.com/documentation/swiftui/state-and-data-flow):State、Binding、ObservedObject 等 28 | - [绘画与动画](https://developer.apple.com/documentation/swiftui/drawing-and-animation):绘制形状、添加动画 29 | - [触控识别](https://developer.apple.com/documentation/swiftui/gestures):识别用户触摸输入 30 | - View modifier 31 | - [外观](https://developer.apple.com/documentation/swiftui/view-appearance) 32 | - [文字相关](https://developer.apple.com/documentation/swiftui/view-text-and-symbols) 33 | - [额外的 UI 部件](https://developer.apple.com/documentation/swiftui/view-auxiliary-views) 34 | - [布局](https://developer.apple.com/documentation/swiftui/view-layout) 35 | - [图像与渲染](https://developer.apple.com/documentation/swiftui/view-graphics-and-rendering) 36 | - [用户输入与事件](https://developer.apple.com/documentation/swiftui/view-input-and-events) 37 | - [视图的展示](https://developer.apple.com/documentation/swiftui/view-presentation) 38 | - 在 SwiftUI 中使用 UIKit 39 | - [CS193p](https://www.bilibili.com/video/BV1q64y1d7x5?p=15) 40 | - [官方教程](https://developer.apple.com/tutorials/SwiftUI/interfacing-with-uikit) 41 | - [官方文档](https://developer.apple.com/documentation/swiftui/framework-integration) 42 | 43 | ## 其它相关知识 44 | 45 | - [Combine 框架](https://developer.apple.com/videos/play/wwdc2019/722/):为 SwiftUI 设计的异步事件管理框架 46 | - [UIKit 课程](https://www.bilibili.com/video/BV1Mx411L7dS):CS193p 的 UIKit 完整课程 47 | -------------------------------------------------------------------------------- /docs/frontend/swiftui/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SwiftUI 与 iOS 开发入门 3 | --- 4 | 5 | SwiftUI 是用于 iOS/macOS/watchOS/tvOS 等平台的通用原生 UI 框架,使用(且仅适用于)Swift 语言,于 [WWDC19](https://developer.apple.com/videos/play/wwdc2019/216/)(2019 年)推出,支持 iOS 13.0+、macOS 10.15+ 等。 6 | 7 | SwiftUI 基于各平台原有的 UI 框架开发,如 iOS 的 UIKit,macOS 的 AppKit 等。相对于这些框架,SwiftUI 的概念更加简单,且构建方式更加符合直觉,逐渐成为入门 iOS 开发的首选。 8 | 9 | SwiftUI 在经历几年的发展后已经逐渐完善,基本上可以胜任小型应用的开发。令人遗憾的是,目前(2022 年 1 月)由于 SwiftUI 仍在发展初期,iOS 开发中某些复杂的功能需要依赖 UIKit 实现,因此只学习 SwiftUI 可能并不能够支持某些较为复杂应用的开发。本文仅介绍纯 SwiftUI 框架,与 UIKit 相关的内容可以参考 [Stanford CS193p 2020 年之前的课程](https://www.bilibili.com/video/BV1Mx411L7dS)(2020 年开始该课程改为 SwiftUI)。 10 | 11 | ## 前置知识 12 | 13 | Swift 语言基本知识,建议先阅读 [Swift 语言基础](../../languages/swift/index.md)。 14 | 15 | ## 环境配置 16 | 17 | 目前支持 iOS 开发的平台有 macOS 和 iPadOS。本教程基于 iOS 15 SDK,需要: 18 | 19 | - macOS:[Xcode](https://apps.apple.com/cn/app/xcode/id497799835) 13.0 以上版本 20 | - iPadOS:[Swift Playgrounds](https://apps.apple.com/app/id908519492) 4.0 以上版本 21 | 22 | 本教程基于 iPadOS 上 4.0 版本的 Swift Playgrounds,macOS 上 13.2 以上版本的 Xcode 拥有类似的环境。部分截屏在 Xcode 下获得。 23 | 24 | ## 学习资源 25 | 26 | 可以参考如下资源: 27 | 28 | - [Swift 官方文档](https://swift.org/documentation/):权威的语言和标准库参考 29 | - [WWDC Sessions](https://developer.apple.com/videos/):WWDC 上官方的 API、语言等介绍 30 | - [Stanford CS193p](https://cs193p.sites.stanford.edu/):斯坦福 SwiftUI 课程 31 | - [Stack Overflow](https://stackoverflow.com/):搜索时加上 `iOS`、`Swift`、`SwiftUI` 等关键词 32 | - [Hacking with Swift](https://www.hackingwithswift.com/):比较全面的 Swift 和 iOS 各种 API 的教程 33 | - [The SwiftUI Lab](https://swiftui-lab.com/):对 SwiftUI 的一些深度探索 34 | -------------------------------------------------------------------------------- /docs/frontend/web: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/frontend/web_foundation/Readme.md: -------------------------------------------------------------------------------- 1 | Web Foudation 2 | html.md 3 | css.md 4 | javascript.md 5 | hw.pdf 6 | -------------------------------------------------------------------------------- /docs/frontend/web_foundation/css.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### **CSS(层叠样式表)** 4 | CSS 是一种用于控制网页样式和布局的语言,它可以让开发者定义网页的外观,例如字体、颜色、间距、布局等。CSS 的主要作用是将HTML文档的结构与样式分离,从而提高开发效率和页面的可维护性。 5 | 6 | #### **1. CSS 的作用** 7 | - **样式设计**:定义字体、颜色、背景、边框等视觉元素。 8 | - **布局控制**:通过CSS的布局模型(如Flexbox、Grid、定位等)来安排页面元素的位置。 9 | - **响应式设计**:通过媒体查询(Media Queries)实现不同设备上的自适应布局。 10 | - **动画和交互**:创建简单的动画效果(如过渡、关键帧动画)和交互反馈(如悬停效果)。 11 | 12 | #### **2. CSS 的基本语法** 13 | CSS 的基本语法由选择器和声明块组成: 14 | ```css 15 | 选择器 { 16 | 属性1: 值1; 17 | 属性2: 值2; 18 | ... 19 | } 20 | ``` 21 | - **选择器**:用于选择页面中的HTML元素,例如类选择器(`.class`)、ID选择器(`#id`)、标签选择器(`div`)等。 22 | - **声明块**:包含一系列属性和值,用于定义样式。 23 | 24 | #### **3. 示例代码** 25 | ```html 26 | 27 | 28 | 29 | 30 | 31 | CSS 示例 32 | 53 | 54 | 55 | Hover over me 56 | 57 | 58 | ``` 59 | 在这个示例中,CSS 定义了一个绿色的盒子,并在鼠标悬停时放大。 60 | 61 | -------------------------------------------------------------------------------- /docs/frontend/web_foundation/foundation.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Web开发基础 4 | 5 | ### 1. Web通信 6 | Web通信是Web应用的核心,主要涉及客户端(通常是浏览器)与服务器之间的交互。其核心概念和框架如下: 7 | 8 | #### **1.1 HTTP协议** 9 | - **定义**:HTTP(HyperText Transfer Protocol,超文本传输协议)是Web通信的基础协议,用于定义客户端和服务器之间请求和响应的格式。 10 | - **请求(HTTP Request)**: 11 | - **请求方法**:常用的有GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)。 12 | - **参数传递**:可以通过路径(如`/info/aaa`)、查询字符串(如`?username=aaa`)或请求体(如JSON格式)传递数据。 13 | - **身份验证**:通过Cookies等方式实现用户身份验证,但也存在安全性问题(如第三方Cookies)。 14 | - **响应(HTTP Response)**: 15 | - **状态码**:用于表示请求的结果,如200(成功)、400(请求错误)、403(禁止访问)、404(未找到)、500(服务器错误)。 16 | - **正文**:响应中可以携带文件或数据,如HTML页面、图片等。 17 | - **HTTPS**:HTTP的加密版本,通过SSL/TLS协议实现数据加密传输,解决HTTP的不安全问题(如信息明文传输、无法验证身份等)。 18 | 19 | #### **1.2 请求与响应流程** 20 | 以网上选课系统为例: 21 | 1. 用户通过浏览器访问选课系统(GET请求)。 22 | 2. 服务器返回选课页面(200 OK状态码)。 23 | 3. 用户输入用户名和密码并提交(POST请求)。 24 | 4. 服务器验证用户信息,返回课表数据(响应正文)。 25 | 26 | #### **1.3 调试工具** 27 | - **Postman/Apifox**:用于手动发送HTTP请求,测试API接口。 28 | 29 | --- 30 | 31 | ### 2. Web页面 32 | Web页面是用户通过浏览器访问的内容,由HTML、CSS和JavaScript组成,统称为“前端三件套”。 33 | 34 | #### **2.1 HTML(HyperText Markup Language)** 35 | - **定义**:HTML是用于描述网页内容的标记语言,通过标签定义网页的结构和内容。 36 | - **常用标签**: 37 | - **文本标签**:`-`(标题)、``(段落)、``(无序列表)、``(有序列表)、``(列表项)。 38 | - **图像和链接**:``(插入图片)、``(超链接)。 39 | - **容器标签**:``(分区容器)、``(文本片段)。 40 | - **其他**:``(页眉)、`bindmodifyModelView -------------------------------------------------------------------------------- /docs/static/languages/css/1-after.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | CSS 示例 12 | 13 | 14 | 这是标题 15 | 这是段落。和我一起读: 16 | 你——好——世——界—— 17 | 18 | 前往百度 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/static/languages/css/1-before.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | CSS 示例 9 | 10 | 11 | 这是标题 12 | 这是段落。和我一起读: 13 | 你——好——世——界—— 14 | 15 | 前往百度 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/static/languages/css/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 24 | CSS 示例 25 | 26 | 27 | 28 | 红色主题 29 | 30 | 31 | 蓝色主题 32 | 33 | 34 | 绿色主题 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/static/languages/css/3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | CSS 示例 18 | 19 | 20 | 21 | 红色主题,红色链接 22 | 23 | 普通链接 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/static/languages/css/4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 56 | CSS 示例 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/static/languages/html/0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML 示例 6 | 7 | 8 | 这是标题 9 | 这是段落。和我一起读: 10 | 你——好——世——界—— 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/static/languages/html/1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML 示例 6 | 7 | 8 | HTML 文本具有丰富的格式,如加粗、斜体、删除。 9 | 标签之间可以嵌套,以表达更为花哨多样的格式。 10 | 你还可以在 HTML 文本中插入链接。 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/static/languages/html/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML 示例 6 | 7 | 8 | 这是 HTML 无序列表: 9 | 10 | 第一项 11 | 第二项 12 | 第三项 13 | 14 | 这是 HTML 有序列表: 15 | 16 | 第一项 17 | 第二项 18 | 第三项 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/static/languages/html/3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML 示例 6 | 7 | 8 | 你也可以添加图片。 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/static/languages/html/4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML 示例 6 | 7 | 8 | 9 | 10 | (1, 1) 11 | (1, 2) 12 | 13 | 14 | (2, 1) 15 | (2, 2) 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/static/languages/java/compile-and-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/java/compile-and-run.png -------------------------------------------------------------------------------- /docs/static/languages/java/create-new-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/java/create-new-project.png -------------------------------------------------------------------------------- /docs/static/languages/javascript/dom-html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DOM 操作方法演示网页 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | This is a test text node. 28 | 29 | -------------------------------------------------------------------------------- /docs/static/languages/javascript/event-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 按钮点击事件演示网页 6 | 7 | 8 | 9 | Click me! 10 | 11 | -------------------------------------------------------------------------------- /docs/static/languages/javascript/event-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 按钮点击事件演示网页 6 | 7 | 13 | 14 | 15 | Click me! 16 | 17 | -------------------------------------------------------------------------------- /docs/static/languages/javascript/event-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 按钮点击事件演示网页 6 | 7 | 14 | 15 | 16 | Click me! 17 | 18 | -------------------------------------------------------------------------------- /docs/static/languages/javascript/function-proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/javascript/function-proto.png -------------------------------------------------------------------------------- /docs/static/languages/javascript/proto-proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/javascript/proto-proto.png -------------------------------------------------------------------------------- /docs/static/languages/javascript/proto-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/javascript/proto-triangle.png -------------------------------------------------------------------------------- /docs/static/languages/swift/multiline-string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAST-skill-docers/sast-skill-docs/7a48e43087ecc5cfee0ad43688f9544d094f2482/docs/static/languages/swift/multiline-string.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs 2 | mkdocs-git-authors-plugin 3 | mkdocs-git-revision-date-localized-plugin 4 | mkdocs-material 5 | mkdocs-material-extensions 6 | mkdocs-minify-plugin -------------------------------------------------------------------------------- /theme/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | {{ super() }} 4 | {% if git_page_authors %} 5 | 6 | 7 | 作者: {{ git_page_authors | default('enable mkdocs-git-authors-plugin') }} 8 | 9 | 10 | {% endif %} 11 | {% endblock %} -------------------------------------------------------------------------------- /theme/partials/comments.html: -------------------------------------------------------------------------------- 1 | 2 | {{ lang.t("meta.comments") }} 3 | 4 | 19 | 20 | 21 | --------------------------------------------------------------------------------
`|定义段落| 25 | |`
一个段落包含一部分加粗的文字
This is a square!
We have click it for {this.state.clickCnt} time(s)!
`(段落)、`
这是段落。和我一起读:
你——好——世——界——
18 | 前往百度 19 |
15 | 前往百度 16 |
红色主题
蓝色主题
绿色主题
红色主题,红色链接
普通链接
HTML 文本具有丰富的格式,如加粗、斜体、删除。
标签之间可以嵌套,以表达更为花哨多样的格式。
你还可以在 HTML 文本中插入链接。
这是 HTML 无序列表:
这是 HTML 有序列表:
你也可以添加图片。
This is a test text node.