0%

我们是什么

这里是一个由怺加冢学计算机社团运营的校园博客网站。您可以点击关于我们查看详情。

《三社演义》第八十五回 谷先社遗诏托孤儿 司十尃安居平五路

主题:学习计算机社光荣历史,培养伟大爱社情操(?)

却说先社在永中,染病不起,渐渐沉重,至二零二三年夏四日,先主自知病入四肢,又哭金、董二弟,其病愈深:两目昏花。
……
先社命内侍扶起司博,一手掩泪,一手执其手,曰:“朕今死矣,有心腹之言相告!”司博曰:“有何圣谕!”先主泣曰:“君才十倍科帆,必能安室定社,终定大事。若嗣子①可辅,则辅之;如其不才,君可自为计算机社之主。”司博听毕,汗流遍体,手足失措,泣拜于地曰:“臣安敢不竭股肱之力,尽忠贞之节,继之以死乎!”言讫,叩头流血。
……
先社又谓众社员曰:“卿等众社员,朕不能一一分嘱,愿皆不要摸鱼,多学技术。”言毕,驾崩,寿六十三岁。时章武三年夏四月二十四日也。后杜工部有诗叹曰:“怺主窥吴向机房,崩年亦在永中学。翠华想像机房外,玉殿虚无怺冢中。古庙杉松巢蚆蛒②,岁时伏腊走摸鱼。武侯祠屋长邻近,一体君臣祭祀同。”

注释:①:指谷徐铭 ②:同“BUG”。

演员表:
谷虚怀 饰演 刘备
金日成 饰演 关羽
董车干 饰演 张飞
卢氪翻 饰演 曹丕
司十尃 饰演 诸葛亮
谷徐铭 饰演 阿斗

社团QQ群欢迎加入

你说得对,但是《忄永冢计算机社QQ群》是由忄永冢计算机社创建一个QQ群,群聊发生在一个被称作“鹰忑网”的幻想世界,在这里,被计算机社选中的人将被授予“社员身份”,导引冯诺依曼之力。玩家将扮演一位名为“社团成员”的神秘角色,在不自由的QQ群中邂逅抽象的同伴们,和他们一起聊技术、解决计算机难题、修电脑、看计算机屌图,找回失散的阿兰图灵——同时,逐步发掘 “群号是 835879517” 的真相。

乡巴佬社长

听好了乡巴佬,等我当上计算机社社长,我要指定新的社法
不学技术要扣税
摸鱼要扣税
不做任务要扣税
用机房电脑玩原神要扣税
刷B站要扣税
带非社团成员进机房要扣税
抗议以上的税要扣税!

计算机社管理方法(征求意见稿)

(注:此文件一出,计算机社yjzx股立刻下降了20%,使得GCVillager立刻撤销了此文件。)

社团宗旨

社团宗旨为创建一个供永嘉中学学生交流、学习计算机知识的场所,传播、交流、提升计算机相关的技能,促进个人全面发展。

管理人员

社团需要有2-4名在校管理人员(含社长),理想情况下应为3-4名,且为高二成员。管理人员需要在每次活动时主持讲座,同时管理机房秩序,管理社团网站,并参加学校举办的令人绝望的会议。
社团历代管理成员和部分成员组成“老东西团”,为社团活动提供帮助。

活动内容

  1. 活动分为讲授活动和实践活动。原则上,将一个月分为4周,则3周为讲授活动,1周为实践活动,即3次讲授搭配1次实践。考虑内容量、学校安排等情况,可以酌情调整为2+1或4+1。若干次讲授+一次实践称为一个周期。
  2. 讲授活动时,通常由一名管理人员讲述提前准备好的内容。当一名管理人员在教授知识时,其他管理人员需要维持秩序并准备之后活动的内容。
    在一个周期即将结束时,管理人员需要决定下个周期准备讲述的内容和实践活动的任务,并告知“老东西团”,由“老东西团”决定是否讲述该内容,或者是否进行修改。
  3. 实践活动时,所有管理人员之外的成员需要根据布置的任务,完成一定的实践,并将结果实名上传至指定位置(目前设定为极域教师端)。期间,管理人员负责管理秩序并解答疑惑。完成后,管理成员将接收到的内容打包并提交给“老东西团”,并由“老东西团”评分,评分为“优秀”“及格”“不及格”三档。如果一个成员在一学期内2次不及格,或未上交内容且事后未补交,视为“摸鱼狗”,需要离开社团,不得在活动时间进入机房。
  4. 鼓励社团非管理成员上台传授知识。如果成员有意愿,可以向管理人员提出,管理人员将该成员打算讲的内容写进下一周期的安排里提交,在得到同意后,该成员准备好内容并在下一周期的某一次活动中讲述。成员讲述的内容也可以成为实践活动任务的一部分。

浏览文章

点击文章的标题即可进入文章的页面。
为了得到更好的浏览体验,推荐使用 Firefox 浏览器Chrome 浏览器 以及 Edge 浏览器 (Win 10 自带)浏览我们的网页。手机端可以安装 Firefox 安卓版Edge 安卓版Via 浏览器
同时,我们强烈不建议使用 IE 以及各大国内浏览器(包括但不限于360,QQ,搜狗等) 。因为 IE 是出了名难兼容,而国内的浏览器(诸如360,QQ, 搜狗)大多数用了 Chromium 的内核,只有外观显示上的不同,而且内核版本通常比较滞后,不能很好地兼容很多 HTML5 特性,在较新网页的显示上可能会出现问题。
最近的文章会按照时间顺序显示在首页上,可以直接在首页进行浏览。当然您也可以点击首页左上角的“标签”,“分类”页面进行更细致的筛选。在“归档”页面能找到我们的所有文章。
我们推荐您通过标签,分类等方式进行筛选,当然如果您要搜索文章,也可以打开“归档”页面按 Ctrl+F 快捷键来搜索。

这里是网课的视频合集。我会在这里慢慢更新我们的教程视频合集。

如果有人邀请我讲课,我还会继续在这里放上我视频。这样方便大家学习。

社团介绍和 Markdown 教程

你们有什么要反馈的随时写评论.

因为录视频的时候没弄好,导致屏幕只有左上角的内容,把markdown 预览刚好截没了。

没有关系,你们可以自己在 VSCode 里面试试看。

本来稿子里还有个路线介绍的,没有讲进去。我这里附上来

我们的技术路线并不是固定的,归根结底是靠大家分享。我们网站上面这么多前端的教程是因为我个人选择的是 web 前端开发技术,并且贡献了很多文章,而其他路线没有人写文章,就变成前端占大头了。

各位如果想要写文章,也可以随时投稿我们的网站。yjzxlub 的账号我已经传了一代了,不知道下一代有没有传下去。但是有人投稿可以只管给我发邮箱,我会尽快安排。

你们还可以主动报名讲课,只要准备讲稿和提前确定主题即可,这个具体细节可以给现任社长处理。

视频已过期

作业和评价

吾乃GCVillager,离开永嘉中学已足足五分之一坤年矣。今日且让老夫来评评你们交上来的东西。
先社创社未半而中道毕业,今技术不传,成员摆烂,此诚危急存亡之秋也。
因此,我们决定推行社团改革,初步打算几次活动后有一次任务,不会很难,每个人要上交并评级。都是简单的任务,不必担心。
另外,社长要讲的内容以后要找我们讨论,不要自己搞……
具体内容会在寒假出,到时候大家可以再提建议。

注意:编辑器可以用vscode,并在拓展里面下载Markdown All In One以及Live Preview的拓展插件
这是谁说的,预览md用右上角小按钮不就能预览了,干嘛下这么多插件,快来认罪

名字后面带+的是好的,带-是不好的。希望有则改之无则加勉。
其实好几篇我都觉得不太行,但是最后没有打-号。这些同学都没有完全理解markdown,把东西往标题里塞,而且内容也少。希望端正态度。
以下内容按照上交的IP排序,请自己找自己的名字(

为了节约版面折叠了一下

点击此处展开评价

夏理超 +

非常好数学教程,爱来自大连。感觉用markdown和latex挺熟练的,厉害。
不过建议代码开头的三个点后面加上语言,这样有些网站/编辑器会按照语法渲染代码。
这个typst我还真没了解过,不过……感觉是不是用的没md多?可能暂时不考虑吧,感谢建议(

叶瑞丰

有点少,不过还行。话说为什么想食汉堡(

高一十二班的某某

有点少,下次记得用真名谢谢

吴臻恩

有点少,还有爱好很……嗯

徐润达

有点少。还有要指出,不要全用标题,该用文本的时候没必要打6个#。看来还没有完全理解md的用途

丁一德

有点少,斜体是下划线或者一个星

李添睿 +

不错,擅长使用斜体和粗体(虽然正式用的时候没必要那么多),还有感谢建议

邵友均 -

交个exe上来肯定不行,什么叫不兼容(不能理解啥意思)。而且这程序我输4个1你就退出了,健壮性差。

李新瑜

还不错。我化学也不好,加油(

潘谢纯达 -

写这么几个字上来啥意思嘛真的是

王涵轩

有点少,还行

施钧耀 +

不错。之前会教生活中用得上的知识,但是不可能每次都教这个。之后应该也考虑这样吧。

朱辰硕

不错。不过真的有必要打这么多箭头吗

吴涵

有点少。还有一二三四级标题的含义是大标题、小标题、小小标题,不是第一个第二个第三个标题。

马柏昕

不错。

马柏腾

还行。但是一二三四级标题的含义是大标题、小标题、小小标题,不是第一个第二个第三个标题。

夏文杰

别把太多不是标题的文字写在标题里。

朱贤博

好偷懒啊(
还有后面那段应该不是复制的吧……?

黄潇康

太少。

孙文卓

少。下学期会加强管理(只要社长认真执行的话)

田所浩二 -

下次用自己真名,不要把文字塞标题里,不然我让先社把你服务器DDos了(划掉)先社尼泽:?

先社:下次用“田浩”吧,万一我信了呢?

蒋昊伦

有点少。

彭劭帅

标题井号后面记得打一个空格。

潘步干

少。不要把文本塞到标题里。

潘裕琨

有点少。

郑子谦

Web 开发入门 —— 开发基础 和 HTML

上回有人和我反馈,说放视频的时间太长,不方便大家安排时间。而且统一网课的安排,就我们的观察来说,效果也并不理想。考虑到这次的主题比较泛,所以我这次就不再安排统一的网课,而是给出指导,让大家自己阅读教程。内容不难,只是知识可能有些琐碎,相信各位可以做到的。

开发基础

有些同学的计算机基础可能不是特别好,这没有关系,如果你有什么不懂的名词,可以看看我们的 基础教程,我们准备了一份对新手的计算机基础说明。

我们推荐的开发环境是 VSCode。这是适合开发的一款文本编辑器。机房的电脑一般来说都预装好了。这款编辑器因为强大的功能丰富的插件生态深受程序员欢迎。我们写 HTML 可以装一个 Live server 插件,这是一个简单的测试服务器,可以方便调试网页。直接用浏览器打开 HTML 文件是不被推荐的做法,因为如果涉及一些外部 CSS 样式和 JS 脚本,这样很可能会导致功能异常。所以通过一个测试服务器完成。

请给每个项目一个单独的文件夹,然后用 VSCode 打开这个文件。因为 VSCode 假设一个项目占据一个独立的文件夹,如果只是单独打开一个文件,会导致部分功能无法使用(包括我们的 Live Server)。

HTML

我们推荐阅读已有的教程。一节课的时间可能不够,所以请社长这边根据大家实际的完成情况再安排下时间。因为我这边看不到大家的情况。

下面的教程任选一个进行入门就可以。我们的教程是 HTML CSS JS 各部分分开的传统方式,而 MDN 的则是各个元素齐头并进,再进行拓展。各位可以按照自己的风格去学,都是殊途同归的。

英语好的同学可以试试看 freecodecamp, 他们提供了一个动态教程,还是比较生动的。

作业

这次肯定是写不完什么项目了。各位就对着 GCVillager 的教程或者 MDN 的教程上面的实例边读边敲,然后把你们的这份草稿 HTML 的文件夹(可能包含多个草稿文件)打成 zip 包交上来就可以。注意,这个文件夹是你们的项目文件夹,下次可能还要用到。我好看看各位的进度,再做安排。

作业评价和接下来的安排

这次作业轮到老社长改了😂

有几句话想对社长说:应该打 zip 包的,不是所有人都有 rar. 然后,应该审查下大家交上来的文件,不要把 MC 整合包也打进来,害得我下载下半天。

我发现大家对 HTML 的理解还是不够。一方面是浏览器太宽容了,纯 HTML 随便怎么写都能显示出一个不错的效果。一方面还是各位没有理解 HTML 的树形结构,每个元素都有自己的级别,最后形成一个严谨的结构。这点参考 MDN 的描述。

在 VSCode 中,HTML 文件里面打出 ! 就能补全

有些掌握得好的同学,可以继续推进了。掌握的不是很好的同学,可以再去回顾下教程,重新纠正下错误。其实很多时候掌握这种新概念多花点时间是正常的,等到入门之后那理解起来就很简单了。

进度更难统一了,等这节课之后大家都学会了,就可以讨论安排下期末的活动。

点击此处展开评价

潘玉捆

首先,忘了 <html> 标签。其次,忘了 <body> 标签。这是 HTML 的规范,无论哪个教程都有强调,不应该忘记。在 VSCode 中,一个 HTML 文件在打了 ! 之后就应该会出现提示,自动补全整个结构。

然后,

标签不应该大写,同时最好不要嵌套。因为很多 HTML 的标签是具有语义的,最好结合常识使用,方便大家阅读,

是 paragraph 的意思,嵌套自然段是一件很奇怪的事情。如果有样式需要导致的嵌套需求,建议使用

这种无语义元素配合 CSS 使用。

原版:

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<head>
<title>ZHESHI YIGE BIAOTI</title>
</head>
<h1>WRITER:潘裕捆 grade10 class</h114>
<P>
<P>建议加强司空震!<hr>司空震在这个赛季!<hr>竟然还被策划<strong>削弱!</strong> </P>
<p>(打中文太累了我想打拼音)</p>
<p>yi xia shi dui xue ruo SKZ de ti hui </p>
<p>shou xian shi fan xia<hr> <strong>傲慢</strong>之罪的加罗</p>
<p>qi ci shi fanxia<hr> <strong>嫉妒</strong>之罪的李信</p>
<p>weiwandaixu...(qi shi shi xia ke le )</p>
</P>

正确版本

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ZHESHI YIGE BIAOTI</title>
</head>
<body>
<h1>WRITER:潘裕捆 grade10 class</h1>
<p>建议加强司空震!<hr>司空震在这个赛季!<hr>竟然还被策划<strong>削弱!</strong> </p>
<p>(打中文太累了我想打拼音)</p>
<p>yi xia shi dui xue ruo SKZ de ti hui </p>
<p>shou xian shi fan xia<hr> <strong>傲慢</strong>之罪的加罗</p>
<p>qi ci shi fanxia<hr> <strong>嫉妒</strong>之罪的李信</p>
<p>weiwandaixu...(qi shi shi xia ke le )</p>
</body>
</html>

phr_10.145.85.62

没有名字,自己认领。交个 .minecraft 上来并不会有什么加分,只会让我因为要下载 800M 的文件而感到恼火。当然也有社长的锅。

<body> 应该是在 <head> 之后,而不是在 <title> 之后,因为他们是同级别的,身体不会长在头里面。而且全部显示的内容都应该放进 body 元素里面,就像内脏要放在身体里面一样。在 VSCode 中,一个 HTML 文件在打了 ! 之后就应该会出现提示,自动补全整个结构。

原版

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/mdn/learning-area/html/tables/basic/minimal-table.css">
<title>
996
</title>
<body><p>我不要996</p></body>
<table>
<tr>
<th colspan="3"><h2>PHR</h2></td>
</tr>
<tr>
<th><h3>我不会打英文</h3></td>
<th><h3>我不会玩游戏</h3></td>
<th><h3>我不爱玩电脑</h3></td>
</tr>
<tr>
<td>假的</td>
<td>假的</td>
<td>假的</td>
</tr>
</table>
</head>
</html>

正确版:

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/mdn/learning-area/html/tables/basic/minimal-table.css">
<title>996</title>
</head>
<body>
<p>我不要996</p>
<table>
<tr>
<th colspan="3"><h2>PHR</h2></td>
</tr>
<tr>
<th><h3>我不会打英文</h3></td>
<th><h3>我不会玩游戏</h3></td>
<th><h3>我不爱玩电脑</h3></td>
</tr>
<tr>
<td>假的</td>
<td>假的</td>
<td>假的</td>
</tr>
</table>
</body>
</html>

彭劭帅

很好,HTML 的结构是对的,语义嵌套都不错。最好把 <head> 加上,不要让你的 HTML 变成无头骑士。

徐润达

结构挺好,就是 DOCTYPE<html> 根元素没有加,成无根之萍了。

丁一德

标签写错了。多了几个 >> ,不知道是不是写 C++ 写的。<title> 里面不应该有 <strong>, 因为那个是浏览器的标签页上面的标题,不属于页面内容,这里应该是纯文本。

换行是 <br> (Break row)。

田浩

我帮你改名了。以后就叫这个。

lang 设置中文倒是还行.

喜欢弹 alert 是吧?不要用 var ,用 let ,没看 MDN 或者我的教程导致的,Remake 去。

黄潇康

html 结构全乱了。<body> 不应该在 <head> 里面,就像身体不会长在头里。同时,所有文本最好都要放在标签里面。

原版:

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
<head>
<body>
姓名:黄潇康
<hr>
<p>班级:高一7</p>
<p>爱好:<strong>玩游戏</strong>(包括玩原,星铁,Minecraft等等)及看小说</p>
<p>e不知道要写什么了</p>
<p><strong>1145141919810</strong></p>



</body>


<title>自我介绍</title>





</head>
</html>

正确版:

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title>自我介绍</title>
</head>
<body>
<p>姓名:黄潇康</p>
<hr>
<p>班级:高一7</p>
<p>爱好:<strong>玩游戏</strong>(包括玩原,星铁,Minecraft等等)及看小说</p>
<p>e不知道要写什么了</p>
<p><strong>1145141919810</strong></p>
</body>
</html>

施钧耀

HTML 结构正确,嵌套合理整齐,非常好。我稍微修了一下缩进。

点击此处展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>自我介绍2.0</title>
</head>

<body>
<h1>自我介绍2.0</h1>
<h2>1.信息</h2>
<p>性别:男</p>
<p>名字:施钧耀</p>
<p>状态:<strong>aaaaaaaaaaaaa</strong></p>
<h2>2.爱好</h2>
<p><em>玩原神</em></p>
<p>粥(</p>
<p>看旁边的发电</p>
<h2>3.建议</h2>
<p>好诶</p>
<hr>
<p><a href="https://yjzxclub.github.io/16030018f428/">来源</a></p>
</body>

</html>

马柏昕

也是 DOCTYPE<html> 忘了加。

课程能看懂就行,术语什么不重要,搜索引擎搜一下的事情。加油!

吴涵

槽点挺多的。应该有个 HTML 的结构。<html> <head> <body> 这些还是要有的。而且标题和段落应该是并列关系而不是嵌套关系。

可以再去看看 MDN,注意自己在写的是一个文档,应该有文档的语义。

潘步干

<html> 根元素没加,然后是 <body> 没加。 <strong> 这些不是块级元素最好不要直接放在 <body> 里面而是放在其他块级元素里面。其他倒是没什么毛病。

吴臻恩

<strong> 不是块级元素最好不要直接放在 <body> 里面而是放在其他块级元素里面。其他都没毛病,结构层次很好。

王涵轩

最好要完整的 HTML 文件,而不是一个 HTML 片段。 <li> 不应该单独出现,应该最为 <ul> 或者 <ol> 的子元素。

马柏腾

<html><body> 是需要的,文档的层次倒是没问题。

夏文杰

很好,虽然 <html> 忘记了。不需要 <br>,块级元素会自己换行

朱贤博

HTML 结构都没问题,不错,就是内容稍微少点。为什么不打算试试学过的标签呢?

周嘉泰

不懂。你是想教我 DP 么?那我觉得应该不必。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<bits/stdc++.h>
using namespace std;
#define re(i,a,b) for(int i=(a);i<=(b);i++)
#define er(i,a,b) for(int i=(a);i>=(b);i--)
int n,u[100005],d[100005],pre_u[100005],pre_d[100005],
maxsum_left_d[100005],maxsum_right_d[100005],
maxans_left[100005],
ans=-0x3fffffff;
inline void upd(int &a,int b){
a=max(a,b);
}
signed main(){
memset(maxans_left,~0x3f,sizeof(maxans_left));
ios::sync_with_stdio(false);
cin>>n;
re(i,1,n){
cin>>u[i];
pre_u[i]=pre_u[i-1]+u[i];
}
re(i,1,n){
cin>>d[i];
pre_d[i]=pre_d[i-1]+d[i];
}
re(i,1,n){
maxsum_left_d[i]=d[i]+max(maxsum_left_d[i-1],0);
}
er(i,n,1){
maxsum_right_d[i]=d[i]+max(maxsum_right_d[i+1],0);
}
re(i,2,n-1){
maxans_left[i]=max(maxans_left[i-1]+u[i]+d[i],
u[i]+d[i]+maxsum_left_d[i-1]);
}
re(i,2,n-1){
upd(ans,maxans_left[i]+maxsum_right_d[i+1]);
}
cout<<ans<<endl;
return 0;
}

孙文卓

完美的结构,很好,值得表扬。一看就是 VSCode 补全的,连 lang="en" 都没改。

朱辰硕

标签不应该大写,应该是 <p> 。在 <h1> 里面套 <p> 是一件比较困惑的时期,一句话不应该既是标题又是段落。而且段落套段落也不好。如果你很需要,就用 <div> 这种无语义元素,不会出现语义理解问题。

谢奥挺

不应该把全文丢进 <p> 标签,因为不应该把标题放在段落里面,也不应该让段落变成段落中的段落。如果是为了显示效果,可以用 <div> 这种无语义元素。

李添睿

HTML 的片段很好,考虑写成完整的?加油!

感谢推荐!可惜我离得很远已经不了解社团现状,不能插手社团的人事,你们可以自己来。

蒋昊伦

HTML 的结构很不错, 加油!时间没关系,没写完的这节课可以继续写。

Jin Peiyun

虽然 Markdown 可以内嵌 HTML, 但是问什么不直接用 HTML 呢?

还是那句话,要给用户看的内容都得写在 <body> 里面,标签最好也要纯小写。

郑子谦

有个 <hr> 漏到 <body> 外面了。而且 <p> 忘了 </p> 的结束标签。<title> 里面要纯文本。问题还是挺多的,仔细改改。

潘谢纯达

HTML 的结构很不错,就是 <h1> 作为一号标题,一个页面最好只用一次。多次使用的应该是 <h2> 或者 3456 这种小标题。

夏理超

结构很好,嵌套列表的思路很清晰。细节不错,lang="zh-cn" 试试加点 CSS?

地图 project

这是一个简单的团队合作的挑战项目,主要锻炼前端编程能力以及团队协作的能力。

需求介绍

Tux 前不久接到了一个任务,要做个小游戏。结果把这个事情忘记了,现在对面要看进度,但是它只画了一些地图。为了糊弄对方,现在需要你写个网页展示这些地图,假装这个游戏正在开发。

地图是一个 .zip 格式的文件,根目录下面有这么些文件

1
2
3
4
5
6
7
8
wall.png
floor.png
start.png
end.png
mp1.txt
mp2.txt
...
mp*.txt

其中,mp*.txt 是地图,**可能有一个或者多个(最多九个,不用考虑两位数)**。*.png 则是一些图片文件,每一张 32px*32px 大小。这四个张用来显示地图。

mp*.txt 里面的内容是一个 N*M 的矩阵(N <= 20, M <= 20) (也就是最大面积 640*640 像素),大概看起来是这样的。(当然实际上肯定不是这样子的,不然就可以直接写成静态网页了)

1
2
3
4
5
6
########
##....##
#..##..#
#S###.##
#...#.E#
########

其中 # 代表墙壁 (wall.png),. 表示地板 (floor.png), S 表示开始 (start.png),E 表示结束 (end.png)。

你需要的是把它显示出来,每个字符对应成一张小型图片,这样排列成为一个二维的地图,比如这样子:

maping

鉴于地图应该是存在本地,读档之后进行操作,那么我们的页面应该是要用户手动上传地图文件到页面,之后经过一系列操作,转到另一个显示地图的页面。

比如可以长这样

drag file

显示地图的页面最好要支持多个地图。这是一种可能的 UI,通过一个轮播图片的形式来展示,左右按钮进行地图之间的切换。当然你也完全可以用更好的方法。

preview

样例

这是用于测试的地图文件

map.zip

帮助与提示

帮助

解析 zip 包需要用到一个叫做 zip.js 的库。鉴于对上传文件的解析操作过度复杂,而且也不属于前端基本功,我决定自己写好这一个函数,把 input 的 event 里面那个文件的引用传给这个函数,函数就可以把解析好的地图放进一个对象返回回去。这样可以方便大家开发。

一个用于参考的例子,示范了如何导入这个库并且使用,下载链接如下:

下载

这是一个在线的页面,是上面的例子部署到 Github pages 上面 https://yjzx-site.github.io/zipExample/。选中自己的地图 zip,就可以看到材质和地图显示出来了。

这是个 async 函数,声明如下。需要加上 await 调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
*
* @typedef {Object} ResolvedMap
* @param {ObjectURL} wall - 墙壁图片的引用,下同
* @param {ObjectURL} floor
* @param {ObjectURL} start
* @param {ObjectURL} end
* @param {Array<String>} maps - 每个 map 文件的内容的字符串,包括换行(最后文件尾也有换行)
*/

/**
*
* @param {File} zipFile
* @returns {ResolvedMap}
*/
async function resolveFileToObject(zipFile) {
/** waiting for further update */
}

一个返回值的例子

1
2
3
4
5
6
7
8
9
10
11
12
{
wall: [一个 ObjectURL,直接使用],
floor: [同上],
start: ,
end: ,
map: [
"########\n##....##\n#..##..#\n#S###.##\n#...#.E#\n########",
"########\n##....##\n#..##..#\n#S###.##\n#...#.E#\n########",
..
.
]
}

提示

(待更新)

评分标准

每点 10 分。

功能 (60分)

  • 能够拖进文件,并对这个文件进行操作
  • 能够接受 Myfunc(提供的解析 zip 包函数) 的返回值,并且尝试解析
  • 成功解析同时尝试打印到 div
  • 成功打印到一个 div,并可正常显示
  • 可以进行返回再上传新的地图
  • 完整,与UI结合

UI (40分)

  • 有一个主页,显示上传控件,包括选择上传和拖拽上传
  • 有一个展示地图的页面,可以切换当前显示的地图,比如切换 mp1 mp2 之类。方法不限
  • 可以显示当前文件名,有“返回上页”的按钮
  • 要拥有一个美观的页面框架,不要裸控件

现在,到了让我们上手做个项目的时候了。

鉴于很多人还没有做项目的经验,我们决定先从一个最简单的项目开始,向大家讲述一个项目的制作流程。

就让我们做一个 Markdown 在线编辑器吧!

明确需求

首先,我们需要明确自己的需求。一个编辑器要有什么功能呢?首先肯定是要有能输入 MD 的框框,另外还要能够根据用户的输入进行实时预览,这才有个在线编辑器的基本功能。

程序设计

有了基本的需求,下一步要进行的就是程序的设计了。这个程序设计,我们按照管理分成两个部分。UI 和逻辑。UI,就是所谓的 User Interface,是直接展现给用户的部分,能够给用户看见,相当于一个外壳。逻辑呢,就是内部的操作,这些用户没法直接看见,但是给程序提供了内部的功能。两者合起来,就是一个完整的程序了。我们分别进行设计分析。

UI 侧

我们应当提供这些东西:

  • 一个给用户进行输入的框
  • 一个展示生成的预览效果的框

有了这个以后,我们就可以用画图软件画出大概的界面来了。左侧一个输入,右侧一个预览,各占网页的一半。

逻辑侧

我们应该有这些功能:

  • 获取用户的输入
  • 转换成对应的 HTML
  • 将 HTML 输出到指定的地方,渲染出来

接口

你可以看到,这两个之间的相互独立的部分,可是也要有一些地方让它们联系起来。比如 UI 的输入框和输出框,以及逻辑的输入和输出,就应该联系在一起。这种联系,我们管它叫做接口。

在前端工程当中,实现接口方式很多样。最简单的应该有两种。一种是接在 HTML 上,是把对应的某些功能的块加上指定的 class 或者 id, 交给 JS 程序接管。一种是用自己的简单的 JS 程序调用别人封装好的 API,然后传给自己的网页。这两种方法应当按照实际情况灵活使用。

我们这个例子里面,UI 和逻辑部分的接口,就可以用给指定的块加上 class 的方式,来使两个结合起来。

合作

有了这些分析之后,你们也许会发现,这两个工作可以交给不同的人来完成,最后组合成一个完整的程序。事实上,这就是分工合作的基础。把大的程序拆成不同的小块,然后交给不同的人完成,最后组合起来。

所以这个程序,大家要分 2-3 人一组,自己尝试去完成。我们把这次和下次活动的时间都给大家去做。

一个示例

我自己写的一个例子。

文件下载

来源:https://www.cnblogs.com/sqchen/p/10757927.html
暂未获得作者授权且不知道是否允许转载,如有侵权请联系gcv8040@qq.com

一、环境准备

使用Github Pages搭建个人博客,一劳永逸,可以让我们更加专注于博客的撰写。博客的更新是通过将新建或改动的博客放在指定文件夹并推送到远程Github仓库来完成的,所以我们本地需要有Git环境,如果还没有安装Git,可以看下面的文章:

  1. 安装Git
  2. Git关联远程GitHub仓库

二、搭建博客

1、新建仓库

username.github.io作为仓库名字。

2、本地克隆

本地创建文件夹,用于存放远程仓库,打开所创建的文件夹,右键选择git bash here,表示在当前目录打开git bash程序,然后执行如下命令,将刚才创建的仓库克隆到本地:

git clone https://github.com/AmazingChen/amazingchen.github.io.git

如果步骤1中创建仓库时,没有勾选Initialize this repository with a README,将有如下提示:

warning,可以忽略,或手动在远程仓库创建一个readme.md,然后重新clone

3、新建主页

在仓库文件夹下创建index.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>

</head>
<body>
<p>hello, my first page!</p>
</body>
</html>

4、推送到远程仓库

在仓库文件夹下,右键选择git bash here,然后执行命令:

1
2
3
git add --all
git commit -m "add index.html"
git push origin master

5、验证

成功push到远程仓库后,访问 username.github.io,看到如下界面,就表示成功通过Github Pages搭建了个人的博客。

三、更换主题

上面裸奔的博客主页,跟原始人类一样,你一定不满意,我们穿越几千年文明,直接站在巨人的肩膀上,选一套主题吧。

Github Pages基于Jekyll构建,**Jekyll** 可以帮助我们把纯文本转换为静态博客网站,实现一劳永逸。

你可以在JekyllThemes找到喜欢的主题,也可以在其他地方找。

“I want you, Vno-Jekyll.” 我选择Vno。

1、下载主题

下载后,首先将我们仓库文件夹下的文件清空,但是要保留.git文件夹:

然后将下载的主题压缩包解压到仓库文件夹下,结果如下:

访问 Jekyll-目录结构 详细了解每个文件夹的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── _config.yml
├── _drafts
| ├── begin-with-the-crazy-ideas.textile
| └── on-simplicity-in-technology.markdown
├── _includes
| ├── footer.html
| └── header.html
├── _layouts
| ├── default.html
| └── post.html
├── _posts
| ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
| └── 2009-04-26-barcamp-boston-4-roundup.textile
├── _site
├── .jekyll-metadata
└── index.html

2、搭建Jekyll环境

只有主题文件是不够的,我们需要搭建Jekyll环境,通过遵循Jekyll的规范,让Jekyll帮助我们生成静态网站。

(1) 安装Ruby:Ruby安装教程
注:需要安装带有devkit的版本哦!

(2)打开CMD,执行命令安装Jekyll:

gem install jekyll

(3)进入仓库文件夹,执行命令:

bundle install

注意,必须进入仓库文件夹下再执行上述命令,否则会有如下提示,表示bundle找不到gemfile文件:

Rails 3中引入Bundle来管理项目中的所有Gem依赖,该命令只能在一个含有Gemfile的目录下执行,bundle install 命令将尝试更新系统中已存在的gem包。更多参考:bundle install 命令

(4)启动Jekyll服务

bundle exec jekyll serve

启动Jekyll服务时,可能会遇到如下错误:

error: Jekyll::Converters::Scss encountered an error
1
2
3
    while converting 'css/main.scss':
Invalid GBK character "\xE2" on line 10
jekyll 3.4.0 | Error: Invalid GBK character "\xE2" on line 10

很明显,是编码问题,参考网上方法解决 Invalid GBK character “\xE2” 过程中的发现,找到D:\RailsInstaller\Ruby2.3.3\lib\ruby\gems\2.3.0\gems\sass-3.7.2\lib\sass.rb文件,在require后追加:

Encoding.default_external = Encoding.find('utf-8')

然后重新启动Jekyll服务,看到如下打印,表示启动成功:

(5)验证

访问 http://127.0.0.1:4000,当你发现你的博客首页从一个原始人变成光鲜亮丽的现代人时,表示博客主题已经应用成功了。

(6)推送到远程仓库

做完上述操作后,由于还没有将修改提交到远程仓库,所以当你访问username.github.io时,你看到的还是一个光溜溜的原始人,执行以下命令完成进化吧皮卡丘:

1
2
3
git add .
git commit -m "apply theme"
git push origin master

成功推送到远程仓库后,等待几分钟,访问username.github.io,OK,成功。天黑请闭眼,有问题请留言。

四、发布博客

在仓库文件夹下,进入_posts目录,所有的文章都必须放在_posts文件夹下,访问 Jekyll-目录结构 详细了解每个文件夹的功能。

以markdown文档为例,按照如下格式创建md文件。

yyyy-MM-dd-filename.md

完成后push到远程仓库,即可完成更新。

五、修改主题

将网站的信息改成自己的,修改_config.yml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Basic
title: 陈贤靖
subtitle: 井与陆地,海和岛屿。
description: Android Developer.
creator: <a href="http://onev.cat">@onevcat</a>

url: "https://amazingchen.github.io/#blog"

permalink: /:year/:month/:title/

# Format
highlighter: rouge

# supported colors: blue, green, purple, red, orange or slate. If you need clear, leave it empty.
# cover_color: red

# The blog button should not be removed.
blog_button:
title: Blog
description: Visit blog

# Navigation buttons in the front page.
nav:
- {title: Projects, description: My Projects, url: 'https://github.com/AmazingChen/VHabit'}
# - {title: Another Button, description: A button, url: 'http://example.com'}

# Pagination
plugins: [jekyll-paginate]
paginate: 10
paginate_path: "page/:num/"

# Comment
comment:
disqus: vno-jekyll
# duoshuo:

# Social
social:
github: AmazingChen
mail: shixianjingla@gmail.com

# Google Analytics
ga:
# id: your_ga_id
# host: your_host


如果你对这套主题不太满意,并且具备web基础,可以动手修改。

如果不想博客数据被人轻易获取,建议将github仓库设置为私有。

修改之后,我的博客长这样:陈贤靖


完。

创建一个Github Repository

Repository,有人译为仓库。我们就叫它仓库好了,或者称为repo,因为单词我不会拼。

首先我们需要创建一个仓库,登录你的账号,点击右上角的“+”号,在出现的页面里点击“New repository”,然后就会出现创建仓库的页面。

创建仓库

如图,在这个界面里:

第一个框写repo的名字,要求不能与自己已有的repo重名。可以起一个很响亮的名字。 也可以:“好过分!我要给它取一个很难听的名字!” 由于我们现在的教学是以搭建github博客为主题的,所以建议你命名为:[你的Github用户名].github.io。当然,其他时候就随便命名。

第二个框是简介,可以让人看到你这个仓库的时候更快知道这是什么。可以不写。

第三个框是选择仓库是公开还是私有。如果公开,所有人都可以看到源码;如果私有,只有自己和被自己邀请的人能看到。私有仓库有一些限制。

为了使用方便,我们把“Add a README file”点起来。就是第四个框的内容。

第五个框,完成之前的内容后,点击就可以创建一个新的repo。

于是你的账号下面就有了一个repo。现在,访问https://github.com/[用户名]/[repo名]即可看到你的仓库。此刻,你的仓库里空空如也,只有一个README文件。

clone仓库

现在我们的仓库在Github上托管着。我们需要把仓库下到本地来。

你可能会问:Github上不是可以直接修改吗?为什么不直接那么做?因为有的时候我们需要一次性执行大量更改,直接在Github上改可能会导致历史版本非常混乱。再说,直接在本地改,可以用功能更强大的软件,不是更好吗?

于是我们回到把仓库clone下来这个主题上。找到你希望存仓库的地方,右键,Git Bash Here。现在出来一个黑框框了。此黑框者,人称 Git Bash 。输入以下命令:

$ git clone https://github.com/[用户名]/[repo名].git

比如说我的用户名是GCVillager,仓库名是GCVillager.github.io,就输入这个指令:

$ git clone https://github.com/GCVillager/GCVillager.github.io.git

然后它就会开始 高 速 下 载

接下来,原先那个文件夹里就会多出来一个文件夹,名字和你的仓库名是一样的。你可以直接在刚刚用的那个 Bash 里输入这样的指令,进入这个新出现的文件夹里:

$ cd [路径名]

你也可以在系统里进入这个文件夹,再打开一个新的 Git Bash 。

提交更改

假设你在里面加了你要加的文件,现在要把这个仓库提交到 Github 上,该怎么做呢?
在 Git Bash 里输入这样一串玩意:

$ git add .
$ git commit -m "[一段关于这次更改的描述]"
$ git push

于是你的玩意就会开始 高 速 上 传 。完成之后,再去 Github 上看,就能看到你的仓库的更新内容了。

不过既然 Git 是有多人合作的用途的,如果你 clone 仓库之后,有人更改过 Github 上的内容了,你 push 上去岂不是会覆盖别人的内容?我们需要在这三道指令最前面加上这样一道:

$ git pull

这指令会将远端的内容同步过来,并合并。你在本地的修改当然不会丢失。这样就完成了多人协作的目的。

演讲

为了总结这个学期的活动,我也准备一个演讲。

这个学期的活动,我们应该是做了不少的。

首先是我们的前端技术,HTML 和 CSS ,都已经进行了一些基本的了解,做一些简单的项目肯定是没有问题了。但我也是有点错误估计了这个技术的难度,定下了太高的目标,搞得一开始走掉了不少人,好在及时调整过来了。

其次我们在次之外也进行了一些额外的活动。就比如说从Bilibili上面下载视频、番剧,给一些视频加字幕(打轴),还有一些装软件,装浏览器这些基本的计算机技巧。了解了这些,虽然看上去没有什么用,但是在面对电脑的时候,除掉打游戏,是不是又多出来一些可以干的事情了?

对于前端的学习,我觉得还是有必要的。虽然看起来可能有点“硬”,比较难啃,但是完全不啃硬骨头,似乎对一个技术类的社团来说,也不是很好。毕竟各种小技巧看起来很酷,可实际产出还是要实打实的知识。

所以我们这个学期是有收获的,可能没有我最开始画下的饼那么大,不过也不能说没有。

讲完过去,我们再谈谈未来。下学期我还会带大家进行一个学期的活动,之后我们高二退下来,社团就要换届了。我们现在实际上的人数已经不到三十个,如果下学期要开活动可能还要二次招新。我们会在高一发传单,你们也可以拉人。

新的社员只好让他们补一下计算机基础知识,你们老社员就可以根据自己的兴趣来,可以去做一些实际的作品,也可以继续深入学习硬知识,还可以去整一些计算机小技巧。一个学期的时间很够了,到时候大家应该都可以有拿得出手的东西。计算机的东西很多,我们不可能真的说完完全全带着大家全部过一遍,最好的方式就是你自己走。我就在寒假里面给大家理出来一些大体的方向。

我希望大家可以珍惜这个发展自己兴趣的平台。我们几个都是原先在电脑上面花了不少时间的,对于各个领域都有一些基本的了解,也各有专长。如果你有什么东西想要学习的话,我们基本都可以给出大体的路线,比你们自己到时候独自摸索,肯定是能节约不少时间的。我初中的时候,就是在这里浪费了不少时间。大家现在就不用走这么多弯路。

好的,大概就到这里。现在我说下这个活动的安排:我们要通过这次活动,选出来两个优秀社员。下面算是通过:

  • 完成 Must do ,和所有 Basic
  • 完成 Must do ,两个 Basic 和一个 Medium
  • 单个 Extend

至于 VERY HARD 里面的,做出来一个下一任社长就是你了!

Contests

Must do

给下面两个仓库点 Star (目的是为了看是否有 Github 帐号,当然也有你懂得原因):

Basic

给指定的 Github 仓库提一个 Issue。暂定 https://github.com/yjzx-site/yjzx-site-source

在 Github 新建一个仓库,使用 Git 上传一些文件。要求本地用 Git,而不是在 Github 网页上传。(这个用 commit 可以查的)

下面有一个文件是 GB2312 的 txt,你需要转成 UTF8。(下载过去自己解压)

txtfile

获取一张屏幕截图,并且在上面加上一些文字。

用 Markdown 写一篇一百字以上的文章,要求有标题和五个以上的段落。

Medium

用 HTML 语法写出下面的内容,文本不需要完全一致,但是元素都要有,要求语义结构清晰。

HTMLtest

使用 CSS 实现一个卡片,里面包含标题和介绍。下面是 HTML 部分:

1
2
3
4
5
6
7
8
<div class="card">
<h1>Card Title</h1>
<p>A simple discription of this item.</p>
<ul class="infos">
<li>Auther</li>
<li>2077-07-07</li>
</ul>
</div>

效果图:

CSStest

Extend

很短,很难。

  1. 给 yjzx-site.github.io 投稿一篇文章,要求遵守规范。
  2. 安装 Apache Httpd,并且能让别人内网访问自己的服务器。

VERY HARD

  1. 安装一个 MinGW。
  2. 在 USB Flash Disk 中安装 Arch linux。
  3. 编译一个 openssl。
  4. 现场攻陷我们的内网服务器。
  5. 拿下学校门禁系统。

我们发现没有文字版教程的情况下,大家很难跟上节奏。所以我们决定继续写文字。

什么是Github?什么是Git?

GitHub是一个面向开源及私有软件项目的托管平台。因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。在Github上,你可以分享自己的代码,或者学习他人的代码;可以托管自己的代码,实现版本管理;可以在协议许可的情况下使用他人的代码;可以使用Github和团队成员协作。

Git则是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。我们使用Github,就必须了解Git。

额……上面的东西是不是说了和没说一样?

安装Dev-sidecar

由于一些懂的都懂的原因,Github访问会遇到一些问题。为此,我们需要一些工具。
前往这里下载。
安装完成后,打开软件,会看到一个类似这样的页面:

安装根证书

这里你们的页面和我的是不一样的,按照自己的页面去做。图片很详细,不用我多讲了吧。

这一步完成之后,还不行。我们只是把根证书安装在了系统里,但是Firefox里还需要再安装。打开浏览器,你可以看到右上角有一个三条杠的按钮。点击它会出现一个下拉栏,你可以在里面找到“设置”选项。

安装根证书到浏览器

如上图,在设置里选到“隐私与安全,在“安全-查看证书”里点“导入”,接下来你需要找到.crt文件的位置,并选中。

那个.crt文件在 C:\Users\(用户名).dev-sidecar 文件夹内。社团的计算机用户名是Administrator,也就是说文件在 C:\Users\Administrator.dev-sidecar 路径下。如果你没有Users文件夹,那就是“用户”文件夹。

安装根证书到浏览器

接下来弹出这样一个页面。注意:两个选项都要勾选!然后点击确定。

如果一切正常的话,访问GithubUserContent就会自动跳转到Github。这样就成功了。另外,以后访问Github的时候,一定要加上https,即:https://github.com。

安装Git

有了这个工具,我们可以更方便地访问Github了。那么,使用Github就一定要使用Git;我们先去安装Git。

搜索引擎搜索Git,或者直接访问 https://git-scm.com/ ,就可以找到Git的官网。在右下角你能看到一个长的像电脑屏幕的玩意,里面有一个“Download for Windows”的按钮。点进去之后是这样一个页面:

下载Git

点击红色框里那个,就可以下载了。

下载完成之后,点击打开安装包来安装。接着是一大堆英文的东西,看不懂就算了,你只需要把同意协议的页面勾了,一路Next就好了。

完成之后,在一个文件夹里右键,就可以看到“Git Bash Here”。如果有这个,就安装成功了。

使用Github

首先创建一个Github账号。这个我真的不想讲了,就点那个“Sign Up”,一路跟着走就好。如果看不懂就复制到机翻里翻译。

创建完成之后,我们还需要申请一个token。token是什么?

我们登录网站需要密码。密码这东西给别人知道了,别人就可以随意操纵你的账号。token这东西是一段长得乱七八糟的文本,类似于密码,不过一个账号可以同时有很多token,但是只会有一个密码。

在登录Github网址时,我们依然使用密码而非token。但是使用Git推文件到Github的时候,在那个输密码的框里就需要使用token。

那么接下来我们创建一个token。登录Github,点击右上角你的大头像,在下拉栏里点击Settings。然后在左边的菜单栏里找到Developer Settings,暴扣它。在跳转到的页面里有Personal access tokens,再暴扣它。你可以在这个页面里找到Generate new token,点!

接下来你就进入了创建新token的页面。如图:

创建token

第一个框里的是提示,告诉你自己它是干什么的;第二个框里是过期的日期,默认30天,你可以改成no expiration让它永不过期;第三个框(以及下面一长串东西)是这个token的权限,包括修改repo、创建删除repo等。框里选的部分是修改repo(不包括删除)的所有权限,我们只需要把这个框整个勾起来就好了。然后翻到最下面,点Generate token完成生成。

复制token

然后点击图中框起来的那个按钮就可以复制了。注意,请一定记下来,比如写成txt放在u盘里,不然下次它就看不到了。不过忘了也没关系,点到那个token里面,可以再次生成。

别想偷偷使用我的token,那个token我已经删掉了。

经过了几个月自己写 JS 的几个项目,我觉得有几个概念也很有必要介绍一下。但是我没有那么多时间去重写教程了。所以就引用别人的链接好了。

这里我们补充一些其他的 JS 教程的链接。推荐去按顺序阅读它们。如果是英语的,可以点击网页右边的”English (US)”,将其换为”中文(简体)”

闭包

和大多数其他语言不一样,JS 的函数里面可以创建函数。这种函数叫做闭包,它有许多有意思的行为,有时候让许多操作变得简单。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

面向对象编程

面向对象是一个很重要的编程理念,在项目当中灵活使用面向对象的思想,有时候能够起到事半功倍的效果。

JS 是一个多范式编程语言,也支持面向对象的特性。这篇文章讲述了 JS 当中面向对象的各种方式,你可以一一了解它们。不过我建议对于构造器函数了解本质即可,真正在工程实践的时候尽可能使用 Class,因为后者语法更加简洁易懂,不容易出错。

https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects

Class 的介绍:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes

异步

异步设计可以说是 JS 当中的亮点。这也是因为 JS 经常需要遇到异步相关操作。异步有传统回调,Promise 和 async/await 三种方式。同样的道理,我们建议大家了解所有方法,但是尽量使用 async 来进行异步操作。

https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Asynchronous

模块

模块可以用来和 class 结合,使得项目更加有逻辑性。我们建议在较大的项目上面使用模块来管理各个部分的逻辑。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules

本文按照 Mozilla 贡献者基于 CC-BY-SA 2.5 协议发布的以下文章改编:

本文基于 CC-BY-SA 4.0 协议发布。

很抱歉现在才提到 DOM,这在 JS 教程里面可以算是一种异类了。但是我觉得这是有必要的。因为事先了解一点点程序的运行逻辑,可以少犯一点错误。有句话是这么说的,拿着一把锤子,看啥都想敲两下。JS 不是锤子,而是一个非常强大的工具,所以事先了解再步入,肯定会减少很多不必要的麻烦。

到这里我们的教程就是最后一章了。之后的如果有需要的内容,可能就需要大家通过自己去网上查找相应的文档进行学习了,我们不可能面面俱到,路还是要自己走的。

废话不多说,开始我们的内容吧!

什么是 API

我们之前好像已经提过了,但是已经时隔很久了,所以再讲一次。

应用程序接口(API,Application Programming Interface)是基于编程语言构建的结构,使开发人员更容易地创建复杂的功能。它们抽象了复杂的代码,并提供一些简单的接口规则直接使用。

来看一个现实中的例子:想想您的房子、公寓或其他住宅的供电方式,如果您想在您的房子里用电,只要把电器的插头插入插座就可以,而不是直接把它连接到电线上——要不然实在太可怕了。

同样,比如说,编程来显示一些3D图形,使用以更高级语言编写的 API (例如 JavaScript 或 Python )将会比直接编写直接控制计算机的GPU或其他图形功能的低级代码(比如 C 或 C++ )来执行操作要容易得多。

JavaScript 中有很多可用的API — 他们本身并不是 JavaScript 语言的一部分,却建立在 JavaScript 语言核心的顶部,为使用 JavaScript 代码提供额外的超强能力。他们通常分为两类:

  • 浏览器 API 内置于 Web 浏览器中,能从浏览器和电脑周边环境中提取数据,并用来做有用的复杂的事情 。我们的 DOM 就是浏览器 API。
  • 第三方 API 缺省情况下不会内置于浏览器中,通常必须在 Web 中的某个地方获取代码和信息。例如大名鼎鼎的 JQuery,一个轻量级前端框架,适合一些简单的网页。

浏览器内部的 API 又分这么多种:

  • 操作文档的 API 内置于浏览器中。最明显的例子是DOM(文档对象模型)API,它允许您操作HTML和CSS — 创建、移除以及修改HTML,动态地将新样式应用到您的页面,等等。每当您看到一个弹出窗口出现在一个页面上,或者显示一些新的内容时,这都是DOM的行为。 您可以在在Manipulating documents中找到关于这些类型的API的更多信息。
  • 从服务器获取数据的API 用于更新网页的一小部分是相当好用的。这个看似很小的细节能对网站的性能和行为产生巨大的影响 — 如果您只是更新一个股票列表或者一些可用的新故事而不需要从服务器重新加载整个页面将使网站或应用程序感觉更加敏感和“活泼”。使这成为可能的API包括XMLHttpRequest和Fetch API。您也可能会遇到描述这种技术的术语Ajax。您可以在Fetching data from the server找到关于类似的API的更多信息。
  • 用于绘制和操作图形的API目前已被浏览器广泛支持 — 最流行的是允许您以编程方式更新包含在HTML <canvas> 元素中的像素数据以创建2D和3D场景的Canvas和WebGL。例如,您可以绘制矩形或圆形等形状,将图像导入到画布上,然后使用Canvas API对其应用滤镜(如棕褐色滤镜或灰度滤镜),或使用WebGL创建具有光照和纹理的复杂3D场景。这些API经常与用于创建动画循环的API(例如window.requestAnimationFrame())和其他API一起不断更新诸如动画和游戏之类的场景。
  • 音频和视频API例如HTMLMediaElement,Web Audio API和WebRTC允许您使用多媒体来做一些非常有趣的事情,比如创建用于播放音频和视频的自定义UI控件,显示字幕字幕和您的视频,从网络摄像机抓取视频,通过画布操纵(见上),或在网络会议中显示在别人的电脑上,或者添加效果到音轨(如增益,失真,平移等) 。
  • 设备API基本上是以对网络应用程序有用的方式操作和检索现代设备硬件中的数据的API。我们已经讨论过访问设备位置数据的地理定位API,因此您可以在地图上标注您的位置。其他示例还包括通过系统通知(参见Notifications API)或振动硬件(参见Vibration API)告诉用户Web应用程序有用的更新可用。
  • 客户端存储API在Web浏览器中的使用变得越来越普遍 - 如果您想创建一个应用程序来保存页面加载之间的状态,甚至让设备在处于脱机状态时可用,那么在客户端存储数据将会是非常有用的。例如使用Web Storage API的简单的键 - 值存储以及使用IndexedDB API的更复杂的表格数据存储。

我们要介绍的 DOM 就属于浏览器内部 API,并且已经几乎被作为 JS 的一部分看待。

API 通常是基于对象的。它们就像普通的对象一样,拥有各种方法,可以进行调用,然后做出你想要的事情来。

DOM 树状结构

DOM 就是用来改变网页 HTML 的内容用的。这可以让你做很多光靠 HTML 本身做不到的事情。

在浏览器标签中当前载入的文档用一个 document 对象来表示。这个对象是一个树状结构。比如这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Simple DOM example</title>
</head>
<body>
<section>
<img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
<p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p>
</section>
</body>
</html>

显示成为一个树状结构是这样子的:

tree

看到这个你想到了什么?对,就和电脑的文件夹一样,一层一层往下套。我们把每个 HTML 元素对应在树中的入口称为节点。我们有这么几个术语:

  • 元素节点: 一个元素,存在于DOM中。
  • 根节点: 树中顶层节点,在HTML的情况下,总是一个HTML节点(其他标记词汇,如SVG和定制XML将有不同的根元素)。
  • 子节点: 直接位于另一个节点内的节点。例如上面例子中,IMG是SECTION的子节点。
  • 后代节点: 位于另一个节点内任意位置的节点。例如 上面例子中,IMG是SECTION的子节点,也是一个后代节点。IMG不是BODY的子节点,因为它在树中低了BODY两级,但它是BODY的后代之一。
  • 父节点: 里面有另一个节点的节点。例如上面的例子中BODY是SECTION的父节点。
  • 兄弟节点: DOM树中位于同一等级的节点。例如上面例子中,IMG和P是兄弟。
  • 文本节点: 包含文字串的节点

可能会有点难理解,但是在实际查阅文档的时候,你将会遇到大量代码术语的使用,所以事先了解是有必要的。

基本的 DOM 操作

在 HTML 当中 </body> 之前(就是 <body></body> 结尾的地方)加入这样一行:

1
<script src="script.js"></script>

在同目录下新建一个 script.js,然后开始你的表演。

修改元素

要想修改一个元素,我们要先选中它们。操作 document 对象,使用 querySelector() 方法选中你想要的元素。这个方法使用一个 CSS 选择器来筛选元素。

比如我们使用这个代码可以选中页面中第一个 a 元素,并且创建一个引用:

1
let link = Document.querySelector('a');

现在你可以通过 link 对象操作 HTML 当中被选中的元素,比如修改它的文本:

1
link.textContent = 'Mozilla Developer Network';

或者修改指向的链接:

1
link.href = 'https://developer.mozilla.org';

这个 a 元素立即发生了变化,不用去刷新页面就能看到。

这是对单个元素的做法。如果想对多个元素进行匹配和操作,你可以使用 document.querySelectorAll(),这个方法匹配文档中每个匹配选择器的元素,并把它们的引用存储在一个数组中,你就可以用一个 for 循环进行操作了。

添加元素

让我们进一步看看我们可以怎样来创建新的元素。

  1. 回到当前的例子,我们先获取到 section 元素的引用 — 在已有script中添加下列代码(其他代码也同样处理):
    let sect = document.querySelector('section');
  2. 现在用 Document.createElement() 创建一个新的段落,用与之前相同的方法赋予相同的文本:
    let para = document.createElement('p');
    para.textContent = 'We hope you enjoyed the ride.';
  3. 现在可以用 Node.appendChild()方法在后面追加新的段落:
    sect.appendChild(para);
  4. 最后,在内部链接的段落中添加文本节点,完美的结束句子。首先我们要使用{Document.createTextNode()创建一个文本节点:
    let text = document.createTextNode(' — the premier source for web development knowledge.');
  5. 现在获取内部连接的段落的引用,并把文本节点绑定到这个节点上:
    let linkPara = document.querySelector('p');
    linkPara.appendChild(text);

现在 HTML 当中的 section 部分变成了这样:

1
2
3
4
5
<section>
<img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
<p>Here we will add a link to the <a href="https://developer.mozilla.org">Mozilla Developer Network</a></p>
<p>We hope you enjoyed the ride.</p> — the premier source for web development knowledge.
</section>

你看到的内容应该是这样(图片省略了):

Here we will add a link to the Mozilla Developer Network

We hope you enjoyed the ride.

— the premier source for web development knowledge.

移动和删除元素

也许有时候你想移动或从DOM中删除节点,这是完全可能的。

如果你想把具有内部链接的段落移到sectioin的底部,简单的做法是:

sect.appendChild(linkPara);

这样可以把段落下移到section的底部。你可能想过要做第二个副本,但是情况并非如此 — linkPara是指向该段落唯一副本的引用。如果你想做一个副本并也把它添加进去,只能用 Node.cloneNode() 方法来替代。

删除节点也非常的简单,至少,你拥有要删除的节点和其父节点的引用。在当前情况下,我们只要使用 Node.removeChild() 即可,如下:

sect.removeChild(linkPara);

要删除一个仅基于自身引用的节点可能稍微有点复杂,这也是很常见的。没有方法会告诉节点删除自己,所以你必须像下面这样操作。

linkPara.parentNode.removeChild(linkPara);

把上述代码行加到你的代码中去

元素样式

你可以使用 JS 操作 CSS。

第一种方法是直接在想要动态设置样式的元素内部添加内联样式。这是用 HTMLElement.style 属性来实现。这个属性包含了文档中每个元素的内联样式信息。你可以设置这个对象的属性直接修改元素样式。假设我们现在创建了一个 para 元素:

1
2
3
4
5
6
7
8
let para = document.createElement('p');
para.textContent = "We hope you enjoyed the ride.";

para.style.color = 'white';
para.style.backgroundColor = 'black';
para.style.padding = '10px';
para.style.width = '250px';
para.style.textAlign = 'center';

这对应的 HTML 是这样的:

1
<p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p>

现在你可以看到这和普通的 CSS 是差不多的。不同在于 CSS 样式的 JS 属性版本以小驼峰式命名法书写,而 CSS 版本带连接符号(backgroundColor 对应 background-color)。

现在我们来看看另一个操作文档样式的常用方法。

  1. 删除之前添加到 JavaScript 中的五行代码。
  2. 在HTML的 head 中添加下列代码(外链的 CSS 同理) :
    <style>
    .highlight {
      color: white;
      background-color: black;
      padding: 10px;
      width: 250px;
      text-align: center;
    }
    </style>
  3. 现在我们改为使用HTML操作的常用方法 — Element.setAttribute() — 这里有两个参数,你想在元素上设置的属性,你要为它设置的值。在这种情况下,我们在段落中设置类名为 highlight :
    para.setAttribute('class', 'highlight');
  4. 刷新页面,看不到改变 — CSS 仍然应用到段落,但是这次给出CSS规则选择的类不是内联CSS样式。

这其实就是给元素更改了一个类,然后对应的规则就理所当然地加上了。

元素操作

事件

有一些特殊的元素会引发**事件(Event)**,比如 HTML 当中的按钮(button)在被点击的时候就会有 ‘click’ 事件被引发。

可以把相应的函数和事件进行绑定,这样这个事件引发的时候就可以调用相应的函数来处理。比如我们可以做个按一下按钮就在列表中添加一个元素的网页。

有关事件我们有更详细的教程,感兴趣可以自己去看: https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Building_blocks/Events

我们先使用 document.querySelector() 来选中对应的 button 元素,然后使用这个元素的 addEventListener() 方法来绑定事件和对应的函数。比如我们要在点击页面中第一个按钮的时候在控制台输出 “Clicked button.” 消息:

1
2
3
4
5
let button = document.querySelector('button');
// 第一个参数是事件类型,第二个参数是这个事件发生后执行的函数。函数可以现场定义一个,就像这样
button.addEventListener('click', function () {
console.log("Clicked button.");
});

看看这个例子

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>按钮演示</title>
<link rel="stylesheet" href="demo.css">
</head>
<body>
<h1>按钮演示</h1>
<!-- 元素会被加在 ul 当中 -->
<ul class="place">
<button class="addnum">添加数字</button>
</ul>

<script src="button.js"></script>
</body>
</html>

demo.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
html {
font-family: sans-serif;
}
ul {
width: 32em;
list-style-type: none;
}
li {
border: 0.3em solid rgb(0, 250,154);
background-color: rgba(127, 255, 212, 0.8);
padding: 0.5em;
margin: 0.5em;
border-radius: 0.4em;
}
.addnum {
margin: 0.5em;
font-size: large;
}

button.js

1
2
3
4
5
6
7
8
9
10
11
12
13
// 用来存放自己的全局变量
let myAPP = {
cnt: 0,
ul: document.querySelector('.place'),
button: document.querySelector('.addnum')
};
// 这里的 () => 是箭头函数,和 function () 的匿名函数类似,只是更短一点
myAPP.button.addEventListener('click', () => {
let li = document.createElement('li');
myAPP.cnt += 1;
li.textContent = "点击了 " + myAPP.cnt + " 次";
myAPP.ul.appendChild(li);
}); // 注意这里几个嵌套的括号

点了几次之后是这样子的:

button

输入

我们可能还需要从一些输入框(表单当中的 <input> 不见)当中获取输入。现在我们有另一个 HTML,我们将会在每次点击按钮的时候把输入框里面的数据写到列表里面。这个 HTML 的 css 部分和原来的相同,就不再重复列出了。

这里仅仅使用了表单当中的 inputlabel 部件。

label 是一个文本,一般用来说明下面的 input 是干什么的。for 属性里面是一个 id 表明是给对应 id 的 input 元素的 label。

input 有个 type 属性,可以指定这个部件的类型。比如 text 值表明这是个文本框,可以进行输入。而 submit 就成了一个按钮。

在 JS 当中,文本框有个 value 属性,值就是文本框当中输入的值。你也可以用给这个值赋值的方式来覆盖掉原来的值。

完整的指南可以查看https://developer.mozilla.org/zh-CN/docs/Learn/Forms

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>输入实例</title>
<link rel="stylesheet" href="demo.css">
</head>
<body>
<h1>输入演示</h1>
<div class="form">
<label for="inputField">请输入: </label>
<input type="text" id="inputField" class="inputField">
<input type="submit" value="确定" class="inputSubmit">
</div>
<ul class="place">
</ul>

<script src="input.js"></script>
</body>
</html>

input.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let myAPP = {
// 这是文本框在 JS 当中的引用
inputField: document.querySelector('.inputField'),
// 这是那个按钮
inputSubmit: document.querySelector('.inputSubmit'),
ul: document.querySelector('.place'),
cnt: 0,
};

myAPP.inputSubmit.addEventListener('click', () => {
// 获取当前输入值
let text = myAPP.inputField.value;
// 清空当前输入(就是赋值一个空的字符串)
myAPP.inputField.value = '';
let li = document.createElement('li');
myAPP.cnt += 1;
li.textContent = "在第 " + myAPP.cnt + " 次输入了: " + text;
myAPP.ul.appendChild(li);
});

输入了一些内容之后:

input

实例

之前都是一些基础用法,现在就来把这些东西用在实战里面吧。

名称空间

在开始之前,我要提一个小小的建议:你最好把自己的所有东西放在一个对象里面,通过对象方法进行调用,这样可以防止命名冲突。因为一个页面包含的所有 JS 代码都是放在一起执行的,如果全局变量太多就有概率会影响到其他的同名变量,导致很多难以预料的问题。

比如我们之前的实例代码:

1
2
3
4
5
6
7
8
9
let link = document.querySelector('a');
link.textContent = 'Mozilla Developer Network';
link.href = 'https://developer.mozilla.org';
let sect = document.querySelector('section');
let para = document.createElement('p');
para.textContent = 'We hope you enjoyed the ride.';
sect.appendChild(para);
let text = document.createTextNode(' — the premier source for web development knowledge.');
sect.appendChild(text);

就可以重新变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let myTest = {
run: function() {
let link = document.querySelector('a');
link.textContent = 'Mozilla Developer Network';
link.href = 'https://developer.mozilla.org';
let sect = document.querySelector('section');
let para = document.createElement('p');
para.textContent = 'We hope you enjoyed the ride.';
sect.appendChild(para);
let text = document.createTextNode(' — the premier source for web development knowledge.');
sect.appendChild(text);
}
};
myTest.run();

占用的名称从 link, sect, para, text 这四个一下变成了只有一个 myTest,可以有效减少撞车机率。

动态调整窗口大小

新建一个这样的 HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Window resize example</title>
<style>
body {
margin: 0;
}
div {
box-sizing: border-box;
width: 100px;
height: 100px;
background-image: url(https://raw.fastgit.org/mdn/learning-area/master/javascript/apis/document-manipulation/bgtile.png);
border: 10px solid white;
}
</style>
</head>
<body>
<div>

</div>
<script>

</script>
</body>
</html>

我们将会使用这个作为例子,演示一系列的东西。

首先在 <script> 中间创建这样一个函数 ``,在其中放我们需要执行的代码:

1
2
3
4
function run(){
// 这里放代码
}
run();

在这个例子中,我们解决了一个常见的问题 — 不管窗口的大小是多少,确保应用程序和它所在的窗口视图一样大。比如你要做游戏,想在游戏中尽可能多地使用屏幕区域,这种方法是很有用的。

我们使用 window 对象来获取窗口的高度和宽度,使用 DOM 对 div 的宽高进行修改。

首先获取高度和宽度, 这两个值包含在 Window.innerWidthWindow.innerHeight 属性中。以及对 div 的引用:

1
2
3
let div = document.querySelector('div');
let WIDTH = window.innerWidth;
let HEIGHT = window.innerHeight;

接下来,我们将动态地改变div的宽度和高度,使其等于视窗的宽度和高度。 在您的代码下面添加以下两行:

1
2
div.style.width = WIDTH + 'px';
div.style.height = HEIGHT + 'px';

保存并刷新浏览器 — 现在可以看到不管你使用什么大小的屏幕,div变得和视窗一样大。如果要调整窗口大小使其更大,你可以看到div会保持相同大小 — 因为只有刷新时才会重新执行 JS。

有个更好的办法是让事件来帮助我们实现。 window 对象有一个称为 resize 的可用事件。每次窗口调整大小时都会触发该事件 — 我们可以通过 window.onresize 事件处理程序来访问它,并返回每次改变大小的代码。比如我们的代码可以写成这样:

1
2
3
4
5
6
7
8
9
function run(){
let div = document.querySelector('div');
let WIDTH = window.innerWidth;
let HEIGHT = window.innerHeight;
div.style.width = WIDTH + 'px';
div.style.height = HEIGHT + 'px';
}
run();
window.onresize = run;

最后那个是要把函数本身传递给它,所以是不需要在 run 后面加上括号的。现在试试变化你的浏览器窗口,看看会发生什么。

结尾

现在我们了解了关于 DOM 的很多东西,这可以为你去做一系列的网页做铺垫。

推荐你们看看这篇: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript 最好一定要了解里面的所有概念。

我们的教程到了这里,已经是最后一篇了。至此,Web 技术的第三块就已经拼上了。到现在,我们已经学了 7 章 HTML, 8 章 CSS,和 7 章 JS。这些将会成为你的技术的一部分。现在,浏览器已经可以成为你的得力助手,帮助你完成一些之前甚至没有想过的事情。

对于前端的技术,我们提到了很多,但是我们没有提到的更多。更广阔的天地,还是需要你们去探索。

—— NetherMobs 2021 年 10 月 31 日

2022 年 3 月 6 日更新:

我们更新了下一篇教程,专门列出了一些其他有用的资源。