HTML5、CSS、JS基础

❀本篇来自尚硅谷老师的听课笔记

练习:95、101-114、116、118-119、120-19:38、123钟表、124魔方立体旋转效果、132导航条、135淘宝导航、141-142移动端页面、145-148美图手机

一、准备知识

1.1 客户端与服务器

服务器开发语言:❀Java、PHP、C#、Python、❀Node.js

客户端形式:文字客户端、图形化界面、网页(B/S架构)

网页中使用的语言:HTML、CSS、JavaScript

1.2 字符编码

所有数据在计算机中均以二进制形式存储,文字也不例外。

1.2.1 编码和解码

编码:将字符转换为二进制码的过程

解码:将二进制码转换为字符的过程

1.2.2 字符集

字符集:编码和解码所采用的规则

常见的字符集:ASCII、ISO88591、GB2312、GBK、❀UTF-8(万国码)

//声明UTF-8:通过meta标签

<head>
    <meta charset="UTF-8">
</head>

1.2.3 乱码问题

如果编码和解码所采用的字符集不同就会出现乱码问题

二、HTML

2.1 注释

```

2.5 实体/转义字符

❗️ 在网页中编写的多个空格默认情况会自动被浏览器解析为一个空格。

空格&nbsp ;
大于号&gt ;
小于号&lt ;
版权符号&copy ;

2.6 标签

2.6.1 meta

meta主要用于设置网页中的一些元数据,元数据不是给用户看。

(1)常用属性
  • charset:指定网页的字符集
  • name:指定数据的名称
  • content:指定数据的内容
//❀❀❀keywords表示网站的关键字(网页搜索关键字可查询相关网页的)。可以同时指定多个关键字,关键字之间使用英文,隔开。
//❀❀❀description用于指定网站的描述,网站的描述会显示在搜索引擎的搜索结果中。

<meta charset="UTF-8">
<meta name="keywords" content="HTML5,前端,CSS">
<meta name="description" content="这是一个很不错的网站">

//将页面重定向到另一个网站,比如3秒后跳转至百度
<meta http-equiv="refresh" content="3;url=https://www.baidu.com">

2.6.2 title

title标签的内容会作为搜索结果的超链接上的文字显示。

2.6.3 标题标签h

【块元素】h1~h6 一共有六级标题

〰️从h1~h6重要性递减。

〰️h1在网页中重要性仅次于title标签,一般情况下一个页面中只会有一个h1​。

〰️一般情况下标题标签只会使用到h1 ~ h3,h4 ~ h6​很少用。

2.6.4 hgroup

hgroup标签用来为标题分组,可以将一组相关的标题同时放入到hgroup。

<hgroup>
	<h1>回乡偶书二首</h1>
	<h2>其一</h2>
</hgroup>

2.6.5 段落标签p

【块元素】p标签表示页面中的一个段落。

2.6.6 em

【行内元素】em:用于表示语音语调的一个加重。即倾斜

2.6.7 strong

strong表示强调重要内容。即加粗

2.6.8 长引用blockquote

【块元素】blockquote表示一个长引用。效果显示为首行空2字符。

<body>
    鲁迅说:
    <blockquote>
        这句话我是从来没有说过的!
    </blockquote>
</body>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EISBaLWS-1646239243780)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220116213144956.png)]

2.6.9 短引用q

【行内元素】q表示一个短引用。效果为自动加引号。

<body>
    子曰
    <q>
        学而时习之,不亦说乎
    </q>
</body>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WGhtmLo-1646239243781)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220116213250568.png)]

2.6.10 换行标签br

br:页面中的换行。

2.6.11 头部标签header

可以有多个header。可以是网页的也可以是部分的。

2.6.12 主体部分main

一个页面中只会有一个main。

2.6.13 底部标签footer

可以有多个footer。可以是网页的也可以是部分的。

2.6.14 导航标签nav

表示网页中的导航。

2.6.15 aside

和主体相关的其他内容,即侧边栏。

2.6.16 article

表示一个独立的文章。

2.6.17 section

表示一个独立的区块,上边的标签都能不能表示时使用section。

2.6.18 ❀div

用来表示一个区块,主要的布局元素。

2.6.19 ❀span

【行内元素】,一般用于在网页中选中文字。

2.6.20 图片标签img

【自结束标签】img:用于向当前页面中引入一个外部图片。

🍶属于替换元素,既有块元素特点,也有行内元素特点。

(1)属性
  • src:指定外部图片的路径。

  • alt:对图片的描述,这个描述默认情况下不会显示,有些浏览器会在图片无法加载时显示。搜索引擎会根据alt中的内容来识别图片。如果不写alt属性则图片不会被搜索引擎所收录。

  • width:图片的宽度。单位是像素px。

  • height:图片的高度。单位是像素px。

    😆宽度和高度中如果只修改了一个,则另一个会等比例缩放。

    ❗️注意:一般情况在pc端,不建议修改图片的大小。需要多大的图片就裁多大。但是在移动端,经常需要对图片进行缩放(大图缩小)。

<img src="./img/1.pig">
(2)格式
  • jpeg(jpg):支持的颜色比较丰富,不支持透明效果,不支持动图。一般用来显示照片。
  • gif:支持的颜色较少,支持简单透明,支持动图。适合颜色单一的图片,动图。
  • png:支持的颜色丰富,支持复杂透明,不支持动图。适合颜色丰富、复杂透明的图片(专为网页而生)。
  • webp:谷歌新推出的专门用来表示网页中的图片的一种格式,具备其他图片格式的所有优点,且文件特别小。缺点:兼容性不好。
  • base64.txt:将图片使用base64进行编码,可以直接将图片转换为字符。通过将字符全选,加在src属性中来引入图片。一般都是一些需要和网页一起加载的图片才会使用base64。【可搜索在线网页进行转换】

💎效果一样,用小的;效果不一样,用效果好的。

2.6.21 内联框架iframe

用于向当前页面中引入一个其他页面(作为窗口的形式引入)。

(1)属性
  • src:指定要引入的网页的路径。
<iframe src="https://www.4399.com" width="800" height="600" frameborder="0"></iframe>
image-20220117001326136

2.7 块元素和行内元素

2.7.1块元素

1️⃣在网页中一般通过块元素来对页面进行布局。

2️⃣一般情况下在块元素中放行内元素,而不会在行内元素中放块元素。

3️⃣块元素中基本什么都能放。

4️⃣p元素中不能放任何的块元素。

2.7.2 行内元素

1️⃣行内元素主要用来包裹文字。

2.8 超链接

超链接可以从一个页面跳转到另一个页面,或者是当前页面的其他位置。

🎁【行内元素】使用a标签定义。

🎁在a标签中可以嵌套除了自身外的任何元素。

2.8.1 属性

  • href:指定跳转的目标路径。其值可以是一个外部网站的地址;也可以是内部页面的地址。
<a href="https://www.baidu.com">超链接</a>
  • target:指定超链接打开的位置。可选值:
    • _self:默认值,在当前页面中打开超链接。
    • _blank:在一个新的页面打开超链接。
<a href="https://www.baidu.com" target="_blank">超链接</a>

2.8.2 其他超链接

(1)回到顶部超链接

可以直接将超链接的href属性设置为#。这样点击超链接以后页面不会发生跳转,而是转到当前页面的顶部位置。

<a href="#">回到顶部</a>
(2)页面内去往指定位置

给要去的位置加上id属性(唯一不重复的)。

💃每一个标签都可以添加一个id属性

💃同一个页面中不能出现重复的id属性。

💃id属性有大小写之区别

//给要去的位置添加id属性

<a id="bottom" href="#"></a>

//去往指定位置的链接

<a href="#bottom">去指定位置</a>
(3)空链接

1️⃣在开发中可以将#作为超链接的占位符使用。

<a href="#">空链接(未指定具体链接时)</a>

2️⃣可以使用javascript:;来作为href属性,此时点击超链接什么也不会发生。

<a href="javascript:;">空链接(未指定具体链接时)</a>

2.8.3 绝对路径与相对路径

(1)相对路径

当需要跳转到一个服务器内部的页面时,一般都会使用相对路径。

👡相对路径都会使用 . 或 … 开头

👡./ 可以省略不写。如果不写 ./ 和 …/ 则默认写了 ./

  • ./ 表示当前文件所在的目录
  • …/ 表示当前文件所在目录的上一级目录

2.9 音视频

2.9.1 引入音频

audio:向页面中引入一个外部的音频文件。

▶️音视频文件引入时,默认情况下不允许用户自己控制播放停止。

(1)属性
  • src:指定音频所在路径
  • controls:允许用户控制播放停止(会出现一个控制标志)。
  • autoplay:音频文件是否自动播放。如果设置了autoplay则音乐在打开页面时会自动播放,但是目前大部分浏览器都不会自动对音乐进行播放。
  • loop:是否循环播放。
<audio src="" controls autoplay loop></audio>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HVJR24Su-1646239243781)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220117001959289.png)]

📡除了通过src来指定外部文件的路径外,还可以通过source来指定文件【此写法友好性更强】

<audio controls>

	//若浏览器不支持,则出现以下提示
	
	对不起,您的浏览器不支持播放音频!请升级浏览器!
	
	//多写照顾兼容性,若第一个不行,则显示第二个...
	
	<source src="">
	<source src="">
	
	//以下代码和上面那句话任选其一。
	//<embed src="" type="audio/mp3" width="200" height="100">
	
</audio>

📡embed老版本浏览器引入音频文件

  • type值,前面是大类,后面是具体格式。
  • src:音频路径。
  • 注意必须指定宽度和高度。
<embed src="" type="audio/mp3" width="200" height="100">

2.9.2 引入视频

video:引入一个视频。

👯使用方式和audio基本一样。

<video controls>
	//最好写两个指明.webm和.mp4格式
	<source src="./1.webm">
	<source src="./1.mp4">
	<embed src="./1.mp4" type="video/mp4">
</video>

😱可以在腾讯视频等生成复制代码,然后通过内联框架移入网页中。

2.10 列表

html中列表一共有三种:

⛵️列表之间可以互相嵌套。

2.10.1 有序列表

使用ol标签,使用li表示列表项。

<body>
    <ol>
        <li>结构</li>
        <li>表现</li>
        <li>行为</li>
    </ol>
</body>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8QvGjBY-1646239243783)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220116220615346.png)]

2.10.2 无序列表

使用ul标签,使用li表示列表项。

<body>
    <ul>
        <li>结构</li>
        <li>表现</li>
        <li>行为</li>
    </ul>
</body>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dGr4lFH2-1646239243784)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220116220544790.png)]

2.10.3 定义列表

使用dl标签创建一个定义列表,使用dt表示定义的内容,使用dd来对内容进行解释说明。

<body>
    <dl>
        <dl>结构</dl>
        <dd>结构表示网页的结构</dd>
        <dd>结构表示网页的结构</dd>
        <dd>结构表示网页的结构</dd>
    </dl>
</body>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lg2Wop4C-1646239243785)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220116220953518.png)]

2.11表格

⛺️通过table标签来创建一个表格。

⛺️在table中使用tr表示表格中的一行,有几个tr就有几行。

⛺️在tr中使用td表示一个单元格,有几个td就有几个单元格。

⛺️可以将一个表格分成三个部分:头部 thead、主体 tbody、底部 tfoot。

⛺️th 表示头部的单元格【有加粗、居中的效果】

<table border="1" width='50%' align="center">
        <thead>
            <tr>
                <th>日期</th>
                <th>收入</th>
                <th>支出</th>
                <th>合计</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>2000.1.1</td>
                <td>500</td>
                <td>200</td>
                <td>300</td>
            </tr>
            <tr>
                <td>2000.1.1</td>
                <td>500</td>
                <td>200</td>
                <td>300</td>
            </tr>
            <tr>
                <td>2000.1.1</td>
                <td>500</td>
                <td>200</td>
                <td>300</td>
            </tr>
            <tr>
                <td>2000.1.1</td>
                <td>500</td>
                <td>200</td>
                <td>300</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <td></td>
                <td></td>
                <td>合计</td>
                <td>300</td>
            </tr>
        </tfoot>
    </table>
  • rowspan 纵向的合并单元格
  • colspan 横向的合并单元格
<table border="1" width='50%' align="center">
        <tr>
            <td>A2</td>
            <td>B2</td>
            <td>C2</td>
            <!-- rowspan 纵向的合并单元格 -->
            <td rowspan="2">D2</td>
        </tr>
        <tr>
            <td>A4</td>
            <td>B4</td>
            <!-- 
                colspan 横向的合并单元格
             -->
            <td colspan="2">C4</td>
        </tr>
    </table>

2.11.1 表格的样式

(1)border-spacing 指定边框之间的距离
border-spacing: 0px;
(2)border-collapse 设置边框的合并
border-collapse: collapse;
(3)逐行变色

如果表格中没有使用tbody而是直接使用tr,那么浏览器会自动创建一个tbody,并且将tr全都放到tbody中。【tr不是table的子元素】

//❀逐行变色
tbody > tr:nth-child(odd){
    background-color: #bfa;
}
(4)vertical-align

默认情况下元素在td中是垂直居中的 可以通过 vertical-align 来修改。vertical-align:middle;

2.12 表单

💟使用form标签来创建一个表单。

2.12.1 form属性

(1)action 表单要提交的服务器的地址
 <form action="target.html">

2.12.2 表单项

(1)文本框

💟数据要提交到服务器中,必须要为元素指定一个name属性值。

💟value的值为文本框上显示的提示文字。

💟属性

  • autocomplete=“off” 关闭自动补全
  • readonly 将表单项设置为只读,数据会提交
  • disabled 将表单项设置为禁用,数据不会提交
  • autofocus 设置表单项自动获取焦点
<input type="text" name="username">

<input type="text" name="username" value="hello" readonly>

<input type="text" name="username" value="hello" disabled>

<input type="text" name="username" autofocus>
(2)密码框

写完后是隐藏状态。

💟数据要提交到服务器中,必须要为元素指定一个name属性值。

<input type="password" name="password">
(3)提交按钮

💟type属性值为submit,按钮上显示的文字默认是“提交”。

💟value的值可指定按钮上的提示文字。

<input type="submit" value="注册">
(4)单选按钮

💟相同组的name属性值必须相同(才能实现多选一效果)。

💟像这种选择框,必须要指定一个value属性,value属性最终会作为用户的填写的值传递给服务器。

💟checked 可以将单选按钮设置为默认选中。

<input type="radio" name="hello" value="a">
<input type="radio" name="hello" value="b" checked>
(5)普通按钮

可以通过JS添加效果

<input type="button" value="按钮">
(6)重置按钮
<input type="reset">
(7)按钮
<button type="submit">提交</button>
<button type="reset">重置</button>
<button type="button">按钮</button>
(8)多选框

💟可以同时选择多个。

💟相同组的name属性值必须相同。

💟需指定name属性、value属性

<input type="checkbox" name="test" value="1">
<input type="checkbox" name="test" value="2">
<input type="checkbox" name="test" value="3" checked>
(9)下拉列表

💟selected把某个选项设置为默认选中。

<select name="haha">
  <option value="i">选项一</option>
  <option selected value="ii">选项二</option>
  <option value="iii">选项三</option>
</select>
(10)电子邮件输入框
<input type="email">
(11)颜色框/调色板

兼容性不太好。

<input type="color">

三、CSS—层叠样式表

网页实际上是一个多层的结构,通过CSS可以分别为网页的每一个层来设置样式。

3.1 引入CSS样式

3.1.1 内联样式/行内样式

标签内部通过style属性设置。【不推荐使用】

🍁问题:使用内联样式,样式只能对一个标签生效。如果希望影响到多个元素必须在每一个元素中都复制一遍。并且当样式发生变化时,必须要一个一个修改,非常不方便。

<p style="color:red; font-size:12px; ">my css</p>

3.1.2 内部样式表

将样式编写在head中的style标签里,然后通过css的选择器来选中元素并为其设置各种样式。

🍃可以同时为多个标签设置样式,并且修改时只需要修改一处即可。

🍃更加方便对样式进行复用。

🍁问题:只能对一个网页起作用,不能跨页面进行复用。

<head>
	<style>
		p{
			color:red; 
			font-size:12px;
		}
	</style>
</head>

3.1.3 外部样式表

可以将CSS样式编写到一个外部的CSS文件中,通过link标签来引入外部的CSS文件。【开发常用】

🍃只要想使用这些样式的网页都可以对其进行引用,使样式可以在不同页面之间进行复用。​

🍃将样式编写到外部的CSS文件中,可以使用到浏览器的缓存机制,从而加快网页的加载速度,提高用户的体验。​

//1.CSS文件

p{
			color:red; 
			font-size:12px;
		}
//引入,写在head中

<link rel="stylesheet" href="./1.css">

3.2 CSS语法

3.2.1 注释

/* */

3.2.2 基本语法

  • 选择器:选中页面中的指定元素。比如p的作用是选中页面中所有的p元素。
  • 声明块:为指定元素设置样式。声明块由一个一个的声明组成。声明是一个名值结构(一个样式名对应一个样式值,名和值之间以:连接,以;结尾)。

3.2.3 常用选择器

👊CSS选择器练习:尚硅谷“餐厅练习”

相关答案即练习地址入口https://blog.csdn.net/qq_44910948/article/details/106444049?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&utm_relevant_index=2

(0)选择器的权重

样式的冲突:当我们通过不同的选择器选中相同的元素,并为相同的样式设置不同的值时,此时就发生了样式的冲突。

🍔从高到低依次为:【优先级越高的优先显示】

  • !important

    • 在某一个样式的后边添加 !important ,则此时该样式会获取到最高的优先级,甚至超过内联样式
    • 注意:在开发中这个玩意一定要慎用!
  • 内联样式 1,0,0,0

  • id选择器 0,1,0,0

  • 类和伪类选择器 0,0,1,0

  • 元素选择器 0,0,0,1

  • 通配选择器 0,0,0,0

  • 继承的样式 没有优先级

🍔比较优先级时,需要将所有的选择器的优先级相加计算,最后优先级越高的优先显示。【注意:分组选择器是单独计算的】​

🍔选择器的累加不会超过其最大的数量级,如类选择器最高也不会超过id选择器。

🍔如果计算后的优先级相同,此时优先使用靠下的样式。

.d1{
            background-color: purple !important;
}
(1)元素选择器

作用:根据标签名选中指定的元素。

语法:标签名{}

p{
	color:red;	
}
h1{
	color:green;
}
(2)id选择器

作用:根据元素的id属性值选中一个元素。

语法:#id属性值{}

<p id="red">id选择器</p>

#red{
	color:red;	
}
(3)类选择器

class是一个标签的属性,它和id类似,不同的是class可以重复使用。

作用:根据class属性值选中一组元素。

语法:.class属性值

🎷可以通过class属性来为元素分组。

🎷可以同时为一个元素指定多个class属性。​多个属性使用空格隔开。

<p class="blue">1</p>
<p class="blue abc">2</p>

.blue{
	color:blue;	
}
.abc{
	font-size:12px;
}
(4)通配选择器

作用:选中页面中的所有元素。

语法:*{}

*{
	color:pink;	
}
(5)交集选择器

作用:选中同时符合多个条件的元素。

语法:选择器1选择器2选择器3…选择器n{ }

❗️交集选择器中如果有元素选择器,必须使用元素选择器开头

//将class为red的div字体设置为红色
div.red{
	color:red;
}

.a.b.c {
	color:blue;	
}

//不建议这样写,因为#box1就能找到指定的
div#box1{}
(6)选择器分组/并集选择器

作用:同时选中多个选择器对应的元素。

语法:选择器1,选择器2…选择器n{ }

h1,span{
	color:pink;
}

#b1,.p1,h1,div,.red{
	color:blue;	
}
(7)关系选择器
<div>我是一个div
	<p>我是div中的p
		<span>我是p中的span</span>
	</p>
	<span>我是div中的span</span>
</div>
  • 父元素:直接包含子元素的元素。(只要一个父元素)
  • 子元素:直接被父元素包含的元素。
  • 祖先元素:直接或间接包含后代元素的元素。一个元素的父元素也是它的祖先元素。(可能有很多个祖先元素)
  • 后代元素:直接或间接被祖先元素包含的元素。子元素也是后代元素。
  • 兄弟元素:拥有相同父元素的元素。
子元素选择器

作用:选中指定父元素的指定子元素

语法:父元素>子元素

//为div直接包含的span设置一个字体颜色
div>span{
	color:orange;
}

div.box>span{
	color:blue;
}

div>p>span{
	color:red;
}
后代元素选择器

作用:选中指定元素内的指定后代元素。

语法:祖先 后代{ }

div span{
	color:blue;
}
兄弟元素选择器

1️⃣作用:选择下一个兄弟(紧挨着的那个)。

语法:前一个+下一个

2️⃣作用:选择下边所有的兄弟

语法:兄 ~ 弟

p + span{
	color:gray;
}

p ~ span{
	font-size:19px;
}
(8)属性选择器

给标签添加title:网页中鼠标放在对应内容上会出现title值的内容。

<dl title="什么是结构">结构</dl>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k45ENMjF-1646239243787)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220117153912469.png)]

🎃应用:

[属性名]:选择含有指定属性的元素。

[属性名=属性值]:选择含有指定属性和属性值的元素。

[属性名^=属性值]:选择属性值以指定值开头的元素。

[属性名$=属性值]:选择属性值以指定值结尾的元素。

[属性名*=属性值]:选择属性值中含有某值的元素。

p[title]{
	color:yellow;
}

p[title=abc]{
	color:yellow;
}

p[title^=abc]{
	color:yellow;
}

p[title$=abc]{
	color:yellow;
}

p[title*=abc]{
	color:yellow;
}
(9)伪类选择器

🎒一个:开头

伪类用来描述一个元素的特殊状态,比如第一个元素、被点击的元素、鼠标移入的元素等。

伪类一般情况下都是使用: 开头。

🎡以下这些伪类都是根据所有的子元素进行排序。

  • :first-child 选择第一个子元素

  • :nth-child( ) 选择第n个子元素

    • 特殊值:

      n:表示第n个范围,即0~正无穷

      2n:表示选中偶数位的元素,即2、4、6…

      even:表示选中偶数位的元素

      2n+1:表示选中奇数位的元素

      odd:表示选中奇数位的元素

//将ul里的第一个li设置为红色

ul>li:first-child{
	color:red;
}

🎡以下几个伪类的功能和上述类似。不同点是他们是在同类型元素中进行排序。

  • :first-of-type:选中同类型的第一个元素

  • :last-of-type

  • :nth-of-type

  • :not() 否定伪类。将符合条件的元素从选择器中去除。

ul>li:not(:nth-of-type(3)){
	color:blue;
}

#####a元素的伪类

  • :link 用来表示没访问过的链接(正常的链接)。

  • :visited 用来表示访问过的链接。

    • 由于隐私的原因,visited这个伪类只能修改链接的颜色。
  • :hover 表示鼠标移入的状态。

  • :active 表示鼠标点击的状态。

a:link{
	color:red;
}

a:visited{
	color:blue;
}

a:hover{
             color: aqua;
             font-size: 50px;
}

a:active{
             color: yellowgreen;
}
(10)伪元素选择器

🎒两个: 开头

伪元素表示页面中一些特殊的并不真实存在的元素(特殊的位置)。

  • ::first-letter 表示第一个字母
  • ::first-line 表示第一行
  • ::selection 表示用鼠标选中的内容
  • ::before 表示元素的开始❀
  • ::after 表示元素的结束❀
    • before和after必须结合content属性来使用
p::first-letter{
	font-size:50px;
}

div::after{
	content:'abc';    //其中值可更改
	color:red;
}

3.2.4 继承

样式的继承:我们为一个元素设置的样式同时也会应用到它的后代元素上。

👩‍👩‍👧‍👧继承是发生在祖先和后代之间的。

👩‍👩‍👧‍👧利用继承可以将一些通用的样式统一设置到共同的祖先元素上,这样只需设置一次即可让所有的元素都具有该样式。

❗️不是所有样式都会被继承

  • 比如背景相关、布局相关等样式都不会被继承。

3.2.5 单位

(1)长度单位
  • 像素

    • 屏幕(显示器)实际上是由一个一个的小点点构成的。不同屏幕的像素大小是不同的,像素越小的屏幕显示的效果越清晰。所以同样的200px在不同的设备下显示效果不一样。(200px表示200个点)【详细可见3.2.6】
  • 百分比

    • 相对于其父元素属性的百分比,可以使子元素跟随父元素的改变而改变。
  • em

    • 1em = 1font-size,相对于元素的字体大小来计算。
    • em会根据字体大小的改变而改变。
  • rem

    • 相对于根元素的字体大小来计算。【根元素即html】
(2)颜色单位
  • 可以直接使用颜色名来设置各种颜色,如red、orange、yellow、blue、green …
  • RGB值
    • 语法:RGB(红色,绿色,蓝色)。如白色的rgb(255,255,255);
    • RGB通过三种颜色的不同浓度来调配出不同的颜色。R red,G green ,B blue。
    • 每一种颜色的范围在 0 - 255 (0% - 100%) 之间。
  • RGBA
    • 语法:rgba(red, green, blue, alpha);
    • 就是在rgb的基础上增加了一个a,即不透明度。【1表示完全不透明 0表示完全透明 .5半透明】
  • 十六进制的RGB值
    • 语法:#红色绿色蓝色。如红色为#ff0000
    • 颜色浓度通过 00-ff
    • 如果颜色两位两位重复可以进行简写。如#aabbcc可以简写为 #abc
  • HSL值 HSLA值
    • 语法:hsl(hue, saturation, lightness); 如hsl(0, 50%,50%);
    • H 色相(取值范围是0 - 360)、 S 饱和度,颜色的浓度 0% - 100%、L 亮度,颜色的亮度 0% - 100%

3.2.6 像素

屏幕是由一个一个发光的小点构成,这一个个的小点就是像素。

🐹分辨率:1920 x 1080 说的就是屏幕中小点的数量。

🐹在前端开发中像素要分成两种情况讨论:CSS像素 和 物理像素。

  • 物理像素:上述所说的小点点就属于物理像素。

  • CSS像素:编写网页时,我们所用像素都是CSS像素。如:

     .box1{
        width: 100px;
        height: 100px;
    }
    
    • 浏览器在显示网页时,需要将CSS像素转换为物理像素然后再呈现。
    • 一个css像素最终由几个物理像素显示,由浏览器决定:默认情况下在pc端,一个css像素 = 一个物理像素。(拓展见3.2.7视口)

3.2.7 视口viewport

视口就是屏幕中用来显示网页的区域。

🐹可以通过查看视口的大小,来观察CSS像素和物理像素的比值。

  • 默认情况下:【此时,css像素和物理像素的比是 1:1】
    • 视口宽度 1920px(CSS像素)
    • 1920px(物理像素)
  • 放大两倍的情况:【此时,css像素和物理像素的比是1:2】
    • 视口宽度 960px(CSS像素)
    • 1920px(物理像素)

🐹我们可以通过改变视口的大小,来改变CSS像素和物理像素的比值。

3.3 布局样式

3.3.1 文档流

网页是一个多层的结构,一层摞着一层。通过CSS可以分别为每一层来设置样式。作为用户来讲只能看到最顶上一层。这些层中,最底下的一层称为文档流,文档流是网页的基础。我们所创建的元素默认都是在文档流中进行排列。

对于我们来元素主要有两个状态:在文档流中、不在文档流中(脱离文档流)。

(1)元素在文档流中的特点
  • 块元素
    • 块元素会在页面中❀独占一行❀(自上向下垂直排列)。
    • 默认宽度是父元素的全部(会把父元素撑满)。
    • 默认高度是被其中内容(子元素)撑开。
  • 行内元素
    • 行内元素不会独占页面的一行,只占自身的大小。
    • 行内元素在页面中左向右水平排列,如果一行之中不能容纳下所有的行内元素,则元素会换到第二行继续自左向右排列(与书写习惯一致)。
    • 行内元素的默认宽度和高度都是被内容撑开。
(2)脱离文档流的特点
  • 块元素
    • 块元素不再独占页面的一行。
    • 脱离文档流以后,块元素的宽度和高度默认都被内容撑开。
  • 行内元素
    • 行内元素脱离文档流以后会变成块元素,特点和块元素一样。

🍇脱离文档流以后,不需要再区分块和行内了。

3.3.2 盒子模型/框模型

CSS将页面中的所有元素都设置为了一个矩形的盒子。

将元素设置为矩形的盒子后,对页面的布局就变成将不同的盒子摆放到不同的位置。

(1)组成部分

🌾内容区、内边距、边框决定盒子的大小(计算盒子大小时,需要将这三个区域加到一起计算),外边距决定盒子的位置。

🌾每一个盒子都由以下几个部分组成:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMSJHnmH-1646239243789)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220117174414106.png)]

  • 内容区(content)

    • 元素中的所有的子元素和文本内容都在内容区中排列。
    • 内容区的大小由width 和 height两个属性来设置。(width的值默认就是auto)
  • 内边距(padding)

    • 内容区和边框之间的距离是内边距。内边距的设置会影响到盒子的大小。
    • 背景颜色会延伸到内边距上。
    • 一共有四个方向的内边距:padding-top、padding-right、padding-bottom、padding-left。
    • padding 内边距的简写属性,可以同时指定四个方向的内边距。规则和border-width 一样。
  • 边框(border)

    • 简写属性:通过该属性可以同时设置边框所有的相关样式,并且没有顺序要求。
      • 除了border以外还有四个 border-xxx:border-top、border-right、border-bottom、border-left。
    border: solid 10px orange;
    
    • 设置边框,需要至少设置三个样式:

      • 边框的宽度 border-width:用来指定四个方向的边框的宽度。默认值一般是 3个像素。

        • 值的情况:

          🍏四个值:上 右 下 左

          🍏三个值:上 左右 下

          🍏两个值:上下 左右

          🍏一个值:上下左右

        • border-xxx-width

          🍏xxx可以是 top right bottom left,用来单独指定某一个边的宽度。

      border-width: 10px;
      
      • 边框的颜色 border-color

        🍏用来指定边框的颜色,同样可以分别指定四个边的边框。规则和border-width一样。

        🍏border-color也可以省略不写,如果省略了则自动使用color的颜色值。

      border-color: orange;
      
      • 边框的样式 border-style。默认值是none,表示没有边框

        🍏指定边框的样式。同样可以分别指定四个边的边框。规则和border-width一样。

        🍏值: solid 表示实线、dotted 点状虚线、dashed 虚线、double 双线

    border-style: solid;
    
    • 边框属于盒子边缘,边框里边属于盒子内部,出了边框都是盒子的外部。
    • 边框的大小会影响到整个盒子的大小。
  • 外边距(margin)

    • 外边距不会影响盒子可见框的大小,但是会影响盒子的位置(即盒子实际占用空间)。

    • 一共有四个方向的外边距:

      • margin-top:上外边距,设置一个正值,元素会向下移动。
      • margin-left:左外边距,设置一个正值,元素会向右移动。
      • margin-right:默认情况下设置margin-right不会产生任何效果。
      • margin-bottom:下外边距,设置一个正值,其下边的元素会向下移动。

      💩margin也可以设置负值,如果是负值则元素会向相反的方向移动。

      💩元素在页面中是按照自左向右的顺序排列的,所以默认情况下如果我们设置的左和上外边距则会❀移动元素自身❀,而设置下和右外边距会❀移动其他元素❀。

    • margin的简写属性:可以同时设置四个方向的外边距 ,用法和padding一样。

    margin: 100px;
    
(2)水平方向的布局

不懂看尚硅谷P49https://www.bilibili.com/video/BV1XJ411X7Ud?p=49

📰元素在其父元素中水平方向的位置由以下几个属性共同决定:

  • margin-left
  • border-left
  • padding-left
  • width
  • padding-right
  • border-right
  • margin-right

📰一个元素在其父元素中,水平布局必须要满足以下的等式:

margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = 其父元素内容区的宽度 (必须满足)

  • 没写的属性值默认是0。

  • 👜以上等式必须满足,如果相加结果使等式不成立,则称为过度约束,则等式会自动调整。

    👜调整的情况:

    • 如果这七个值中没有为 auto 的情况,则浏览器会自动调整margin-right值以使等式满足(调整的值也可以为负值)。

    • 这七个值中有三个值和设置为auto:width、margin-left、 maring-right。如果某个值为auto,则会自动调整为auto的那个值以使等式成立。

      • 如果将一个宽度和一个外边距设置为auto,则宽度会调整到最大,设置为auto的外边距会自动为0。
      • 如果将三个值都设置为auto,则外边距都是0,宽度最大。
      • 如果将两个外边距设置为auto,宽度固定值,则会将外边距设置为相同的值。
      //所以我们经常利用这个特点来使一个元素在其父元素中水平居中。
      
      //示例:
      width:10px;
      margin:0 auto;
      
(3)竖直方向的布局

默认情况下父元素的高度被其中内容(子元素)撑开。

子元素是在父元素的内容区中排列的,如果子元素的大小超过了父元素,则子元素会从父元素中溢出。

  • 使用 overflow 属性来设置父元素如何处理溢出的子元素

    〰️可选值:

    • visible 默认值,子元素会从父元素中溢出,在父元素外部的位置显示。
    • hidden 溢出内容将会被裁剪,不显示。
    • scroll 生成两个滚动条,通过滚动条来查看完整的内容。
    • auto 根据需要生成滚动条来查看完整的内容。

    〰️overflow-x: 、overflow-y:

(4)垂直外边距的折叠

相邻的垂直方向外边距会发生重叠现象。

  • 兄弟元素

    🏜兄弟元素间的相邻垂直外边距会取两者之间的较大值(两者都是正值)。

    ​ 特殊情况:

    • 如果相邻的外边距一正一负,则取两者的和。
    • 如果相邻的外边距都是负值,则取两者中绝对值较大的。

    🏜兄弟元素之间的外边距的重叠,对于开发是有利的,所以我们不需要进行处理。

  • 父子元素

    🏜父子元素间相邻外边距,子元素的会传递给父元素(上外边距)。【父随子动】

    🏜父子外边距的折叠会影响到页面的布局,必须要进行处理。

(5)行内元素的盒模型

#️⃣行内元素的盒模型的特点:

  • 行内元素不支持设置宽度和高度。
  • 行内元素可以设置padding,但是垂直方向padding不会影响页面的布局。
  • 行内元素可以设置border,垂直方向的border不会影响页面的布局。
  • 行内元素可以设置margin,垂直方向的margin不会影响布局。

#️⃣display 用来设置元素显示的类型

​ 可选值:

  • inline 将元素设置为行内元素。
  • block 将元素设置为块元素。
  • inline-block 将元素设置为行内块元素。行内块,既可以设置宽度和高度又不会独占一行。
  • table 将元素设置为一个表格。
  • none 元素不在页面中显示。

#️⃣visibility 用来设置元素的显示状态

​ 可选值:

  • visible 默认值,元素在页面中正常显示。
  • hidden 元素在页面中隐藏,即不显示,但是依然占据页面的位置。
(6)盒子的尺寸

默认情况下,盒子可见框的大小由内容区、内边距和边框共同决定。

  • box-sizing 用来设置盒子尺寸的计算方式(设置width和height的作用).

    可选值:

    • content-box 默认值,宽度和高度用来设置内容区的大小。

    • border-box 宽度和高度用来设置整个盒子可见框的大小。

      ​ 🏬 width 和 height 指的是内容区 和 内边距 和 边框的总大小。

    box-sizing: border-box;
    
(7)轮廓、阴影和圆角
  • outline 用来设置元素的轮廓线,用法和border一模一样。
    • 轮廓和边框不同的点,就是轮廓不会影响到可见框的大小。
.box1:hover{
     outline: 10px red solid;
}
  • box-shadow 用来设置元素的阴影效果,阴影不会影响页面布局。

    属性值参数:

    • 第一个值 水平偏移量,设置阴影的水平位置:正值向右移动、负值向左移动。
    • 第二个值 垂直偏移量,设置阴影的水平位置:正值向下移动、负值向上移动。
    • 第三个值 阴影的模糊半径。
    • 第四个值 阴影的颜色。一般用rgba,因为可以调整透明度。
box-shadow: 0px 0px 50px rgba(0, 0, 0, .3) ; 
  • border-radius: 用来设置圆角。圆角设置的圆的半径大小

    ​ 方位:

    • border-top-left-radius
    • border-top-right-radius
    • border-bottom-left-radius
    • border-bottom-right-radius
    //圆角是圆形
    border-top-left-radius:50px;
    
    //圆角是椭圆
    border-top-left-radius:50px 100px;
    

    ​ 简写方式:

    • border-radius 可以分别指定四个角的圆角
      • 四个值:左上 右上 右下 左下
      • 三个值:左上 右上/左下 右下
      • 两个值:左上/右下 右上/左下

😞应用

//设置椭圆
border-radius: 20px / 40px;

//将元素设置为一个圆形
border-radius: 50%;

3.3.3 浏览器默认样式

通常情况,浏览器都会为元素设置一些默认样式。默认样式的存在会影响到页面的布局,通常情况下编写网页时必须要去除浏览器的默认样式(PC端的页面)。

如:li标签前面自带小圆点;初始网页自带边距等。

不同的浏览器默认样式也可能不同。

💝清除样式:

​ 1️⃣方式1

//清除默认样式

*{
    margin: 0;
    padding: 0;
}

​ 2️⃣方式2 重置样式表:专门用来对浏览器的样式进行重置的。

【二选一,推荐reset.css】

  • reset.css 直接去除了浏览器的默认样式。
  • normalize.css 对默认样式进行了统一。

3.3.4 浮动

通过浮动可以使一个元素向其父元素的左侧或右侧移动。

💛使用 float 属性来设置于元素的浮动。

​ 可选值:

  • none 默认值 ,元素不浮动。
  • left 元素向左浮动。
  • right 元素向右浮动。

💛元素设置浮动以后,水平布局的等式便不需要强制成立。

💛元素设置浮动以后,会完全从文档流中脱离,不再占用文档流的位置。所以元素下边的且还在文档流中的元素会自动向上移动。

(1)特点
  • 浮动元素会完全脱离文档流,不再占据文档流中的位置。
  • 设置浮动以后元素会向父元素的左侧或右侧移动。
  • 浮动元素默认不会从父元素中移出(只能在父元素的框框中)。
  • 浮动元素向左或向右移动时,不会超过它前边的其他浮动元素。
  • 如果浮动元素的上边是一个没有浮动的块元素,则浮动元素无法上移。
  • 浮动元素不会超过它上边的浮动的兄弟元素,最多最多就是和它一样高。
  • 浮动元素不会盖住文字,文字会自动环绕在浮动元素的周围,所以我们可以利用浮动来设置文字环绕图片的效果。

🎆简单总结:浮动目前来讲它的主要作用就是让页面中的元素可以水平排列,通过浮动可以制作一些水平方向的布局。

💛元素设置浮动以后,将会从文档流中脱离,从文档流中脱离后,元素的一些特点也会发生变化。

####(2)脱离文档流的特点

见3.3.1文档流的(2)

(3)高度塌陷的问题及解决方法BFC、clear、after伪元素、clearfix

在浮动布局中,父元素的高度默认是被子元素撑开的,当子元素浮动后,其会完全脱离文档流,子元素从文档流中脱离,将会无法撑起父元素的高度,导致父元素的高度丢失。父元素高度丢失以后,其下的元素会自动上移,导致页面的布局混乱。

所以高度塌陷是浮动布局中比较常见的一个问题,这个问题我们必须要进行处理!

解决方法:

1️⃣把父元素高度写死。(但是我们希望内容将其撑开)

2️⃣BFC(Block Formatting Context) 块级格式化环境

  • BFC是一个CSS中的一个隐含的属性,可以为一个元素开启BFC。开启BFC该元素会变成一个独立的布局区域。

  • 元素开启BFC后的特点:

    • 开启BFC的元素不会被浮动元素所覆盖。
    • 开启BFC的元素子元素和父元素外边距不会重叠。
    • 开启BFC的元素可以包含浮动的子元素。
  • 可以通过一些特殊方式来开启元素的BFC:

    • 设置元素的浮动(不推荐)。即父子元素均设置浮动,但是此时脱离文档流了。

    • 将元素设置为行内块元素(不推荐)。即父子元素设置为行内块元素,但是行内块元素不适合做外部的容器,并且宽度也没了。

    • 将元素的overflow设置为一个非visible的值。(有副作用但比较小)

      🌓常用的方式 为元素设置 overflow:hidden 开启其BFC 以使其可以包含浮动元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box1{
            width: 200px;
            height: 200px;
            background-color: #bfa;
            /* float: left; */
            /*开启BFC,元素子元素和父元素外边距不会重叠*/
            overflow: hidden;
        }

        .box2{
            width: 200px;
            height: 200px;
            background-color: orange;
            /*开启BFC,让其不被浮动的元素所覆盖*/
            overflow: hidden;
        }

        .box3{
            width: 100px;
            height: 100px;
            background-color: yellow;
            margin-top: 100px;
        }
    </style>
</head>
<body>

    <div class="box1">

        <div class="box3"></div>
    </div>

    <!-- <div class="box2">
    </div> -->
    
</body>
</html>

3️⃣clear

如果我们不希望某个元素因为其他元素浮动的影响而改变位置,可以通过clear属性来清除浮动元素对当前元素所产生的影响。

  • 作用:清除浮动元素对当前元素所产生的影响。
  • 可选值:
    • left 清除左侧浮动元素对当前元素的影响。
    • right 清除右侧浮动元素对当前元素的影响。
    • both 清除两侧中最大影响的那侧。
  • 原理:设置清除浮动以后,浏览器会自动为元素添加一个上外边距,以使其位置不受其他元素的影响。
clear: both;

4️⃣after伪元素。【完美方式!基本没有副作用。】

//给父元素盒子加after伪元素(尚硅谷零基础入门HTML5+CSS3 P67)

.box1::after{
     content: '';
     clear: both;
     /* 默认after是行内元素,得转换成块元素,撑起父元素高度。*/
     display: block;
}

5️⃣clearfix 这个样式可以同时解决高度塌陷和外边距重叠的问题,当在遇到这些问题时,直接使用clearfix这个类即可。【最完美方式!基本没有副作用】

.clearfix::before,
.clearfix::after{
     content: '';
     display: table;
     clear: both;
}

3.3.5 定位(position)

定位是一种更加高级的布局手段,通过定位可以将元素摆放到页面的任意位置。

💛使用position属性来设置定位。

​ 可选值:

  • static 默认值,元素是静止的没有开启定位。
  • relative 开启元素的相对定位。
  • absolute 开启元素的绝对定位。
  • fixed 开启元素的固定定位。
  • sticky 开启元素的粘滞定位。
(1)偏移量(offset)

当元素开启了定位以后,可以通过偏移量来设置元素的位置(不影响其他元素)。

  • top:定位元素和定位位置上边的距离。
  • bottom:定位元素和定位位置下边的距离。
  • left:定位元素和定位位置的左侧距离。
  • right:定位元素和定位位置的右侧距离。

💛定位元素垂直方向的位置由top和bottom两个属性来控制,通常情况下我们只会使用其中一。

​ top值越大,定位元素越向下移动;bottom值越大,定位元素越向上移动。

💛定位元素水平方向的位置由left和right两个属性控制,通常情况下只会使用一个。

​ left越大元素越靠右;right越大元素越靠左。

(2)相对定位

当元素的position属性值设置为relative时则开启了元素的相对定位。

💛特点:

  • 元素开启相对定位以后,如果不设置偏移量,元素不会发生任何的变化。
  • 相对定位是参照于元素在文档流中的位置进行定位的。
  • 相对定位会提升元素的层级。
  • 相对定位不会使元素脱离文档流。
  • 相对定位不会改变元素的性质。即块还是块、行内还是行内。
(3)绝对定位

当元素的position属性值设置为absolute时,则开启了元素的绝对定位。

💛特点:

  • 开启绝对定位后,如果不设置偏移量,元素的位置不会发生变化。

  • 开启绝对定位后,元素会从文档流中脱离。

  • 绝对定位会改变元素的性质,行内变成块,块的宽高会被内容撑开。

  • 绝对定位会使元素提升一个层级。

  • 绝对定位元素是相对于其包含块进行定位的。

    🤹‍♀包含块( containing block ):

    • 正常情况下:包含块就是离当前元素最近的祖先块元素。

      //中间div的包含块就是外面的div
      <div> <div></div> </div>
      
      //span的包含块是div;em的包含块是div(因为span是行内元素)
      <div><span><em>hello</em></span></div>
      
    • 绝对定位的包含块:包含块就是离它最近的开启了定位的祖先元素,如果所有的祖先元素都没有开启定位则根元素就是它的包含块。

    • html(根元素、初始包含块)

💛绝对定位元素的布局

​ 📰开启绝对定位后,水平布局的公式为:

left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 包含块的内容区的宽度

  • 水平方向的布局等式就需要添加left 和 right 两个值。此时规则和之前一样只是多添加了两个值:

    • 当发生过度约束(即所有值加在一起不满足等式时):
      • 如果9个值中没有 auto 则自动调整right值以使等式满足;
      • 如果有auto,则自动调整auto的值以使等式满足。
    • 可设置auto的值:margin、width、left、right。
    • left 和 right的值默认是auto,所以如果不指定left和right,等式不满足时会自动调整这两个值。

    📰垂直方向布局的等式的也必须要满足:

top/bottom + margin-top/bottom + padding-top/bottom + border-top/bottom + height = 包含块的高度

//通过绝对定位设置水平垂直居中(主要代码为两模块的空格以下的)

.box1{
    width: 500px;
    height: 500px;
    background-color: #bfa;

    position: relative;
}

.box2{
    width: 100px;
    height: 100px;
    background-color: orange;
    
    position: absolute;
    margin: auto;
    left: 0;
    right: 0;
	top: 0;
	bottom: 0;
}
(4)固定定位

将元素的position属性设置为fixed则开启了元素的固定定位。

💛固定定位也是一种绝对定位,所以固定定位的大部分特点都和绝对定位一样。

​ 🍋唯一不同的是固定定位永远参照于浏览器的视口进行定位。固定定位的元素不会随网页的滚动条滚动。

(5)粘滞定位

当元素的position属性设置为sticky时则开启了元素的粘滞定位。(兼容性不是很好)

💛粘滞定位和相对定位的特点基本一致,不同的是粘滞定位可以在元素到达某个位置时将其固定。

//开启粘滞定位
position: sticky;
top: 0;
(6)元素的层级

对于开启了定位元素,可以通过z-index属性来指定元素的层级。

💛z-index需要一个整数作为参数,值越大元素的层级越高。

  • 元素的层级越高越优先显示。
  • 如果元素的层级一样,则优先显示网页编写中靠下的元素。
  • 祖先的元素的层级再高也不会盖住后代元素。

3.3. 实战

(1)创建外部容器
  • nav(div)
  • div(div)
  • ul(li)
(2)轮播图

1️⃣让图片叠在一起。即让所有图片脱离文档流。

position: absolute;

2️⃣通过修改元素的层级来显示指定的图片。

//简单轮播图布局

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>京东的轮播图</title>
    <link rel="stylesheet" href="../CSS/reset.css">
    <style>
        .img-list {
            width: 590px;
            height: 470px;
            margin: 100px auto;
            /* 为ul开启相对定位,目的是使小圆点可以相对于ul定位 */
            position: relative;
        }

        .img-list li {
            position: absolute;
        }

        .img-list li:nth-child() {
            z-index: 1;
        }

        .pointer {
            /* 确保小圆点可以显示,需要开启定位,还要注意子绝父相 */
            position: absolute;
            /* 确保在最上方 */
            z-index: 9999;
            bottom: 20px;
            left: 40px;
        }

        .pointer a {
            /* a是行内元素,需要转换 */
            display: block;
            float: left;
            width: 10px;
            height: 10px;
            /* 设置小圆点 */
            border-radius: 50%;
            margin: 0 2px;
            background-color: rgba(255, 255, 255, .3);
            /* 将背景颜色值设置到内容区,边框和内边距不在有背景颜色 */
            background-clip: content-box;
            border: 2px solid transparent;
        }

        .pointer a.active,
        .pointer a:hover {
            background-color: #fff;
            border: 2px solid rgba(255, 255, 255, .3);
        }
    </style>
</head>

<body>
    <ul class="img-list">
        <li>
            <a href="javascript:;"><img src="./img/1.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/2.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/3.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/4.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/5.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/6.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/7.jpg" alt=""></a>
        </li>
        <li>
            <a href="javascript:;"><img src="./img/8.jpg" alt=""></a>
        </li>

        <!-- 设置图中的小圆点 -->
        <div class="pointer">
            <a class="active" href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
            <a href="javascript:;"></a>
        </div>
    </ul>
</body>

</html>
(2)设置项目符号
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VICo3pJh-1646239243790)(C:\Users\小半\AppData\Roaming\Typora\typora-user-images\image-20220117235756528.png)]

1️⃣

/* 设置项目符号 */

list-style: square;

2️⃣

.news-list li::before {
            content: '■';
            color: rgb(218, 218, 218);
            font-size: 12px;
}

3.4 字体样式

3.4.1 字体相关样式

🌬字体的简写属性

font 可以设置字体相关的所有属性。

  • 语法:

    font: 自重 字体风格 字体大小/行高 字体族

    【自重 、字体风格、行高可以省略不写,如果不写使用默认值】

    font: 50px/2  微软雅黑, 'Times New Roman', Times, serif;
    
    font: bold italic 50px/2  微软雅黑, 'Times New Roman', Times, serif;
    

  • color 用来设置字体颜色。

  • font-size 设置字体的大小。

    • 和font-size相关的单位:
      • em 相当于当前元素的一个font-size。
      • rem 相对于根元素的一个font-size。
  • font-family 设置字体族(字体的格式)。

    (用此设置字体不会涉及到版权问题)

    ♥️可选值:【指定字体的类别,浏览器会自动使用该类别下的字体】

    • serif 衬线字体
    • sans-serif 非衬线字体
    • monospace 等宽字体

    ♥️font-family 可以同时指定多个字体,多个字体间使用,隔开。(字体生效时优先使用第一个,第一个无法使用则使用第二个…以此类推)

    一般可选值的那几个写在最后,是为了保证字体正常显示。如Microsoft YaHei,Heiti SC,tahoma,arial,Hiragino Sans GB,“\5B8B\4F53”,sans-serif

    font-family: 'Courier New', Courier, monospace; 
    
  • font-weight 设置字重,即字体的加粗

    ♥️可选值:

    • normal 默认值 不加粗。
    • bold 加粗。
    • 100-900 九个级别(没什么用)。
  • font-style 设置字体的风格

    ♥️可选值:

    • normal 正常的。

    • italic 斜体。

  • 🍇font-face可以将服务器中的字体直接提供给用户去使用 。

    • 存在的问题:加载速度、版权、字体格式。
@font-face {
    /* 指定字体的名字 */
    font-family:'myfont' ;
    /* 服务器中字体的路径 */
    src: url('./font/ZCOOLKuaiLe-Regular.ttf') format("truetype");
}


//引用字体
font-family: myfont;

3.4.2 图标字体iconfont

在网页中经常需要使用一些图标,可以通过图片来引入图标。但是图片大小本身比较大,并且非常的不灵活。所以在使用图标时,我们还可以将图标直接设置为字体,然后通过font-face的形式来对字体进行引入。这样我们就可以通过使用字体的形式来使用图标。

(1)fontawesome 使用步骤

1️⃣下载fontawesome https://fontawesome.com/

2️⃣解压

3️⃣将css和webfonts移动到项目中(必须在同一级目录下)

4️⃣将all.css引入到网页中

5️⃣使用图标字体

👧使用:

  • 直接通过类名来使用图标字体
//前缀一般为fas或fab,后面是在找到自己要用的图标前对应的名字
<i class="fas fa-bell-slash"></i>
<i class="fab fa-accessible-icon"></i>

<i class="fas fa-otter" style="font-size: 160px; color:green;"></i>
  • 通过伪元素来设置图标字体

    • 找到要设置图标的元素通过before或after选中。

    • 在content中设置字体的编码。

    • 设置字体的样式

      fab
      font-family: 'Font Awesome 5 Brands';
      
      fas
      font-family: 'Font Awesome 5 Free';
      font-weight: 900; 
      
  • 通过实体来使用图标字体

    &#x图标的编码;

    <span class="fas">&#xf0f3;</span>
    
(2)阿里的字体库

1️⃣下载所需图标文件

3️⃣将下载的内容移动到项目中(可以删除demo.html和demo.css)

4️⃣将iconfont.css引入到网页中

5️⃣使用图标字体(同上)

i.iconfont{
   font-size: 100px;
}


<i class="iconfont">&#xe61c;</i>
<i class="iconfont icon-qitalaji"></i>
p::before{
   content: '\e625';
   font-family: 'iconfont';
   font-size: 100px;
}


<p>Hello</p>

3.4.3 行高line height

行高指的是文字占有的实际高度。

🍙可以通过line-height来设置行高。

  • 行高可以直接指定一个大小(px em)。
  • 也可以直接为行高设置一个整数。【如果是一个整数的话,行高将会是字体的指定的倍数】

🍙行高经常还用来设置文字的行间距。

​ 行间距 = 行高 - 字体大小

☎️可以将行高设置为和高度一样的值,使单行文字在一个元素中垂直居中

line-height: 200px;

字体框:字体存在的格子,设置font-size实际上就是在设置字体框的高度。

🍙行高会在字体框的上下平均分配。

3.5 文本样式

3.5.1 文本的水平对齐text-align

💴可选值:

  • left 左侧对齐
  • right 右对齐
  • center 居中对齐
  • justify 两端对齐

3.5.2 垂直对齐的方式vertical-align

💴可选值:

  • baseline 默认值 基线对齐
  • top 顶部对齐
  • bottom 底部对齐
  • middle 居中对齐

3.5.3 文本修饰text-decoration

💴可选值:

  • none 什么都没有
  • underline 下划线
  • line-through 删除线
  • overline 上划线
//IE不支持
text-decoration: underline red dotted;

3.5.4 设置网页如何处理空白white-space

💴可选值:

  • normal 正常
  • nowrap 不换行
  • pre 保留空白(即编写的代码如实显示,如很多空格不会被浏览器默认为一个空格)
//将溢出的内容设置成省略号【缺一不可】

white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

3.6 背景样式

背景相关简写属性:所有背景相关的样式都可以通过该样式来设置,并且该样式没有顺序要求,也没有哪个属性是必须写的。

:happy:background-size必须写在background-position的后边,并且使用/隔开。即background-position/background-size。

:happy:background-origin background-clip 两个样式 ,orgin要在clip的前边。

background: url('./img/2.jpg') #bfa  center center/contain border-box content-box no-repeat ;

3.6.0-1 精灵图/雪碧图

引入:图片属于网页中的外部资源,外部资源都需要浏览器单独发送请求加载,浏览器加载外部资源时是按需加载的,用则加载,不用则不加载。

案例08背景练习2-按钮可看出,若同时用很多小图完成一个效果,可能出现图片闪烁的问题。

🚘解决图片闪烁的问题:

可以将多个小图片统一保存到一个大图片中,然后通过调整background-position来显示的图片。这样图片会同时加载到网页中 就可以有效的避免出现闪烁的问题。这个技术在网页中应用十分广泛,被称为CSS-Sprite,这种图我们称为雪碧图。

(1)使用步骤

1️⃣先确定要使用的图标。

2️⃣测量图标的大小。

3️⃣根据测量结果创建一个元素。

4️⃣将雪碧图设置为元素的背景图片。

5️⃣设置一个偏移量以显示正确的图片。【利用background-position】

.box1 {
   width: 42px;
   height: 30px;
   background: url(./img/amazon-sprite_.png);
   background-position: -58px -338px;
}


<div class="box1"></div>
(2)特点

一次性将多个图片加载进页面,降低请求的次数,加快访问速度,提升用户的体验。

3.6.0-2 渐变

通过渐变可以设置一些复杂的背景颜色,可以实现从一个颜色向其他颜色过渡的效果。

🔴!!渐变是图片,需要通过background-image来设置。

(1)线性渐变 linear-gradient()

线性渐变:颜色沿着一条直线发生变化。

linear-gradient(red,yellow) 红色在开头,黄色在结尾,中间是过渡区域
  • 线性渐变的开头,我们可以指定一个渐变的方向:
    • to left
    • to right
    • to bottom
    • to top
    • deg 表示度数
    • turn 表示圈
//方位组合
background-image: linear-gradient(to top left,red,yellow);

//度数
background-image: linear-gradient(90deg,red,yellow);

//圈
background-image: linear-gradient(.25turn,red,yellow);
  • 渐变可以同时指定多个颜色,多个颜色默认情况下平均分布,也可以手动指定渐变的分布情况。
//默认情况下平均分布
background-image: linear-gradient(red,yellow,#bfa,orange);

//手动指定渐变的分布情况
background-image: linear-gradient(red 50px,yellow 100px, green 120px, orange 200px);
  • repeating-linear-gradient() 可以平铺的线性渐变
background-image: repeating-linear-gradient(red 50px, yellow 50px);

background-image: repeating-linear-gradient(to right ,red, yellow 50px);
(2)径向渐变 radial-gradient()

径向渐变:放射性的效果。

🔴默认情况下径向渐变的形状根据元素的形状来计算的。如正方形 --> 圆形、长方形 --> 椭圆形。

🔴语法:

radial-gradient(大小 at 位置, 颜色 位置 ,颜色 位置 ,颜色 位置)

  • 我们也可以手动指定径向渐变的大小:

    background-image: radial-gradient(100px 100px, red , yellow)
    

    🐇大小可取值:

    • circle 圆形
    • ellipse 椭圆
    • closest-side 近边
    • closest-corner 近角
    • farthest-side 远边
    • farthest-corner 远角
  • 也可以指定渐变的位置

    🐇位置可取值:

    • top
    • right
    • left
    • center
    • bottom
background-image: radial-gradient(100px 100px at 100px 100px, red , #bfa)

background-image: radial-gradient(at top, red , #bfa)

background-image: radial-gradient(at 100px 100px, red , #bfa)

background-image: radial-gradient(farthest-corner at 100px 100px, red , #bfa)

3.6.1 背景颜色 background-color

background-color: #bfa;

3.6.2 背景图片 background-image

✳️可以同时设置背景图片和背景颜色,这样背景颜色将会成为图片的背景色。

✳️如果背景的图片小于元素,则背景图片会自动在元素中平铺将元素铺满;

​ 如果背景的图片大于元素,将会一个部分背景无法完全显示;

​ 如果背景的图片大于元素,将会一个部分背景无法完全显示。

background-image: url("./img/1.png");

3.6.3 背景的重复方式 background-repeat

✳️可选值:

  • repeat 默认值 , 背景会沿着x轴 y轴双方向重复。
  • repeat-x 沿着x轴方向重复。
  • repeat-y 沿着y轴方向重复。
  • no-repeat 背景图片不重复。

3.6.4 背景图片的位置 background-position

✳️设置方式:

​ 1️⃣通过 top left right bottom center 几个表示方位的词来设置背景图片的位置。

  • 使用方位词时必须要同时指定两个值,如果只写一个则第二个默认就是center。
background-position: top right;

background-position: center;

​ 2️⃣通过偏移量来指定背景图片的位置:水平方向的偏移量、垂直方向变量。

background-position: -50px 300px;

3.6.5 背景的范围 background-clip

✳️可选值:

  • border-box 默认值,背景会出现在边框的下边。
  • padding-box 背景不会出现在边框,只出现在内容区和内边距。
  • content-box 背景只会出现在内容区。
background-clip: content-box; 

3.6.6 背景图片的偏移量计算的原点 background-origin

✳️可选值:

  • padding-box 默认值,background-position从内边距处开始计算。
  • content-box 背景图片的偏移量从内容区处计算。
  • border-box 背景图片的变量从边框处开始计算。
background-origin: border-box;

3.6.7 背景图片的大小 background-size

第一个值表示宽度;第二个值表示高度。【如果只写一个,则第二个值默认是 auto】

background-size:200px 200px;

background-size:200px auto;

background-size:100% auto;

✳️可选值:

  • cover 图片的比例不变,将元素铺满(图片可能显示不完整)。
  • contain 图片比例不变,将图片在元素中完整显示。
background-size: contain;

3.6.8 背景图片是否跟随元素移动 background-attachment

✳️可选值:

  • scroll 默认值 背景图片会跟随元素移动。
  • fixed 背景会固定在页面中,不会随元素移动。

3.7 过渡 transition

通过过渡可以指定一个属性发生变化时的切换方式。

通过过渡可以创建一些非常好的效果,提升用户的体验。

3.7.1 属性

🌮简写属性:​

transition 可以同时设置过渡相关的所有属性,只有一个要求,如果要写延迟,则两个时间中第一个是持续时间,第二个是延迟。

transition:2s margin-left 1s cubic-bezier(.24,.95,.82,-0.88);
(1)transition-property: 指定要执行过渡的属性

🌮多个属性间使用,隔开。

🌮如果所有属性都需要过渡,则使用all关键字。

🌮大部分属性都支持过渡效果(如宽度、颜色等),注意过渡时必须是从一个有效数值向另外一个有效数值进行过渡(auto不是一个有效数值)。

transition-property: height,width;

transition-property: all;
(2)transition-duration: 指定过渡效果的持续时间

🌮时间单位:s 和 ms 【1s = 1000ms】

🌮分别给过度的属性指定时间,使用,隔开。

transition-duration: 2s;

transition-duration: 100ms, 2s;
(3) transition-timing-function: 过渡的时序函数

指定过渡的执行的方式。

🌮可选值:

  • ease 默认值,慢速开始,先加速,再减速。
  • linear 匀速运动。
  • ease-in 加速运动。
  • ease-out 减速运动。
  • ease-in-out 先加速 后减速。
  • cubic-bezier() 来指定时序函数。
    • 参考网址:https://cubic-bezier.com
  • steps() 分步执行过渡效果
    • 可以设置一个第二个值:
      • end 在时间结束时执行过渡(默认值)。
      • start 在时间开始时执行过渡
transition-timing-function: cubic-bezier(.24,.95,.82,-0.88);

transition-timing-function: steps(2, start);
(4)transition-delay: 过渡效果的延迟,等待一段时间后在执行过渡
ransition-delay: 2s;

3.8 动画

动画和过渡类似,都是可以实现一些动态的效果。

不同的是过渡需要在某个属性发生变化时才会触发,动画可以自动触发动态效果。

🍔设置动画效果,必须先要设置一个关键帧,关键帧设置了动画执行每一个步骤。

@keyframes test {
    /* from表示动画的开始位置 也可以使用 0% */
    from{
         margin-left: 0;
         background-color: orange;
    } 

    /* to动画的结束位置 也可以使用100%*/
    to{
          background-color: red;
          margin-left: 700px;
    }
}

###3.8.1 属性

简写属性:

animation:test 2s 2 1s alternate;
(1)animation-name 要对当前元素生效的关键帧的名字
animation-name: test;
(2)animation-duration: 动画的执行时间
animation-duration: 4s;
(3)animation-delay 动画的延时
animation-delay: 2s;
(4)animation-timing-function 动画的时序函数
animation-timing-function: ease-in-out;
(5)animation-iteration-count 动画执行的次数

😋可选值:

  • 次数
  • infinite 无限执行
animation-iteration-count: 1;
(6)animation-direction 指定动画运行的方向

😋可选值:

  • normal 默认值 从 from 向 to运行,每次都是这样 。
  • reverse 从 to 向 from 运行,每次都是这样。
  • alternate 从 from 向 to运行,重复执行动画时反向执行。
  • alternate-reverse 从 to 向 from运行,重复执行动画时反向执行。
animation-direction: alternate-reverse;
(7)animation-play-state 设置动画的执行状态

😋可选值:

  • running 默认值 动画执行。
  • paused 动画暂停。
animation-play-state: paused;
(8)animation-fill-mode 动画的填充模式

😋可选值:

  • none 默认值,动画执行完毕元素回到原来位置。
  • forwards 动画执行完毕元素会停止在动画结束的位置。
  • backwards 动画延时等待时,元素就会处于开始位置。
  • both 结合了forwards 和 backwards。
animation-fill-mode:both;

3.8.2 关键帧

3.9 变形

变形就是指通过CSS来改变元素的形状或位置。transform 用来设置元素的变形效果。

🙉变形不会影响到页面的布局,不会脱离文档流。

🙉只能给一个元素设置transform。

3.9.0 transform-origin变形的原点

默认值 center。

transform-origin:20px 20px;

3.9.1 平移

平移元素,百分比是相对于自身计算的。

  • translateX() 沿着x轴方向平移。
  • translateY() 沿着y轴方向平移。
  • translateZ() 沿着z轴方向平移。
transform: translateY(-100px);

//平移元素,百分比是相对于自身计算的。
transform: translateX(100%);
//应用:水平垂直居中
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);

3.9.2 Z轴平移

z轴平移,调整元素在z轴的位置,正常情况就是调整元素和人眼之间的距离,距离越大,元素离人越近。

z轴平移属于立体效果(近大远小),默认情况下网页是不支持透视,如果需要看见效果,必须要设置网页的视距。

html{
    /* 设置当前网页的视距为800px,人眼距离网页的距离 */
    perspective: 8000px;
}
//测试效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        html{
            perspective: 8000px;
        }
        body{
            border: 1px red solid;
            background-color: rgb(241, 241, 241);
        }
        .box1{
            width: 200px;
            height: 200px;
            background-color: #bfa;
            margin: 200px auto;
            transition:2s;
        }
        body:hover .box1{
            transform: translateZ(800px);
        }
    </style>
</head>
<body>
    <div class="box1"></div>
</body>
</html>

3.9.3 旋转

🎉通过旋转可以使元素沿着x y 或 z旋转指定的角度。

  • rotateX()
  • rotateY()
  • rotateZ()

🎉如果需要看见效果,最好要设置网页的视距。

//按度数旋转
transform: rotateY(180deg);

//按圆旋转
transform: rotateZ(.25turn);

transform: rotateY(180deg) translateZ(400px);

🎉旋转一般有个透视效果。可以设置是否显示元素的背面:

backface-visibility: hidden;

3.9.4 缩放

对元素进行缩放的函数:

  • scaleX() 水平方向缩放。
  • scaleY() 垂直方向缩放。
  • scale() 双方向的缩放。

【对Z进行缩放,得是三维的图像,效果是拉伸】

transform:scale(2);

transform:scale(1.2);

3.10 弹性盒、伸缩盒flex

flex是CSS中的又一种布局手段,它主要用来代替浮动来完成页面的布局。

🤝flex可以使元素具有弹性,让元素可以跟随页面的大小的改变而改变。

3.10.1 弹性容器

🤝要使用弹性盒,必须先将一个元素设置为弹性容器。我们通过 display 来设置弹性容器。

  • display:flex 设置为块级弹性容器。
  • display:inline-flex 设置为行内的弹性容器。

3.10.2 弹性元素

🤝弹性容器的子元素是弹性元素(弹性项)。

🤝弹性元素可以同时是弹性容器。

3.10.3 弹性容器的样式

(1)flex-direction 指定容器中弹性元素的排列方式

🤝 可选值:

  • row 默认值,弹性元素在容器中水平排列(左向右)。
    • 主轴 自左向右
  • row-reverse 弹性元素在容器中反向水平排列(右向左)。
    • 主轴 自右向左
  • column 弹性元素纵向排列(自上向下)。
  • column-reverse 弹性元素方向纵向排列(自下向上)。

主轴:弹性元素的排列方向称为主轴。

侧轴:与主轴垂直方向的称为侧轴。

flex-direction: row;
(2)flex-wrap:设置弹性元素是否在弹性容器中自动换行

🤝 可选值:

  • nowrap 默认值,元素不会自动换行。
  • wrap 元素沿着辅轴方向自动换行。
  • wrap-reverse 元素沿着辅轴反方向换行。
flex-wrap: wrap-reverse;
(3)flex-flow: wrap 和 direction 的简写属性
flex-flow: row wrap;
(4)justify-content分配主轴上的空白空间

如何分配主轴上的空白空间(即主轴上的元素如何排列)。

🤝 可选值:

  • flex-start 元素沿着主轴起边排列。
  • flex-end 元素沿着主轴终边排列。
  • center 元素居中排列。
  • space-around 空白分布到元素两侧。
  • space-between 空白均匀分布到元素间。
  • space-evenly 空白分布到元素的单侧。
justify-content: center;
(5)align-items 元素在辅轴上如何对齐

设置元素间的关系。

🤝 可选值:

  • stretch 默认值,将元素的长度设置为相同的值(行与行之间的高度)。
  • flex-start 元素不会拉伸,沿着辅轴起边对齐。
  • flex-end 沿着辅轴的终边对齐。
  • center 居中对齐。
  • baseline 基线对齐。
//居中对齐
justify-content: center;
align-items: center;
(6)align-content: 辅轴空白空间的分布
align-content: space-between;
(7)align-self: 用来覆盖当前弹性元素上的align-items
/* align-self: 用来覆盖当前弹性元素上的align-items */
align-self: stretch;

3.10.4 弹性元素的样式

(0)简写属性flex

flex 可以设置弹性元素所有的三个样式。

🔓有顺序要求:flex 增长 缩减 基础;

🔓可取值​

  • initial “flex: 0 1 auto”.
  • auto “flex: 1 1 auto”
  • none “flex: 0 0 auto” 弹性元素没有弹性
flex: initial;
(1)flex-grow 指定弹性元素的伸展的系数

即当父元素有多余空间时,子元素如何伸展。

🔓父元素的剩余空间,会按照比例进行分配。

//设置后,父元素的多余空间将给各子元素按比例分配

li:nth-child(1){
    flex-grow: 0;
}

li:nth-child(2){
	flex-grow: 2; */
}

li:nth-child(3){
	flex-grow: 3; 
}
(2) flex-shrink 指定弹性元素的缩减系数。

即当父元素中的空间不足以容纳所有的子元素时,如何对子元素进行收缩。值越大,收缩得越多。

🔓缩减系数的计算方式比较复杂。缩减多少是根据 缩减系数 和 元素大小来计算。

flex-shrink: 0;
(3)flex-basis 指定元素在主轴上的基础长度

🔓如果主轴是 横向的 则 该值指定的就是元素的宽度;如果主轴是 纵向的 则 该值指定的是就是元素的高度。

  • 默认值是 auto,表示参考元素自身的高度或宽度。
  • 如果传递了一个具体的数值,则以该值为准。
flex-basis: auto;
(4)order 决定弹性元素的排列顺序
order: 2;

3.11 移动端

不同的屏幕,单位像素的大小是不同的,像素越小屏幕会越清晰。(24寸 1920x1080)

查看各产品屏幕尺寸:https://screensiz.es/

智能手机的像素点 远远小于 计算机的像素点。因此有个问题:一个宽度为900px的网页在iphone6中要如何显示呢?【i6 4.7寸 750 x 1334 】 (750是物理像素、900px是CSS像素)。

😋默认情况下,移动端的网页都会将视口设置为980像素(css像素)。

  • 以确保pc端网页可以在移动端正常访问,但是如果网页的宽度超过了980,移动端的浏览器会自动对网页缩放以完整显示网页。
  • 所以基本大部分的pc端网站都可以在移动端中正常浏览,但是往往都不会有一个好的体验,为了解决这个问题,大部分网站都会专门为移动端设计网页。

3.11.1 移动端页面

😋移动端默认的视口大小是980px(css像素)。

😋默认情况下,移动端的像素比就是 980/移动端宽度 (iphone6 980/750)。

如果我们直接在网页中编写移动端代码,这样在980的视口下,像素比是非常不好,导致网页中的内容非常非常的小。

😋编写移动页面时,必须要确保有一个比较合理的像素比,如1css像素 对应 2个物理像素、1css像素 对应 3个物理像素等。

  • 我们可以通过改变视口的大小,来改变CSS像素和物理像素的比值。
  • 可以通过meta标签来设置视口大小。
//❀【写移动端的页面必须写】设置视口大小 device-width表示设备的宽度(完美视口)
<meta name="viewport" content="width=device-width, initial-scale=1.0">

😋每一款移动设备设计时,都会有一个最佳的像素比,一般我们只需要将像素比设置为该值即可得到一个最佳效果,将像素比设置为最佳像素比的视口大小我们称其为完美视口。

3.11.2 视口宽度vm及VM适配

不同的设备完美视口的大小是不一样的。由于不同设备视口和像素比不同,所以同样的375个像素在不同的设备下意义是不一样,所以在移动端开发时,就不能再使用px来进行布局了。

😋vw 表示的是视口的宽度(viewport width)。(vw这个单位永远相当于视口宽度进行计算)

  • 100vw = 一个视口的宽度
  • 1vw = 1%视口宽度

😋常见移动端设计图:750px 1125px

  • 如果在设计图像素为750px时,要在网页中创建一个 48px x 35px 大小的元素,计算如下:
    • 100vw = 750px(设计图的像素)。用100除以750得到0.1333333333333333vw = 1px。
    • 所以6.4vw = 48px(设计图像素)。
    • 所以4.667vw = 35px。

👻VM适配

  • 1 rem = 1 html的字体大小

⚠️网页中字体大小最小是12px,不能设置一个比12像素还小的字体。如果我们设置了一个小于12px的字体,则字体自动设置为12。

3.12 响应式布局

响应式布局:网页可以根据不通的设备或窗口大小呈现出不同的效果。使用响应式布局,可以使一个网页适用于所有设备

响应布局的关键就是 媒体查询。通过媒体查询,可以为不同的设备,或设备不同状态来分别设置样式。

3.12.1 媒体查询

(1)语法

@media 查询规则{}

(2)媒体类型

🐥可以使用,连接多个媒体类型,这样它们之间就是一个或的关系。

  • all 所有设备。
  • print 打印设备。
  • screen 带屏幕的设备。
  • speech 屏幕阅读器。

🐥可以在媒体类型前添加一个only,表示只有。only的使用主要是为了兼容一些老版本浏览器。

//所有设备的背景颜色都为#bfa
@media all{
    body{
        background-color: #bfa;
}


@media print,screen{
    body{
         background-color: #bfa;
}


//表示只要屏幕时,背景颜色为#bfa
@media only screen {
   body{
        background-color: #bfa;
    }
}
(3)媒体特性
  • width 视口的宽度。(一般在设计时只考虑宽度)
  • height 视口的高度。
  • min-width 视口的最小宽度(视口大于指定宽度时生效)。
  • max-width 视口的最大宽度(视口小于指定宽度时生效)。
//当视口宽度是500px时,背景颜色为#bfa
@media (max-width: 500px){
   body{
       background-color: #bfa;
}
(4)断点

样式切换的分界点,我们称其为断点,也就是网页的样式会在这个点时发生变化。

🐥一般比较常用的断点:

  • 小于768 超小屏幕 max-width=768px
  • 大于768 小屏幕 min-width=768px
  • 大于992 中型屏幕 min-width=992px
  • 大于1200 大屏幕 min-width=1200px
//大于500或小于300
@media only screen and (min-width: 500px) ,(max-width:300px){
   body{
        background-color: #bfa;
   }
}

//500到700之间
@media only screen and (min-width: 500px) and (max-width:700px){
   body{
        background-color: #bfa;
   }
}

//非
@media not screen and (min-width: 500px) and (max-width:700px){
   body{
        background-color: #bfa;
   }
}

3.13 应用效果

3.13 .1 水平垂直居中

(1)通过方位实现

这种居中方式,只适用于元素的大小确定。

top:0;
left:0;
bottom:0;
right:0;
margin:auto;
(2)通过平移方式实现
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
(3)通过flex实现
justify-content: center;
align-items: center;

四、less

4.1 less基础

less是一门css的预处理语言。less是一个css的增强版,通过less可以编写更少的代码实现更强大的样式。

在less中添加了许多的新特性:像对变量的支持、对mixin的支持… …

less的语法大体上和css语法一致,但是less中增添了许多对css的扩展,所以浏览器无法直接执行less代码,要执行必须向将less转换为css,然后再由浏览器执行。

🍨VSCode中easy less插件可以自动将less文件转换为css文件。

🦅css原生也支持变量的设置。但是兼容性不好。

  • 变量设置
 html{
    /* css原生也支持变量的设置 */
    --color:#ff0;
}


.box1{
    background-color: var(--color);
}
  • calc()计算函数
width: calc(200px*2);

4.1.1 语法

(1)注释

//less中的单行注释,注释中的内容不会被解析到css中。

/* */ css中的注释,内容会被解析到css文件中。

(2)引入其他less文件

import用来将其他的less引入到当前的less。

@import "syntax2.less";
(3)变量

在变量中可以存储一个任意的值,并且我们可以在需要时任意的修改变量中的值。

🦄语法: @变量名

🦄使用:

  • 使用变量时,如果是直接使用则以 @变量名 的形式使用即可。
  • 作为类名或者一部分值使用时,必须以 @{变量名} 的形式使用

🦄注意:

  • 变量发生重名时,会优先使用比较近的变量。
  • 可以在变量声明前就使用变量。
@a:200px;
@b:#bfa;
@c:box6;

.box5{
    //使用变量时,如果是直接使用则以 @变量名 的形式使用即可
    width: @a;
    color:@b;
}

//作为类名,或者一部分值使用时必须以 @{变量名} 的形式使用
.@{c}{
    width: @a;
    background-image: url("@{c}/1.png");
}

🦄直接引用样式的值:

div{
    width: 300px;
    // 新版的语法
    // height: $width;
}

🦄在less中所有的数值都可以直接进行运算。

.box1{
    // 在less中所有的数值都可以直接进行运算
    // + - * /
    width: 100px + 100px;
    height: 100px/2;
    background-color: #bfa;
    
}
(4)父元素

& 就表示外层的父元素。

.box1{
    .box2{
        color: red;
    }
    
    //设置一个子元素
    >.box3{
        color: red;
        
        //此处&表示box1>box3
        &:hover{
            color: blue;
        }
    }

    //为box1设置一个hover
    //& 就表示外层的父元素,此处&表示box1
    &:hover{
        color: orange;
    }

    div &{
        width: 100px;
    }
}
(5)扩展

:extend() 对当前选择器扩展指定选择器的样式(选择器分组)。

.p1{
    width: 100px;
    height: 200px;
}

.p2:extend(.p1){
    color: red;
}


//对应的CSS如下:
.p1,
.p2 {
  width: 100px;
  height: 200px;
}
.p2 {
  color: red;
}
.p3{
    //直接对指定的样式进行引用,这里就相当于将p1的样式在这里进行了复制
    .p1();
}

//对应的CSS如下:
.p3 {
  width: 100px;
  height: 200px;
}
// 使用类选择器时可以在选择器后边添加一个括号,这时我们实际上就创建了一个mixins,即混合函数(专门给别人用而自己不用)。
.p4(){
    width: 100px;
    height: 100px;
}
.p5{
    .p4;
}

//对应的CSS如下:
.p5 {
  width: 100px;
  height: 100px;
}
(6)混合函数 mixins

🦄在混合函数中可以直接设置变量。

.test(@w:100px,@h:200px,@bg-color:red){
    width: @w;
    height: @h;
    border: 1px solid @bg-color;
}

div{
    //调用混合函数,按顺序传递参数
    // .test(200px,300px,#bfa);
    .test(300px);
    // .test(@bg-color:red, @h:100px, @w:300px);
}

4.2 配置

设置,扩展,Easy LESS configuration,在setting.json中编辑,在原有里面的最后一行代码加入一个,然后输入以下代码:

"less.compile": {
        "compress": false, //是否压缩
        "sourceMap": true, //是否生成源码(less和css映射文件)
        "out": true // 是否生成CSS文件
    }

五、JavaScript

5.1 JS基础

5.1.0 前言

JavaScript是高级语言。

JavaScript诞生于1995年,它的出现主要是用于处理网页中的前端验证。前端验证即检查用户输入的内容是否符合一定的规则,如用户名长度、密码长度、邮箱格式等。

ECMAScript是JavaScript标准。

📗一个完整的JavaScript实现应该由以下三部分构成:ECMAScript、DOM、BOM。

📗特点:

  • 解释型语言(不用编译,写完即运行)。
  • 类似于C和Java的语法结构。
  • 动态语言。
  • 基于原型的面向对象。
//我的第一个JS代码


<script type="text/javascript">
        // JS代码是从上到下一行一行执行的
        // 控制浏览器弹出一个警告框
        alert("hello");

        // 让计算机在页面中输出一个内容
        // document.write()可以向body中输出一个内容
        document.write("world");

        // 向控制台输出一个内容
        console.log("我在控制台");
</script>
(1)Unicode编码

在字符串中使用转义字符\输入Unicode编码。

  • 在JS中使用,格式如 \u四位编码。
  • 在网页中使用,格式如 &#编码;
//在JS中使用
console.log("\u0031"); //输出1

//在网页中使用:&#编码;【这里的编码需要采用十进制】
<h1>$#1</h1>
(2)其它进制的数字

在JS中,
16进制数字以0x开头;
8进制以0开头;
2进制以0b开头(不是所有浏览器都支持);

//二进制
a=0b10;

🥖像"070"这种字符串,有些浏览器会当成八进制解析,有些浏览器会当成十进制解析。

a="070";

🥖可以在parseInt();中传递一个 第二个参数,用于指定数字的进制。

var a = "070";
//指定为八进制解析
a = parseInt(a,8);

console.log(typeof a);
console.log(a);
(3)垃圾回收GC

程序运行过程中也会产生垃圾。积攒过多,会导致程序运行的速度过慢。

当一个对象没有任何的变量或属性对它进行引用,此时将无法对它进行操作,
此时这种对象就是一个垃圾,过多会占用大量的内存空间,导致程序运行变慢。

JS中有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁。

我们需要做的只是将不再使用的对象设置null即可。

5.1.1 JS编写位置

(1)写在标签属性中

🌏虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用。

  • 可以将JS代码编写到标签的onclick属性中。

    <body>
        <!-- 注意是点击按钮时,JS代码才会执行 -->
        <button onclick="alert('嘿哟');">
            点我一下
        </button>
    </body>
    
  • 可以将JS代码编写到超链接的href属性中。

    <body>
        <a href="javascript:alert('哈呀');">点我两下</a>
        <!-- 点击后没有任何反应 -->
        <a href="javascript:;">点我两下</a>
    </body>
    
(2)编写到script标签中
<script type="text/javascript">
		/*控制浏览器弹出一个警告框*/
        alert('呀呼');

	 /*让计算机在页面中输出一个内容*/
	 document.write("world");

	 /*向控制台输出一个内容*/
	 console.log("hello world");
</script>
(3)编写在JS文件中

将JS代码编写在外部JS文件中,然后通过script标签引入。

<script type="text/javascript" src="js/script.js"></script>

写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制。【推荐使用】

🌏script标签一旦引入外部文件了,就不能再编写代码了,即使编写了浏览器也会忽略。如果需要,可以再创建一个新的script标签用于编写内部代码。

<script src="js/script.js"></script>
<script type="text/javascript">
    alert("hello");
</script>

5.1.2 基本语法

(1)注释

多行注释/**/

单行注释//

(2)语句

程序是由一条一条语句构成的。

语句是按照自上向下的顺序一条一条执行的。

在JS中可以使用{}来为语句进行分组。同一个{}中的语句称为一组语句,它们要么都执行要么都不执行。

  • 一个{}中的语句也称为一个代码块。
  • 在代码块的后边就不用再编写;了。

JS中的代码块,只具有分组的作用,没有其他的用途。

{
	alert("hello");
    document.write("world");
    console.log("hello world");
}
(3)注意
  • JS中严格区分大小写。
  • JS中每一条语句以分号;结尾。(如果不写分号,浏览器会自动添加,但是会消耗一些系统资源。并且有时浏览器会加错分号)
  • JS中会忽略多个空格和换行,所以可以利用空格和换行对代码进行格式化。

5.1.3 字面量和变量

(1)字面量

字面量都是一些不可改变的值,比如1、2、3、4

🙉字面量都是可以直接使用,但是我们一般都不会直接使用字面量。

(2) 变量

变量可以用来保存字面量,而且变量的值是可以任意改变的。

🙉在开发中都是通过变量区保存一个自变量,而很少直接使用字面量。

🙉可以通过变量名对字面量进行描述。如 var age=21;

声明变量

使用var关键字来声明一个变量。

//声明变量
var a;
//为变量赋值
a=123;
//再控制台输出变量a的值
console.log(a);
//声明和赋值同时进行
var b=789;
console.log(b);
变量的声明提前
//不写var,就相当于window.a
a=123;
console.log("a="+a);

使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)。
但是如果声明变量时,不使用var关键则,则变量不会被声明提前。

console.log("a="+a);
var a=123;

其实相当于:

var a;
console.log("a="+a);
a=123;

//于是输出为:a=undefined

5.1.4 标识符

在JS中所有的可以由我们自主命名的都可以称为标识符。例如变量名、函数名、属性名。

命名一个标识符时需要遵守如下规则:

  • 标识符中可以含有字母、数字、下划线 _ 、$。
  • 标识符不能以数字开头。
  • 标识符不能是JS中的关键字或保留字。
  • 标识符一般都采用驼峰命名法。(不强制要求)
    • 首字母小写,每个单词的开头字母大写,其余字母小写。如helloWorld。

JS底层把保存标识符时实际上时采用的Unicode编码。所有理论上讲,所有的utf-8含有的内容都可以作为标识符。中文也可以用,但是最好不用。

5.1.5 数据类型

数据类型指的是字面量的类型。

在JS中一共有六种数据类型:String 字符串、Number数值、Boolean布尔值、Null空值、Undefined未定义、Object对象。

  • 基本数据类型:String 字符串、Number数值、Boolean布尔值、Null空值、Undefined未定义。
  • 引用数据类型:Object对象。
(1)String 字符串

在JS中使用字符串时需要使用引号引起来。使用双引号或单引号都可以。

  • 引号不能嵌套
    • 双引号中不能放双引号。
    • 单引号中不能放单引号。
    • ❗双引号中可以放单引号。
    • ❗单引号中可以放双引号。
var str="hello";
console.log(str);
console.log("hello");
  • 在字符串中我们可以使用\作为转义字符,当表示一些特殊符号时可以使用\进行转义。
    • \ " 表示"
    • \ ’ 表示’
    • \n 表示换行
    • \t 表示制表符
    • \ \ 表示\ 【打印\需要转义,即在\加上\。比如需要打印\就需要编写6个\】
str="我说:\"今天天气真不错!\"";

🎮可以使用一个运算符typeof检查一个变量的类型。如检查字符串时返回"string",检查数值时返回"number"。

  • 语法: typeof 变量
console.log(typeof b);
(2)Number数值

在JS中所有的数值都是Number类型,包括整数和浮点数(小数)。

😻JS中可以表示的数字的最大值:Number.MAX_VALUE。即1.7976931348623157e+308。

​大于0(正值)的最小值:Number.MIN_VALUE。即5e-324。

console.log(Number.MAX_VALUE);

【❀特殊值:】

😻J如果使用Number表示的数字超过了最大值,则会返回一个Infinity,表示正无穷。-Infinity表示负无穷

  • Infinity是一个字面量。
  • 🎮使用typeof检查Infinity,也会返

😻NaN是一个特殊的数字,表示Not A Number。

  • 🎮使用typeof检查NaN,也会返回"number"。

😻运算:

  • 在JS中整数的运算基本可以保证精确。

    var c=1837874+34787;
    console.log(c);
    
  • 在JS中浮点数运算可能得到一个不精确的结果。所以千万不用使用JS进行对精度要求比较高的运算。

    var c=0.1+0.2;
    console.log(c);
    
    //运算结果显示为0.30000000000000004
    
(3)Boolean布尔值

布尔值主要用来进行逻辑判断,布尔值只有两个:

  • true 逻辑的真。
  • false 逻辑的假。
var bool=true;
console.log(bool);

🎮使用typeof检查一个布尔值时,会返回"boolean"。

(4)Null空值

Null类型的值只有一个,即null。

null这个值专门用来表示为空的对象。

🎮使用typeof检查一个Null类型的值时会返回"object"。

(5)Undefined未定义

Undefined类型的值只有一个,即undefined。

如果声明一个变量但是没有为变量赋值此时变量的值就是undefined。

var b;
console.log(b);
var b=undefined;
console.log(b);

🎮使用typeof检查一个undefined时会返回"undefined"。

(6)Object对象
(7)强制类型转换

指将一个数据类型强制转换为其他的数据类型。

  • 转换为String、Number、Boolean。
将其它的数据类型转换为String

1️⃣调用被转换数据类型的toString()方法。

  • 该方法不会影响到原变量,它会将转换的结果返回。
  • 注意:null和undefined这两个值没有toString()方法,如果调用会报错。
//该方法不会影响到原变量,它会将转换的结果返回。

var a=123;
//调用a的toString()方法
a.toString();

console.log(typeof a);
console.log(a);


//运算结果显示为:
// number
// 123
//因此此处我们将转换后的值赋值给变量b


var a = 123;
//调用a的toString()方法
var b = a.toString();

console.log(typeof b);
console.log(b);


//运算结果显示为:
// string
// 123
//也可以直接将转换后的值传给变量a


var a = 123;
//调用a的toString()方法
a = a.toString();

console.log(typeof a);
console.log(a);


//运算结果显示为:
// string
// 123

2️⃣调用String()函数,并将被转换的数据作为参数传递给函数。

  • 使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法。

    但是对于null和undefined,就不会调用toString()方法,而是直接将null直接转换为"null"(字符串)、undefined直接转换为"undefined"。

var a = 123;
//调用a的String()函数
a = String(a);

console.log(typeof a);
console.log(a);


//运算结果显示为:
// string
// 123

3️⃣隐式的类型转换:为任意数据类型+一个""即可将其转换为String。

由浏览器自动完成,实际上它也是调用了String()函数。

将其它的数据类型转换为Number

1️⃣调用Number()函数。

  • 字符串转数字
    • 如果是纯数字的字符串,则直接将其转换为数字。
    • 如果字符串中有非数字的内容,则转换为NaN。
    • 如果字符串是一个空串或是一个全是空格的字符串,则转换为0。
  • 布尔转数字
    • true转换为1。
    • false转换为0。
  • null转数字
    • null转换为0。
  • undefined转数字
    • undefined 转换为NaN。
var s = "123";
s = Number(s);

console.log(typeof a);
console.log(a);

//运算结果显示为:
//  number
//  123
var a = "abc";
a = Number(a);

console.log(typeof a);
console.log(a);

//运算结果显示为:
//  number
//  NaN

2️⃣调用parseInt()或parseFloat()

专门用来对付字符串。

  • parseInt()可以将一个字符串中的有效的整数内容取出来,然后转换为Number。
var a = "123a789";
a = parseInt(a);

console.log(typeof a);
console.log(a);

//运算结果显示为:
//  number
//  123
var a = "b123a789";
a = parseInt(a);

console.log(typeof a);
console.log(a);

//运算结果显示为:
//  number
//  NaN
  • parseFloat()可以获得有效的小数
var a = "123.789px";
a = parseFloat(a);

console.log(typeof a);
console.log(a);


//运算结果显示为:
//  number
//  123.789
var a = "123.789.567px";
a = parseFloat(a);

console.log(typeof a);
console.log(a);


//运算结果显示为:
//  number
//  123.789

🐐如果对非String使用parseInt()或parseFloat(),它会先将其转换为String,然后再操作。

3️⃣隐式类型转换:通过为一个值-0或 *1或/1来将其转换为Numebr。

原理和Number()一样。

4️⃣可以对一个其他的数据类型使用+(表正号),来将其转换为number。

原理和Number()一样。

将其它的数据类型转换为Boolean

1️⃣调用Boolean()函数。

  • 数字转布尔
    • 除了0和NaN其余的全是true。
  • 字符串转布尔
    • 除了空串其余全是true。
  • null、undefined 转 布尔
    • 都会转换为false。
  • 对象 转 布尔
    • 都会转换为true。

2️⃣为一个任意数据类型取两次反,即!!a。

原理和Boolean()一样。

(8)基本和引用数据类型

JS中的变量都是保存到栈内存中的。

  • 基本数据类型的值直接在栈内存中存储。值与值之间是独立存在,修改一个变量不会影响其他的变量。

  • 对象是保存到堆内存中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(即对象的引用)。如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响。【指针】

    (相当于对象是把变量和值的地址存放在栈内存中,而对象的值存储于堆内存中,最后通过指针读取数据)

    var obj = new Object();
    obj.name = "孙悟空";
    			
    var obj2 = obj;
    			
    //修改obj的name属性
    obj.name = "猪八戒";
    			
    //当一个通过一个变量修改属性时,另一个也会受到影响。以下两个显示结果均为 猪八戒				
    console.log(obj.name);
    console.log(obj2.name);
    
    
    
    	//设置obj2为null
    	obj2 = null;
    	
        //obj2链接对象的值的指针断开,但是obj1的指针没有影响。所以obj仍是object,obj2为null。
    	console.log(obj);
    	console.log(obj2);
    
  • 当比较两个基本数据类型的值时,就是比较值。

    而比较两个引用数据类型时,它是比较的对象的内存地址,如果两个对象是一摸一样的,但是地址不同,它也会返回false。

    var obj3 = new Object();
    var obj4 = new Object();
    obj3.name = "沙和尚";
    obj4.name = "沙和尚";
    console.log(obj3 == obj4);
    
    //运行显示结果为
    //false
    

5.1.5 运算符/操作符

通过运算符可以对一个或多个值进行运算或操作。

typeof运算符:获得一个值的数据类型。它会将该值的类型以字符串的形式返回。

(0)运算符的优先级

先级越高的越优先计算;优先级相同的,从左往右计算。

💝在下面优先级列表中越靠上的优先级越高:

  • .、[]、 new
  • ()
  • ++、 –
  • !、~、+(单目)、-(单目)、typeof、void、delete
  • %、*、/
  • +(双目)、-(双目)
  • << 、 >>、 >>>
  • <、<=、>、>= •
  • == 、!== 、===
  • &
  • ^
  • |
  • &&
  • ||
  • ?:
  • =、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=
  • ,

💝可使用()来改变优先级。

####(1)算术运算符

当对非Number类型的值进行运算时,会将这些值转换为Number然后再运算。【除了字符串的+运算】

💝任何值和NaN做运算都得NaN。

💝任何值和字符串相加都会转换为字符串并做拼串操作。(可以利用这一特点将一个任意的数据类型转换为String:为任意数据类型+一个""即可将其转换为String——隐式的类型转换)。

💝任何值做-*/运算都会自动转换为Number(可以利用这一特点做隐式类型转换:通过为一个值-0或 *1或/1来将其转换为Numebr。原理和Number()一样)。

  • +对两个值进行加法运算并返回结果。
    • 如果对两个字符串进行加法运算,则会做拼串,即将两个字符串拼接为一个字符串并返回。【双引号里的内容只能在一行中编写否则会报错】
    • 任何值和字符串做加法,都会先转换为字符串,然后再拼串。
  • -对两个值进行减法运算并返回结果。
  • *对两个值进行乘法运算并返回结果。
  • /对两个值进行除法运算并返回结果。
  • %对两个值进行取余运算并返回结果。
result = 1 + 2 + "3";

console.log("result=" + result);

// 运算结果显示为:
// result=33
result = "1" + 2 + 3;

console.log("result=" + result);

// 运算结果显示为:
// result=123
(2)一元运算符

只需要一个操作数。

  • +正号
    • 正号不会对数字产生任何影响。
  • -负号
    • 负号可以对数字进行符号的取反。

🃏对于非Number类型,会先转换为Number类型,再运算。

🃏可以对一个其他的数据类型使用+,来将其转换为number。他的原理和Number()一样。

(3)自增和自减

自增++:可以使变量在自身的基础上加1。

  • 对一个变量自增后,原变量的值会立即自增1。
  • 自增分成两组:后++(a++)、前++(++a)
    • 无论是a++或++a,都会使原变量的值自增1。
    • 不同的是:a++的值等于原变量的值(自增前的值)【先用再加】;++a的值等于原变量新值(自增后的值)【先加再用】。
//注意自增后原变量的值就变了

var d=20;
var result=d++ + ++d +d;   //20+22+22
console.log("result="+result);

// 运算结果显示为:
// result=64

自减:可以使变量在自身的基础上减1。(同自增)

(4)逻辑运算符

♍️!非:对一个值进行非运算。非运算即值对一个布尔值进行取反操作(true变false、false变true)。

  • 如果对一个值进行两次取反,它不会发生变化。
  • 如果对非布尔值进行运算,则会先转换为布尔值,再取反。(可以利用这一特点来将一个其他的数据类型转换为布尔值:为一个任意数据类型取两次反。原理和Boolean()一样)。

♍️&&与:对符号两侧的值进行与运算并返回结果。

  • 运算规则:
    • 如果两个值都是true,则返回true。
    • 只要有一个false,就返回false。
  • JS中的“与”属于短路的与,如果第一个值为false,则不会看第二个值。

♍️||或:对符号两侧的值进行或运算并返回结果。

  • 运算规则:
    • 如果两个值都是false,则返回false。
    • 只要有一个true,就返回true。
  • JS中的“或”属于短路的或,如果第一个值为true,则不会看第二个值。

♍️&& ||非布尔值的情况:

  • 对于非布尔值进行与或运算时,会将其转换为布尔值,然后再运算,并且返回原值。
  • 与运算:如果两个值都为true,则返回后边的true;如果两个值都为false,则返回前面的false。【如果第一个值为true则必然返回第二个值,如果第一个值为false则直接返回第一个值】。
  • 或运算:如果第一个值为true则直接返回第一个值;如果第一个值为false则返回第二个值。
//与运算:如果两个值都为true,则返回后边的值。

var d=5&&4;
console.log("d="+d);

// 运算结果显示为:
// d=4
(5)赋值运算符

=:可以将符号右侧的值赋值给符号左侧的变量。

+=:a=a+5即可表示为a+=5。

-=

*=

/=

%=

(6)关系运算符

通过关系运算符可以比较两个值之间的大小关系。如果关系成立会返回true,如果不成立返回false。

包括>、>=、<、<=

✴️非数值的情况:对于非数值情况,会将其转换成数字,再进行比较。

  • 任何值和NaN做任何比较都是false。

  • 如果符号两侧的值都是字符串,不会将其转换为数字比较,而会分别比较字符串中字符的Unicode编码。

    ​ 比较字符编码时是一位一位进行比较,若相同才比较下一位。(可以借用它来对英文进行排序。。比较中文没有意义。。如果比较的两个字符串型的数字,可能会得到不可预期的效果,因此一定一定一定要转型)

//"hello"转换为数字为NaN。任何值和NaN做任何比较都是false。

console.log(10<="hello");

// 运算结果显示为:
// false
//比较字符串中字符的Unicode编码

console.log("11" < "5");

// 运算结果显示为:
// true
//比较字符串中字符的Unicode编码

console.log("a" < "b");

// 运算结果显示为:
// true
//比较字符编码时是一位一位进行比较,若相同才比较下一位

console.log("abc" < "b");

// 运算结果显示为:
// true
(7)相等运算符

🐐==:相等运算符用来比较两个值是否相等,若相等返回true,不相等返回false。

  • 当使用==来比较两个值时,如果值的类型不同,会自动进行类型转换,将其转换为相同的类型后再进行比较。
  • undefined衍生自null,所以这两个值做相等判断时,返回true。
  • NaN不和任何值相等,包括它本身。
    • 可以通过isNaN()函数来判断一个值是否是NaN。如果该值是NaN则返回true,否则返回false。

🐐!=:不相等运算符用来比较两个值是否不相等,若不相等返回true,相等返回false。

  • 不等也会对变量进行自动的类型转换,如果转换后相等它也会返回false。

🐐===:全等,用来判断两个值是否全等,它和相等类似,但是全等不会进行类型转换。如果两个值的类型不同,直接返回false。

🐐!==:不全等,用来判断两个值是否不全等,它和不相等类似,但是不全等不会进行类型转换。如果两个值的类型不同,直接返回true。

(8)条件运算符

条件运算符也叫三元运算符。

👧语法: 条件表达式?语句1:语句2;

👧执行的流程:首先对条件表达式进行求值,如果该值为true,则执行语句1并返回结果;若该值为false,则执行语句2并返回执行结果。

  • 如果条件表达式的求值结果是一个非布尔值,会将其转换为布尔值再进行运算。
var a=30;
var b=45;
var c=23;

//获取a和b中的最大值
var max=a>b ? a : b;

//获取a、b和c中的最大值
max =max>c ? max : c;
//获取a、b和c中的最大值。不推荐
var max= a>b ? (a>c ? a : c ) : (b>c ? b : c);
(9),运算符

使用,可以分割多个语句,一般可以在声明多个变量时使用。

5.1.6 流程控制语句

通过流程控制语句可以控制程序执行流程,使程序可以根据一定的条件来选择执行。

(1)条件判断语句

使用条件判断语句可以在执行某个语句之前进行判断,如果条件成立才会执行语句,条件不成立则语句不成立。

🌐if语句

  • 语法:

    • 1️⃣if(条件表达式){

      ​ 语句

      }

      • 先对条件表达式进行求值判断,如果条件表达式的值为true则执行if后的语句;如果值为false则不会执行if后的语句。
      • if语句只能控制紧随其后的那个语句。如果希望if语句可以控制多条语句,可以将这些语句统一放在代码块中。
      • if语句后的代码块不是必须的,但是在开发中尽量写上代码块,即使if后只要一条语句。
    • 2️⃣if(条件表达式){
      语句…
      }else{
      语句…
      }

      • 当语句执行时,会先对 if后的条件表达式进行求值判断,若该值为true则执行if后的语句;若该值为false则执行else后的语句。
    • 3️⃣if(条件表达式){
      语句…
      }else if(条件表达式){
      语句…
      }else if(条件表达式){
      语句…
      }else if(条件表达式){
      语句…
      }else{
      语句…
      }

      • 自上至下依次对条件表达式进行求值判断:

        如果判断结果为true则执行当前if后的语句,执行完成后语句结束;

        如果判断结果为false,则继续向下判断,直到找到为true的为止;

        如果所有的条件表达式都是false,则执行else后的语句。

      • 该语句中只会有一个代码块被执行,一旦被执行了,则语句结束。


练习1:键入成绩并判断对应的奖品

<script>
        // prompt()可以弹出一个提示框,该提示框中会带有一个文本框,用户可以在文本框
        // 中输入一段内容,该函数需要一个字符串作为参数,该字符串将会作为提示框的提示文字

        // 用户输入的内容将会作为函数的返回值返回,可以定义一个变量来接收该内容。
        var score = prompt("请输入小明的期末成绩(0-100)");
        // 判断值是否合法
        if (score > 100 || score < 0 || isNaN(score)) {
            alert("您输入的成绩有误");
        }
        //若合法才执行
        else {
            if (score == 100) {
                alert("奖励一个笔记本");
            }
            else if (score >= 80) {
                alert("奖励一支铅笔");
            }
            else if (score >= 60) {
                alert("奖励一个橡皮擦");
            }
            else {
                alert("再接再厉");
            }
        }
</script>

练习2:键入3个整数,对其排序并按从小到大输出。

//思路可如下

<script>
        // prompt()函数的返回值是String类型.直接在其前添加+转换成Number类型
        var num1 = +prompt("请输入第一个数:");
        var num2 = +prompt("请输入第二个数:");
        var num3 = +prompt("请输入第三个数:");
        // 找到最小的数,此时num1最小
        if (num1 < num2 && num1 < num3) {
            if (num < num3) {
                alert(num1 + "," + num2 + "," + num3);
            }
            else {
                alert(num1 + "," + num3 + "," + num2);
            }
        }
</script>
(2)条件分支语句

条件分支语句也叫switch语句。

🌐switch语句

  • 语法:

    switch(条件表达式){

    ​ case 表达式:

    ​ 语句…

    ​ break;

    ​ case 表达式:

    ​ 语句…

    ​ break;

    ​ case 表达式:

    ​ 语句…

    ​ break;

    ​ default:

    ​ 语句…

    ​ break;

    }

    • 执行流程:会依次将case后的表达式的值和switch后的条件表达式的值进行全等比较,如果比较结果为true则从当前case处开始执行代码(当前case后的所有代码都会执行);如果比较结果为false则继续向下比较;如果所有比较结果都为false,则执行default后的语句。
    • 使用break可以退出switch语句。

switch语句和if语句的功能实际上有重复的,使用switch可以实现if的功能,同样使用if也可以实现switch的功能,所以使用时可以根据自己的习惯选择。


练习1:对于成绩大于60分的,输出’合格’。低于60分的,输出’不合格’。

//法一:

<script type="text/javascript">
        /*
         * 对于成绩大于60分的,输出'合格'。低于60分的,输出'不合格'
         * 
         * 6x  /  10 = 6
         * 7x  /  10 = 7
         * 8x  /  10 = 8
         * 9x  /  10 = 9
         * 100 /  10 = 10
         * 
         */
         
        var score = 75;
        
        //转换为整数类型,是为了类似99的数字的正确输出
        switch (parseInt(score / 10)) {
            case 10:
            case 9:
            case 8:
            case 7:
            case 6:
                console.log("合格");
                break;
            default:
                console.log("不合格");
                break;
        }
        
</script>
//法二

<script type="text/javascript">

        switch (true) {
            case score >= 60:
                console.log("合格");
                break;
            default:
                console.log("不合格");
                break;
        }

</script>
(3)循环语句

通过循环语句可以反复地执行一段代码多次。

创建一个循环,往往需要三个步骤:

1️⃣创初始化一个变量

2️⃣在循环中设置一个条件表达式

3️⃣定义一个更新表达式,每次更新初始化变量

//1.创初始化一个变量
var i = 11;

//2.在循环中设置一个条件表达式
while(i <= 10){
	//3.定义一个更新表达式,每次更新初始化变量
	document.write(i++ +"<br />")
			
}*/
🌐while循环
  • 语法:

    • while(条件表达式){

      ​ 语句…

      }

    • 执行流程:先对条件表达式进行求值判断,如果值为true则执行循环体,循环体执行完毕后继续对表达式进行判断,如果为true仍继续执行循环体,依次类推…如果值为false则终止循环。

    • 死循环:向条件表达式写死为true的循环。该循环不会停止,除非浏览器关闭。(在开发中慎用)。

      while(true){
      	alert(n++);
      }
      
    • 可以使用break终止循环。

      while(true){
      	alert(n++);
      	//判断n是否是10
      	if(n == 10){
      		//退出循环
      		break;
      }
      
🌐do…while循环
  • 语法:

    • do{

      ​ 语句…

      }while(条件表达式)

    • 执行流程:do…while语句在执行时,会先执行循环体,循环体执行完毕以后,在对while后的条件表达式进行判断,如果结果为true,则继续执行循环体,执行完毕继续判断以此类推…如果结果为false,则终止循环。

🌐实际上这两个语句功能类似,不同的是while是先判断后执行,而do…while会先执行后判断。do…while可以保证循环体至少执行一次,而while不能。


练习1:假如投资的年利率为5%,试求从1000块增长到5000块,需要花费多少年?

<script type="text/javascript">
			
			/*
			 * 1000 1000*1.05
			 * 1050 1050*1.05
			 */
			
			//定义一个变量,表示当前的钱数
			var money = 1000;
			
			//定义一个计数器
			var count = 0;
			
			//定义一个while循环来计算每年的钱数
			while(money < 5000){
				money *= 1.05;
				
				//使count自增
				count++;
			}
			
			
			//console.log(money);
			console.log("一共需要"+count+"年");		
</script>

练习2:从键盘输入小明的期末成绩:当成绩为100时,‘奖励一辆BMW’;当成绩为[80-99]时,‘奖励一台iphone15s’;当成绩为[60-80]时,‘奖励一本参考书’;其他时,什么奖励也没有。

		<script type="text/javascript">

			//将prompt放入到一个循环中
			while(true){
				//score就是小明的期末成绩
				var score = prompt("请输入小明的期末成绩(0-100):");
				//判断用户输入的值是否合法
				if(score >= 0 && score <= 100){
					//满足该条件则证明用户的输入合法,退出循环
					break;
				}
				
				alert("请输入有效的分数!!!");
			}
			
			
			
			//判断值是否合法
			if(score > 100 || score < 0 || isNaN(score)){
				alert("拉出去毙了~~~");
			}else{
				//根据score的值来决定给小明什么奖励
				if(score == 100){
					//奖励一台宝马
					alert("宝马,拿去~~~");
				}else if(score >= 80){
					//奖励一个手机
					alert("手机,拿去玩~~~");
				}else if(score >= 60){
					//奖励一本参考书
					alert("参考书,拿去看~~~");
				}else{
					alert("棍子一根~~");
				}
			}
			
		</script>
🌐for循环

for语句,也是一个循环语句,也称为for循环。

在for循环中,为我们提供了专门的位置用来放三个表达式:初始化表达式、条件表达式、更新表达式。

//创建一个执行10次的while循环
					
			for(var i = 0 ; i < 10 ; i++ ){
				alert(i);
			}
  • 语法:

    • for(①初始化表达式;②条件表达式;④更新表达式){

      ​ ③语句…

      }

    • 执行流程:

      • ①执行初始化表达式,初始化变量(初始化表达式只会执行一次);
      • ②执行条件表达式,判断是否执行循环。如果为true,则执行循环;如果为false,终止循环。
      • ④执行更新表达式,更新表达式执行完毕继续重复②。
    • for循环中的三个部分都可以省略,也可以写在外部。

      • 如果在for循环中不写任何的表达式,只写两个";",此时循环是一个死循环会一直执行下去,慎用。
      //死循环
      for(;;){
      	alert("hello");
      }
      

练习1:打印1-100之间所有奇数之和。

<script type="text/javascript">
			
			//3.创建一个变量,用来保存奇数之和。如果不写在for循环里面充当条件,就注意一定得写在循环体外面,否则每一次循环都会令sum=0
			//var sum = 0;
			
			//1.打印1-100之间的数
			for(var i=1 , sum=0 ; i<=100 ; i++){
				
				//2.判断i是否是奇数
				//不能被2整除的数就是奇数
				if(i%2 != 0){
					//如果i除以2有余数则证明i是奇数
					//console.log(i);
					sum = sum+i;
				}
			}
			
			console.log("奇数之和为 : "+sum);
			
</script>

练习2:打印1-100之间所有7的倍数的个数及总和。

		<script type="text/javascript">
			
			//3.定义一个变量,来保存总和
			var sum = 0;
			//5.定义一个计数器,来记录数量
			var count = 0;
			
			//1.打印1-100之间所有的数
			for(var i=1 ; i<=100 ; i++){
				
				//2.判断i是否是7的倍数
				if(i % 7 == 0){
					//console.log(i);
					sum += i;
					//使计数器自增1
					count++;
					
				}
				
			}
			
			//4.输出总和
			console.log("总和为:"+sum);
			//6.输出总数
			console.log("总数量为:"+count);			
						
		</script>

练习3:水仙花数是指一个3位数,它的每个位上的数字的3 次幂之和等于它本身。(例如:1^3 + 5^3 + 3^3 = 153),请打印三位数所有的水仙花数。

		<script type="text/javascript">
						
			//1.打印所有的三位数
			for(var i=100 ; i<1000 ; i++){
				
				//2.获取i的百位 十位 个位的数字
				//获取百位数字,注意取整。
				var bai = parseInt(i/100);
				 
				//获取十位的数字
				var shi = parseInt((i-bai*100)/10);
				
				//获取个位数字
				var ge = i % 10;
				
				//3.判断i是否是水仙花数
				if(bai*bai*bai + shi*shi*shi + ge*ge*ge == i){
					console.log(i);
				}	
			}
						
		</script>

练习4:在页面中接收一个用户输入的数字,并判断该数是否是质数。

质数:只能被1和它自身整除的数,1不是质数也不是合数,质数必须是大于1的自然数。

		<script type="text/javascript">
			
			//1.键入数字
			var num = prompt("请输入一个大于1的整数:");
						
			//2.判断键入的值是否合法
			if(num <= 1){
				alert("该值不合法!");
			}else{
				
				//3-3创建一个变量来保存当前的数的状态
				//默认当前num是质数
				var flag = true;
				
				//3.判断num是否是质数
				//3-1.获取2-num之间的数
				for(var i=2 ; i<num ; i++){
					//console.log(i);
					//3-2.判断num是否能被i整除
					if(num % i == 0){
						//3-2-1.如果num能被i整除,则说明num一定不是质数(逆向判断)
						//设置flag为false,即num不是质数
						flag = false;
					}
				}
				
				//3-2-2.如果num是质数则输出
				if(flag){
					alert(num + "是质数!!!");
				}else{
					alert("这个不是质数")
				}
				
				
			}
			
			
		</script>
嵌套的for循环

练习1:阶级*号的显示。

    <script type="text/javascript">

        /*
         
              通过程序,在页面中输出如下的图形:
                    行号 j的值
              *      1   <1   i=0
              **     2   <2   i=1
              ***    3   <3   i=2
              ****   4   <4   i=3
              *****  5   <5   i=4
         	
              *****
              *****
              *****
              *****
              *****
         	
              ***** 1   j<5即(5-0)  i=0
              ****  2	j<4即(5-1)  i=1
              ***   3   j<3即(5-2)  i=2
              **    4   j<2即(5-3)  i=3
              *     5   j<1即(5-4)  i=4
         	
         
         */

        //0.向body中输出一个内容
        //document.write("*****<br />");

        //1.通过一个for循环来输出图形,这个for循环执行几次,图形的高度就是多少(它可以用来控制图形的高度)
        for (var i = 0; i < 5; i++) {

            /*
             * 2.在循环的内部再创建一个循环,用来控制图形的宽度,即*的个数
             * 目前我们的外部的for循环执行1次,内部的就会执行5次
             * (内层循环可以来决定图形的宽度,执行几次图形的宽度就是多少)
             */

            //从上到下依次增加的阶级*号的显示
            /*for(var j=0 ; j<i+1 ; j++){
                document.write("*&nbsp;&nbsp;&nbsp;");
            }*/

            //从上到下依次减少的阶级*号的显示
            for (var j = 0; j < 5 - i; j++) {
                document.write("*&nbsp;&nbsp;&nbsp;");
            }

            //3.一次输出循环一换行
            document.write("<br />");
        }

    </script>

练习2:九九乘法表

    <script>
        // 1.创建外层循环,用来控制乘法表的高度
        for (var i = 1; i <= 9; i++) {
            // 2.创建内层循环,用来控制乘法表的宽度
            for (var j = 1; j <= i; j++) {
                // 5.为了好看,将内容放在span标签里
                // 3.写内容
                document.write("<span>" + j + "*" + i + "=" + i * j + "</span>");
            }
            // 4.换行
            document.write("<br>");
        }
    </script>
    <style>
        /* 5-1为span设置样式 */
        span {
            /* span是行内元素,无法设置宽高,得转换,但是又要保证能在同一行显示 */
            display: inline-block;
            width: 80px;
        }
    </style>

练习3:打印1-100之间所有的质数。

    <script>

        // 1.打印2-100之间所以的数
        for (var i = 2; i <= 100; i++) {

            // 3.创建一个布尔值用于保存结果,默认i是质数
            var flag = true;

            // 2.判断i是否是质数
            // 2-1获取1-i之间所有的数
            for (var j = 2; j < i; j++) {

                // 2-2判断i是否能被j整除(反向思维--如果进入判断则证明i不是质数)
                if (i % j == 0) {
                    // 3-2进入判断证明i不是质数,则修改flag值为false,并判断其不是质数
                    flag = false;
                }
            }

            // 2-3如果是质数,则打印i的值
            // console.log(i);
            //3-1即flag为true,增加一个判断语句.
            if (flag) {
                console.log(i);
            }
        }

    </script>
(4)break和continue

🍨不能在if语句中使用break和continue。

//注意此处是正确的。因为break实际上是对for循环起作用。

for(var i=0 ; i<5 ; i++){
	console.log(i);	
	if(i == 2){
		break;
	}
}
break

break关键字可以用来退出switch或循环语句。

  • break关键字,会立即终止离他最近的那个循环语句。
continue

continue关键字可以用来跳过当次循环。同样continue也是默认只会对离他最近的循环循环起作用。


🍨可以为循环语句创建一个label标签,用于来标识当前的循环。

  • 语法:label:循环语句

  • 使用break语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。【continue同样适用】

    outer:
    for(var i=0 ; i<5 ; i++){
    console.log("@外层循环"+i)
    	for(var j=0 ; j<5; j++){
    		//outer终止的是外层循环
    		break outer;
    		console.log("内层循环:"+j);
    	}
    }
    

5.1.7 对象

🌋不属于基本数据类型的值全是对象。

🌋基本数据类型都是单一的值"hello" 123 true,值和值之间没有任何的联系。

  • 如果使用基本数据类型的数据,我们所创建的变量都是独立,不能成为一个整体。

🌋对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。

(1)对象的分类

1️⃣内建对象

由ES标准中定义的对象,在任何的ES的实现中都可以使用。比如:Math、String、Number、Boolean、Function、Object…

2️⃣宿主对象

由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象。比如 BOM、DOM

  • 如console.log();的console、document.write();的document都属于宿主对象。

3️⃣自定义对象

由开发人员自己创建的对象。

  • 创建对象:使用new关键字调用的函数,是构造函数constructor。构造函数是专门用来创建对象的函数。【使用typeof检查一个对象时,会返回object】

    //空对象
    var obj = new Object();
    
  • 向对象添加属性:(在对象中保存的值称为属性)

    • 语法:对象.属性名 = 属性值;
    //向obj中添加一个name属性
    obj.name = "孙悟空";
    
    //向obj中添加一个gender属性
    obj.gender = "男";
    
    //向obj中添加一个age属性
    obj.age = 18;
    
  • 读取对象中的属性:

    • 语法:对象.属性名
    • 如果读取对象中没有的属性,不会报错而是会返回undefined。
    console.log(obj.gender);
    
    //如果读取对象中没有的属性,不会报错而是会返回undefined
    console.log(obj.hello);
    
  • 修改对象的属性值:

    • 语法:对象.属性名 = 新值
    obj.name = "tom";
    
  • 删除对象的属性:

    • 语法:delete 对象.属性名
    delete obj.name;
    
(2)属性名和属性值

属性名:对象的属性名不强制要求遵守标识符的规范。(但是我们使用时还是尽量按照标识符的规范去做)

  • 如果要使用特殊的属性名,不能采用.的方式来操作,需要使用另一种方式:(读取时也需要采用这种方式)

    • 语法:对象[“属性名”] = 属性值

      obj["nihao"] = "你好";
      
    • 使用[]这种形式去操作属性,更加的灵活。在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性。

      var n = "nihao";
      console.log(obj["123"]);
      
      //控制台打印出 你好
      
  • 函数也可以作为对象的属性:如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法;调用函数就说调用对象的方法。

  • 【但是他只是名称上的区别,其他没有区别】

//调方法
obj.sayName();

//调函数
fun();

属性值:JS对象的属性值,可以是任意的数据类型(可以是个函数,也可以是一个对象)。

//函数可以作为属性值

 var obj = new Object();
 obj.name = "孙悟空";

obj.sayName=function(){
	console.log(obj.name);	
};

obj.sayName();

<也可以如下写>

var obj2={
	name:"猪八戒";
	age:18;
	sayName:function(){
		console.log(obj2.name);	
	};
};
in 运算符

in 运算符:通过该运算符可以检查一个对象中是否含有指定的属性。如果有则返回true,没有则返回false。

  • 语法:

    “属性名” in 对象

console.log("name" in obj);
(3)对象自面量

使用对象字面量,可以在创建对象时,直接指定对象中的属性。

  • 语法: {属性名:属性值,属性名:属性值…}
  • 对象字面量的属性名可以加引号也可以不加,建议不加。
  • 如果要使用一些特殊的名字,则必须加引号。
  • 属性名和属性值是一组一组的名值对结构,名和值之间使用:连接,多个名值对之间使用,隔开。如果一个属性之后没有其他的属性了,就不要写","
var obj2 = {
	name:"猪八戒",
	age:13,
	gender:"男",
	
	test:{name:"沙僧"}
};
(4)枚举对象中的属性

使用for…in语句

  • 语法:
    for(var 变量 in 对象){

      	}
    
  • for…in语句:对象中有几个属性,循环体就会执行几次;每次执行时,会将对象中的一个属性的名字赋值给变量

 var obj={
 	name:"猪八戒",
	age:13,
	gender:"男",
 };

//n即属性名
for(var n in obj){
	console.log("属性名:"+n);

	//打印出对应的属性值
	console.log("属性值"+obj[n]);
}

(5)使用工厂方法创建对象

通过该方法可以大批量创建对象。

function create Person(name,age,gender){
	//创建一个新的对象
	var obj=new Object();
	
	//向对象中添加属性
	obj.name=name;
	obj.age=age;
	obj.gender=gender;
	obj.sayName=function(){
		alert(this.name);
	};
	
	//将新的对象返回
	return obj;
}

var obj2=create Person("孙悟空",18,"男");

console.log(obj2);

使用工厂方法创建的对象,使用的构造函数都是Object,所有创建的对象都是Object类型,无法区分出多种不同类型的对象。

(6)原型对象prototype

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype。
prototype属性对应着一个对象,这个对象就是原型对象。

❗【原型对象里还有一个原型】

如果函数作为普通函数调用,prototype没有任何作用。
如果函数以构造函数的形式调用,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象。我们可以通过__proto__来访问该属性。

function MyClass(){

}
var mc=new MyClass();
console.log(mc.__proto__==MyClass.prototype);

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象。我们可以将对象中共有的内容,统一设置到原型对象中。
当我们访问对象的一个属性或方法时,会现在对象【自身】中寻找,如果直接使用;如果没有则会去【原型对象】中寻找,如果找到则直接使用;如果还没有,则去【原型的原型】中寻找,直到找到【Object对象的原型】。

❗Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined。

function MyClass(){

}
//向MyClass的原型中添加属性a
MyClass.prototype.a=123;

//向MyClass的原型中添加一个方法sayHello
MyClass.prototype.sayHello=function(){
	alert("hello");
};

var mc=new MyClass();
console.log(mc.__proto__==MyClass.prototype);
console.log(mc.a);
mc.sayHello();

因此创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中。

使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true。

hasOwnProperty()

可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性。
返回true或者false。
只有当对象自身中含有属性时,才会返回true。

console.log(mc.hasOwnProperty("name"));

hasOwnProperty在原型的原型里。
测试:

console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));
(7)toString

当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值。

如果希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法。

per.toString=function(){
	return "person"
};
var result=per.toString();
console.log("result="+result);

(8)Date对象

表示一个时间。

📕创建一个Date对象

var d=new Date();
console.log(d);
  • 如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间。

📕创建一个指定的时间对象
需要在构造函数中传递一个表示时间的字符串作为参数。
日期的格式 月/日/年/ 时:分:秒(年份注意写完整的,避免歧义)

var d2=new Date("12/03/2022 11:12:12");
console.log(d2);
方法

getDate()获取当前日期是几日。

var date=d.getDate();

getDay()获取当前日期对象是周几。会返回0-6的值,0表示周日,1表示周一…
getMonth()获取当前日期对象的月份,会返回一个0-11的值,0表示一月。
getFullYear()获取当前日期对象的年份。
getHours()
getMinutes()

🥥getTime()获取当前日期对象的时间戳。

  • 时间戳指的是从格林威治标准时间的1970年1月1日0时0分0秒到当前日期所花费的毫秒数。(1秒=1000毫秒)
  • 计算机底层在保存时间时使用都是时间戳
  • 可以利用时间戳来测试代码的执行性能
//获取当前的时间戳
time =Date.now();
//利用时间戳来测试代码的执行性能
var start=Date.now();
for(var i=0;i<100;i++){
	console.log(i);
}
var end=Date.now();
console.log("执行了:"+(end-start)+"毫秒");
(9)Math对象

它不是一个构造函数,属于一个工具类。不用创建对象,它里面封装了数学运算相关的属性和方法。

对象属性

Math.PI表示圆周率。

对象方法

📕abs()计算一个数的绝对值。
📕ceil()对一个数进行向上取整,(小数位有值则自动进1)。
📕floor()对一个数向下取整,(小数部分会被舍掉)。
📕round()四舍五入取整
📕random()生成0-1之间的随机数。

//生成一个0-10的随机数
Math.round(Math.random()*10)

//生成一个0-x的随机数
Math.round(Math.random()*x)

//生成一个1-10的随机数
Math.round(Math.random()*9)+1

//生成一个x-y的随机数
Math.round(Math.random()*(y-x))+x

📕max()获取多个数中最大值
📕min()最小值
📕Math.pow(x,y)返回x的y次幂
📕sqrt()开方

5.1.8 函数

函数也是一个对象。

函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)。

函数中可以保存一些代码在需要的时候调用。

使用typeof检查一个函数对象时,会返回function。

(1)创建函数对象
构造函数创建函数对象(开发中少用)

🎋创建一个函数对象

  • var fun = new Function( );
  • 可以将要封装的代码以字符串的形式传递给构造函数。
  • 封装到函数中的代码不会立即执行,函数中的代码会在函数调用的时候执行。
var fun = new Function("console.log('Hello 这是我的第一个函数');");

🎋调用函数

  • 语法:函数对象()
  • 当调用函数时,函数中封装的代码会按照顺序执行(调用几次便执行几次)。
fun();
函数声明创建函数
  • 语法:

    function 函数名([形参1,形参2…形参N]){

    ​ 语句…

    }

function fun2(){
	console.log("这是我的第二个函数~~~");
	alert("哈哈哈哈哈");
	document.write("~~~~(>_<)~~~~");
}

//调用fun2
fun2();
函数表达式创建函数
  • 语法:

    var 函数名 = function([形参1,形参2…形参N]){

    ​ 语句…

    }

var fun3 = function(){
	console.log("我是匿名函数中封装的代码");
};

fun3();
(2)函数的参数

可以在函数的()中来指定一个或多个形参(形式参数)。

  • 多个形参之间使用,隔开,声明形参就相当于在函数内部声明了对应的变量,但是并不赋值。

在调用函数时,可以在()中指定实参(实际参数)。

  • 实参将会赋值给函数中对应的形参。
  • 函数的实参可以是任意的数据类型。
  • 调用函数时解析器不会检查实参的类型。
    • 所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查。
  • 调用函数时,解析器也不会检查实参的数量。
    • 多余实参不会被赋值。
    • 如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined。
//定义一个用来求两个数和的函数

//在函数的()中指定形参
function sum(a,b){
	console.log("a = "+a);
	console.log("b = "+b);
	console.log(a+b);
}

//调用函数时,在()中指定实参
sum(123,456);
  • 实参可以是任意的数据类型,可以是一个对象。也可以是一个函数。
  • 当参数过多时,可以将参数封装在一个对象中,然后通过对象传递。
this

解析器在调用函数时每次都会向函数内部传递进一个隐含的参数,即this

  • this指向的是一个对象,这个对象称为函数执行的上下文对象。
  • 根据函数的【调用方式】的不同,this会指向不同的对象。
    📕以函数的形式调用时,this永远都是window;
    📕以方法的形式调用时,this就是调用方法的那个对象。
    📕以构造函数的形式调用时,this就是新创建的那个对象。
    📕使用call和appy调用时,this是指定的那个对象。
    📕在事件的响应函数中,响应函数是给谁绑定的,this就是谁。
(3)返回值

可以使用 return 来设置函数的返回值。

  • 语法:

    ​ return 值

  • return后的值将会会作为函数的执行结果返回,可以定义一个变量,来接收该结果。

  • 在函数中return后的语句都不会执行。

  • 如果return语句后不跟任何值就相当于返回一个undefined;如果函数中不写return,则也会返回undefined;return后可以跟任意类型的值

  • 返回值可以是任意的数据类型,可以是一个对象。也可以是一个函数。

(4)立即执行函数

立即执行函数:函数定义完立即被调用。往往只执行一次

//

(function(){
	alert("我是一个立即执行函数");
})();
(function(a,b){
	console.log("a="+a);
	console.log("b="+b);
})(123,456);
(5)函数的声明提前

使用函数声明形式创建的函数:function 函数(){}

  • 它会在所有的代码执行之前就被创建,所以可以在函数声明之前就调用函数。

使用函数表达式创建的函数,不会声明提前,因此不可以在函数声明之前调用函数。

(6)作用域

作用域:一个变量的作用的范围。

  • 分为全局作用域和函数作用域
全局作用域

直接编写在script标签中的JS代码,都在全局作用域。

  • 全局作用域在页面打开时创建,在页面关闭时销毁。
  • 有一个全局对象window,代表一个浏览器的窗口,它由浏览器创建,我们可以直接使用。
  • 在全局作用域中,创建的变量都会作为window对象的属性保存;创建的函数都会作为window对象的方法保存。

全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问到。

函数作用域
  • 调用函数时创建函数作用域,函数执行完毕以后销毁。
  • 每调用一次函数,就会创建一个新的函数作用域,他们之间相互独立。
  • 在函数作用域中可以访问到全局作用域的变量。在全局作用域中无法访问到函数作用域的变量。
  • 当在函数作用域中操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用;如果没有,则向【上一级作用域】寻找(此不一定是全局作用域);直到找到全局作用域,若在全局作用域中仍未找到,则会报错。

在函数中访问全局变量可以使用window对象。

在函数作用域中也有声明提前的特性,使用var关键字声明的变量,也会在函数中所有的代码执行之前被声明。函数声明也会在函数在所有的代码执行之前执行。

❗在函数中,不使用var声明的变量都会成为全局变量。

var c=33;
function fun5(){
	c=10;
}
fun5();
console.log("c="+c);

//输出结果:c=10
function fun6(){
	d=100;
}
fun6();
console.log("d="+d);

//输出结果:d=100

定义形参就相当于在函数作v 用域中声明了变量。

function fun7(a){
	a=456;
}
(7)构造函数

构造函数习惯上首字母大写。

构造函数和普通函数的区别就是调用方式的不同:

  • 普通函数是直接调用;
  • 构造函数需要使用new关键字来调用。

构造函数的执行流程:
①立刻创建一个新的对象;
②将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象;
③逐行执行函数中的代码
④将新建的对象作为返回值返回

使用同一构造函数创建的对象,成为一类对象;也称一个构造函数称为一个类。
将通过一个构造函数创建的对象称为该类的实例。

function Person(name,age,gender){
	this.name=name;
	this.age=age;
	this.gender=gender;
	//向对象中添加一个方法
	this.sayName=function(){
		alert(this.name);
	};
}
var per = new Person("孙悟空",12,"男");
console.log(per);

在Person构造函数中,为每一个对象都添加了一个sayName方法。
在构造函数内部创建的:每执行一次构造函数,就会创建一个新的sayName方法。
所有实例的sayName都是唯一的。这样就导致了构造函数执行一次就会创建一个新的方法,而这些方法都是一样的。----------->这是没有必要的,因此可以使所有的对象共享同一个方法。

因此优化修改如下:(将sayName方法在全局作用域中定义)

function Person(name,age,gender){
	this.name=name;
	this.age=age;
	this.gender=gender;
	//向对象中添加一个方法
	this.sayName=fun;
	};
}

//将sayName方法在全局作用域中定义
function fun(){
	alert(this.name);
};

var per = new Person("孙悟空",12,"男");
console.log(per);

这样写的坏处:将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也不安全。

因此修改优化如下:(向原型中添加sayName方法)

function Person(name,age,gender){
	this.name=name;
	this.age=age;
	this.gender=gender;
}

//向原型中添加sayName方法
Person.prototype.sayName=function(){
	alert(this.name);
};

var per = new Person("孙悟空",12,"男");
console.log(per);

instanceof

使用instanceof可以检查一个对象是否是一个类的实例。

  • 语法:
    对象 instanceof 构造函数
  • 是,返回true;不是返回false。

所有的对象都是Object的后代;
所以任何对象和Object做instanceof检查时都会返回true

(8)函数的方法
call()

函数对象的方法,需要通过函数对象来调用。
可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this。

可以将实参在对象之后依次传递

fun.call(obj,2,3);
apply()

函数对象的方法,需要通过函数对象来调用。
可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this。

需要将实参封装到一个数组中统一传递。

fun.apply(obj,[2,3]);
arguments()

在调用函数时,浏览器每次都会传递两个隐含的参数
①函数的上下文对象this
②封装实参的对象arguments

  • arguments是一个类数组对象,它也可以通过索引来操作数据,可以获取长度
  • 在调用函数时,我们所传递的实参都会在arguments中保存。
  • arguments.length可以用来获取实参的长度。
  • 即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦:
    arguments[0]表示第一个实参;
    arguments[1]表示第二个实参。
  • 它里面有一个属性callee。这个属性对应一个函数对象,就是当前正在指向的函数的对象。

5.1.9 数组

数组也是一个对象。

区别:

  • 普通对象使用字符串作为属性名,而数组使用数字作为索引操作元素。

PS:索引即从0开始的整数。

(1)创建数组对象

📕向数组中添加元素

  • 语法:
    数组[索引]=值

📕读取数组中元素

  • 语法:
    数组[索引]
  • 如果读取不存在的索引,不会报错,而是返回undefined
//创建数组对象
var arr=new Array();

//向数组中添加元素
arr[0]=10;

//读取数组中元素
console.log(arr[0]);

使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数传递。

var arr=new Array(10,20,30);

📕获取数组的长度length属性

  • 语法:
    数组.length
  • 对于连续的数组,使用length返回数组的长度(元素的个数);对于非连续的数组,返回数组的最大的索引+1。

❗尽量不要创建非连续的数组

修改length:
如果修改的length大于原长度,则多出部分会空出来;
若小于原长度,则多出的元素会被删除。

  • 像数组的最后一个位置添加元素:
    语法: 数组[数组.length]=值;
arr[arr.length]=70;
(2)数组字面量

📕使用字面量来创建数组

  • 语法:[]
var arr=[];

使用字面量创建数组时,可以在创建时就指定数组中的元素。

var arr=[1,2,3,4,5,10];

🥥区别:

  • arr=[10]; //创建一个数组元素中只有一个元素10
  • var arr=[10]; //创建一个长度为10的数组

🐟数组中的元素可以是任意的数据类型。

arr=["hello",1,true,null,undefined];

🐟也可以是对象。

var obj={name:"孙悟空"};
arr[arr.length]=obj;

arr=[{name:"孙悟空"},{name:"猪八戒"}];

🐟也可以是一个函数。

arr=[function(){alert(1)},function(){alert(2)}];

🐟数组中也可以放数组,如下这种称为二维数组。

arr=[[1,2,3],[4,5,6]];
(3)Array对象方法
push()

该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度。

可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾。

arr.push("孙悟空","猪八戒","沙和尚");
pop()

该方法删除数组的最后一个元素,并将删除的元素作为返回值返回。

arr.pop();
unshift()

该方法向数组开头添加一个或多个元素,并返回新的数组长度。

向前边插入元素以后,其他元素的索引会依次调整。

arr.unshift("牛魔王","红孩儿");
shift()

删除并返回数组的第一个元素

arr.shift();
forEach()

该方法用于遍历数组。
❗需要一个函数作为参数。

var arr=["孙悟空","猪八戒","红孩儿"];
function fun(){
}
arr.forEach(fun());

一般像如下写:

var arr=["孙悟空","猪八戒","红孩儿"];
arr.forEach(function(){
	console.log("hello");
});

像上述函数,由我们创建但是不由我们调用的(浏览器调用),称为回调函数。
数组中有几个元素,函数就会执行几次。每次执行时,浏览器会将遍历到的元素以实参的形式传递进来👇

var arr=["孙悟空","猪八戒","红孩儿"];
arr.forEach(function(a){
	console.log("a="+a);
});

(我们可以定义形参来读取这些内容)👇
浏览器会在回调函数中传递三个参数:
①当前正在遍历的元素
②当前正在遍历的元素的索引
③正在遍历的数组

var arr=["孙悟空","猪八戒","红孩儿"];
arr.forEach(function(value,index,obj){
	console.log(value);
});
slice()

从某数组中提取出指定元素。
该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回。

参数:
①截取开始的位置的索引
②截取结束的位置的索引(可以省略不写,此时会截取从开始索引到以后的所有元素)

🚗索引可以传递一个负值。如果传递一个赋值,则从后往前计算。(如-1即倒数第一个)

var arr=["孙悟空","猪八戒","红孩儿"];
var result= arr.slice(0,2);
console.log(result);

splice()

删除数组中的指定元素。
会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回。

参数:
①开始位置的索引
②删除的数量
③及以后:可以传递一些新的元素,这些元素将会自动插入到开始位置索引的前面

arr.splice(0,2,"牛魔王","红孩儿","铁扇公主");
concat()

连接两个或多个数组,并将新的数组返回。
不会对原数组产生影响。

可以传数组,也可以传单一元素👇

var result=arr.concat(arr2,arr,"牛魔王");
join()

将数组转换为一个字符串。
不会对原数组产生影响,而是将转换后的字符串作为结果返回。
指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符。
如果不指定连接符,则默认使用,作为连接符。

arr=["牛魔王","红孩儿","铁扇公主"];

result=arr.join("@");
reverse()

反转数组(前边的去后边,后边的去前边)。
会直接修改原数组。

sort()

对数组中的元素进行排序。
会影响原数组,默认会按照Unicode编码进行排序。

【纯数字,也会按照Unicode编码进行排序。(因此可能得到错误结果)】

我们可以自己指定排序规则。
—在sort()添加一个回调函数,来指定排序规则。

  • 需要定义两个形参。浏览器将会分别使用数组中的元素作为实参去调用回调函数。(使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边)。
  • 浏览器会根据回调函数的返回值决定元素的顺序,若返回一个大于0的值,则元素会交换位置。若返回一个小于0的值,则位置不变。若返回0则不交换位置(认为两个元素相等)。

🐂升序排列
return a-b;
🐂降序排列
return b-a;

arr=[5,4];

arr.sort(function(a,b){
	if(a>b){
		return 1;
	}else if(a<b){
		return -1;
	}else{
		return 0;
	}
});
arr=[5,4];

arr.sort(function(a,b){
//升序排列
		return a-b;
//降序排列
		return b-a;
});
(4)数组的遍历

遍历数组即将数组中所有的元素都取出来。

for(var i=0;i<arr.length;i++){
	console.log(arr[i]);
}

5.1.10 包装类

JS提供三个包装类,可以将基本数据类型的数据转换为对象。
String()将基本数据类型字符串转换为String对象

var str= new String("hello");

Number()将基本数据类型的数字转换为Number对象

var num= new Number(3);

//向num中添加一个属性
num.hello="nihao";

Boolean()将基本数据类型的布尔值转换为Boolean对象

var bool= new Boolean(true);

❗注意:在实际应用中不会使用基本数据类型的对象。如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果。

❗方法和属性只能添加给对象,不能添加给基本数据类型。
当我们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后再调用对象属性和方法,调用完以后,再将其转换为基本数据类型。

5.1.11 字符串

字符串在底层是以字符数组的形式保存的。
如[“H”,“e”,“l”];

📕创建一个字符串

var str="hello";
属性

length获取字符串长度

方法

📕charAt()返回字符串中指定位置的字符。根据索引获取指定的字符。
📕charCodeAt()获取指定位置字符的字符编码(Unicode编码)。
📕fromCharCode()根据字符编码获取字符。
📕concat()连接两个或多个字符串。
📕indexOf()检索一个字符串中是否含有指定内容。【从前往后找】

  • 如果字符串中含有该内容则会返回其第一次出现的索引;若未找到则返回-1。
  • 可以指定一个第二个参数,指定开始查找的位置。
    📕lastIndexOf()【从后往前找】,其余同indexOf()。
    📕slice()截取指定的内容。不会影响原字符串,而是将截取到的内容返回。
  • 参数:
    ①开始位置的索引(包括开始位置)
    ②结束位置的索引(不包括结束位置)👉如果省略第二个参数,则会截取到后面所有的。
    也可以传递一个参数作为参数,负数即从后面开始计算。
    📕substring()截取一个字符串,与slice()类似。
  • 参数
    ①开始位置的索引(包括开始位置)
    ②结束位置的索引(不包括结束位置)
  • 与slice()不同的是:
    ①这个方法不能接受负值作为参数,如果传递了一个负值,则默认使用0。
    ②会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。
    📕substr()截取字符串。
  • 参数:
    ①截取开始位置的索引
    ②截取的长度
    📕split()将一个字符串拆分为一个数组。
    参数:
  • 需要一个字符串作为参数,将会根据该字符串去拆分数组。
  • 可以传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
str="abc,bcd,efg,hij";
result=str.split("d");
//也可以传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
result=str.split("");

📕toLowerCase()将一个字符串转换为小写并返回。
📕toUpperCase()将一个字符串转换为大写并返回。

5.1.12 正则表达式

正则表达式用于定义一些字符串的规则。
计算机可以根据正则表达式,检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来。

(1)创建正则表达式对象
使用构造函数创建(更灵活)

语法:
var 变量=new RegExp(“正则表达式”,“匹配模式”);
【使用typeof检查,会返回object】

  • 匹配模式
    ① i 忽略大小写
    ② g 全局匹配模式
//检查一个字符串中是否含有a
var reg=new RegExp("a","i");
使用字面量来创建(更简单)

语法:
var 变量=/正则表达式/匹配模式

reg=/a/i;

🥥|表示或
🥥[]里的内容也是或的关系
[ab]==a|b
[a-z]任意小写字母
[A-Z]任意大写字母
[A-z]任意字母
🥥[^ ]表示除了

//检查一个字符串中是否有a或b
reg=/a|b/;

//检查是否有字母
reg1=/[A-z]/;

//检查是否含有abc或adc或aec
reg2=/a[bde]c/;

//检查是否含有任意数字。
reg3=/[0-9]/;
(2)正则表达式的语法

量词:设置一个内容出现的次数。
❗两次只对它前面的一个内容起作用
{n} 正好出现n次
{m,n} 出现m-n次
{m,} 出现m次以上
+ 至少一个,相当于{1,}
* 0个或多个,相当于{0,}
? 0个或1个,相当于{0,1}
^ 表示开头
[^ ] 表示除了
$ 表示结尾
. 表示任意字符
ps:如果在正则表达式中同时使用^ $,则要求字符串必须完全符合正则表达式。

❗注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用 \ 则需要使用 \ 来代替。
如:reg=new RegExp(“\.”);

//a出现3次
var reg=/a{3}/;

//ab出现3次
var reg=/(ab){3}/;

//b出现1到3次
var reg=/ab{1,3}c/;

//是否以a开头
reg=/^a/;

//是否以a结尾
reg=/a$/;

//是否含有.
//  正则表达式中\作为转义字符,用\.表示.
var reg=/\./;
//使用构造函数时,要使用 \ 需要使用 \\ 来代替。
 reg=new RegExp("\\.");

\w 任意字母、数字、下划线_
\W 除了字母、数字、下划线_
\d 任意数字[0-9]
\D 除了任意数字[^0-9]
\s 空格
\S 除了空格
\b 单词边界
\B 除了单词边界

//检查一个字符串中是否含有单词child
reg = /\bchild\b/;
console.log(reg.test("hello child"));
去除字符串空格

去除字符串空格就是用""代替空格

//去除字符串开头和结尾任意个空格
str=str.replace(/^\s*|\s*$/g,"");
检查合法的手机号

🐟手机号规则(11位)

  • 第一位以1开头 ^1
  • 第二位 3-9任意数字 [3-9]
  • 三位以后任意数字9个 [0-9]{9}$
//检查一个字符串是否是一个合法的手机号
var phoneStr="13098321231";
var phoneReg=/^1[3-9][0-9]{9}$/;
console.log(phoneReg.test(phoneStr));

电子邮件的正则

格式:
任意字母数字下划线 . 任意字母数字下划线 @ 任意字母数字 . 任意字母(2-5位) . 任意字母(2-5位)
\w{3,} (.\w+)* @ [A-z0-9]+ (.[A-z]{2,5}){1,2}

var emailReg=/^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
(3)正则表达式的方法

test()检查一个字符串是否符合正则表达式的规则。符合则返回true,否则返回false。

(4)字符串和正则相关的方法
split()

将一个字符串拆分为一个数组。
这个方法即使不指定全局匹配,也会全部拆分

//根据任意字母将字符串拆分-方法中可以传递一个正则表达式作为参数
var str="1h2h312h314h1";

var result=str.split(/[A-z]/);

search()

搜索字符串中是否含有指定内容。

  • 搜索到则返回第一次出现的索引;没有搜索到则返回-1
  • 可以接受一个正则表达式作为参数,然后根据正则表达式检索字符串

❗只会查找第一个,即使设置全局匹配也没用。

match()

根据正则表达式,从一个字符串中将符合条件的内容提取出来。
默认情况下match只会找到第一个符合要求的内容,找到后就停止检索。

  • 可以设置正则表达式为全局匹配模式,这样就会匹配到所有内容。
  • 可以为一个正则表达式设置多个匹配模式,且顺序无所谓。

match()会将匹配到的内容封装在一个数组中返回,即使只查询到一个结果。

replace()

将字符串中指定内容替换为新的内容。
参数:
①被替换的内容,可以接受一个正则表达式作为参数
②新的内容
默认只会替换第一个。

5.2 DOM

5.2.1 简介

在这里插入图片描述

(1)模型

在这里插入图片描述

(2)节点

浏览器已经提供文档节点,这个对象是window属性。可以在页面中直接使用,文档节点代表的是整个网页。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)事件

在这里插入图片描述
在事件对应的属性中设置js代码,当事件被触发时,这些代码将会执行。
可以为按钮的对应事件绑定处理函数的形式来响应事件,这样当事件被触发时,其对应的函数将会被调用。

为单击事件绑定的函数,称为单击响应函数。

<button id="btn">按钮</button>
//获取按钮对象
<script>
var btn=document.getElementById("btn");
//绑定一个单击事件,为单击事件绑定的函数,称为单击响应函数
btn.onclick=function(){
	alert("点击按钮");
};
</script>

5.2.2 文档的加载

onload事件会在整个页面加载完成之后才触发。
该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保代码执行时所有的DOM对象已经加载完毕。

window.οnlοad=function(){
	var btn=document.getElementById("btn");
	btn.οnclick=function(){
	alert("点击按钮");
	};
};

5.2.3 DOM查询

(1) 获取元素节点

🐟innerHTML这个属性可以获取到元素内部的html代码。

  • 对于自结束标签,这个属性没有意义。

🥥如果需要读取元素节点的属性,直接使用【元素.属性名】

  • 例子:元素,id 元素.name 元素.value
  • ❗但是class属性不能采用这种方式。【读取class属性时需要使用 元素.className】

🐟innerText获取元素内部的文本内容。和innerHTML类似,不同的是它会自动将html去除。
在这里插入图片描述
ps:getElementsByTagName()会返回一个类数组对象,所有查询到的元素都会封装到对象中。(即使查询到的元素只有一个,也会封装到数组中返回)

(2) 获取元素节点的子节点


ps:
①childNodes会获取包括文本节点在内的所有节点。根据DOM标签标准,标签间空白也会当成文本节点。【注意IE8即以下的浏览器中,不会吧空白文本当成子节点】
②firstChild可以获取到当前元素的第一个子节点(包括空白文本节点)。
③🐟firstElementChild获取当前元素的第一个子元素。(不支持IE8即以下的浏览器)

(3)获取父节点和兄弟节点

在这里插入图片描述
previousSibling也可能获取到空白的文本。
🐟previousElementSibling获取前一个兄弟元素。(不支持IE8即以下的浏览器)

(4)document对象的其他的属性和方法

📕document.body 获取页面中的body元素。
📕document.documentElement 获取html根标签。
📕document.all 获取页面中所有的元素。

  • 也可以写为:all=document.getElementsTagName(“*”);

📕getElementsByClassName() 可以根据元素的class属性值查询一组元素节点对象。(不支持IE8即以下的浏览器)

var box1=document.getElementsByClassName("box1");


<div class="box1"></div>

📕document.querySelector() 可以根据一个css选择器来查询一个元素节点对象。

  • 需要一个选择器的字符串作为参数。
  • 使用该方法总会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个。
  • (IE8支持)

📕document.querySelectorAll()

  • 和querySelector() 用法类似,不同的是它会将符合条件的元素封装到一个数组中返回。
  • 即使符合条件的元素只有一个,它也会返回数组。

5.2.4 DOM增删改

📕document.createElement(“TagName”) 创建元素节点对象

  • 需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回。
    📕document.createTextNode(“textContent”)
    可以根据文本内容创建一个文本节点对象
    • 需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回。

📕appendChild() 向父节点中添加指定的子节点

  • 用法:父节点.appendChild(子节点)

📕insertBefore() 在指定的子节点前插入新的子节点

  • 用法:父节点.insertBefore(新节点,旧节点)

📕replaceChild() 使用一个新的节点去替换旧节点

  • 用法:父节点.replaceChild(新节点,旧节点)

📕removeChild() 删除指定的子节点

  • 用法:父节点.removeChild(子节点)
  • 推荐方式(常用):
    子节点.parentNode.removeChild(子节点)

ps:先获取到父节点,再删除

🐟使用innerHTML也可以实现DOM的增删改的相关操作。如:
(一般会两种方式结合使用,见下方代码2)

city.innerHTML += "<li>广州</li>";
myClick("btn07",function(){  
    //向city中添加广州  
    var city = document.getElementById("city");  
  
    /*  
	* 使用innerHTML也可以完成DOM的增删改的相关操作  
	* 一般我们会两种方式结合使用  
	*/  
  
    //创建一个li  
    var li = document.createElement("li");  
    //向li中设置文本  
    li.innerHTML = "广州";  
    //将li添加到city中  
    city.appendChild(li);  
  
});  

5.2.5 使用DOM操作CSS

(1)内联样式

通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示。

但是如果在样式中写了【!important】,则此时样式会有最高的优先级,即使通过JS也不能覆盖改样式,此时将会导致JS修改样式失效。所以尽量不要为样式添加!important。

📕通过JS修改元素的样式

  • 语法: 元素.style.样式名=样式值

ps:如果CSS的样式名中含有-,这种名称在JS在是不合法的(比如background-color),需要将这种样式名修改为驼峰命名法(去掉-,然后将-后的字母大写)。

📕读取元素的样式

  • 语法: 元素.style.样式名
  • 通过style属性设置和读取的都是内联样式。无法读取样式表中的样式。
(2)获取元素当前显示的样式

📕getComputedStyle()获取元素当前显示的样式。

  • 需要两个参数
    ①要获取样式的元素;
    ②可以传递一个伪元素,一般都传null
  • 该方法会返回一个对象,对象中封装了当前元素对应的样式。可以通过【对象.样式名】来读取样式。
  • 如果获取的样式没有设置,则会获得真实的值,而不是默认值。(如width未设置,不会获取到auto,而是一个长度)
  • (window方法,可直接使用。其它浏览器也可使用,不支持IE8及以下浏览器)
//定义一个函数,用来获取指定元素的当前的样式(保证浏览器兼容)
//参数:obj要获取样式的元素 name要获取的样式名
function getStyle(obj,name){
	//注意这里必须要加window,否则ie8中会报错
	if(window.getComputedStyle){
		//正常浏览器的方式
		return getComputedStyle(obj,null)[name];
	}else{
		//IE8的方式
		return obj.currentStyle[name];
	}
}

📕currentStyle

  • 语法:元素.currentStyle.样式名
  • 用来读取当前元素正在显示的样式。
  • 如果当前元素没有设置样式,则获取默认值。
  • (只有IE浏览器支持)

❗通过currentStyle和getComputedStyle()读取到的样式都是只读的,不能修改。
如果要修改只能通过style属性

(3)其他样式相关的属性

📕clientWidth和clientHeight 可以获取元素的可见宽度和高度

  • 这些属性都是不带px的,返回的是一个数字,可以直接进行计算。
  • 会获取元素宽度和高度,包括内容区和内边距。
  • 这些属性都是只读的,不能修改。

📕offsetWidth和offsetHeight 获取元素的整个的宽度和高度,包括内容去、内边距、边框。
📕offsetParent 获取当前元素的定位父元素

  • 获取离当前元素最近的开启了定位的祖先元素。【如果所有的祖先元素都没有开启定位,则返回body】
    📕offsetLeft 当前元素相对于其定位父元素的水平偏移量
    📕offsetTop 当前元素相对于其定位父元素的垂直偏移量

📕scollWidth和scollHeight 可以获取元素整个滚动区域的宽度高度
📕scollLeft 获取水平滚动条滚动的距离

  • 当满足scollWidth-scollLeft=clientWidth时,说明水平滚动条滚动到底了。
    📕scollTop 获取垂直滚动条滚动的距离
  • 当满足scollHeight-scollTop=clientHeight时,说明垂直滚动条滚动到底了。

5.2.6 事件

(1)事件对象

当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。
在事件对象中封装了当前事件相关的一切信息,比如鼠标的坐标、键盘哪个键被按下等。

  • 在IE8中。响应函数被触发时,浏览器不会传递事件对象。(在IE8及以下浏览器中,是将事件对象作为window对象的属性保存的)👉利用如下处理
//解决事件对象兼容性问题

元素.事件 = function(event){  
    event = event || window.event;  
};  
  
元素.事件 = function(e){  
	e = e || event;  
	  
};  

📕onmousemove 该事件将会在鼠标在元素中移动时被触发。

📕clientX 获取鼠标指针的水平坐标
clientY 获取鼠标指针的垂直坐标

(2)事件的冒泡

事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。

事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消冒泡。

  • 可以将事件对象的cancelBubble设置为true,即可取消冒泡
元素.事件 = function(event){  
    event = event || window.event;  
    event.cancelBubble = true;  
};  
(3)事件的委派

将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。

  • 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。
  • 我们希望只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的。因此尝试将其绑定给元素的共同的祖先元素。

📕target

  • event中的target表示的触发事件的对象
(4)事件的绑定

使用【对象.事件=函数】的形式绑定响应函数,只能同时为一个元素的一个事件绑定一个响应函数。

  • 不能绑定多个,如果绑定了多个,则后边会覆盖掉前面的。

📕addEventListener() 为元素绑定响应函数

  • 参数:
    ①事件的字符串,注意不要on。【如btn01.addEventListener(“click”);】
    ②回调函数,当事件触发时该函数会被调用
    ③是否在捕获阶段触发事件,需要一个布尔值,一般都传false

  • 使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数。这样当事件被触发时,响应函数将会按照函数的绑定顺序执行。

  • (这个方法不支持IE8及以下的浏览器)

btn01.addEventListener("click",function(){  
	alert(1);  
},false);  
  
btn01.addEventListener("click",function(){  
	alert(2);  
},false);					  

📕attachEvent() 在IE8中可以用来绑定事件

  • 参数:
    ①事件的字符串,要on。【如btn02.attachEvent(“onclick”);】
    ②回调函数
  • 这个方法也可以同时为一个事件绑定多个处理函数,不同的是它是后绑定先执行,执行顺序和addEventListener()相反。
btn01.attachEvent("onclick",function(){  
alert(1);  
});  
  
btn01.attachEvent("onclick",function(){  
alert(2);  
});	  

//定义一个函数,用来为指定元素绑定响应函数  
/*  
			 * addEventListener()中的this,是绑定事件的对象  
			 * attachEvent()中的this,是window  
			 *  因此需要统一两个方法this  
			 */  
/*  
			 * 参数:  
			 * 	obj 要绑定事件的对象  
			 * 	eventStr 事件的字符串(不要on)  
			 *  callback 回调函数  
			 */  
function bind(obj , eventStr , callback){  
    if(obj.addEventListener){  
        //大部分浏览器兼容的方式  
        obj.addEventListener(eventStr , callback , false);  
    }else{  
        /*  
					 * this是谁由调用方式决定  
					 * callback.call(obj)  
					 */  
        //IE8及以下  
        obj.attachEvent("on"+eventStr , function(){  
            //在匿名函数中调用回调函数  
            callback.call(obj);  
        });  
    }  
}  
(5)事件的传播

关于事件的传播网景公司和微软公司有不同的理解:

  • 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。
  • 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后在向内传播给后代元素。

W3C综合了两个公司的方案,将事件传播分成了三个阶段:

  • 1.捕获阶段
    在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
  • 2.目标阶段
    事件捕获到目标元素,捕获结束开始在目标元素上触发事件
  • 3.冒泡阶段
    事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false

(IE8及以下的浏览器中没有捕获阶段)

5.2.7 练习

(1)图片切换的练习
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>图片切换练习</title>
	</head>
	<body>
		<div id="content">
			<p id="info">当前是第1张图片,一共3张</p>
			<img src="./img/pic1.jpg">
			<br />
			<button type="button" id="prev">上一张</button>
			<button type="button" id="next">下一张</button>
		</div>
	</body>
</html>

<script type="text/javascript">
	// 点击按钮切换图片
	var prev = document.getElementById("prev");
	var next = document.getElementById("next");
	// 获取info
	var info = document.getElementById("info");
	// 注意方法返回的是类数组
	var img = document.getElementsByTagName("img")[0];
	console.log(img)
	// 使用数组保存图片路径
	var imglist = ["./img/pic1.jpg","./img/pic2.jpg","./img/pic3.jpg"]
	// 正在显示图片的索引
	var temp = 0;
	prev.onclick = function(){
			temp--;
			// 实现循环
			if(temp<0)
				temp+=imglist.length;
			console.log(temp);
			// 修改src值
			img.src = imglist[temp];
			console.log(img.src);
			info.innerText = "这是第"+(temp+1)+"张图片,一共"+imglist.length+"张";
	}
	next.onclick = function(){
			temp++;
			if(temp == imglist.length)
				temp-=imglist.length;
			console.log(temp);
			img.src = imglist[temp];
			console.log(img.src);
			info.innerText = "这是第"+(temp+1)+"张图片,一共"+imglist.length+"张";
	}
</script>

<style type="text/css">
	#content{
		width: 37.5rem;
		margin: 3.125rem auto;
		background-color: #f5f5f5;
		text-align: center;
	}
	button{
		width: 6.25rem;
		margin: 0.3125rem;
		padding: 0.3125rem;
		color: #333333;
		border-radius:0.3125rem ;
		background-color: #f2f2f2;
		border:0.0625rem solid #d4d4d4;
	}
</style>

(2)全选练习

🥥按钮描述

  • 全选按钮:点击按钮以后,4个多选框全都被选中。
  • 全不选按钮:点击按钮以后,4个多选框都变成未被选中的状态。
  • 反选按钮:点击按钮以后,选中的变成没选中,没选中的变成选中。
  • 提交按钮:点击按钮以后,将所有的多选框的value属性值弹出。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>全选练习</title>
	</head>
	<body>
		<p>你爱好的运动是?</p>
		<input id="chooseall" type="checkbox" name="chooseall" value="全选" />
		全选
		<br />
		<div id="sportslist">
			<input type="checkbox" name="sports" value="篮球" />
			篮球
			<input type="checkbox" name="sports" value="足球" />
			足球
			<input type="checkbox" name="sports" value="羽毛球" />
			羽毛球
			<input type="checkbox" name="sports" value="乒乓球" />
			乒乓球
		</div>
		<br />
		<button type="button" id="btn01">全选</button>
		<button type="button" id="btn02">全不选</button>
		<button type="button" id="btn03">反选</button>
		<button type="button" id="btn04">提交</button>
	</body>
</html>

<script type="text/javascript">
	var btn01 = document.getElementById("btn01");
	btn01.onclick = function(){
		var sports = document.getElementsByName("sports");
		console.log(sports);
		for(var i = 0;i < sports.length;i++){
		//设置4个多选框变成选中状态
			sports[i].checked = true
		}
		var chooseall = document.getElementById("chooseall");
		chooseall.checked = true;
	}
	
	var btn02 = document.getElementById("btn02");
	btn02.onclick = function(){
		var sports = document.getElementsByName("sports");
		console.log(sports);
		
		for(var i = 0;i < sports.length;i++){
			sports[i].checked = false
		}
		var chooseall = document.getElementById("chooseall");
		chooseall.checked = false;
	}
	
	//在反选时也需要判断四个多选框是否全都选中
	var btn03 = document.getElementById("btn03");
	btn03.onclick = function(){
		var sports = document.getElementsByName("sports");
		var chooseall = document.getElementById("chooseall");
		console.log(sports);
		for(var i = 0;i < sports.length;i++){
			sports[i].checked = !sports[i].checked;
			// 判断是否全选
			// 进入判断前将chooseall状态设置为true
			chooseall.checked = true;
			for(var j = 0;j < sports.length;j++){
				console.log(sports[j].checked)
				// 只要有一个没选上chooseall状态为false
				if(!sports[j].checked){
					chooseall.checked = false;
				}
			}
		}
	}
	
	var btn04 = document.getElementById("btn04");
	btn04.onclick = function(){
		var result =[]
		var sports = document.getElementsByName("sports");
		console.log(sports);
		for(var i = 0;i < sports.length;i++){
			if(sports[i].checked == true)
				result.push(sports[i].value)
		}
		alert(result)
	}
	
	// 为chooseall绑定响应函数
	var chooseall = document.getElementById("chooseall")
	chooseall.onclick = function(){
		var sports = document.getElementsByName("sports");
		for(var i = 0;i < sports.length;i++){
			sports[i].checked = this.checked
		}
		
	}
	
	// 如果多选框全部选中,chooseall选中
	// 如果多选框全部没选中,chooseall不选中
	var sports = document.getElementsByName("sports");
	var chooseall = document.getElementById("chooseall");
	for(var i = 0;i < sports.length; i++){
		sports[i].onclick = function(){
			// 进入判断前将chooseall状态设置为true
			chooseall.checked = true;
			for(var j = 0;j < sports.length;j++){
				console.log(sports[j].checked)
				// 只要有一个没选上chooseall状态为false
				if(!sports[j].checked){
					chooseall.checked = false;
				}
			}
		}
	}
</script>
(3)添加删除记录练习
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>添加删除记录练习</title>
		<script type="text/javascript">
		/**
		 * 删除tr的响应函数
		 */
		function delA(){
			/**
			*点击超链接以后需要删除超链接所在的那行
			*/
			/*点击那个超链接,this便是谁*/
			var tr=this.parentNode.parentNode;
			/*获取要删除的员工的名字*/
			var name=tr.getElementsByTagName("td")[0].innerHTML;
			
			//删除之前弹出提示框 
			/**
			*confirm()用于弹出一个带有确认和取消按钮的提示框
			 * confirm需要一个字符串作为参数,该字符串作为提示文字显示
			 * 用户点击确认返回true,点击取消返回false
			 */					
			var flag=confirm("确认删除"+name+"吗?");
			if(flag==true)	tr.parentNode.removeChild(tr);
			/**
			 * 点击超链接之后 超链接会跳转页面, 但是此时不希望出现默认行为
			 */
			return false;//取消超链接的默认行为
		};
		
		/*
		*添加员工的功能:
		*点击按钮以后,将员工的信息添加到表格中
		*/
	window.onload=function(){
				//为提交按钮绑定单机响应函数
				var addEmpButton=document.getElementById("addEmpButton");
				addEmpButton.onclick=function(){
					
					//获取用户添加的员工信息
					//获取员工的名字
					var name=document.getElementById("empName").value;
					//获取员工的email
					var email=document.getElementById("email").value;
					//获取员工的salary
					var salary=document.getElementById("salary").value;
					
					//将获取到的信息保存到tr和td中
					//创建一个tr
					var tr=document.createElement("tr");
					//创建四个td
					var nameTd=document.createElement("td");
					var emailTd=document.createElement("td");
					var salaryTd=document.createElement("td");
					var aTd=document.createElement("td");
					
					//创建一个a元素
					//超链接a 超链接里面的字aTd 
					var a=document.createElement("a");
					
					//创建文本节点
					var nameText=document.createTextNode(name);
					var emailText=document.createTextNode(email);
					var salaryText=document.createTextNode(salary);
					var delText=document.createTextNode("Delete");
					
					//将文本添加到td中							 				
					nameTd.appendChild(nameText);
					emailTd.appendChild(emailText);
					salaryTd.appendChild(salaryText);	
						
					//向a中添加文本
					a.appendChild(delText);		
					//将a添加到dt中													 						
					aTd.appendChild(a);
					
					//将td添加到tr中
					tr.appendChild(nameTd);
					tr.appendChild(emailTd);
					tr.appendChild(salaryTd);
					tr.appendChild(aTd);
					
					//向a中添加href属性
					a.href="javascript:;";
					//为新添加的a绑定单击响应函数
					a.onclick=delA;
					//将td添加到table中
					
					//获取table
					var employeeTable=document.getElementById("employeeTable");
					//tbody是浏览器自动加的
					//获取employeeTable中的tbody
					var tbody=employeeTable.getElementsByTagName("tbody")[0];
					//将tr添加到table中
					tbody.appendChild(tr);
					
				};
				
				//获取所有的超链接
				var allA=document.getElementsByTagName("a");
				//为每个超链接都绑定一个删除tr的响应函数
				for(var i=0;allA.length;i++){
					allA[i].onclick=delA;
				}			
			};
		</script>
	</head>
	<body>
		<table id="employeeTable">
			<tr>
				<th>Name</th>
				<th>Email</th>
				<th>Salary</th>
				<th>&nbsp;</th>
			</tr>
			<tr>
				<td>Tom</td>
				<td>Tom@Tom.com</td>
				<td>5000</td>
				<td><a href="deleteEmp?id=001">Delete</a></td>
			</tr>
			<tr>
				<td>Jerry</td>
				<td>Jerry@jerry.com</td>
				<td>3000</td>
				<td><a href="deleteEmp?id=002">Delete</a></td>
			</tr>
			<tr>
				<td>Bob</td>
				<td>Bob@Bob.com</td>
				<td>6000</td>
				<td><a href="deleteEmp?id=003">Delete</a></td>
			</tr>
		</table>
		<div id="formDiv">
			<h4>添加新员工</h4>
			<table>
				<tr>
					<td class="word">name:</td>
					<td class="inp">
						<input type="text" name="empName" id="empName"/>
					</td>
				</tr>
				<tr>
					<td class="word">email:</td>
					<td class="inp">
						<input type="text" name="email" id="email"/>
					</td>
				</tr>
				<tr>
					<td class="word">salary:</td>
					<td class="inp">
						<input type="text" name="salary" id="salary"/>
					</td>	
				</tr>
				<tr>
					<td colspan="2" align="center">
						<button id="addEmpButton">Submit</button>
					</td>	
				</tr>
			</table>
		</div>
	</body>
</html>


(4)滚动条练习
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>霸王条款</title>
	</head>
	<body>
		<h3>用户注册</h3>
		<p id="info">
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
			亲爱的用户,这是霸王协议,如果不看到底就不能提交
		</p>
		<input type="checkbox" id="checkbox" disabled="true" />
		我已仔细阅读以上协议
		<br />
		<button type="button" id="btn" disabled="true" >提交</button>
	</body>
</html>

<script type="text/javascript">
	var btn = document.getElementById("btn");
	var info = document.getElementById("info");
	var checkbox = document.getElementById("checkbox");
	// onscroll事件在滚动条滚动时触发
	//为info绑定一个滚动条滚动事件
	info.onscroll = function(){
		// alert(info.scrollHeight - info.scrollTop);
		// alert(info.clientHeight)
		//检查垂直滚动条是否滚动到底
		if((info.scrollHeight - info.scrollTop) == info.clientHeight){			
			// disabled设置元素是否禁用,禁用为true
			//若滚动到底,则使表单项可用
			checkbox.disabled = false;
			btn.disabled = false;
		}
	}
	btn.onclick = function(){
		if(checkbox.checked == true)
			alert("下一步");
		else
			alert("请确认以上协议");
	}
</script>
<style type="text/css">
	#info{
		height: 31.25rem;
		background-color: #F2F2F2;
		overflow: auto;
	}
	button{
		padding: 0.3125rem;
	}
	body{
		text-align: center;
	}
</style>
(5)div跟随鼠标移动
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>使div跟随鼠标移动</title>
	</head>
	<body style="height: 1000px;width: 2000px;">
		<div id="box1">
			
		</div>
	</body>
</html>
<script type="text/javascript">
	//绑定鼠标移动事件,注意这里是给document绑定
	document.onmousemove = function(e){
		//解决兼容性问题
		e=e||window.e;
		
		//获取到鼠标的坐标
		// clientX和clientY获取鼠标当前可见窗口坐标(使用这个一定要先开启绝对定位)
		// pageX和pageY获取鼠标相对于当前页面的坐标
		// console.log(document.documentElement.scrollTop)
		var left = e.pageX;
		var top = e.pageY;
		// 设置div偏移量,注意加上px单位
		box1.style.left = left+"px";
		box1.style.top = top+"px";
	}
</script>
<style type="text/css">
	#box1{
		width: 3.125rem;
		height: 3.125rem;
		border-radius: 1.5625rem;
		background-color:red ;
		position: absolute;
	}
</style>
(6)拖拽练习

拖拽的流程:

  • 当鼠标在被拖拽元素上按下时,开始拖拽。onmousedown
  • 当鼠标移动时被拖拽元素跟随鼠标移动。onmousemove
  • 当鼠标松开时,被拖拽元素固定在当前位置。onmouseup

注意:当拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常。这是浏览器提供的默认行为。如果不希望发生这个行为,则可以通过return false来取消默认行为。(但是对IE8不起作用)
📕setCapture()调用此方法以后,这个元素将会把下一次所有的鼠标按下相关的事件捕获到自身上。
📕releaseCapture()取消捕获。

<!DOCTYPE html>  
    <html>  
    <head>  
    <meta charset="UTF-8">  
        <title></title>  
<style type="text/css">  
  
    #box1{  
width: 100px;  
height: 100px;  
background-color: red;  
position: absolute;  
}  
  
#box2{  
width: 100px;  
height: 100px;  
background-color: yellow;  
position: absolute;  
  
left: 200px;  
top: 200px;  
}  
  
    </style>  
  
<script type="text/javascript">  
  
    window.onload = function(){  
    /*  
				 * 拖拽box1元素  
				 *  - 拖拽的流程  
				 * 		1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown  
				 * 		2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove  
				 * 		3.当鼠标松开时,被拖拽元素固定在当前位置	onmouseup  
				 */  
  
    //获取box1  
    var box1 = document.getElementById("box1");  
    var box2 = document.getElementById("box2");  
    var img1 = document.getElementById("img1");  
  
    //开启box1的拖拽  
    drag(box1);  
    //开启box2的  
    drag(box2);  
  
    drag(img1);  
  
};  
  
/*  
			 * 提取一个专门用来设置拖拽的函数  
			 * 参数:开启拖拽的元素  
			 */  
function drag(obj){  
    //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown  
    obj.onmousedown = function(event){  
  
        //设置box1捕获所有鼠标按下的事件  
        /*  
					 * setCapture()  
					 * 	- 只有IE支持,但是在火狐中调用时不会报错,  
					 * 		而如果使用chrome调用,会报错  
					 */  
        /*if(box1.setCapture){  
						box1.setCapture();  
					}*/  
		//上述可以写为以下
        obj.setCapture && obj.setCapture();  
  
  
        event = event || window.event;  
        //div的偏移量 鼠标.clentX - 元素.offsetLeft  
        //div的偏移量 鼠标.clentY - 元素.offsetTop  
        var ol = event.clientX - obj.offsetLeft;  
        var ot = event.clientY - obj.offsetTop;  
  
  
        //为document绑定一个onmousemove事件  
        document.onmousemove = function(event){  
            event = event || window.event;  
            //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove  
            //获取鼠标的坐标  
            var left = event.clientX - ol;  
            var top = event.clientY - ot;  
  
            //修改box1的位置  
            obj.style.left = left+"px";  
            obj.style.top = top+"px";  
  
        };  
  
        //为document绑定一个鼠标松开事件  
        document.onmouseup = function(){  
            //当鼠标松开时,被拖拽元素固定在当前位置	onmouseup  
            //取消document的onmousemove事件  
            document.onmousemove = null;  
            //取消document的onmouseup事件  
            document.onmouseup = null;  
            //当鼠标松开时,取消对事件的捕获  
            obj.releaseCapture && obj.releaseCapture();  
        };  
  
 /*  
* 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,  
* 	此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,  
* 	如果不希望发生这个行为,则可以通过return false来取消默认行为  
*   
* 但是这招对IE8不起作用  
* IE8处理见上方
*/  
        return false;  
    };  
}  
  
  
</script>  
</head>  
<body>  
  
    我是一段文字  
  
<div id="box1"></div>  
  
<div id="box2"></div>  
  
  //注意要开启绝对定位
<img src="img/an.jpg" id="img1" style="position: absolute;"/>  
    </body>  
</html>  
(7)滚轮事件练习

实现功能:当鼠标滚轮向下滚动时,box1变长;当滚轮向上滚动时,box1变短。

📕onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发。(但是火狐不支持该属性)
📕在火狐中需要使用 DOMMouseScroll 来绑定滚动事件。注意该事件需要通过addEventListener()函数来绑定。

📕**bind()**方法主要就是将函数绑定到某个对象。bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值。

📕event.wheelDelta 可以获取鼠标滚轮滚动的方向【向上滚 120 向下滚 -120】
📕在火狐中使用event.detail来获取滚动的方向【向上滚 -3 向下滚 3 】

📕需要使用event来取消默认行为event.preventDefault()。(使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false )。(IE8不支持)。

<!DOCTYPE html>  
    <html>  
    <head>  
    <meta charset="UTF-8">  
        <title></title>  
<style type="text/css">    
    #box1{  
width: 100px;  
height: 100px;  
background-color: red;  
}    
    </style>
      
<script type="text/javascript">    
    window.onload = function(){   
    //获取id为box1的div  
    var box1 = document.getElementById("box1");  
  
    //为box1绑定一个鼠标滚轮滚动的事件  
    /*  
				 * onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,  
				 * 	但是火狐不支持该属性  				 
				 * 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件  
				 * 	注意该事件需要通过addEventListener()函数来绑定  
				 */  
    box1.onmousewheel = function(event){  
        event = event || window.event;   
  
        //event.wheelDelta 可以获取鼠标滚轮滚动的方向  【向上滚 120   向下滚 -120】  【wheelDelta这个值我们不看大小,只看正负  】
        //alert(event.wheelDelta);  
  
        //wheelDelta这个属性火狐中不支持,在火狐中使用event.detail来获取滚动的方向【向上滚 -3  向下滚 3 】  
        //alert(event.detail);  
  
  
        /*  
					 * 当鼠标滚轮向下滚动时,box1变长  
					 * 	当滚轮向上滚动时,box1变短  
					 */  
        //判断鼠标滚轮滚动的方向(浏览器兼容考虑)  
        if(event.wheelDelta > 0 || event.detail < 0){  
            //向上滚,box1变短(每次变化10)
            box1.style.height = box1.clientHeight - 10 + "px";  
  
        }else{  
            //向下滚,box1变长 
            box1.style.height = box1.clientHeight + 10 + "px";  
        }  
  
        /*  
					 * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false  
					 * 需要使用event来取消默认行为event.preventDefault();  
					 * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错  
					 */  
        event.preventDefault && event.preventDefault();  
  
  
        /* 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,如果不希望发生,则可以取消默认行为 */  
        return false;  
    };  
  
    //为火狐绑定滚轮事件  
        bind(box1,"DOMMouseScroll",box1.onmousewheel);      
};  
  
  
function bind(obj , eventStr , callback){  
    if(obj.addEventListener){  
        //大部分浏览器兼容的方式  
        obj.addEventListener(eventStr , callback , false);  
    }else{  
        /*  
					 * this是谁由调用方式决定  
					 * callback.call(obj)  
					 */  
        //IE8及以下  
        obj.attachEvent("on"+eventStr , function(){  
            //在匿名函数中调用回调函数  
            callback.call(obj);  
        });  
    }  
}    
</script>  
</head>  
<body style="height: 2000px;">  
  
    <div id="box1"></div>  
  
</body>  
</html>    
(8)键盘事件练习

📕onkeydown按键被按下

  • 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发
  • 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。
    📕onkeyup按键被松开

❗键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document。

📕keyCode获取按键的编码,可以判断哪个按键被按下。
除了keyCode,事件对象中还提供了几个属性:

  • altKey
  • ctrlKey
  • shiftKey
    这个三个用来判断alt ctrl 和 shift是否被按下
    如果按下则返回true,否则返回false。
//console.log(event.keyCode);  
  
//判断y和ctrl是否同时被按下  
if(event.keyCode === 89 && event.ctrlKey){  
	console.log("ctrl和y都被按下了");  
}  
input.onkeydown = function(event) {  
    event = event || window.event;  
    //数字的keyCode: 48 - 57  
    //使文本框中不能输入数字  
    if(event.keyCode >= 48 && event.keyCode <= 57) {  
        //在文本框中输入内容,属于onkeydown的默认行为  
        //如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中  
        return false;  
    }  
};  
  
div移动练习

使div可根据不同的方向键向不同的方向移动,如按左键向左移,按右键向右移…(37左,38上,39右,40下)。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>方向键控制div</title>
	</head>
	<body>
		<div id="box1"></div>
	</body>
</html>
<script type="text/javascript">
	window.onload=function(){
			// 使div更具不同方向键向不同方向移动
	var box1 = document.getElementById("box1")
	document.onkeydown = function(e){
		e = e || event;
		//表示移动的速度
		var speed = 20;
		//  按下shift后速度加快
		if(e.shiftKey)
			speed = 50;
			//也可以用switch语句
		if(e.keyCode == 38){
			box1.style.top = (box1.offsetTop - speed) + "px"
		}
		else if(e.keyCode == 40){
			box1.style.top = (box1.offsetTop + speed) + "px"
		}
		else if(e.keyCode == 37){
			//向左:left值减小
			box1.style.left = (box1.offsetLeft - speed) + "px"
		}
		else if(e.keyCode == 39){
			box1.style.left = (box1.offsetLeft + speed) + "px"
		}
	}
	};
	
</script>
<style type="text/css">
	#box1{
		width: 6.25rem;
		height: 6.25rem;
		background-color: red;
		position: absolute;
	}
</style>

5.3 BOM

BOM浏览器对象模型(browser object model):

  • BOM可以使我们通过JS来操作浏览器。
  • 在BOM中为我们提供了一组对象,用来完成对浏览器的操作:

🥥BOM对象

  • Window代表的是整个浏览器的窗口,同时window也是网页中的全局对象。
  • Navigator代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器。
  • Location代表当前浏览器的地址栏信息。通过Location可以获取地址栏信息,或者操作浏览器跳转页面
  • History代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录。由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,且该操作只在当次访问时有效。
  • Screen代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息

🐟这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用。如window.navigator或navigator。

5.3.1 Navigator

由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了。
🐟一般我们只会使用userAgent来判断浏览器的信息,

  • userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent。
  • 用法:navigator.userAgent

火狐的userAgent:
Mozilla5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko20100101 Firefox50.0


Chrome的userAgent
Mozilla5.0 (Windows NT 6.1; Win64; x64) AppleWebKit537.36 (KHTML, like Gecko) Chrome52.0.2743.82 Safari537.36


IE8
Mozilla4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)


IE9
Mozilla5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)


IE10
Mozilla5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)


IE11
Mozilla5.0 (Windows NT 6.1; WOW64; Trident7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
❗在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了
【则通过一些浏览器中特有的对象判断】

  • ActiveXObject

//判断浏览器
alert(navigator.appName);  
  
var ua = navigator.userAgent;    
console.log(ua);  
  
if(/firefox/i.test(ua)){  
alert("你是火狐!!!");  
}else if(/chrome/i.test(ua)){  
alert("你是Chrome");  
}else if(/msie/i.test(ua)){  
alert("你是IE浏览器~~~");  
}
//通过一些浏览器中特有的对象判断
else if("ActiveXObject" in window){  
alert("你是IE11,枪毙了你~~~");  
}  

5.3.2 History

History对象可以用来操作浏览器向前或向后翻页。

🥥对象属性:
length属性,可以获取到当成访问的链接数量。(即看了几个页面)

🥥对象方法:
back() 可以用来回退到上一个页面,作用和浏览器的回退按钮一样。
forward() 可以跳转下一个页面,作用和浏览器的前进按钮一样。
go() 可以用来跳转到指定的页面。

  • 它需要一个整数作为参数:
    ①1:表示向前跳转一个页面 相当于forward()
    ②2:表示向前跳转两个页面
    ③-1:表示向后跳转一个页面
    ④-2:表示向后跳转两个页面

5.3.3 Location

Location对象中封装了浏览器的地址栏的信息。

//如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)

alert(location);
//如果直接将location属性修改为一个完整的路径或相对路径,则我们页面会自动跳转到该路径,并且会生成相应的历史记录。

location = "http:www.baidu.com";
location = "01.BOM.html";

🥥对象方法:
assign() 用来跳转到其他的页面,作用和直接修改location一样。
**reload()**用于重新加载当前页面,作用和刷新按钮一样。

  • 如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面
location.reload(true);

replace()
可以使用一个新的页面替换当前页面,调用完毕也会跳转页面。不会生成历史记录,不能使用回退按钮回退。

5.3.4 Window

(1)对象方法

JS的程序的执行速度是非常快的,如果希望一段程序可以每间隔一段时间执行一次,可以使用定时调用。

关于定时调用

📕setInterval() 定时调用。可以将一个函数,每隔一段时间执行一次。

  • 参数:
    ①回调函数,该函数会每隔一段时间被调用一次;
    ②每次调用间隔的时间,单位是毫秒。7
  • 返回值:返回一个Number类型的数据,这个数字用来作为定时器的唯一标识。
//1000毫秒调用该函数
var num=1;
setInterval(function){
	count.innerHTML=num++;
},1000;

📕clearInterval() 可以用来关闭一个定时器。

  • 方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器
  • clearInterval()可以接收任意参数,如果参数是一个有效的定时器的标识,则停止对应的定时器;如果参数不是一个有效的标识,则什么也不做。
if(num==11){
	clearInterval(timer);
}
关于延时调用

📕setTimeout 延时调用。即一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次。

🐟延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次。
🐟延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择。

var timer = setTimeout(function(){
	console.log(num++);
},3000);

📕使用**clearTimeout()**来关闭一个延时调用

clearTimeout(timer);

5.3.5 类的操作

🐟通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面。

  • 这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时,也不太方便。希望一行代码可以同时修改多个样式。

🐟我们可以通过修改元素的class属性来间接的修改样式。

box.className += " b2";	//注意有空格,添加class属性  
  • 这样只需修改一次,即可同时修改多个样式。
  • 此时浏览器只需要重新渲染页面一次,性能比较好,且这种方式可以使表现和行为进一步的分离。

注意:可以将以下代码加入tools.js中(会常用)。

//定义一个函数,用来向一个元素中添加指定的class属性值  
/*  
 * 参数:  
 * 	obj 要添加class属性的元素  
 *  cn 要添加的class值  
 * 	  
 */  
function addClass(obj, cn) {  
	//添加之前先检查obj中是否有cn
	if (!hasClass(obj, cn)) {  
		obj.className += " " + cn;  
	}  
}  

/*  
 * 判断一个元素中是否含有指定的class属性值  
 * 	如果有该class,则返回true,没有则返回false  
 * 用正则表达式判断  \b单词边界
 */  
function hasClass(obj, cn) {  
	//通过构造函数设置正则表达式进行判断
	var reg = new RegExp("\\b" + cn + "\\b");  
	return reg.test(obj.className);  
}  

/*  
 * 删除一个元素中的指定的class属性  
 */  
function removeClass(obj, cn) {  
	//创建一个正则表达式  
	var reg = new RegExp("\\b" + cn + "\\b");  
	//删除class,即替换为空串 
	obj.className = obj.className.replace(reg, "");  
}  

/*  
 * toggleClass可以用来切换一个类  
 * 	如果元素中具有该类,则删除  
 * 	如果元素中没有该类,则添加  
 */  
function toggleClass(obj , cn){	  
	//判断obj中是否含有cn  
	if(hasClass(obj , cn)){  
		//有,则删除  
		removeClass(obj , cn);  
	}else{  
		//没有,则添加  
		addClass(obj , cn);  
	}  
}  

5.3.6 JSON

JSON:JavaScript Object Notation,即JS对象表示法。

JS中的对象只有JS自己认识,其他的语言都不认识。
🐟JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
🐟JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号。其他的和JS语法一致。

(1)JSON分类

JSON分类
①对象{}
②数组[]

JSON中允许的值
①字符串
②数值
③布尔值
④null
⑤对象
⑥数组

🦖举例:

var arr = '[1,2,3,"hello",true]';  
			  
var obj2 = '{"arr":[1,2,3]}';  
  
var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]';  
(2)JSON格式
  1. 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。
  2. 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。
  3. 字符串必须使用双引号表示,不能使用单引号。
  4. 对象的键名必须放在双引号里面。
  5. 数组或对象最后一个成员的后面,不能加逗号。
(3)JSON工具类

在JS中,提供了一个工具类,就叫JSON。这个对象可以将JSON字符串和JS对象互相转换。

JSON->JS对象
📕JSON.parse() 可以将以JSON字符串转换为js对象。

  • 需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回。
//JSON字符串
var arr = '[1,2,3,"hello",true]';  

var o = JSON.parse(arr);

JS对象->JSON
📕JSON.stringify() 可以将一个JS对象转换为JSON字符串。

  • 需要一个js对象作为参数,会返回一个JSON字符串。
//JS对象
var obj3 = {name:"猪八戒" , age:28 , gender:"男"};

var str = JSON.stringify(obj3);
console.log(str);

注意:JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错。

(4)补充
eval()

eval():这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回。

  • 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块。
  • 如果不希望将其当成代码块解析,则需要在字符串前后各加一个()。
var str = '{"name":"孙悟空","age":18,"gender":"男"}';  
var obj = eval("("+str+")");  

eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,但是在开发中尽量不要使用,因为它的执行性能比较差且具有安全隐患。

❗如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理。

//引入一个外部的js文件来处理
<script type="text/javascript" src="js/json2.js"></script>

5.3.7 练习

(1)图片自动切换的练习

功能描述:使图片可以自动切换。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>自动切换图片</title>
	</head>
	<body>
		<div id="content">
			<img id="img" src="img/pic1.jpg" >
			<br />
			<button type="button" id="btn01">开始</button>
			<button type="button" id="btn02">停止</button>
		</div>
	</body>
</html>
<script type="text/javascript">
	//获取img标签
	var img =document.getElementById("img")
	// 创建一个数组保存图片路径
	var imgArr = ["img/pic1.jpg","img/pic2.jpg","img/pic3.jpg"]
	// 保存图片索引
	var index = 0;
	// 保存定时器标识
	var timer;
	//为btn01绑定一个单击响应函数
	var btn01 = document.getElementById("btn01");
	btn01.onclick = function(){
		// 在开启定时器之前,需要将荡秋千元素上的其他定时器关闭
		//(如果不设置此,则每点击一次按钮就会开启一个定时器,会导致图片切换速度越来越快)
		clearInterval(timer);
		
		//开启一个定时器,来自动切换图片
		timer = setInterval(function(){
			//使索引自增
			index++;
			
			//判断索引是否超过最大索引写法一
			if(index >= imgArr.length)
				index =0;
			//判断索引是否超过最大索引写法二
			//index%=imgArr.length;

			//修改img1的src属性
			img.src = imgArr[index];
			
		},1000)
		console.log(timer)
	}
	//为btn02绑定一个单击响应函数
	var btn02 = document.getElementById("btn02");
	btn02.onclick = function(){
		//点击按钮以后,停止图片的自动切换,即关闭定时器
		clearInterval(timer);
	}
</script>

<style type="text/css">
	#content{
		width: 37.5rem;
		margin: 3.125rem auto;
		background-color: #f5f5f5;
		text-align: center;
	}
	button{
		width: 6.25rem;
		margin: 0.3125rem;
		padding: 0.3125rem;
		color: #333333;
		border-radius:0.3125rem ;
		background-color: #f2f2f2;
		border:0.0625rem solid #d4d4d4;
	}
</style>
(2)div移动练习修改

解决5.2.7(8)中div移动初始时的卡顿问题。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>方向键控制div</title>
</head>

<body>
    <div id="box1"></div>
</body>

</html>
<script type="text/javascript">
    window.onload = function () {
        //表示移动的速度
        var speed = 20;

        //表示方向。通过修改dir影响移动的方向
        var dir = 0;

        //开启一个定时器,来控制div的移动
        setInterval(function () {
            switch (dir) {
                //向左
                case 37:
                    box1.style.left = (box1.offsetLeft - speed) + "px";
                    break;
                //向右
                case 39:
                    box1.style.left = (box1.offsetLeft + speed) + "px";
                    break;
                //向上
                case 38:
                    box1.style.top = (box1.offsetTop - speed) + "px";
                    break;
                //向下
                case 40:
                    box1.style.top = (box1.offsetTop + speed) + "px";
                    break;
            }

        }, 30);


        //为document绑定一个按键按下的事件
        document.onkeydown = function (event) {
            event = event || window.event;

            //  按下shift后速度加快
            if (event.shiftKey){ 
                speed = 50;
            }else{
                speed=10;
            }
               
            //使dir等于按键的值
            dir = event.keyCode;
        }

        //当按键松开时,div不再移动
        document.onkeyup=function(){
            dir=0;
        }
    };

</script>
<style type="text/css">
    #box1 {
        width: 6.25rem;
        height: 6.25rem;
        background-color: red;
        position: absolute;
    }
</style>
(3)div随按钮移动练习

📕parseInt() 把字符串中的合法数字取出来。

ps:该部分将功能js单独写为tools.js

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
		*{
			margin: 0;
			padding: 0;
		}
		#box1{
			width: 100px;
			height: 100px;
			background-color: #6495ED;
			position: absolute;
			left:0;
		}
		#box2{
			width: 100px;
			height: 100px;
			background-color: #FFFF00;
			position: absolute;
			left:0;
			top:200px;
		}
		#line{
			width: 0;
			height: 1000px;
			border-left:1px black solid;
			position: absolute;
			left:800px;
			top: 0;
		}
		</style>
		<script src="./js/tools.js" type="text/javascript"></script>
		<script type="text/javascript" >
			/**
			 * 所有正在执行的定时器都在这个变量中保存
			 */
			//var timer;
			window.onload=function(){
				var box1=document.getElementById("box1");
				var box2=document.getElementById("box2");
				var btn01=document.getElementById("btn01");	//点击按钮以后box1向右移动
				var btn02=document.getElementById("btn02");//点击按钮以后box1向左移动
				var btn03=document.getElementById("btn03");//box1你停下来
				var btn04=document.getElementById("btn04");//点击按钮以后box2向右移动
				var btn05=document.getElementById("btn05");//测试按钮
				var btn06=document.getElementById("btn06");//box2你停下来
				btn01.onclick=function(){//点击按钮以后box1向右移动
					move(box1,"left",800,10);
				}
				btn02.onclick=function(){//点击按钮以后box1向左移动
					move(box1,"left",0,10);
					
				}
				btn04.onclick=function(){//点击按钮以后box2向右移动
					 move(box2,"left",800,10);
				}
				btn05.onclick=function(){//测试按钮
					// move(box2,"width",800,10);
					// move(box2,"top",800,10);
					// move(box2,"height",800,10);
					 move(box2,"height",800,10,function(){
						 move(box2,"width",800,10,function(){
							 //这里我就不套娃了
						 });
					 });
				}
				//box1你停下来
				btn03.onclick=function(){
					stop(box1);
				}
				//box2你停下来
				btn06.onclick=function(){
					stop(box2);
				}
				
				
			}
			
		</script>
	</head>
	<body>
		<button id="btn01">点击按钮以后box1向右移动</button>
		<button id="btn02">点击按钮以后box1向左移动</button>
		<button id="btn04">点击按钮以后box2向右移动</button>
		<button id="btn05">测试按钮</button>
		<br />		<br />	
		<button id="btn03">box1你停下来</button>
		<button id="btn06">box2你停下来</button>
		<br />		<br />	
		<div id="box1"></div>
		<div id="box2"></div>
		<div id="line" ></div>
	
		
	</body>
</html>

tools.js

/**
			 * 创建一个可以执行简单动画的函数
			 * obj:执行对象
			 * attr:要执行动画的样式
			 * speed:移动速度(有正负)正数向右 负数向左
			 * target:执行动画的目标位置
			 * callback:回调函数 在动画执行完毕之后执行
			 */
			function move(obj,attr,target,speed,callback){
				//开启一个定时器 执行动画效果
				clearInterval(obj.timer);
				//判断速度的正负 如果从0到800 移动 speed大于0 反之小于0
				var current=parseInt(getStyle(obj,attr));//元素目前的位置
				if(current>target) {
					speed=-speed;
				}
				obj.timer=setInterval(function(){
				//	box1.style.left=box1.offsetLeft-10+"px";
					var oldValue=parseInt(getStyle(obj,attr));
					var newValue=oldValue+speed;
					//停止条件
					if((speed<0&&newValue<=target)||(speed>0&&newValue>=target)){
						newValue=target;	
					}				
					obj.style[attr]=newValue+"px";
					if(newValue==target){
						clearInterval(obj.timer);
						//动画执行完毕 调用回调函数
						callback &&callback();
					}
				},30);
			}
			/**
			 * 你停下来函数
			 */
			function stop(obj){
				clearInterval(obj.timer);
			}
			/**
			 * 定义一个函数用来获取指定元素当前的样式
			 */
			function getStyle(obj,name){
				if(window.getComputedStyle){
					return getComputedStyle(obj,null)[name];// //正常浏览器的方式	// return getComputedStyle(obj,null)[name];
				}else{
					return obj.currentStyle[name];	// //IE8的方式	// return obj.currentStyle[name];
				}
			}

(4)轮播图练习

注意同样需要引入(3)中的tools.js文件。

<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title></title>
	<style type="text/css">
		* {
			margin: 0;
			padding: 0;
		}

		#outer {
			width: 520px;
			height: 333px;
			margin: 50px auto;
			background-color: greenyellow;
			padding: 10px 0;
			/*子绝父相*/
			position: relative;
			/* 裁剪溢出的内容*/
			overflow: hidden;
		}

		#imgList {
			/*去除项目符号*/
			list-style: none;
			/*设置ul宽度*/
			width: 2100px;
			position: absolute;
			/* 每向左移动520 就会显示下一张 */
			left: 0px;
		}

		#imgList li {
			/* 设置浮动 */
			float: left;
			margin: 0 10px;

		}

		/* 设置导航按钮 */
		#navDiv {
			position: absolute;
			/*开启绝对定位*/
			bottom: 15px;
			/* 设置位置 */
		}

		#navDiv a {
			float: left;
			width: 15px;
			height: 15px;
			background-color: #FF0000;
			margin: 0 5px;
			/*设置左右外边距*/
			opacity: 0.5;
			/*设置透明*/
			fill-opacity: alpha(opacity=50);
			/*兼容IE8透明*/
		}

		#navDiv a:hover {
			background-color: black;
		}
	</style>
	<!-- 引入工具 -->
	<script type="text/javascript" src="./js/tools.js"></script>
	<script type="text/javascript">
		window.onload = function () {
			var imgList = document.getElementById("imgList");
			var imgArr = document.getElementsByTagName("img");
			//设置imgList宽度
			imgList.style.width = 520 * imgArr.length + "px";
			//设置导航按钮居中
			var navDiv = document.getElementById("navDiv");
			var outer = document.getElementById("outer");
			navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth) / 2 + "px";
			var allA = document.getElementsByTagName("a");
			//默认显示图片的索引
			var index = 0;
			/**
			 * 设置默认选中效果
			 */
			allA[index].style.backgroundColor = "black";
			/**
			 * 点击超链接切换到指定的图片,即点击第一个超链接显示第一个图片
			 */
			for (var i = 0; i < allA.length; i++) {
				allA[i].num = i;
				//单击响应函数
				allA[i].onclick = function () {
					//关闭自动切换的定时器
					clearInterval(timer);
					index = this.num;
					//imgList.style.left=-index*520+"px";//切换图片
					allA[index].style.backgroundColor = "black";
					//设置选中的a
					setA();
					//使用move函数切换对象
					move(imgList, "left", -520 * index, 20, function () {
						//动画执行完毕后,开启自动切换
						autoChange();
					});
				}
			}

			/**
			 * 自动切换
			 */
			autoChange();


			//创建一个方法设置选中a(即导航方点)
			function setA() {
				//判断当前索引是否是最后一张
				if (index >= imgArr.length - 1) {
					index = 0;
					//此时显示的是最后一张图片,而最后一张图片和第一张是一模一样的
					//通过CSS将最后一张换成第一张
					imgList.style.left = 0;

				}
				//遍历所有的a 并将他们的背景颜色设置为红色
				for (var i = 0; i < allA.length; i++) {
					allA[i].style.backgroundColor = "";
				}
				//将选中的a设置为黑色
				allA[index].style.backgroundColor = "black";
			}

			/**
			 * 创建一个函数用来开启自动切换
			 */
			//定义一个自动切换的定时器的标识
			var timer;
			function autoChange() {
				//开启一个定时器 用来定时切换图片
				timer = setInterval(function () {
					index++;
					//判断index的值
					index = index % imgArr.length;
					//执行动画,切换图片
					move(imgList, "left", -520 * index, 20, function () {
						//修改导航点
						setA();
					});
				}, 3000);
			}
		}
	</script>
</head>

<body>
	<!-- 创建一个大的div作为大的容器 -->
	<div id="outer">
		<!-- 创建一个ul用于放置图片 -->
		<ul id="imgList">
			<li>
				<img id="img1" src="./img/1.jpg" width="500px" height="333px" />
			</li>
			<li>
				<img id="img2" src="./img/2.jpg" width="500px" height="333px" />
			</li>
			<li>
				<img id="img3" src="./img/3.jpg" width="500px" height="333px" />
			</li>
			<li>
				<img id="img4" src="./img/4.jpg" width="500px" height="333px" />
			</li>
			<li>
				<img id="img1" src="./img/5.jpg" width="500px" height="333px" />
			</li>
			<!-- 为了循环播放 -->
			<li>
				<img id="img1" src="./img/1.jpg" width="500px" height="333px" />
			</li>
		</ul>
		<!-- 创建导航按钮 -->
		<div id="navDiv">
			<a href="javascript:;"></a>
			<a href="javascript:;"></a>
			<a href="javascript:;"></a>
			<a href="javascript:;"></a>
			<a href="javascript:;"></a>
		</div>
	</div>
</body>
</html>
(5)二级菜单练习

分为html、css、js三个文件。

①index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>二级菜单</title>
        <link rel="stylesheet" href="./css/second.css">
        <style>
            *{
                padding: 0px;
                margin: 0px;
                list-style-type: none;
            }
            a,img{
                border: 0px;
                text-decoration: none;
            }
            body{
                font: 12px/180%;
            }
        </style>
        <script src="./js/tools.js"></script>
        <script>
            window.onload = function(){
                /* 
                    我们的每一个菜单都是一个div
                        当div具有collapsed这个类时,div就是折叠状态
                        当div没有这个类时,div就是展开状态
                        
                    点击菜单,切换菜单的显示状态
                 */

                 //获取所有的class为menuSpan的元素
                var menuSpan = document.querySelectorAll(".menuSpan");
                console.log(menuSpan.length);    
                
                //定义一个变量,保存当前打开的菜单
                var openDiv = menuSpan[0].parentNode;

                //绑定span单击响应函数
                for(var i=0; i<menuSpan.length; i++){
                    menuSpan[i].onclick = function(){
                        //this代表当前点击的span
                        //获取当前span的父元素
                        var  parentDiv = this.parentNode;

                        //调用函数,切换菜单的显示状态
                        toggleMenu(parentDiv);

                        //判断openDiv和parentDiv是否相同。不一样才加
                        if(openDiv != parentDiv && !hasClass(openDiv, "collapsed")){
                            //打开菜单以后,应该关闭之前打开的菜单
                            //为了可以统一处理动画过渡效果,我们希望将addClass改为toggleClass;
                            // addClass(openDiv, "collapsed");
                            // 此处toggleClass()不需要有移除功能(只需要加入的功能),即if中第二个条件判断
                            // toggleClass(openDiv, "collapsed");
                            //上五行可以写为如下一行代码
                            //调用函数,切换菜单的显示状态
                            toggleMenu(openDiv);
                        }
                        //修改openDiv 为当前打开的菜单
                        openDiv = parentDiv;

                    };
                }

                //切换菜单的折叠和显示状态
                function toggleMenu(obj){
                    //在切换类之前,获取元素的高度
                    var begin = obj.offsetHeight;

                        //切换parentDiv的显示
                        toggleClass(obj, "collapsed");

                        //在切换类之后,获取一个高度
                        var end = obj.offsetHeight;
                        // console.log(begin+ " "+end);
                        // 动画效果就是将高度从begin向end过渡
                        // 将元素的高度重置为begin(设置一个内联样式)
                        obj.style.height = begin + "px"
                        // console.log(parentDiv.style.height);
                        // 执行动画,从begin向end过渡
                        move(obj, "height", end, 10, function(){
                            // 动画执行完毕,内联样式已经没有存在的意义,需删除
                            //当回调函数执行时,动画即执行完
                            obj.style.height = "";
                        });
                }
            };

            
        </script>
    </head>
    <body>
        <div id="my_menu" class="sdmenu">
			<div>
				<span class="menuSpan">在线工具</span>
				<a href="#">图像优化</a>
				<a href="#">收藏夹图标生成器</a>
				<a href="#">邮件</a>
				<a href="#">htaccess密码</a>
				<a href="#">梯度图像</a>
				<a href="#">按钮生成器</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">支持我们</span>
				<a href="#">推荐我们</a>
				<a href="#">链接我们</a>
				<a href="#">网络资源</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">合作伙伴</span>
				<a href="#">JavaScript工具包</a>
				<a href="#">CSS驱动</a>
				<a href="#">CodingForums</a>
				<a href="#">CSS例子</a>
			</div>
			<div class="collapsed">
				<span class="menuSpan">测试电流</span>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
				<a href="#">Current or not</a>
			</div>
		</div>
    </body>
</html>

②second.css

@charset "utf-8";

/* sdmenu */

div.sdmenu {
	width: 150px;
	margin: 100px auto;
	font-family: Arial, sans-serif;
	font-size: 12px;
    padding-bottom: 10px;
    background-color: darkblue;
    /* background: url(bottom.gif) no-repeat right bottom; */
    color: #fff;
}

div.sdmenu div {
    background: url(title.gif) repeat-x;
    overflow: hidden;
}

div.sdmenu div:first-child{
    background: url(toptitle.gif) no-repeat;
}

div.sdmenu div.collapsed{
    height: 25px;
}

div.sdmenu div span{
    display: block;
    height: 15px;
    overflow: hidden;
    padding: 5px 25px;
    font-weight: bold;
    color: white;
    background: url(expanded.gif) no-repeat 10px center;
    cursor: pointer;
    border-bottom: 1px solid #ddd;
}

div.sdmenu div.collapsed span{
    background-image: url(collapsed.gif);
}

div.sdmenu div a{
    padding: 5px 10px;
    background: #eee;
    display: block;
    border-bottom: 1px solid #ddd;
    color: #066;
}

div.sdmenu div a.current{
    background: #ccc;
}

div.sdmenu div a:hover{
    background: rgb(167, 197, 235) url(linkarrow.gif) no-repeat right center;
    color: #fff;
    text-decoration: none;
}

③tools.js

//移动效果————move()方法
/**
             * 创建一个可以执行简单动画的函数
             * obj:执行对象
             * attr:要执行动画的样式
             * speed:移动速度(有正负)正数向右 负数向左
             * target:执行动画的目标位置
             * callback:回调函数 在动画执行完毕之后执行
             */
function move(obj, attr, target, speed, callback) {
    //开启一个定时器 执行动画效果
    clearInterval(obj.timer);
    //判断速度的正负 如果从0到800 移动 speed大于0 反之小于0
    var current = parseInt(getStyle(obj, attr));//元素目前的位置
    if (current > target) {
        speed = -speed;
    }
    obj.timer = setInterval(function () {
        //	box1.style.left=box1.offsetLeft-10+"px";
        var oldValue = parseInt(getStyle(obj, attr));
        var newValue = oldValue + speed;
        //停止条件
        if ((speed < 0 && newValue <= target) || (speed > 0 && newValue >= target)) {
            newValue = target;
        }
        obj.style[attr] = newValue + "px";
        if (newValue == target) {
            clearInterval(obj.timer);
            //动画执行完毕 调用回调函数
            callback && callback();
        }
    }, 30);
}
/**
 * 你停下来函数
 */
function stop(obj) {
    clearInterval(obj.timer);
}


//版本适配后的获取元素属性的方法_getStyle()
/**
 * 定义一个函数用来获取指定元素当前的样式
 */
function getStyle(obj, name) {
    if (window.getComputedStyle) {
        return getComputedStyle(obj, null)[name];// //正常浏览器的方式	// return getComputedStyle(obj,null)[name];
    } else {
        return obj.currentStyle[name];	// //IE8的方式	// return obj.currentStyle[name];
    }
}


//删除、添加、替换、判断类是否存在  的方法(removeClass、addClass、toggleClass、hasClass)
//定义一个函数,用来向一个元素中添加指定的class属性值  
/*  
 * 参数:  
 * 	obj 要添加class属性的元素  
 *  cn 要添加的class值  
 * 	  
 */
function addClass(obj, cn) {
    //添加之前先检查obj中是否有cn
    if (!hasClass(obj, cn)) {
        obj.className += " " + cn;
    }
}

/*  
 * 判断一个元素中是否含有指定的class属性值  
 * 	如果有该class,则返回true,没有则返回false  
 * 用正则表达式判断  \b单词边界
 */
function hasClass(obj, cn) {
    //通过构造函数设置正则表达式进行判断
    var reg = new RegExp("\\b" + cn + "\\b");
    return reg.test(obj.className);
}

/*  
 * 删除一个元素中的指定的class属性  
 */
function removeClass(obj, cn) {
    //创建一个正则表达式  
    var reg = new RegExp("\\b" + cn + "\\b");
    //删除class,即替换为空串 
    obj.className = obj.className.replace(reg, "");
}

/*  
 * toggleClass可以用来切换一个类  
 * 	如果元素中具有该类,则删除  
 * 	如果元素中没有该类,则添加  
 */
function toggleClass(obj, cn) {
    //判断obj中是否含有cn  
    if (hasClass(obj, cn)) {
        //有,则删除  
        removeClass(obj, cn);
    } else {
        //没有,则添加  
        addClass(obj, cn);
    }
}  
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值