三件套笔记
# 三件套笔记
# HTML
来看一下 HTML
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>My test page</title>
</head>
<body>
<img src="images/firefox-icon.png" alt="My test image" />
</body>
</html>
2
3
4
5
6
7
8
9
10
11
<!doctype html>
——文档类型 (opens new window)。这是必不可少的开头。<html></html>
—— 该元素包含整个页面的所有内容,有时候也称作根元素。它还包含lang
属性,设置页面的主要语种。<head></head>
——<head>
元素。该元素作为想在 HTML 页面中包含但不想向用户显示的内容的容器。<meta charset="utf-8">
——该元素指明你的文档使用 UTF-8 字符编码,UTF-8 包括世界绝大多数书写语言的字符。<meta name="viewport" content="width=device-width">
——视口元素 (opens new window)可以确保页面以视口宽度进行渲染,避免移动端浏览器以比视口更宽的宽度渲染内容,导致内容缩小。<title></title>
—— 该元素设置页面的标题,显示在浏览器标签页上,也作为收藏网页的描述文字。<body></body>
—— 该元素包含期望让用户在访问页面时看到的全部内容,包括文本、图像、视频、游戏、可播放的音轨或其他内容。
# h 标签
<!-- 4 个级别的标题 -->
<h1>主标题</h1>
<h2>顶层标题</h2>
<h3>子标题</h3>
<h4>次子标题</h4>
2
3
4
5
# p 标签
<p>这是一个段落</p>
# 列表
无须列表
<p>At Mozilla, we're a global community of</p>
<ul>
<li>technologists</li>
<li>thinkers</li>
<li>builders</li>
</ul>
<p>working together…</p>
2
3
4
5
6
7
8
9
有序列表
<ol>
<li>沿这条路走到头</li>
<li>右转</li>
<li>直行穿过第一个十字路口</li>
<li>在第三个十字路口处左转</li>
<li>继续走 300 米,学校就在你的右手边</li>
</ol>
2
3
4
5
6
7
描述列表
描述列表的目的是标记一组项目及其相关描述
描述列表使用与其他列表类型不同的包裹标签 <dl>
,每一项用 <dt>
包裹,每个描述都用 <dl>
包裹
<dl>
<dt>内心独白</dt>
<dd>
戏剧中,某个角色对自己的内心活动或感受进行念白表演,这些台词只面向观众,而其他角色不会听到。
</dd>
<dt>语言独白</dt>
<dd>
戏剧中,某个角色把自己的想法直接进行念白表演,观众和其他角色都可以听到。
</dd>
<dt>旁白</dt>
<dd>
戏剧中,为渲染幽默或戏剧性效果而进行的场景之外的补充注释念白,只面向观众,内容一般都是角色的感受、想法、以及一些背景信息等。
</dd>
</dl>
2
3
4
5
6
7
8
9
10
11
12
13
14

# 链接
<a href="https://www.mozilla.org/zh-CN/about/manifesto/">
Mozilla Manifesto
</a>
2
3
我们可以使用 title
属性来补充链接的信息,例如,页面包含什么样的信息或者需要注意的事情
<p>
我创建了一个指向
<a
href="https://www.mozilla.org/zh-CN/"
title="了解 Mozilla 使命以及如何参与贡献的最佳站点。">
Mozilla 主页</a
>的超链接。
</p>
2
3
4
5
6
7
8
当鼠标悬停在链接上面的时候,标题会作为提示信息出现
文档片段
我们还可以指定连接到某一个文档的特定部分,首先,我们需要给链接到的元素分配一个 id
属性,例如
<h2 id="Mailing_address">邮寄地址</h2>
为了连接到那个特定的 id
要把它放在 URL 的末尾,并在前面包含一个 #
<p>
要提供意见和建议,请将信件邮寄至
<a href="contacts.html#Mailing_address">我们的地址</a>。
</p>
2
3
4
你甚至可以在同一份文档下,通过链接文档片段,来链接到当前文档的另一部分
<p>本页面底部可以找到<a href="#Mailing_address">公司邮寄地址</a>。</p>
# 加粗
<strong> </strong>
# 斜体
<em> </em>
# 换行
<br>
水平分割线
<hr>
这个会产生一个水平分割线,用于语义上主题中断元素
# 引用
块引用
如果我们要引用一个段落,多个段落,一个列表等,应该用 <blockquote>
元素包裹起来,且在 cite
属性里面用 URL 指向应用的资源
<p>这是块引用:</p>
<blockquote
cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/blockquote">
<p>
<strong>HTML <code><blockquote></code> 元素</strong>(或<em
>HTML 块级引用元素</em
>)表示所附文本为扩展引用。
</p>
</blockquote>
2
3
4
5
6
7
8
9
10
浏览器默认会渲染为缩进,以表示这是一个引用
行内引用
使用 <q>
元素以表示行内引用
<p>
引用元素 <code><q></code> 是<q
cite="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/q"
>用于不需要段落分隔的短引用。</q
>
</p>
2
3
4
5
6
7
# 图片
<img src="dinosaur.jpg" alt="恐龙" />
alt
是备选文本,用于在图片无法显示或者因为网速慢而加载缓慢的情况下使用width
是图片的高height
是图片的宽
当图片还没有加载出来的时候,浏览器会提前讲图片的位置空出来
给图片添加解说文字
我们可以这样写
<div class="figure">
<img
src="images/dinosaur.jpg"
alt="The head and torso of a dinosaur skeleton;
it has a large head with long sharp teeth"
width="400"
height="341" />
<p>A T-Rex on display in the Manchester University Museum.</p>
</div>
2
3
4
5
6
7
8
9
10
但是浏览器给了我们一个特定的元素 <figure>
和 <figcaption>
它正是为此而被创造出来的:为图片提供一个语义容器,在说明文字和图片之间建立清晰的关联。我们之前的例子可以重写为:
<figure>
<img
src="images/dinosaur.jpg"
alt="The head and torso of a dinosaur skeleton;
it has a large head with long sharp teeth"
width="400"
height="341" />
<figcaption>
A T-Rex on display in the Manchester University Museum.
</figcaption>
</figure>
2
3
4
5
6
7
8
9
10
11
12
<figcaption>
元素会告诉浏览器和辅助技术工具,这段说明文字描述了 <figure>
元素的内容
我们也可以通过 css 属性设置某一个图片为某个元素的背景图片
p {
background-image: url("images/dinosaur.jpg");
}
2
3
4
如果图像对你的内容有意义,则应使用 HTML 图像。如果图像纯粹是装饰,则应使用 CSS 背景图片。
# 视频和音频
# <video>
元素
<video src="rabbit320.webm" controls>
<p>
你的浏览器不支持 HTML 视频。可点击<a href="rabbit320.mp4">此链接</a>观看。
</p>
</video>
2
3
4
5
src
和img
标签里面的src
完全相同,表示你想要嵌入到网页中的视频资源controls
用户应当能够控制视频和音频的播放,你也可以使用适当的 JavaScirptAPI 构建自己的界面<video>
之后的段落,这保证了当浏览器不支持<video>
元素的时候,就会显示这段内容
# <video>
其他属性
<video
controls
width="400"
height="400"
autoplay
loop
muted
preload="auto"
poster="poster.png">
<source src="rabbit320.mp4" type="video/mp4" />
<source src="rabbit320.webm" type="video/webm" />
<p>你的浏览器不支持此视频。可点击<a href="rabbit320.mp4">此链接</a>观看</p>
</video>
2
3
4
5
6
7
8
9
10
11
12
13
14
<width>
和<height>
控制视频的长宽autoplay
来控制音频和视频内容立即播放,不建议使用loop
可以让视频(或者音频)文件在结束时再次开始播放,同样不建议使用muted
这个属性会导致媒体播放时,默认关闭声音。poster
这个属性指向了一个图像的 URL,这个图像会在视频播放前显示,在点开前看到的图片preload
- 这个属性被用来缓冲较大的文件,有三个值可选:
"none"
:不缓冲文件"auto"
:页面加载后缓存媒体文件"metadata"
:仅缓冲文件的元数据
# <audio>
元素
<audio>
元素和 <video>
元素使用方式几乎完全相同
<audio controls>
<source src="viper.mp3" type="audio/mp3" />
<source src="viper.ogg" type="audio/ogg" />
<p>你的浏览器不支持该音频,可点击<a href="viper.mp3">此链接</a>收听。</p>
</audio>
2
3
4
5
这串代码将会产生如下的效果:

<audio>
元素不支持width
/heigth
属性——由于其并没有视觉部件,也就没有内容要设置width
/height
- 它同时也不支持
poster
属性——同样,因为没有视觉部件
除此之外,<audio>
元素支持所有 <video>
元素的特性
# 文档与网站架构
一个标准的网页往往包含:
页眉
通常横跨于整个页面顶部有一个大标题 和/或 一个标志
导航栏
指向网站各个主要区段的超链接。通常用菜单按钮、链接或标签页表示。类似于标题栏,导航栏通常应在所有网页之间保持一致
主内容
中心的大部分区域是当前网页大多数的独有内容
侧边栏
一些外围信息、链接、引用、广告等。通常与主内容相关(例如一个新闻页面上,侧边栏可能包含作者信息或相关文章链接),还可能存在其他的重复元素,如辅助导航系统。
页脚
横跨页面底部的狭长区域。和标题一样,页脚是放置公共信息(比如版权声明或联系方式)的,一般使用较小字体,且通常为次要内容。还可以通过提供快速访问链接来进行 SEO (opens new window)。
一个“典型的网站”可能会这样布局:

为了实现语义化标记,HTML 提供了明确这些区段的专用标签,例如:
<header>
页眉<nav>
导航栏<main>
主内容,主内容中还可以有各种子内容区段,包括<article>
,<section>
,<div>
等元素<aside>
侧边栏,经常嵌套在<main>
中<footer>
页脚
# 无语义元素
<span>
是一个内联的无语义元素,最好只用于无法找到更好的语义元素来包含内容时,或者不想增加特定的含义时。例如:
<p>
国王喝得酩酊大醉,在凌晨 1 点时才回到自己的房间,踉跄地走过门口。<span
class="editor-note"
>[编辑批注:此刻舞台灯光应变暗]</span
>.
</p>
2
3
4
5
6
就可以通过编辑 editor-note
来修改批注的格式
<div>
是一个块级的无语义元素
# 表格基础
什么是表格?

可以使用 <tr>
标签分割每一行,使用 <td>
标签为每一行中的一个元素,使用 <th>
表示标题
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Dogs table</title>
<link href="minimal-table.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Dogs Table</h1>
<table>
<tr>
<td> </td>
<th>Knocky</th>
<th>Flor</th>
<th>Ella</th>
<th>Juan</th>
</tr>
<tr>
<td>Breed</td>
<td>Jack Russell</td>
<td>Poodle</td>
<td>Streetdog</td>
<td>Cocker Spaniel</td>
</tr>
<tr>
<td>Age</td>
<td>16</td>
<td>9</td>
<td>10</td>
<td>5</td>
</tr>
<tr>
<td>Owner</td>
<td>Mother-in-law</td>
<td>Me</td>
<td>Me</td>
<td>Sister-in-law</td>
</tr>
<tr>
<td>Eating Habits</td>
<td>Eats everyone's leftovers</td>
<td>Nibbles at food</td>
<td>Hearty eater</td>
<td>Will eat till he explodes</td>
</tr>
</table>
</body>
</html>
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
48
49
50
51
52
这样就能使用 css 把内容和标题分开了
使用 colspan
属性和 rowspan
属性可以让单元格跨越多行或者多列
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Animals table</title>
<link href="minimal-table.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Animals table</h1>
<table>
<tr>
<th colspan="2">Animals</th>
</tr>
<tr>
<th colspan="2">Hippopotamus</th>
</tr>
<tr>
<th rowspan="2">Horse</th>
<td>Mare</td>
</tr>
<tr>
<td>Stallion</td>
</tr>
<tr>
<th colspan="2">Crocodile</th>
</tr>
<tr>
<th rowspan="2">Chicken</th>
<td>Hen</td>
</tr>
<tr>
<td>Rooster</td>
</tr>
</table>
</body>
</html>
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

# 表单和按钮
# 按钮
使用 <button>
来包裹一个文本会显示在按钮上,例如
<button>Press me</button>
我们这个单独的按钮本身并不能执行任何有用的操作。为了让它执行一些有用的操作,你需要将它放入表单中(我们稍后会介绍),或者添加一些 JavaScript
例如,如果我们在页面里面添加
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
btn.textContent = "YOU CLICKED ME!! ❤️";
setTimeout(() => {
btn.textContent = "Press me";
}, 1000);
});
2
3
4
5
6
7
当你点击了之后,按钮里面的内容就变成了 YOU CLICKED ME!! ❤️
# 表单
<form>
元素,用于包裹所有其他表单内容
一个 <label>
和一个表单控制元素为一对,表单控制元素包括(<input>
或者 <select>
)
表单控制元素允许用户选择或输入一些数据,这些数据将在表单提交时发送到服务器。
当然,表单里面还会存在一个 <button>
标签
来看一个例子,这个表单用于询问用户的姓名和电子邮件,由于它没有连接到任何服务器,因此不会执行任何操作
<form action="./submit_page" method="get">
<h2>Subscribe to our newsletter</h2>
<p>
<label for="name">Name (required):</label>
<input type="text" name="name" id="name" required />
</p>
<p>
<label for="email">Email (required):</label>
<input type="email" name="email" id="email" required />
</p>
<p>
<button>Sign me up!</button>
</p>
</form>
2
3
4
5
6
7
8
9
10
11
12
13
14

<form>
标签充当表单的外部包装器,把所有表单控件组合在一起,当 <botton>
被按下的时候,所有由表单控件表示的数据都会提交到服务器,下面介绍两个属性
action
属性包含我们要将提交的表单数据发送到哪个页面进行处理,提交表单后,我们可以看到,URL 中包含了/submit_page
同时还会收到 404 指令,因为该页面并不存在method
属性包含数据传输的方法,包括POST
和GET
,当我们使用GET
方法提交后,参数会出现在 URL 中
<form>
元素中包含任何您喜欢的 HTML 元素来构造表单元素本身,并提供容器以便使用 CSS 进行样式设置等
我们还常把每个输入/标签对以及提交按钮放在单独的 <p>
标签中,以便他们各自出现在单独的行上。
<input>
标签表示在表单中的输入
<input type="text" name="name" id="name" required />
type
表示创建的表单控件的类型,可以是简单文本,单选按钮,复选框name
指定数据项的名称,提交表单的时候,数据以名称/键值对的形式发送,名称等于这个name
值,值等于文本中输入的文本id
元素的 id,在这里需要与表单控件<label>
关联required
如果有这个属性,说明要在这个元素是必填的
有几种专门为特定文本设定的 type
例如:<input type="number">
,<input type="password">
,<input type="tel">
<label>
标签是与表单控件关联的元素,用于描述在之后的控件中输入的数据,可以在 <label>
中输入合适的内容,每一个 <label>
和后面的表单控件关联的方式是,表单控件中的 id
属性与 <label>
中的 for
属性相同,例如:
<label for="name">Name (required):</label>
<input type="text" name="name" id="name" required />
2
这种方式是显式得表单标签,是这种 for
和 id
绑定的,也可以使用控件嵌套在标签中来实现隐式表单标签
<label>
Name (required):
<input type="text" name="name" required />
</label>
2
3
4
嵌套在控件和标签之间建立了隐式关联,您不再需要 id
和 for
属性
两种方法都可以,但我们建议使用显式标记方法
<botton>
标签包含在 <form>
中,默认行为就是提交表单,前提是表单中没有无效数据
按钮的行为可以利用里面的 type
属性来指定
<button type="submit">
表示这个按钮是提交按钮,一般表单中标签默认就是提交按钮,除非你在<form>
中包含了其他按钮,你需要明确指出哪个是提交按钮<button type="reset">
表示这个是一个重制按钮,这会重制所有数据,但不要使用重制按钮<button type="button">
创建一个按钮,其行为与<form>
元素外的按钮相同,默认不执行任何操作,需要配合使用 JavaScript 才能实现
来看下面一个例子
<form action="./payment_page" method="get">
<h2>Register for the meetup</h2>
<fieldset>
<legend>Choose hotel room type (required):</legend>
<div>
<input
type="radio"
id="hotelChoice1"
name="hotel"
value="economy"
checked />
<label for="hotelChoice1">Economy (+$0)</label>
<input type="radio" id="hotelChoice2" name="hotel" value="superior" />
<label for="hotelChoice2">Superior (+$50)</label>
<input
type="radio"
id="hotelChoice3"
name="hotel"
value="penthouse"
disabled />
<label for="hotelChoice3">Penthouse (+$150)</label>
</div>
</fieldset>
<fieldset>
<legend>Choose classes to attend:</legend>
<div>
<input type="checkbox" id="yoga" name="yoga" />
<label for="yoga">Yoga (+$10)</label>
<input type="checkbox" id="coffee" name="coffee" />
<label for="coffee">Coffee roasting (+$20)</label>
<input type="checkbox" id="balloon" name="balloon" />
<label for="balloon">Balloon animal art (+$5)</label>
</div>
</fieldset>
<p>
<label for="transport">How are you getting here:</label>
<select name="transport" id="transport">
<option value="">--Please choose an option--</option>
<option value="plane">Plane</option>
<option value="bike">Bike</option>
<option value="walk">Walk</option>
<option value="bus">Bus</option>
<option value="train">Train</option>
<option value="jetPack">Jet pack</option>
</select>
</p>
<p>
<label for="comments">Any other comments:</label>
<textarea id="comments" name="comments" rows="5" cols="33"></textarea>
</p>
<p>
<button>Continue to payment</button>
</p>
</form>
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
48
49
50
51
52
53
54
55
56
57
58

来看有几个新的标签
<input type="radio">
表示单选标签
<fieldset>
<legend>Choose hotel room type (required):</legend>
<div>
<input
type="radio"
id="hotelChoice1"
name="hotel"
value="economy"
checked />
<label for="hotelChoice1">Economy (+$0)</label>
<input type="radio" id="hotelChoice2" name="hotel" value="superior" />
<label for="hotelChoice2">Superior (+$50)</label>
<input
type="radio"
id="hotelChoice3"
name="hotel"
value="penthouse"
disabled />
<label for="hotelChoice3">Penthouse (+$150)</label>
</div>
</fieldset>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
radio
输入类型的工作原理与 text
输入类型基本相同,但有一些区别:
- 每组单选按钮的
name
属性必须包含相同的值,才能使得他们关联成一个集合 - 你必须为每个单选按钮添加一个
value
属性,包含提交的值,提交的值将是一个 name:value,例如hotel=superior
- 每个单选按钮的
<label>
应该描述选项,而不是问题,如果你要描述这个问题,需要把他们包在<fieldset>
中,该元素以<legend>
元素作为描述的子元素
在第一个单选按钮添加了 checked
属性,这使得它在页面首次加载的时候被选中
我们在最后一个单选按钮中添加了 disabled
属性,这使得它无法被选中
复选框使用 <input type="checkbox">
控件实现
<fieldset>
<legend>Choose classes to attend:</legend>
<div>
<input type="checkbox" id="yoga" name="yoga" />
<label for="yoga">Yoga (+$10)</label>
<input type="checkbox" id="coffee" name="coffee" />
<label for="coffee">Coffee roasting (+$20)</label>
<input type="checkbox" id="balloon" name="balloon" />
<label for="balloon">Balloon animal art (+$5)</label>
</div>
</fieldset>
2
3
4
5
6
7
8
9
10
11
12
13
与单选框一样,复选框也可以使用 checked
属性
每个复选框有不同的 name
值,当复选框被选中的时候,提交的数据为 on
,例如 yoga=on
<select>
是下拉菜单
<label for="transport">How are you getting here:</label>
<select name="transport" id="transport">
<option value="">--Please choose an option--</option>
<option value="plane">Plane</option>
<option value="bike">Bike</option>
<option value="walk">Walk</option>
<option value="bus">Bus</option>
<option value="train">Train</option>
<option value="jetPack">Jet pack</option>
</select>
2
3
4
5
6
7
8
9
10
数据项的每个可能值都由一个 <option>
元素表示,该元素嵌套在 <select>
元素中。每个 <option>
元素都可以带有一个 value
属性,该属性指定从下拉列表中选择该选项时要提交的值。如果您未指定 value
,则将使用 <option></option>
标签内的文本作为值
使用 <textarea>
元素来构建多行文本输入字段
<label for="comments">Any other comments:</label>
<textarea id="comments" name="comments" rows="5" cols="33"></textarea>
2
他的方式和 <input type="text">
相同,rows
参数为区域默认的行数 cols
为默认的列数
# 表单验证
表单验证又两种类型
- 第一种是客户端验证,发生在浏览器中,例如 (
required
) 和 JS 结合,在用户输入错误数据时能立刻提示用户 - 第二种是服务器验证,在服务器上验证,服务器一般不信任客户端发送的任何消息,要重新验证,然后把结果返回客户端
# CSS
# 插入 CSS
其实有三种方式可以实现,而目前我们更倾向于利用最普遍且有用的方式——在文档的开头链接 CSS
我们在 HTML 的 <head>
标签中输入
<link rel="stylesheet" href="styles.css" />
就表示插入了 CSS
# 选择器
# 选择器列表
如果你有多个使用相同样式的 CSS 选择器,那么这些单独的选择器可以被混编为一个“选择器列表”,这样,规则就可以应用到所有的单个选择器上了
h1 {
color: blue;
}
.special {
color: blue;
}
2
3
4
5
6
7
可以写成
h1, .special {
color: blue;
}
2
3
也可以写成
h1,
.special {
color: blue;
}
2
3
4
当你使用选择器列表时,如果任何一个选择器无效 (存在语法错误),那么整条规则都会被忽略
# 类型、类、ID选择器
h1 {
}
2
.box {
}
2
#unique {
}
2
# 标签属性选择器
这组选择器根据一个元素上的某个标签的属性的存在以选择元素的不同方式
a[属性名] {
}
2
也可以根据一个有特定值的标签属性是否存在来选择
a[href="https://example.com"]
{
}
2
3
# 伪类和伪元素
伪类用来样式化一个元素的特定状态
例如,:hover
伪类会在鼠标指针悬浮到一个元素上的时候选择这个元素:
a:hover {
}
2
伪元素可以表示某一个元素中的某一个部分,例如::first-line
是会选择一个元素(下面的情况中是<p>
)中的第一行
p::first-line {
}
2
# 字体
有一些字体保护起来的,我们需要使用调用 Google Fonts API 把需要的字体引入,例如我们需要引入 Open Sans 字体,需要在 <head>
中插入
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" />
然后在 css 代码中插入
html {
font-size: 10px; /* px 表示“像素(pixel)”: 基础字号为 10 像素 */
font-family:
"Open Sans", sans-serif; /* 这应该是你从 Google Fonts 得到的其余输出。 */
}
2
3
4
5
# 盒模型
CSS 布局主要是基于盒子模型。每个在页面上占用空间的盒子都有类似的属性:
padding
(内边距):是指内容周围的空间。在下面的例子中,它是段落文本周围的空间。border
(边框):是紧接着内边距的实线。margin
(外边距):是围绕元素边框外侧的空间。

当然还有其他属性,包括了:
width
:元素的宽度。background-color
:元素内容和内边距底下的颜色。color
:元素内容(通常是文本)的颜色。text-shadow
:为元素内的文本设置阴影。display
:设置元素的显示模式
# 外部显示格式和内部显示格式
外部显示格式决定该元素在父元素中的行为方式 —— 即它是被当作一个块级元素、行内元素,还是其他类型元素
block
元素在页面上表现为块级元素(独占一行)inline
元素在页面上表现为行内元素(不独占一行)
内部显示格式决定该元素内部的布局机制 —— 即其子元素是如何布局的,比如是普通文档流、flex 布局还是 grid 布局
flow
默认文档流布局,块级或行内元素按顺序排列flex
弹性布局,用于一维排列子元素grid
网格布局,二维排列子元素
看一段代码
<p>I am a paragraph. A short one.</p>
<ul>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
</ul>
<p>
I am another paragraph. Some of the <span class="block">words</span> have been
wrapped in a <span>span element</span>.
</p>
2
3
4
5
6
7
8
9
10
body {
font-family: sans-serif;
}
p,
ul {
border: 2px solid rebeccapurple;
padding: 0.2em;
}
.block,
li {
border: 2px solid blue;
padding: 0.2em;
}
ul {
display: flex;
list-style: none;
}
.block {
display: block;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第一个 <p>
标签的外部显示格式是 block
第二个 <ul>
标签设置了 display: flex
相当于 display: block flex
说明这个盒子的外部显示格式是 block
内部显示格式是浮动,所以可以看到 <li>
标签是横着排的
第三个 <p>
表示厘米强制让第二行的外部显示格式是 block
可以看到垂直方向被推开了
再来看一个例子
<p>
I am a paragraph. Some of the
<span>words</span> have been wrapped in a <span>span element</span>.
</p>
<ul>
<li>Item One</li>
<li>Item Two</li>
<li>Item Three</li>
</ul>
<p class="inline">I am a paragraph. A short one.</p>
<p class="inline">I am another paragraph. Also a short one.</p>
2
3
4
5
6
7
8
9
10
11
body {
font-family: sans-serif;
}
p,
ul {
border: 2px solid rebeccapurple;
}
span,
li {
border: 2px solid blue;
}
ul {
display: inline-flex;
list-style: none;
padding: 0;
}
.inline {
display: inline;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

- 第一段中的
<span>
默认为行级,不会换行 <ul>
设置为display: inline-flex
,也就是display: inline flex
,可看到对外部是行内格式,对内部是flex
格式
# 代替盒子模型
在替代盒模型中,任何宽度都是页面上可见方框的宽度
在标准模型中,width/height
只包含内容区,不包含 padding 和 border,设置方式为 box-sizing: content-box
在代替盒子模型中,width/height
包含内容区 + padding + border,即页面上可见方框的宽度,设置方式为 box-sizing: border-box
看下面一个代替盒子
width: 200px;
padding: 10px;
border: 5px solid;
2
3
内容实际宽度是:
几乎所有现代前端项目都会统一设置成 border-box
,因为它更符合我们对“盒子尺寸”的直觉理解。
使用这段 CSS 代码
* {
box-sizing: border-box;
}
2
3
# 外边距
外边距是盒子周围一圈看不到的空间。它会把其他元素退推离盒子。外边距属性值可以为正也可以为负。在盒子一侧设置负值会导致盒子和页面上的其他内容重叠。无论使用标准模型还是替代模型,外边距总是在计算可见部分后额外添加
外边距会存在一种叫做外边距折叠的现象
根据外边距相接触的两个元素是正边距还是负边距,结果会有所不同
- 两个正外边距将合并为一个外边距。其大小等于最大的单个外边距。
- 两个负外边距会折叠,并使用最小(离零最远)的值。
- 如果一个为正一个为负,那么就把两个外边距相加
# 行内盒子
上面的所有属性都适用于块级盒子,有些属性也适用于行内盒子
行内盒子中,width
、height
是会被忽略的,但是 margin
、border
和 padding
会被保留
<p>
I am a paragraph and this is a <span>span</span> inside that paragraph. A span
is an inline element and so does not respect width and height.
</p>
2
3
4
body {
font-family: sans-serif;
}
p {
border: 2px solid rebeccapurple;
width: 200px;
}
span {
margin: 20px;
padding: 20px;
width: 80px;
height: 150px;
background-color: lightblue;
border: 2px solid blue;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在这个例子中,可以看到盒子的内边距和边框被渲染了
# 层叠、优先级、继承
# 层叠
样式表层叠,就是 CSS 规则的顺序很重要;当应用两条同级别的规则到一个元素的时候,写在后面的就是实际使用的规则。
# 继承
一些设置在父元素上的 CSS 属性是可以被子元素继承的,有些则不能
例如,我们在 <body>
上定义 color: blue
会让页面的所有字体都变成蓝色
一些属性是不能继承的,如果在一个元素上设置 width: 50%
后代就不会继承
<ul class="main">
<li>项目 1</li>
<li>
项目 2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
项目 3
<ul class="special">
<li>
3.1
<ul>
<li>3.1.1</li>
<li>3.1.2</li>
</ul>
</li>
<li>3.2</li>
</ul>
</li>
</ul>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.main {
color: rebeccapurple;
border: 2px solid #ccc;
padding: 1em;
}
.special {
color: black;
font-weight: bold;
}
2
3
4
5
6
7
8
9
10

在这个例子中,.main
从 <ul>
继承到了 <li>
CSS 中的五个通用属性值,它们用于控制属性继承和行为的特殊情况
inherit
无论该属性是否默认继承,都从父元素那里继承值,适用于border
、padding
这种默认不继承多属性initial
将属性值设置为该属性在 CSS 规范中定义的默认初始值,不是浏览器的默认值unset
如果该属性可继承 → 就inherit
,如果该属性不可继承 → 就initial
revert
将应用于选定元素的属性值重置为浏览器的默认样式revert-layer
回到前一个样式层中的值
下面来看一个例子
<ul>
<li>默认<a href="#">链接</a>颜色</li>
<li class="my-class-1">继承<a href="#">链接</a>颜色</li>
<li class="my-class-2">重置<a href="#">链接</a>颜色</li>
<li class="my-class-3">取消<a href="#">链接</a>颜色的设置</li>
</ul>
2
3
4
5
6
body {
color: green;
}
.my-class-1 a {
color: inherit;
}
.my-class-2 a {
color: initial;
}
.my-class-3 a {
color: unset;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15

- 第一行默认使用浏览器的默认格式,蓝色
- 第二行设置了
inherit
选择继承父节点的属性值,绿色 - 第三行设置了
initial
,使用了 CSS 默认的格式,是黑色 - 第四行
unset
,color
可以继承,就继承
# 优先级
有些规则在最后出现,但是却应用了前面的具有冲突的规则。这是因为前面的有更高的优先级
本质上,不同类型的选择器有不同的分数值,把这些分数相加就得到特定选择器的权重,然后就可以进行匹配
一个选择器的优先级可以说是由三个不同的值(或分量)相加,可以认为是百(ID)十(类)个(元素)——三位数的三个位数:
- ID:选择器中包含 ID 选择器则百位得一分。
- 类:选择器中包含类选择器、属性选择器或者伪类则十位得一分。
- 元素:选择器中包含元素、伪元素选择器则个位得一分。

# 内联样式
内联样式就是 style
属性内的样式声明,高于其他所有优先级
# !important
有一个特殊的 CSS 可以用来覆盖所有上面所有优先级计算,不过需要很小心的使用——!important
,最好在开发中不要使用它
# 值和单位
# 长度
在计算机中,一般使用 px
为单位,表示像素,这是绝对长度
em
相对于本元素的字体大小
1em = 当前元素的字体大小(font-size
)
如果某元素的 font-size: 16px
,那么:
padding: 2em;
表示 padding = 2 × 16px = 32px
<div style="font-size: 16px">
<div style="font-size: 1.5em"> <!-- 实际是 24px -->
<div style="font-size: 1.5em"> <!-- 实际是 36px -->
</div>
</div>
</div>
2
3
4
5
6
em
是相对于当前元素的 font-size
,rem
是相对于根节点 html
的 font-size
vh
是 CSS 中的一种 相对视口单位,它的意思是:1vh = 视口高度的 1%
假设当前浏览器窗口高度是 900px:1vh
= 1% × 900px = 9px
# 百分比
百分比总是相对于其他值设置的。例如,如果将元素的字体大小设置为百分比,那么它将是元素父元素字体大小的百分比。如果使用百分比作为宽度值,那么它将是父值宽度的百分比
虽然许多值接受长度或百分比,但也有一些值只接受长度
# 数字
有些值接受数字,不添加任何单位,例如,透明度 opacity
只接受一个 0
(完全透明) 到 1
(完全不透明)之间的数字
# 颜色
首先颜色可以使用关键字来确定,关键字可以在 这个网站中 (opens new window)找到
<div class="wrapper">
<div class="box one">古董白(antiquewhite)</div>
<div class="box two">靛色(blueviolet)</div>
<div class="box three">黄绿色(greenyellow)</div>
</div>
2
3
4
5
.box {
padding: 10px;
margin: 0.5em 0;
border-radius: 0.5em;
}
.one {
background-color: antiquewhite;
}
.two {
background-color: blueviolet;
}
.three {
background-color: greenyellow;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

下面一种方法是 十六进制 RGB 表示
每个十六进制颜色值由一个井号(#
)后跟三个或六个十六进制字符组成(例如 #fcc
或 #ffc0cb
),还可以选择性地添加一个或两个十六进制字符来表示前三个或六个字符颜色值的透明度
每一对十六进制字符代表一个通道(红、绿、蓝)的十进制数值,允许我们为每个通道指定 256 个可用值中的任意一个(16 x 16 = 256)
这种表示法不够直观,但是可以表示所有的颜色
<div class="wrapper">
<div class="box one">#02798b</div>
<div class="box two">#c55da1</div>
<div class="box three">#128a7d</div>
</div>
2
3
4
5
.box {
padding: 10px;
margin: 0.5em 0;
border-radius: 0.5em;
}
.one {
background-color: #02798b;
}
.two {
background-color: #c55da1;
}
.three {
background-color: #128a7d;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

直接创建 RGB 值,rgb()
参数接受三个值,分别表示颜色的红、绿和蓝通道值,每一个通道是一个介于 0 ~ 255 之间的值
<div class="wrapper">
<div class="box one">rgb(2 121 139)</div>
<div class="box two">rgb(197 93 161)</div>
<div class="box three">rgb(18 138 125)</div>
</div>
2
3
4
5
.box {
padding: 10px;
margin: 0.5em 0;
border-radius: 0.5em;
}
.one {
background-color: rgb(2 121 139);
}
.two {
background-color: rgb(197 93 161);
}
.three {
background-color: rgb(18 138 125);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

也可以向 rgb()
传入第四个参数,它代表颜色的 alpha
通道,控制不透明度,如果你把这个值设置为 0
它使颜色完全透明,而 1
为完全不透明
<div class="wrapper">
<div class="box one">rgb(2 121 139 / .3)</div>
<div class="box two">rgb(197 93 161 / .7)</div>
<div class="box three">rgb(18 138 125 / .9)</div>
</div>
2
3
4
5
.wrapper {
background-image: url(https://mdn.github.io/shared-assets/images/examples/balloons.jpg);
padding: 40px 20px;
}
.box {
padding: 10px;
margin: 0.5em 0;
border-radius: 0.5em;
}
.one {
background-color: rgb(2 121 139 / 0.3);
}
.two {
background-color: rgb(197 93 161 / 0.7);
}
.three {
background-color: rgb(18 138 125 / 0.9);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 图像
在 CSS 中插入图像可以使用 url()
函数指向图像的实际文件,也可以是一个渐变
下面这个例子中,我们就使用渐变和图像作为 background-image
的属性值
<div class="box image"></div>
<div class="box gradient"></div>
2
.box {
height: 150px;
width: 300px;
margin: 20px auto;
border-radius: 0.5em;
}
.image {
background-image: url(https://mdn.github.io/shared-assets/images/examples/big-star.png);
}
.gradient {
background-image: linear-gradient(
90deg,
rgb(119 0 255 / 39%),
rgb(0 212 255 / 100%)
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 位置
可以使用 background-postion
来定位一个背景图像的位置
一个典型的位置值由两个值组成。第一个值水平地设置位置,第二个值垂直地设置位置。如果只指定一个轴的值,另一个轴将默认为 center
在以下示例中,我们使用关键字将背景图像定位在容器顶部右侧 40px 处
<div class="box"></div>
.box {
height: 100px;
width: 400px;
background-image: url(https://mdn.github.io/shared-assets/images/examples/big-star.png);
background-repeat: no-repeat;
background-position: right 40px;
margin: 20px auto;
border-radius: 0.5em;
border: 5px solid rebeccapurple;
}
2
3
4
5
6
7
8
9
10

# 函数
CSS 中的函数和别的语言中的函数类似,例如 rgb()
,hsl()
都是函数
# CSS 中调整大小
在 HTML 中插入一个图像的时候,长宽由这个图像文件自身确定,这个尺寸就是固有尺寸
在 HTML 中插入一个 div 它本身是没有尺寸的,如果设置上边框属性,我们只会看到一条线,因为它没有高度,长度拓展到整个容器的宽度
元素的固有尺寸是由其本身内容决定的
我们可以给元素指定长宽,我们将其称为外部尺寸我们可以给它一个具体的width
和 height
值,然后无论我们放什么内容就去他都是该尺寸
如果内容的数量超过了元素可以容纳的空间,则设置的高度会导致内容溢出
<div class="wrapper">
<div class="box"></div>
<div class="box">
These boxes both have a height set, this box has content in it which will
need more space than the assigned height, and so we get overflow.
</div>
</div>
2
3
4
5
6
7
body {
font: 1.2em sans-serif;
}
.wrapper {
display: flex;
}
.wrapper > * {
margin: 20px;
}
.box {
border: 5px solid darkblue;
height: 100px;
width: 200px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

由于存在溢出问题,在网络上使用长度或百分比固定元素的高度需要非常小心。
当然,我们也可以使用百分比作为长度单位,就是在使用百分比的时候,你要非常清楚,他是什么东西的百分比
但是同时要注意,百分比 padding
和 margin
,它们是相对于 包含块(containing block)
的宽度 计算的,不是相对于自己的高度!
我们可以通过设定 min-
和 max-
来给元素设定一个最大的或者最小的尺寸
<div class="wrapper">
<div class="box"></div>
<div class="box">
These boxes both have a min-height set, this box has content in it which
will need more space than the assigned height, and so it grows from the
minimum.
</div>
</div>
2
3
4
5
6
7
8
body {
font: 1.2em sans-serif;
}
.wrapper {
display: flex;
align-items: flex-start;
}
.wrapper > * {
margin: 20px;
}
.box {
border: 5px solid darkblue;
min-height: 100px;
width: 200px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在这个例子中,两个盒子都设置了 min-height
保证了最小的高度
视口,即你在浏览器中看到的部分页面,也是有尺寸的。在 CSS 中,我们有与视口尺寸相关的度量单位,即意为视口宽度的 vw
单位,以及意为视口高度的 vh
单位。使用这些单位,你可以把一些东西做得随用户的视口改变大小。
1vh
等于视口高度的 1%,1vw
则为视口宽度的 1%。你可以用这些单位约束盒子的大小,还有文字的大小。
在下面这个例子中,我们有一个大小为 20vh
和 20vw
的盒子,盒子里面有一个字母 A,他的 font-size
属性被设置为 10vh
<div class="box">A</div>
body {
font-family: sans-serif;
}
.box {
border: 5px solid darkblue;
width: 20vw;
height: 20vh;
font-size: 10vh;
}
2
3
4
5
6
7
8
9
10
11
如果你改变了 vh
和 vw
的对应值,盒子和字体的大小也会改变;视口大小的变化也会让它们的大小变化,因为它们是依照视口来定大小的。
# 溢出的内容
溢出是在盒子无法容纳下太多的内容的时候发生的。
我们可以通过 CSS 来给 width
和 height
约束
<div class="box">
This box has a height and a width. This means that if there is too much
content to be displayed within the assigned height, there will be an overflow
situation. If overflow is set to hidden then any overflow will not be visible.
</div>
<p>This content is outside of the box.</p>
2
3
4
5
6
7
.box {
border: 1px solid #333333;
width: 250px;
height: 100px;
}
2
3
4
5

overflow
属性是你控制一个元素溢出的方式,默认为 visible
就是显示
如果你想要去隐藏溢出的内容,我们需要设置 overflow: hidden

如果你设置了 overflow: scroll
,就可以滚动浏览内容,当设置 overflow: scoll
的时候,无论有没有超过都会有一个滚动条,非常不美观
我们可以使用 overflow: auto
,如果没有超过显示区域的时候就不会有滚动条
# 图像、媒体和表单元素
图像和视频被称为可替换元素,这意味着 CSS 不能影响他们的内部布局
CSS 中万物皆盒子,如果把一张图片放在一个盒子里面,而这张图片的原始长和宽比盒子的小或大,那么这张图要么缩在盒子里,要么就从盒子里面溢出。你需要决定如何处理这样的溢出。
下面的例子中有两个盒子,他们的长宽比均为 200px
- 一个包含了一张小于 200 像素的图像,它比盒子小,并且不会自动拉伸来充满盒子。
- 另一张图像大于 200 像素,溢出了盒子。
<div class="wrapper">
<div class="box">
<img
alt="star"
src="https://mdn.github.io/shared-assets/images/examples/big-star.png" />
</div>
<div class="box">
<img
alt="balloons"
src="https://mdn.github.io/shared-assets/images/examples/balloons.jpg" />
</div>
</div>
2
3
4
5
6
7
8
9
10
11
12
.wrapper {
display: flex;
align-items: flex-start;
}
.wrapper > * {
margin: 20px;
}
.box {
border: 5px solid darkblue;
width: 200px;
}
img {
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
如何处理溢出的问题,一种方法是设置图片的 max-width
设置成 100%
还有一种方法比较常用,就是使用 object-fit
属性
object: cover
让图像填充盒子,但保持原来的长宽,多出的部分截取object: contain
让图像填充为盒子的最短的那个边,保持原来的长宽,填不满的部分就留白object: fill
让图像充满盒子,但不会维持比例
# 弹性盒子
弹性盒子(Flexbox)是一种现代布局方式,他的主要作用是,在容器中自动排列、对其和分配空间给子元素,无论他们大小是否一致
当我们在父元素上设置 display: flex
,子元素就会整齐得排成一行
.wrapper {
display: flex;
}
2
3
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
2
3
4
5
# Grid 布局
Grid 用来把页面分成行和列,非常适合构建复杂的网页布局,比如网格宫格、后台系统、仪表盘等
和 flex 一样,我们可以通过 display 的值来转到 gird 布局:display: grid
在下面这个例子中,我们使用 grid-template-columns: 1fr 1fr 1fr;
定义了表格在行方向平均分成三份,grid-template-rows: 100px 100px;
定义列方向为 100px
我也可以定义每个盒子是从哪里开始的,到哪里结束的,利用 grid-column
和 grid-row
来指定每一个子元素应该从哪一行/列开始,并在哪一行/列结束
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
grid-gap: 10px;
}
.box1 {
grid-column: 2 / 4;
grid-row: 1;
}
.box2 {
grid-column: 1;
grid-row: 1 / 3;
}
.box3 {
grid-row: 2;
grid-column: 3;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
2
3
4
5

# 浮动
把一个元素浮动起来,可以给元素设置长宽,并且行内布局的一种方式,浏览器会优先渲染浮动的元素,可以设置成左浮动或者右浮动,但是处于浮动元素下方的文字会识别浮动并避开浮动元素
float
属性有四个可能值:
left
— 将元素浮动到左侧。right
— 将元素浮动到右侧。none
— 默认值,不浮动。inherit
— 继承父元素的浮动属性。
<h1>Simple float example</h1>
<div class="box">Float</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.box {
float: left;
width: 150px;
height: 150px;
margin-right: 30px;
}
2
3
4
5
6

# JavaScript
# 插入 JavaSrcipt
可以像插入 CSS 那样插入 JavaScript 到 HTML 的页面中
内部 JavaScript
<script>
// 在此编写 JavaScript 代码
</script>
2
3
把这段代码插入到 HTML <body>
标签的末尾
外部 JavaScript
可以通过 <script>
标签来外部引入一个 js 文件
例如,在结束标签 </head>
之前添加以下内容
<script type="module" src="script.js"></script>
内联 JavaScript 处理器
有些时候你会看到这样子的代码
function createParagraph() {
const para = document.createElement("p");
para.textContent = "你点击了按钮!";
document.body.appendChild(para);
}
2
3
4
5
<button onclick="createParagraph()">点我!</button>
在这种写法中,<button>
元素中包含了一个内联 的 onclick
处理器,使得函数在按钮被按下的时候运行
然而请不要这样做。这将使 JavaScript 污染了 HTML,而且效率低下。
# 基本语法
# 注释
单行注释
// 我是一条注释
多行注释
/*
我也是
一条注释
*/
2
3
4
# 变量
基本数据类型:
- number
- string
- boolean
- undefined
- null
引用数据类型:
- object
- 普通对象:
{key: 'value'}
- 数组:
[1, 2, 3]
- 函数:
function(){}
- 日期:
new Date
- 普通对象:
声明变量
在 JavaScript 中,声明变量主要有三种方式 var
,let
和 const
- var
- 作用域:函数作用域(function-scoped),在函数内声明则整个函数内有效。
- 提升:变量声明会被提升到作用域顶部(但赋值不会)。
- 重复声明:允许重复声明。
- 重新赋值:允许重新赋值。
var a = 10;
if (true) {
var a = 20; // 覆盖外层的 a
}
console.log(a); // 输出 20
2
3
4
5
let
- 作用域:块级作用域(block-scoped,如
{}
、if
、for
等内部)。 - 提升:存在暂时性死区(TDZ),必须先声明后使用。
- 重复声明:同一作用域内不允许重复声明。
- 重新赋值:允许重新赋值。
let b = 10;
if (true) {
let b = 20; // 块级作用域,不影响外层的 b
console.log(b); // 输出 20
}
console.log(b); // 输出 10
2
3
4
5
6
const
- 作用域:块级作用域(同
let
)。 - 提升:存在暂时性死区(TDZ)。
- 重复声明:不允许重复声明。
- 重新赋值:不允许重新赋值(常量),但如果是对象或数组,可以修改其属性或元素(因为地址不变)
const c = 30;
// c = 40; // 报错:Assignment to constant variable
const obj = { name: "Alice" };
obj.name = "Bob"; // 允许修改属性
console.log(obj); // { name: "Bob" }
2
3
4
5
6
# 条件语句
let iceCream = "chocolate";
if (iceCream === "chocolate") {
alert("我最喜欢巧克力冰淇淋了!");
} else {
alert("但是巧克力才是我的最爱呀……");
}
2
3
4
5
6
# 循环
和 C++ 一样,包括 continue
和 break
# 函数
function multiply(num1, num2) {
let result = num1 * num2;
return result;
}
2
3
4
# 事件
document.querySelector("html").addEventListener("click", function () {
alert("别戳我,我怕疼!");
});
2
3
这里的 addEventListener()
函数监听了 'click'
事件,然后在监听到事件 click 后运行后面的函数
后面的函数也叫匿名函数,因为没有具体的名字,还有另外一种写法
document.querySelector("html").addEventListener("click", () => {
alert("别戳我,我怕疼!");
});
2
3
# Object
字面量语法(最常用)
const person = {
name: "Alice", // 属性名: 属性值
age: 25,
greet: function() { // 方法(函数作为属性)
console.log(`Hello, I'm ${this.name}`);
}
};
2
3
4
5
6
7
或者使用 new Object()
const car = new Object();
car.brand = "Toyota";
car.year = 2020;
2
3
构造函数或类(es6)
function Person(name, age) {
this.name = name;
this.age = age;
}
const bob = new Person("Bob", 30);
// ES6 类语法
class Animal {
constructor(name) {
this.name = name;
}
}
const cat = new Animal("Tom");
2
3
4
5
6
7
8
9
10
11
12
13
# Array
Array(数组)是 JavaScript 中用于存储有序数据集合的一种对象类型。它是 JavaScript 中最常用的数据结构之一
创建数组
const fruits = ['Apple', 'Banana', 'Orange'];
const numbers = new Array(1, 2, 3);
const emptyArray = new Array(5); // 创建长度为5的空数组
2
访问元素
const first = fruits[0]; // 'Apple'
const last = fruits[fruits.length - 1]; // 'Orange'
2
修改元素
fruits[1] = 'Pear'; // ['Apple', 'Pear', 'Orange']
数组长度
console.log(fruits.length); // 3
添加,删除元素
// 末尾添加
fruits.push('Mango'); // ['Apple', 'Pear', 'Orange', 'Mango']
// 开头添加
fruits.unshift('Strawberry'); // ['Strawberry', 'Apple', 'Pear', 'Orange', 'Mango']
// 末尾删除
fruits.pop(); // 返回 'Mango', 数组变为 ['Strawberry', 'Apple', 'Pear', 'Orange']
// 开头删除
fruits.shift(); // 返回 'Strawberry', 数组变为 ['Apple', 'Pear', 'Orange']
2
3
4
5
6
7
8
9
10
11
切片和拼接
// 切片(不改变原数组)
const citrus = fruits.slice(1, 3); // ['Pear', 'Orange']
// 拼接(可删除、替换、添加元素)
fruits.splice(1, 1, 'Lemon', 'Kiwi');
// 从索引1开始删除1个元素,并添加'Lemon'和'Kiwi'
// 结果: ['Apple', 'Lemon', 'Kiwi', 'Orange']
2
3
4
5
6
7
遍历数组
// forEach
fruits.forEach(fruit => console.log(fruit));
// map
const lengths = fruits.map(fruit => fruit.length); // [5, 5, 4, 6]
// filter
const longFruits = fruits.filter(fruit => fruit.length > 5); // ['Orange']
2
3
4
5
6
7
8
查找元素
// 查找索引
const index = fruits.indexOf('Orange'); // 3
// 检查包含
const hasApple = fruits.includes('Apple'); // true
// 查找元素
const longFruit = fruits.find(fruit => fruit.length > 5); // 'Orange'
2
3
4
5
6
7
8
# HTML DOM
DOM 是什么
DOM 是 HTML 和 XML 的变成接口
一个网页结构能看成一颗 DOM 树
DOM 树中包含不同类型的节点:元素节点、文本节点、属性节点等
每一个节点都可以看成一个 Object
对象
HTML DOM 的核心观念就是利用程序来操作 HTML 标签,从而达到一个修改页面的目的
获取标签对象
// 通过ID获取
const header = document.getElementById('header');
// 通过类名获取(返回HTMLCollection)
const items = document.getElementsByClassName('item');
// 通过标签名获取(返回HTMLCollection)
const divs = document.getElementsByTagName('div');
// 通过CSS选择器获取
const element = document.querySelector('#container .item'); // 获取第一个匹配项
const elements = document.querySelectorAll('.items'); // 获取所有匹配项(NodeList)
2
3
4
5
6
7
8
9
10
11
12
修改标签对象
获取了之后我们可以对标签属性赋值来修改内容
// 修改内容
element.innerHTML = '<strong>New</strong> content';
element.textContent = 'Plain text content'; // 更安全,不会解析HTML
// 修改属性
element.setAttribute('id', 'newId');
const id = element.getAttribute('id');
element.removeAttribute('class');
// 修改样式
element.style.color = 'blue';
element.style.marginTop = '10px';
// 修改类名
element.className = 'new-class'; // 替换所有类
element.classList.add('active'); // 添加类
element.classList.remove('old-class'); // 移除类
element.classList.toggle('visible'); // 切换类
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 事件
事件是 JavaScript 和 HTML 交互的核心机制,它代表了在文档或浏览器窗口中发生的特定交互瞬间
- 鼠标事件
click
:单击(按下并释放主按钮)dblclick
:双击mousedown
/mouseup
:按下/释放鼠标按钮mousemove
:鼠标移动mouseenter
/mouseleave
:进入/离开元素区域(不冒泡)mouseover
/mouseout
:进入/离开元素区域(冒泡)contextmenu
:右键菜单
- 键盘事件
keydown
:按下任意键keyup
:释放按键keypress
:按下字符键(已弃用)
- 表单事件
submit
:表单提交change
:表单控件值改变(失去焦点后触发)input
:值改变时立即触发focus
/blur
:获得/失去焦点(不冒泡)focusin
/focusout
:获得/失去焦点(冒泡)
- 窗口事件
load
:资源加载完成DOMContentLoaded
:DOM解析完成(不等待样式/图片)resize
:窗口大小变化scroll
:滚动事件beforeunload
:窗口关闭前
- 触摸事件(移动端)
touchstart
:开始触摸touchmove
:触摸移动touchend
:触摸结束touchcancel
:触摸中断
事件处理的三大关键
- 在哪个标签上发生
- 发生的种类是什么
- 事件处理的函数是什么
事件处理的方式
- HTML 属性处理(不推荐)
<button onclick="alert('Clicked!')">点击我</button>
一个标签可以搭配多个事件使用
- DOM 属性处理(基本方式)
const btn = document.querySelector('button');
btn.onclick = function() {
console.log('第一次点击');
};
btn.onclick = function() {
console.log('会覆盖之前的处理函数');
};
2
3
4
5
6
7
- 事件监听器(推荐方式)
btn.addEventListener('click', function(event) {
console.log('不会覆盖其他监听器', event.target);
});
// 可添加多个同类型监听器
btn.addEventListener('click', anotherHandler);
2
3
4
5
6
# 箭头函数
函数有三个部分
- 函数的本体
- 函数的参数
- 函数的返回值
let 函数名称=(函数参数列表) => {
函数内部程序;
return 返回值;
}
2
3
4
箭头函数的简化
当函数内部只有返回值的时候,可以对箭头函数做简化
let 函数名称=(函数参数列表) => {
return 返回值;
}
2
3
可以简化成
let 函数名称=(函数参数列表) => (返回值);
# 解构赋值
数组的结构赋值
传统的做法
let arr=[3, 4, 5];
let d1=arr[0];
let d2=arr[1];
let d3=arr[2];
2
3
4
解构赋值的做法
let [d1,d2,d3]=arr;
当长度不够的时候可以使用预设值
let arr=[3,4];
let [d1,d2=6,d3=7]=arr;
2
类的解构赋值
let obj={x:3,y:4};
let {x,y}=obj;
2
宣告和复制分开
let obj={x:3,y:4};
let x, y;
({x,y}=obj); //注意这里需要加一个小括号
2
3
预设值
let obj={x:3};
let x, y;
({x,y=5}=obj);
2
3
制定新的变量名称
let obj={x:3, y:4};
let newX, newY;
({x:newX, y:newY}=obj);
2
3
# 剩余运算符
在解构赋值中,可以使用 Rest 运算符 ...
来合并多个独立元素到一个数组,或一个对象中
function sum(a, b, ...restArgs) {
console.log(a); // 1
console.log(b); // 2
console.log(restArgs); // [3, 4, 5]
}
sum(1, 2, 3, 4, 5);
2
3
4
5
6
7
Rest 运算符有一个约束,一定要放在参数的最后面
let obj={x:3, y:4, z:5};
let {x, ...data} = obj;
console.log(x); // 3
console.log(data); // {y: 4, z: 5}
2
3
4
# 模组系统
模组系统允许开发者将代码分割成独立的,可以复用的单元
预设的输出语法
export default 变量名称
预设的输入语法
import 变量名称 from "模组路径"
当输出的时候加了default
,那么输出的变量名称和输入的变量名称可以是不同的
另外一种是非预设的写法
输出是这样的
export {输出变量1,输出变量2,...}
输入是这样的
import {输入变量1,变量2,...} from "模组路径"
打大括号就是非预设的输出,不打大括号就是预设的输出
const x = 3;
const Obj= {x:3, y:4}
const data = [1, 2, 3, 4, 5];
export default x;
export { Obj, data };
2
3
4
5
import x from './lib.js';
import { Obj, data } from './lib.js';
console.log(x); // 3
console.log(Obj); // { x: 3, y: 4 }
console.log(data); // [1, 2, 3, 4, 5
2
3
4
5
当然也可以把两种方式结合起来
const x = 3;
const Obj= {x:3, y:4}
const data = [1, 2, 3, 4, 5];
export { x as default, Obj, data };
2
3
4
import x, { Obj, data } from './lib.js';
console.log(x); // 3
console.log(Obj); // { x: 3, y: 4 }
console.log(data); // [1, 2, 3, 4, 5
2
3
4
# 深拷贝/浅拷贝
对象的 =
符号是浅拷贝,只会拷贝指针,指向的还是同一块地址
let Obja = {
name: "Obja",
age: 18
};
let Objb = Obja;
Objb.age = 20;
console.log(Obja.age); // 输出 20
2
3
4
5
6
7
使用另外一种方式可以新简历一块空的内存,然后把值复制到空的内存中
let Obja = {
name: "Obja",
age: 18
};
let Objb = {...Obja}; // 使用扩展运算符复制 Obja 的属性
Objb.age = 20;
console.log(Obja.age); // 输出 18
2
3
4
5
6
7
浅拷贝
创建一个新的对象/数组,如果对象有很多层,只会复制原始对象的第一层属性值
我们常见的拷贝方式都是浅拷贝
内存示意图:
原始对象 → { a: 1, b: { x: 2 } }
↑
拷贝对象 → { a: 1, b: ┘ // b属性指向同一内存地址
2
3
浅拷贝的时间方法:
- 对象展开运算符
const original = { a: 1, b: { x: 2 } };
const copy = { ...original };
2
Object.assign()
const copy = Object.assign({}, original);
- 数组方法
const arr = [1, 2, { x: 3 }];
const shallowCopy = arr.slice(); // 或 [...arr] 或 Array.from(arr)
2
深拷贝
无论多少层,递归复制所有层级的属性
修改如何层级都不会影响原始对象
深拷贝的实现方法:
- 使用
JSON.parse(JSON.stringify())
const deepCopy = JSON.parse(JSON.stringify(original));
- 不能处理函数,Symbol,undefined
- 不能循环引用
- 会丢失 Date 对象
- 递归处理
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
2
3
4
5
6
7
8
9
10
11
12
13
- 使用第三方库
import _ from 'lodash';
const deepCopy = _.cloneDeep(original);
2