Resource
[英文生肉] MIT Web开发速成课 2024 WebLab MIT Web Development Crash Course 2024_哔哩哔哩_bilibili
Git Basics
主要是介绍为什么需要 git 这样的版本管理器(解决团队开发问题),git 的实现原理,以及一些 git 的基础操作。
原理
简单来说,git 为每位用户和云端存储了一份完整的项目(也叫 working copy),而这些内容之间的传递通过相互覆盖实现。
在本地,修改一些文件后,我们需要将文件修改储存起来,打包成一个箱子(提交),然后将这个箱子和云端的仓库同步。
这样每个提交都可以视为一个检查点,如果突然需要回退版本,就可以回到某次提交后的内容。
同时 git 也提供了分支,不同的分支可以理解为在开发不同的功能,它们的文件相互独立,提交之后只影响当前分支的内容。
如果一个分支的功能开发完成,就可以将其合并到主分支中(master/main
),覆盖对应文件。如果同一个文件在不同的分支上被修改了,那么后合并的分支就要手动解决合并冲突。
指令
git init
git diff # 查看上一个检查点和现在的文件差异
git status # 查看状态
git add [file-name] # 将文件(夹)的修改存进箱子里
git commit -m ["Your Message Here"] # 打包提交
git log # 查看输出日志
git reset HEAD # 回到某个检查点,HEAD~0/HEAD 表示最新版本,HEAD~k 表示回退 k 次提交
git branch # 查看所有分支
git checkout [branch-name] # 切换到存在的分支
git checkout -b [branch-name] # 切换到新建的分支
git merge [branch-name] # 将其他分支合并到当前分支上
Intro to HTML/CSS
HTML
全称 Hypertext Markup Language,用于描述网页的内容和结构。
HTML 实际上由许多嵌套的盒子组成,通过盒子套盒子完成最基础的网页内容分块和关系描述。
文件内容
<!DOCTYPE html>
<html>
<head>
<title>Title!</title>
</head>
<body>
<h1>Heading!</h1>
<p>Paragraph!</p>
</body>
</html>
一个盒子由一对 <tag>
</tag>
标签组成,标签之间的内容都算在这个盒子里。
对于 <img>
等无文本内容的标签,我们可以在 >
前加一个 /
,而不用 </img>
。这样的标签称为自闭和标签(Self-Closing Tags)。
每个标签有许多属性(Attributes),通过指定属性的值可以实现更多功能(与 CSS 结合)。
一对标签的格式: <tag attribute="value">
<tag>
。
标签
-
<head>
:描述网页的元信息。 -
<title>
:表示标题,显示在标题栏里。 -
<body>
:描述网页正文内容。 -
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
:表示小节标题。数字越小,文字显示得越大。 -
<p>
:表示段落。
其他常用标签:
-
<div>
:表示一个块。根据class
或id
属性,以及 CSS 内容,可以修改样式。 -
<span>
:同样表示一个块。区别在于这是行内块,连续的块显示在同一行内,同时不能再包含块。 -
<section>
:表示文档中的一个独立区段。主要用于组织内容。有助于搜索引擎优化(SEO)等。 -
<img>
:表示图像。常用<img src="path/to/yourimage" />
。 -
<a>
:表示链接,又称锚点(anchor)。常用<a href="yourlink">yourtext</a>
。 -
<link>
:表示外部链接。常用于载入 CSS 样式,如<link rel="stylesheet" href="style.css" />
。
CSS
全称 Cascading Style Sheets,用于描述网页内容如何布局渲染。
CSS 由许多规则组成,每个规则描述了一个选择器,以及若干条样式。
文件内容
div { /* Short Hands */
color: red;
font-family: Arial;
font-size: 24pt;
}
其中,div
是选择器,表示 HTML 中所有 <div>
元素都要应用花括号内的样式。
color
、font-family
、font-size
是预定义的属性,通过 :
右侧的内容来描述属性该如何渲染。
常用的两种样式应用方式:
- 使用
id
:
<div id="subtitle">Info</div>
#subtitle {
color: red;
}
这样 Info
就是红色的。
- 使用
class
:
<div class="info">Info</div>
.info {
color: blue;
}
这样 Info
就是蓝色的。
一般而言更推荐使用 class
,因为它可以复用,可以让多个样式应用到同一元素上;而 id
是唯一的,只能处理单个元素。
优先级
如果有多个冲突的样式需要应用到同一个元素上,该如何选择呢?
对于相同的选择器,最后载入的生效;对于不同的选择器,更具体的生效。
例如:
.special {
color: green;
}
p {
color: red;
}
p {
color: blue;
}
对于以下两句话,结果应该是一蓝一绿:
<p>这是蓝的</p>
<p class="special">这是绿的</p>
这是因为,红色的 p
被蓝色的 p
覆盖了,而 class
比 p
定位的更具体。
HTML(div) = 1 < class(.info) = 10 < id(#subtitle) = 100 < inline style
W0: HTML/CSS
我们要到 react cat book 这里,把仓库克隆到本地,然后切换到 w0-starter
分支。
HTML Part
先添加一下文字内容:
<!DOCTYPE html>
<html>
<head>
<title>Catbook</title>
</head>
<body>
<h1>Buka Buka</h1>
<hr />
<section>
<h4>About Me</h4>
<p>I am more of a turtle person but I'm just trying to fit in and get a catbook.</p>
</section>
<section>
<h4>My Favorite Type of Cat</h4>
<p>I actually prefer turtles.</p>
</section>
</body>
</html>
然后来个图片,我们想要它在 Buka Buka 的上面,所以在对应语句前面加一个:
<img src="cat.png" />
效果图:
CSS Part
现在我们想对这些文本和图像作布局,所以要用到 CSS。
居中
CSS 的引用在元数据处,所以在 <head>
中加入:
<link rel="stylesheet" href="styles.css" />
然后编辑 style.css
:
.u-textCenter {
text-align: center;
}
再回到 html
,改写一下 Buka Buka 行:
<h1 class="u-textCenter">Buka Buka</h1>
像 .u-textCenter
一样表示一种样式的类,称为实用类(utility class),通常以 u-
为前缀。
添加字体
我们可以在 Google Fonts 中寻找字体(以 Open Sans 为例)
打开链接后点击 ”get font“,之后选择 Embed Code,调节成喜欢的样式,最后将右侧两段代码粘贴到 CSS 中:
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,600;1,300;1,600&display=swap");
.u-textCenter {
text-align: center;
}
body {
font-family: "Open Sans", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
font-variation-settings: "wdth" 100;
}
我直接用 Open Sans 修改 body
内容,所以就长这样。
除了 @import
导入,也可以通过 @font-face
导入本地字体:
@font-face {
font-family: "JetBrains Mono";
src: url('fonts/JetBrainsMono-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
这样可以导入 fonts
文件夹下的 JetBrains Mono 字体。
添加导航栏
我们将用到 <nav>
标签制定导航栏,同时上色。
定义颜色
CSS 允许定义变量(在 :root
规则下),变量一定以 --
开头,一般会把颜色定义为变量,以便理解:
:root {
--primary: #396dff;
--grey: #f7f7f7;
--white: #ffffff;
}
要使用变量,将填入数值的地方换成 var([varname])
即可。
导航栏类
.navTitle {
color: var(--white);
font-size: 20px;
}
.navContainer {
background-color: var(--primary);
}
去除边缘
通过观察可以发现,我们的网页在边界处总是有留白,实际上这和默认设置有关。
框盒模型
一个 HTML 元素的盒子由四部分组成:边缘(Margin),边框(Border),内边距(Padding),内容(Content)。
我们可以在 CSS 中设定对应边距的值(单位 pixel),来去掉这个边缘。
修改边缘
在浏览器中 F12,元素视图下,在下面的 CSS 样式中可以看到这样一段:
body {
display: block;
margin: 8px;
}
这说明,我们的网页默认有 8 像素的边缘,在 style.css
中将其修改为 0 即可去除边缘。
实际上,margin 有四种确定方式(其他两个边距同理):
- 指定一个值
x
:四个方向的边缘都是x
。 - 指定两个值
x y
:上下的边缘是x
,左右的边缘是y
。 - 指定三个值
x y z
:上边缘是x
,下边缘是z
,左右的边缘是y
。 - 指定四个值
x y z w
:从上边缘开始,顺时针赋值。
8 像素设计
一种设计风格是,将每个边距都设置为 8 的倍数。
这样就可以使用统一的变量代替边距大小:
:root {
--xs: 4px;
--s: 8px;
--m: 16px;
--l: 24px;
}
.navContainer {
padding: var(--s) var(--m);
background-color: var(--primary);
}
然后将 .navContainer
应用到我们的导航栏上:
<nav class="navContainer">
<h1 class="navTitle">Catbook</h1>
</nav>
现在它长这样:
块还有 width
和 height
等属性可以修改块的大小,可以自行探索。
圆角半径
等价理解:把一个半径为圆角半径的圆靠放在角上,根据圆和矩形的交的轮廓重新绘制这个角的形状。
修改一下 .navContainer
:
.navContainer {
padding: var(--s) var(--m);
background-color: var(--primary);
border-radius: var(--s);
}
这样就给导航栏添加圆角了。
如果使用百分数,就会变成椭圆角。
圆形头像
这部分略显复杂,主要是记下代码。
做一下头像边框和头像类:
.avatarContainer {
padding: 0 35%;
}
.avatar {
/* make it responsive */
max-width: 100%;
width: 100%;
height: auto;
display: block;
/* div height to be the same as width*/
padding-top: 100%;
/* make it a circle */
border-radius: 50%;
/* Add image */
background-image: url("cat.png");
/* Centering on image`s center*/
background-position-y: center;
background-position-x: center;
background-repeat: no-repeat;
/* it makes the clue thing, takes smaller dimension to fill div */
background-size: cover;
/* it is optional, for making this div centered in parent*/
margin: 0 auto;
}
这样我们的 HTML 也要相应地修改:
<div class="avatarContainer">
<div class="avatar"></div>
</div>
Flexbox
现在 "About Me" 和 "My Favorite Type of Cat" 两个块是竖直排列的,我们希望它能水平排列。
这里需要用到 CSS 的 Flexbox 属性。通过 Flexbox,我们可以规定几个并列元素的对齐方式、排列方向、排列顺序、块长等。
排列方向
通过 flex 完成水平排列:
.u-flex {
display: flex;
flex-direction: row;
}
实际上 flex-direction
默认值为 row
,可以省略。
现在确实能水平排列了,就是全都挤在左边了:
调整块的大小
在两个块上添加一个类,用于调整块的大小。
在类中,我们要使用 flex-grow
和 flex-basis
属性。
flex-basis
指定了块的基础长度。如果块实际上没有那么长,则会自动伸长。
flex-grow
指定了块的伸长比例(0
表示不伸长)。例如一个块中的三个元素,它们的伸长比例为 1:2:1
,那么它们最终占有的宽度比例就是 1:2:1
。在本例中,所有的 flex-grow
都为 1
,故所有的块长度应该一样。
<section class="u-textCenter subContainer"></section>
.subContainer {
flex-grow: 1;
flex-basis: 0;
}
额外练习网址
Flexbox Froggy - A game for learning CSS flexbox
Intro to Javascript
Javascript 是一门语言,用于操纵网页的内容:
- 让网页可以互动!
- 是网页和网页应用的主流选择
- 和 Java 没什么关系🙃
基础语法
数据类型
Javascript 的变量本身没有类型,存储的数据有类型:
- Boolean:布尔值,true / false
- Number:数值,包括浮点数
- String:字符串
- Null:无数据,取“empty”
- Undefined:声明了但没有赋值
运算符
- 算数运算符:
+ - * /
,字符串的+
表示连接 - 比较运算符:
=== !== < > <=
,注意相等需要三个等号。 - 那
==
怎么了呢?它在比较之前有强制类型转换(type coercion)(2 == "2"
),所以尽量不使用。
语句书写
const greatestCommonDivisor = (a, b) => {
while(b !== 0){
const temp = b;
b = a % b;
a = temp;
}
return a;
}
const x = 50;
const y = 15;
const gcd = greatestCommonDivisor(x, y); // 5
语句书写与 C 语言相差无几,句末分号、使用花括号、return
、注释等。
声明变量
- 使用
let
语句定义变量:
let myBoolean = true;
let myNumber = 12.0;
let myString = "Hello World!";
- 使用
const
语句也可以定义变量,但是不可修改:
const answerToLife = 6.148;
answerToLife = 42; // Error
- ES6 标准前只能使用
var
语句定义变量,但它实质上会提前声明,会产生其他的错误:
var name = "Trump";
function Chairman() {
if (false){
var name = "Biden";
}
console.log(name);
}
Chairman();
实质上会输出 undefined,因为在 Chairman()
中 var name;
被提前声明了,写入日志的是函数中的变量而非全局变量。
ES6 标准后尽量不要使用 var
,请使用 let
和 const
。
控制台
如何运行 JS:浏览器控制台
- Windows:
Ctrl
+Shift
+J
- Mac:
Cmd
+Opt
+J
/Cmd
+Shift
+J
控制台打印语句:console.log([variable])
console.log(2 * 5);
console.log("Hello World!");
let a = 5; let b = 10; console.log("a * b = ${a * b}");
弹窗
使用 alert()
可以发送弹窗消息:alert("Congratrulations!");
数组
数组的数据类型不要求是一样的,下标从 0 开始。
初始化数组时用方括号而非花括号,也不需要写数组大小。
let pets = ["flower", "bird", 42, false];
console.log(pets[0]); // "flower"
pets[2] = "hamster"; // "flower", "bird", "hamster", false
pets.pop(); // "flower", "bird", "hamster"
pets.push("pig"); // "flower", "bird", "hamster", "pig"
获得数组的大小:pets.length
(注意不是成员函数)
循环
while
和 C++ 一样。
let p = 100;
while(p > 8){
p /= 2;
console.log(p);
}
打印结果:
50
4 25
12.5
6.25
for
和 C++ 区别不大,同样也支持范围 for 循环。
let pets = ["flower", "bird", "hamster", "pig"];
for(let i = 0; i < pets.length; i++){
const phrase = "I love my" + pets[i];
console.log(phrase);
}
for(const animal of pets){
const phrase = "I love my" + animal;
console.log(phrase);
}
对象
构造
JS 中的对象就是键值对:
const myCar = {
make: "Ford",
model: "Mustang",
year: 2005,
color: "red"
};
可以通过 object.membername
和 object["membername"]
的方式访问成员。
将对象声明为 const
,只是声明其不能重新指向另一个对象,其键值仍然可以修改。
析构
JS 中的析构指的是元组赋值:
const {make, model} = myCar;
比较
JS 的对象使用的是使用的是 By Reference,所以对象名实质上是引用,两个引用进行比较,那么就是比较指向的地址是否相同。
所以当两个内容一样的对象做 ===
运算时,会返回 false
。数组同理。
复制
因为 JS 的对象 By Reference 特性,let copyArr = arr;
这样的语句是不会执行内容复制的(指向同一个地址)。
想要进行复制,要使用 ...
运算符:
let arr = [1, 2, 3];
let copyArr = [...arr];
let obj = {name : "Jerry"};
let copyObj = {...obj};
函数
JS 中函数定义的方式和声明变量的语法很像:
const funcname = (parameters) => {
body;
};
同时函数也可以作为参数被传递,这种以函数为参数的函数称为回调函数。
举例:setTimeout()
可以在等待一段时间后执行函数。
const printOver = () => {
console.log("Game Over!");
};
setTimeout(printOver, 5000);
这样 5000ms 后就会打印 "Game Over!"。
类
有很多结构相同的对象,那么就可以用类来定义:
class Rectangle{
constructor(width, height){
this.width = width;
this.height = height;
}
getArea = () => {
return this.width * this.height;
};
}
const rect = new Rectangle(6, 8);
console.log(rect.getArea()); // 48