伪元素选择器
二、任务背景
伪元素选择器通过选择元素的某个部分,对元素的特定部分单独设置样式。伪元素是某个元素的子元素,是逻辑上存在的虚拟元素,但是实际并不存在与DOM树中。
三、任务内容
一个选择器只能使用一个伪元素,伪元素必须在基础选择器语句后使用
为了便于区分伪类选与伪元素,使用双冒号【::】作为伪元素选择符
伪元素 | 描述 | 示例 |
---|---|---|
::after | 用于创建伪元素,在元素内容之后插入内容,该伪元素默认为行内元素 | p::after { content: "结束"; } |
::before | 用于创建伪元素,在元素内容之前插入内容,该伪元素默认为行内元素 | p::before { content: "开始"; } |
::first-line | 向文本的首行添加样式,只能应用于块级元素 | p::first-line { color: #333; } |
::first-letter | 向文本的首字母添加样式,只能应用于块级元素 | p::first-letter { font-size: 16px; } |
::marker | 用于改变li元素的数字或符号的样式,只能作用于display 属性值为list-item 的元素 | ul li::marker { content: '*'; } |
::placeholder | 用于设置表单元素占位符文本的样式 | input::placeholder { color: blue; } |
1、例:将li元素内容前的符号设置为‘星号’
1.1 代码示例
<style>
ul li::marker {
content: '★';
}
</style>
<ul>
<li>C1 见习工程师能力认证</li>
<li>C4 专项工程师能力认证</li>
<li>C5 全栈工程师能力认证</li>
</ul>
CSS优先级
二、任务背景
当创建的CSS样式表越来越多、越来越复杂的时候,一个元素的样式可能受到多个CSS样式表的影响,到底这个元素显示的是哪个样式表的样式呢?通过CSS优先级可以帮助我们得出结论。
三、任务内容
1、CSS优先级
浏览器通过CSS选择器的优先级来判断元素到底应该显示那个属性值
CSS的优先级如下
-
【内联样式】 > 【ID选择器】 > 【类选择器、属性选择器、伪类选择器】 > 【标签选择器 、伪元素选择器】
通配符选择器【*】和关系选择符【+(相邻选择符)、>(子代选择符)、~(兄弟选择符)、" "(后代选择符)等】对优先级没有影响
在选择器使用较多的情况下,使用CSS优先级判断元素的属性值显示很容易出错且不利于排错,可以通过给选择器添加权重的概念来帮助我们更好的理解CSS选择器的优先级
选择器 | 权重 |
---|---|
内联样式 | 1000 |
ID选择器 | 100 |
类选择器、属性选择器、伪类选择器 | 10 |
标签选择器、伪元素选择器 | 1 |
相邻选择符、子代选择符、兄弟选择符、后代选择符 | 0 |
2、选择器权重计算
选择器的权重可以相加
#header .nav li { list-style: none; }
该选择器的权重 = ID选择器100 + 类选择器10 + 标签选择器1 = 111
对于同一个元素的两种选择器均声明了同一个属性情况
-
权重相同时,根据HTML代码从上往下执行的特点,后面选择器会覆盖前面选择器中相同的属性
-
权重不同时,权重大的选择器生效
3、!important规则
当你在一个样式声明中使用
!important
规则时,这个样式将覆盖其他的任何声明!important
规则与优先级无关,但是会直接影响样式的最终显示结果
块级元素与行内元素
二、任务背景
HTML(超文本标记语言)中元素大多数为块级元素或行内元素,浏览器在显示页面时,对这两类元素的默认处理方式是不一样的。
三、任务内容
1、块级元素
-
在浏览器显示时总是独占一行
-
宽高、内外边距可以控制,且上下左右的外边距均可对周围元素产生影响
-
可以包含内容、行内元素和其他块级元素
-
宽度未设置时默认为其父级元素的宽度,高度未设置时为内容的高度
-
常见块级元素:
div、form、footer、h1-h6、ol、ul、p、video
-
设置
display
属性为display: block
可将元素转换为块级元素
2、行内元素
-
不独占一行,默认不自动换行
-
宽高、上下边距不可以控制,仅有左右边距可以控制且会对周围元素产生影响
-
一般只能包含内容和其他行内元素,不可包含块级元素
-
设置宽高无效,宽高默认为内容的宽高
-
常见行内元素:
span、label、a、em、strong、img
-
设置
display
属性为display: inline
可将元素转换为行内元素
ps:img
元素为可替换元素,宽高是由其加载的内容决定的,可以使用CSS覆盖其宽高等样式
3、行内块级元素
-
综合块级元素与行内元素的特性
-
不独占一行
-
元素宽高、内外边距均可设置,上下左右边距均会对周围元素产生影响
-
宽高未设置时默认为内容宽高
-
常见行内块级元素:
button、input、textarea、select
-
设置
display
属性为display: inline-block
可将元素设置为行内块级元素
盒子模型
二、任务背景
所有的HTML元素都可以看做是一个盒子模型,每个盒子模型包含外边距、内边距、边框、实际内容四个部分,通过对以上四个部分的属性设置可以极大的丰富盒模型乃至整个HTML文档的表现效果和布局结构。
三、任务内容
1、什么是盒子模型
当对一个页面进行布局(lay out)的时候,浏览器会将所有元素表示为一个个矩形的盒子(box),HTML页面可以理解为将多个盒子堆叠累加而成。
2、盒子模型的组成部分
盒模型由里到外包括四个部分:内容部分,padding(内边距),border(边框),margin(外边距)
内容部分一般用来显示图像或文字,在标准盒模型中(默认),内容部分的宽高可以通过width、height属性设置
-
padding(内边距)是包围在内容区域外的空白区域,代表的是盒子边框与实际内容之间的距离,通过【padding】相关属性设置大小
-
border指的是盒子模型的边框。border除了可以使用
border-width
设置边框大小外,可以使用border-style
设置边框的样式,如实线、虚线,使用border-color
设置边框颜色 -
margin(外边距)指的是盒子和其他元素之间的空白部分,代表的是盒子的边框与其他相邻盒子边框之间的距离,通过【margin】相关属性设置大小
3、标准盒模型与怪异盒模型的区别
3.1标准盒模型
在标准盒模型中,给盒模型设置
width
和height
,实际上是给内容区域设置大小
标准盒模型的盒子实际宽高 = 内容区域的宽高 + border大小 + padding大小
-
例:将div设置为标准盒模型
box-sizing:content-box
,CSS设置如下
检查元素如下图所示,div设置的
width
和height
是200×100,div的实际大小是236×136,div的实际宽度 =width + padding-left + padding-right + border-left + border-right
= 200 + 15 + 15 + 3 + 3 = 236,div的实际高度计算同理
3.2怪异盒模型
在怪异盒模型中,给盒模型设置的
width
和height
就是盒模型的实际大小,宽高已经包含了border
和padding
怪异盒模型的实际大小 = 盒模型设置的
width、height(包含border和 padding)
在怪异盒模型中,内容部分的实际宽高是盒模型的宽高减去padding和border
例:将div设置为怪异盒模型
box-sizing:border-box
,CSS设置如下
检查元素如下图所示,div设置的width和height设置为200×100,实际大小也是200×100,
div的实际宽度 = width,div的实际高度 = height
不管是标准盒模型还是怪异盒模型,margin都不计入盒子的实际大小。但是margin会影响盒模型所占空间,即影响的盒子模型的外部空间。在计算盒子模型的实际占位大小时才会将margin计入其中。
浏览器默认使用标准盒模型,如需使用怪异盒模型,可用通过将盒模型设置为
box-sizing: border-box
实现
定位
二、任务背景
在一个网页的排版布局中,定位属性是最重要的属性之一,能够熟练使用定位布局对页面美化有很好的帮助。
三、任务内容
1、什么是脱离文档流
文档流指的是在元素排版过程中,元素会自动从上至下,从左往右流式排列,称为文档流
元素脱离文档流后,将不在文档流中占据空间,元素浮于文档流的上方,此时元素层级发生变化
2、position定位
position属性用于指定元素的定位类型,属性值可为
-
static(默认定位)
-
relative(相对定位)
-
absolute(绝对定位)
-
fixed(固定定位)
-
sticky(粘性定位)
设置定位类型后可以通过设置top、right、bottom、left属性确定定位的位置
2.1 static定位
-
页面上的每个盒子从上到下、从左到右依次排列的布局
<div class="box-container">
<div class="box1">box1</div>
<div class="box2">box2</div>
</div>
2.2 relative定位
-
相对于元素自身原始位置定位,元素不脱离文档流,即原来元素所占的空间不会改变
上述static定位示例代码中,将box1设置以下属性,元素会相对于自身原始位置向右偏移20px,向下偏移50px
.box1 {
position: relative;
top: 50px;
left: 20px;
}
2.3 absolute定位
-
元素相对于最近的非static定位的祖先元素定位进行偏移,元素脱离文档流
上述static定位示例代码啊中,将box2以及其父级元素box-container设置如下属性
box2元素相对于relative定位的box-container向右偏移25px,向下偏移30px
.box-container {
position: relative;
}
.box2 {
position: absolute;
top: 30px;
left: 25px;
}
2.4 fixed定位
-
相对于浏览器窗口进行定位,元素脱离文档流
常用于顶部导航栏、顶部搜索框、侧边联系客服等板块
2.5 sticky定位(存在兼容性问题)
-
根据自身原始位置或浏览器窗口进行固定定位,类似relative和fixed的结合
常用于页面的搜索工具栏,初始加载在默认位置(相当于
relative
),页面向下滚动时,工具栏固定在页面头部(相当于fixed
),页面重新向上滚动,工具栏也会回到默认位置
3、层级属性z-index
-
用于设置元素的堆叠顺序,该属性仅能在非static定位的定位元素上生效
-
数值越高,层级越高,层级高的元素会覆盖层级低的元素(层级高的元素会在层级低的元素上方)
z-index属性值相同时,遵循
后来者居上
的原则,后面的元素会覆盖前面的元素
上述
absolute
定位的示例中,给box1、box2添加背景后可以清晰看见,box2覆盖box1
将box1、box2增加以
z-index
属性,可将box1、box2层级改变,使box1在box2的上方
.box1 { z-index: 1; }
.box2 { z-index: 0; }
浮动
二、任务背景
浮动属性产生之初是为了实现“文字环绕”的效果,让文字环绕图片在网页实现类似word中“图文混排”。后可用于所有元素,在页面布局中发挥重要作用。
三、任务内容
1、float属性
-
用于设置元素是否浮动,absolute(绝对)定位的元素会忽略float属性
元素浮动后会被移出正常的文档流,向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。
-
下表为float可设置的属性值
属性值 | 描述 |
---|---|
none | 默认值,元素不浮动 |
left | 元素左浮动 |
right | 元素右浮动 |
2、clear属性
-
用于清除浮动,给元素清除浮动后,元素将会排在该元素之前的浮动元素下方
-
下表为clear可设置的属性值
属性值 | 描述 |
---|---|
none | 默认值,元素不浮动 |
left | 清除左浮动 |
right | 清除右浮动 |
both | 清除左右两侧浮动 |
<style>
.layout {
width: 120px;
height: 300px;
margin: 10px;
background-color: cadetblue;
float: left;
}
.content {
width: 340px;
height: 300px;
margin: 10px;
background-color: powderblue;
float: left;
}
footer {
width: 500px;
height: 40px;
background-color: darkseagreen;
}
</style>
<main>
<section class="layout flex-center">侧边栏</section>
<section class="content flex-center">内容</section>
</main>
<footer></footer>
在以上代码使用浮动实现两列布局中,main中的section都为浮动元素,main元素的高度为0无法被撑开
main后的footer元素在页面布局时无法在main后正常显示(如下图)
section元素左浮动,此时将footer元素左侧浮动清除,即可将footer元素置于main元素下方
/* 清除左右两侧浮动 */
footer {
clear: both;
}
/* 或清除左侧浮动*/
footer {
clear: left;
}
3、浮动布局
-
浮动在布局中最常用于实现两列布局或三列布局
在使用浮动属性实现三列布局的时候常用,左侧盒子左浮动,右侧盒子右浮动,中间的盒子左右外边距设置大于左右两侧盒子大小即可
以下为三列布局的简单实现代码
<style>
main {
width: 500px;
height: 300px;
margin: 50px;
}
.left {
width: 100px;
height: 300px;
background-color: cadetblue;
float: left;
}
.center {
width: 300px;
height: 300px;
background-color: lightblue;
margin: 0 100px;
}
.right {
width: 100px;
height: 300px;
background-color: cadetblue;
float: right;
}
</style>
<main>
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
</main>
JavaScript变量命名规则
三、任务内容
1、语法层面
1.1 变量名不能以数字或者某些特殊字符开头
1
1a
*a
(a
%a
<r
// 以上都是非法的变量名,会直接报错
1.2 变量名不能是关键字
var
if
for
// 以上都是非法的变量名,会直接报错
2、工程层面
-
一般应当坚持使用拉丁字符(0-9,a-z,A-Z)和下划线字符。
-
不应当使用规则之外的其他字符,因为它们可能引发错误,或对国际用户来说难以理解。
-
变量名不要以下划线开头—— 以下划线开头的被某些JavaScript设计为特殊的含义,因此可能让人迷惑。
-
变量名不要以数字开头。这种行为是不被允许的,并且将引发一个错误。
-
一个可靠的命名约定叫做 "小写驼峰命名法",用来将多个单词组在一起,小写整个命名的第一个字母然后大写剩下单词的首字符。
-
让变量名直观,它们描述了所包含的数据。不要只使用单一的字母/数字,或者长句。
-
变量名大小写敏感
-
最后也是最重要的一点—— 你应当避免使用JavaScript的保留字给变量命名。保留字,即是组成JavaScript的实际语法的单词!因此诸如 var, function, let和 for等,都不能被作为变量名使用。浏览器将把它们识别为不同的代码项,因此你将得到错误。
// 以下是一些好的命名,不仅不会报错,还便于理解
age
myAge
init
finalOutputValue
audio1
// 以下是一些不好的命名,有些会报错,有些不便于理解
1
a
_12
MYAGE
var
Document
skjfndskjfnbdskjfb
逻辑运算
三、任务内容
1、比较运算符
我们假定 num = 5,下表中解释了比较运算符:
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
== | 等于 | num == 6 | false |
=== | 值相等且类型相等 | num === "5" | false |
!= | 不等于 | num != 7 | true |
!== | 值不相等或类型不相等 | num !== 5 | false |
> | 大于 | num > 9 | false |
< | 小于 | num < 9 | true |
>= | 大于或等于 | num >= 8 | false |
<= | 小于或等于 | num <= 7 | true |
2、逻辑运算符
我们假定num = 5,下表中解释了逻辑运算符:
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
&& | 与 | (num%2==1 && num>1) | true |
|| | 或 | (num%2==0 || num>1) | true |
! | 非 | !(num%2==0) | true |
3、知识拓展
比较运算和逻辑运算大概率情况下都会配合【条件分支】(if 、三元运算、switch等)结合使用
4、示例
var age = 8
if(age >= 60 || age <=12){
console.log("老人与儿童可以免票")
} else {
console.log("您请购买全票")
}
【思路】
已知预先给定age为8,判断条件为当age大于或等于60或者age小于或等于12时输出"老人与儿童可以免票",否则"您请购买全票"
隐式类型转换
二、任务背景
每一个变量或者值都有其对应的类型,在JavaScript中如Number、String、Boolean、Array、Object等。在强类型的语言中,不同类型的变量或值之间不能进行运算;在弱类型的语言中,不同类型的变量或值可进行一些运算,这主要是因为解释器做了隐式类型转换的工作。
三、任务内容
1、字符串和数字的运算
1.1 字符串和数字进行加运算时,会将数字转换成字符串,然后和另一个字符串进行拼接
var num1 = '123'
var num2 = 12
var num3 = num1 + num2
console.log(num3) // 预期输出:'12312'
1.2 字符串和数字进行减、乘、除运算,以及大小比较时,会将字符串转换成数字,再和另一个数字进行运算或比较
var num1 = '123'
var num2 = 12
var num3 = num1 - num2
console.log(num3) // 预期输出:111
var num1 = '123'
var num2 = 12
var num3 = num1 * num2
console.log(num3) // 预期输出:1476
var num1 = '123'
var num2 = 12
var num3 = num1 / num2
console.log(num3) // 预期输出:10.25
var num1 = '123'
var num2 = 15
var t = num1 > num2
console.log(t) // 预期输出:true
2、各种值转换成布尔值
2.1 数字0,空字符串"",null,undefined 转成布尔值的时候都是false
2.2 非0数字,非空字符串转成布尔值的时候都是true
2.3 任何数组(即使是空数组),任何对象(即使是空对象) 转成布尔值的时候都是true
var a = 0
if (a) {
console.log('hello')
} else {
console.log('world')
}
// 当a=0或""或null或undefined的时候,预期输出:world
// 当a=[]或空对象的时候,预期输出:hello
// 当a=-1或"abc"时候,预期输出:hello
条件分支
二、任务背景
条件分支是编程语言必备的流程控制之一。它能根据所给定值或表达式的真假来运行不同区块的代码。日常编码中,不可避免的要使用到它。
三、任务内容
1、if分支
1.1 基本语法结构
if (条件1) {
// 代码块1
} else if (条件2) {
// 代码块2
} else {
// 代码块3
}
1.2 说明
-
如果条件1为真就会执行代码块1。即使条件2为真也不会去执行代码块2,更不会执行代码块3
-
只有当条件1为假,并且条件2为真的时候,才会执行代码块2
-
如果条件1和条件2都为假,才会执行代码块3
-
else if 和 else 部分不是必需的。
-
可以有多个else if
1.3 示例
var x = 20
if (x > 5) {
console.log('a')
} else if (x > 50) {
console.log('b')
} else {
console.log('c')
}
// 如果x=20,上述代码预期输出:'a'
// 如果x=100,上述代码预期输出也是:'a'
2、switch分支
2.1 基本语法结果
switch (expression) {
case value1:
// 当 expression 的结果与 value1 匹配时,执行此处语句
[break;]
case value2:
// 当 expression 的结果与 value2 匹配时,执行此处语句
[break;]
...
case valueN:
// 当 expression 的结果与 valueN 匹配时,执行此处语句
[break;]
[default:
// 如果 expression 与上面的 value 值都不匹配,执行此处语句
[break;]]
}
2.2 说明
-
[]表示这一部分语句是可选的,并不是说正常代码中要加[]
-
expression和value的是进行严格模式的匹配
-
如果所有case都没有匹配到,将执行default分支的代码
2.3 示例
var expr = '樱桃'
switch (expr) {
case '樱桃':
// 代码块1
console.log('樱桃每斤7元');
break;
case '芒果':
case '木瓜':
// 代码块2
console.log('芒果 和 木瓜 每斤10元');
break;
default:
// 代码块3
console.log('对不起,我们没有 ' + expr + '.');
}
// 如果expr值为'樱桃',则预期输出:'樱桃每斤7元'
// 当expr的值为'樱桃'时就会执行代码块1,且代码块1中有break,所有不会执行其他代码块
// 注意:如果expr匹配到某一个case,且这个case里面代码没有break,那么执行完这个代码块后,紧接着就会执行下一个case的代码,不管expr有没有匹配到下一个case的值
// 所以当expr的值为'芒果'的时候,代码块2也将被执行
For循环
三、任务内容
1、for循环的使用方法
-
for:多次遍历代码块
-
for/in:遍历对象属性
2、使用示例
for (语句 1; 语句 2; 语句 3) {
要执行的代码块
}
2.1 for循环是您希望创建循环时经常使用的语法结构,代码结构如下:
-
语句 1 在循环(代码块)开始之前执行。
-
语句 2 定义运行循环(代码块)的条件。
-
语句 3 会在循环(代码块)每次被执行后执行。
2.2 for循环代码实例一(普通遍历):
for (var i = 0; i < 10; i++) {
console.log(i)
}
// 执行结果
0 1 2 3 4 5 6 7 8 9
说明:
-
语句1在循环之前设置一个变量(var i = 0),从0开始遍历
-
语句2定义运行循环的条件(i必须小于10),当i = 10的时候不满足循环条件
-
语句3会在代码块每次执行之后对变量值i进行递增(i++)
2.3 for循环代码实例二(数组遍历):
var arr = [11, 22, 33, 44, 55]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i])
}
// 执行结果
11 22 33 44 55
说明:
-
语句1在循环之前设置一个变量(var i = 0),从0开始遍历(数组下标从0开始)
-
语句2定义运行循环的条件(i必须小于arr的数组长度),当arr下标正好是0-3,4的时候不满足循环要求
-
语句3会在代码块每次执行之后对变量值i进行递增(i++)从arr[0]-arr[3]
2.4 for循环代码实例三(对象遍历):
var obj = {name:"tom", gender:"man", age:32}
for (var key in obj) {
// 打印键
console.log(key)
// 打印值
console.log(obj[key])
}
// 执行结果
name
tom
gender
man
age
32
说明:
JavaScript提供了一种特殊的循环(也就是for .. in循环),用来迭代对象的属性或数组的每个元素,for...in循环中的循环计数器是字符串,而不是数字。它包含当前属性的名称或当前数组元素的索引
Math内置对象
二、任务背景
Math对象的作用是:执行常见的算数任务。保存数学公式和信息,与我们在JavaScript直接编写计算功能相比,Math对象提供的计算功能执行起来要快得多。
三、任务内容
1、Math对象的常用方法:
方法名称 | 作用 | 示例 | 结果 |
---|---|---|---|
max() | 用于确定一组数值中的最大值 | Math.max(11,3,17,6) | 17 |
min() | 用于确定一组数值中的最小值 | Math.min(11,3,17,6) | 3 |
ceil() | 执行向上取整,即它总是将数值向上取整为最接近的整数 | Math.ceil(25.1) | 26 |
floor() | 执行向下取整,即它总是将数值向下取整为最接近的整数 | Math.floor(25.8) | 25 |
round() | 执行标准取整,即它总是将数值四舍五入为最接近的整数 | Math.round(25.8) | 26 |
random() | 该方法返回介于 0 到 1 之间一个随机小数,包括 0 和不包含 1 | Math.random() | 例如0.3123868992708143 |
abs() | 该方法返回参数的绝对值 | Math.abs(-9) | 9 |
sqrt() | 该方法返回参数的平方根 | Math.sqrt(49) | 7 |
2、实例一
// 要想以下JavaScript代码符合预期,空格处应该填什么?
var a = Math._____(-120.38)
console.log(a)
预期输出结果:
-121
【思路】
-
给出的数值-120.38 ,预期结果-121,说明是向下取整
-
Math.floor() 正是向下取整
3、组合实例
// 获取一个10-50的随机整数
var num = Math.floor(Math.random()*40)+10
Math.random()*40 //获取40以内的随机数(当前还是浮点数)
【思路】
-
Math.random()*40;为获取一个40以内的随机数(浮点数)
-
Math.floor(Math.random()*40);将这个浮点数舍1取整
-
在最后加10则不管随机数是最小数还是最大数,都满足要求10-50
对象属性
二、任务背景
对象属性指的是与JavaScript对象相关的值。JavaScript对象是无序属性的集合。属性通常可以被修改、添加和删除,但是某些属性是只读的。
三、任务内容
1、对象定义(以下操作都基于这个对象)
// 定义一个对象
var obj = { name: "李明", age: 18, gender: "man", city: "山东", hobby: "游泳" }
2、访问对象属性的语法
// 访问对象属性方式一
obj.name
// 访问对象属性方式二
obj['name']
// 访问对象属性方式三
// 将对象属性赋值给一个变量,使用变量方式访问
var key = 'name'
obj[key]
3、添加对象的属性语法
// 添加一个属性方式一
obj.nickName = "小明"
// 添加一个属性方式二
obj["nickName"] = "小明"
console.log(obj)
// {name: '李明', age: 19, gender: 'man', city: '山东', hobby: '游泳', nickName: "小明"}
4、修改对象的属性语法
// 修改一个属性方式一
obj.age = 19
// 修改一个属性方式二
obj["age"] = 19
console.log(obj)
// { name: '李明', age: 19, gender: 'man', city: '山东', hobby: '游泳'}
5、删除对象的属性语法
// 删除一个属性
delete obj.age
console.log(obj)
// {name:'李明', gender: 'man', city: '山东', hobby: '游泳'}
6、for循环遍历对象属性的语法
// for循环遍历对象,需要使用for ... in
for (var key in obj) {
console.log(key)
console.log(obj[key])
}
函数定义与调用
三、任务内容
1、通过声明来定义函数
1.1 function关键字
我们可以使用function关键字来定义一个具有名称的函数,其语法结构如下
function name([param[, param[, ... param]]])
{
[statements]
}
1.2 说明
-
[]表示可选,并不是正常代码中需要使用[]
-
name表示函数名,()中的表示参数,{}中的表示函数体。在函数被调用的时候,会执行函数体中的代码。
-
注意:函数被定义的时候,函数体中的代码并不会被执行。只有到函数被调用的时候,函数体中的代码才会被执行。
-
对于使用函数声明这个方法定义的函数,函数调用可以在函数定义之前,如示例中的pri函数。
1.3 示例
pri(); // 预期输出:"foo"
function pri() {
console.log("foo");
}
2、通过表达式来定义函数
2.1 表达式定义法
我们还可以使用函数表达式的方式来定义一个函数,这时可以将函数直接赋值给一个变量,其语法结构如下
var myFunction = function name([param[, param[, ... param]]]) {
statements
}
2.2 说明
-
[]表示可选,并不是正常代码中需要使用[]
-
name表示函数名,可以省略,()中的表示参数,{}中的表示函数体。在函数被调用的时候,会执行函数体中的代码。
-
注意:函数被定义的时候,函数体中的代码并不会被执行。只有到函数被调用的时候,函数体中的代码才会被执行。
-
对于使用函数表达式这个方法定义的函数,函数调用必须在函数定义之后。
-
如果省略name,我们称该函数为匿名函数。
2.3 示例
var myFunction = function foo() {
// statements
}
myFunction()
foo() // 会报错,并不能调用成功。命名函数表达式的好处是当我们遇到错误时,
//堆栈跟踪会显示函数名,容易寻找错误。
3、函数调用
-
对于使用函数声明的方法定义的函数,可以使用函数名加括号的方式来调用;对于使用函数表达式定义的函数,可以使用表达式所赋值的变量名加括号来调用。如上述代码所示。
-
在函数被执行的时候,会运行函数体中的代码。如果函数体中有return语句,则会在函数被调用处返回return出来的值,并结束函数的运行。return并不是必需的,没有return的话,函数会返回undefined。
function add1(a, b) {
return a + b;
}
var res = add1(4, 5)
console.log(res) // 预期输出:9
function add2(a, b) {
a + b;
}
var res = add2(4, 5)
console.log(res) // 预期输出:undefined
-
函数在调用的时候,会将调用时给定的参数和定义时设定的参数依次绑定。如果调用时给定的参数个数不够,那么函数体中没有绑定的参数将被赋值为undefined
function foo(a, b) {
console.log(b)
}
foo(4) // 预期输出:undefined
foo(4,8) // 预期输出:8
-
函数在调用时可以接受一个函数作为参数,也可以返回一个函数作为返回值。这是函数的高阶用法,暂不涉及,可自行查阅。
常见内置函数
二、任务背景
JavaScript是一个基于原型链的面向对象的语言,很多其他语言常见的函数会以对象上的各种方法存在,例如数组对象的各种方法,字符串对象的各种方法等。即便如此,JavaScript还是有一些顶层的内置函数,了解这些常见的内置函数对我们进行JavaScript编码有很大的帮助。
三、任务内容
1、eval
eval函数会将传入的字符串当做 JavaScript 代码进行执行。这是一个十分危险的函数,一般情况不建议使用。
var a = eval("2+2")
console.log(a)
// 预期输出:4
// 这里eval把字符串"2+2",当成js代码执行,得到结果4
eval("console.log('hello world')")
// 预期输出:hello world
// 这里eval把字符串"console.log('hello world')",当成js代码执行,打印输出:hello world
2、isNaN
用来确定一个值是否为NaN。NaN表示 不是一个数字 。如果isNaN函数的参数不是Number类型, isNaN函数会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是NaN进行判断。因此,对于能被强制转换为有效的非NaN数值来说(空字符串和布尔值 分别 会被强制转换为数值0和1),返回false值也许会让人感觉莫名其妙。比如说,空字符串就明显“不是数值(not a number)”。这种怪异行为起源于:"不是数值(not a number)"在基于IEEE-754数值的浮点计算体制中代表了一种特定的含义。isNaN函数其实等同于回答了这样一个问题:被测试的值在被强制转换成数值时会不会返回IEEE-754中所谓的“不是数值(not a number)”。
isNaN('abc') // 返回值:true 因为字符串'abc'不是一个数字
isNaN('12.23') // 返回值:false 因为字符串'12.23'是一个数字
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: 可以被转换成数值37
isNaN("37.37"); // false: 可以被转换成数值37.37
isNaN("37,5"); // true
isNaN('123ABC'); // true: parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaN
isNaN(""); // false: 空字符串被转换成0
isNaN(" "); // false: 包含空格的字符串被转换成0
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
isNaN("blabla") // true: "blabla"不能转换成数值
// 转换成数值失败, 返回NaN
是的,不是一个数字
3、parseFloat
根据给定的参数返回其对应的浮点数。
parseFloat(3.14);
parseFloat('3.14');
parseFloat(' 3.14 ');
parseFloat('314e-2');
parseFloat('0.0314E+2');
parseFloat('3.14some non-digit characters');
// 以上的返回值都是3.14
4、parseInt
解析一个字符串并返回指定基数的十进制整数。
parseInt("0xF", 16);
parseInt("F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt("015", 10); // parseInt(015, 8); 返回 13 parseInt(15.99, 10);
parseInt("15,123", 10);
parseInt("FXX123", 16);
parseInt("1111", 2);
parseInt("15 * 3", 10);
parseInt("15e2", 10);
parseInt("15px", 10);
parseInt("12", 13); // 以上都返回15,第二个参数表示基数(可以理解为进制)
字符串定义与转义字符
三、任务内容
1、使用引号来定义字符串
我们可以使用一对单引号或者一对双引号来定义一个字符串
var str1 = "这是双引号定义的字符串"
var str2 = '这是单引号定义的字符串'
// 1. 在JavaScript中双引号定义的字符串和单引号定义的字符串没有本质区别
// 2. 无论是单引号还是双引号,都必须配对使用,不能一个单引号和双引号配对
// 3. 单引号中的字符串中不能出现单引号,可以出现双引号;双引号中的字符串中不能出现双引号,可以出现单引号
使用模板字符串的方式定义字符串:我们可以使用一对反引号来定义字符串(Esc键下方的)
var str1 = `这是一个普通的字符串`
var str2 = `这是一个换行的
字符串`
var a = 2
var b = 3
var str3 = `这是一个可以解析变量的字符串,例如:${a + b}`
// 最终str3的值为:
// 这是一个可以解析变量的字符串,例如:5
2、转义符
在定义一个字符串的时候,有些特殊字符并不适合直接出现。例如:换行符、单引号(不能出现在单引号内)、双引号(不能出现在双引号内),这个时候可以我们需要使用\转义符,例如:
var str1 = '这是一个换行的\n字符串'
console.log(str1)
// 预期输出:
// 这是一个换行的
// 字符串
// 在这里使用了\n来代表换行符。如果直接在定义字符串的时候回车换行,将出现语法错误
var str2 = "如何使用双引号\""
console.log(str2)
// 预期输出:
// 如何使用双引号"
// 在这里使用了\"来代表双引号。如果在双引号定义的字符串中直接使用双引号,将出现语法错误。单引号同理。
// 如果使用模板字符串的方式定义字符串,可以直接使用回车换行。但是要在其中使用反引号`,也必须转义
字符串常见方法与属性
二、任务背景
字符串在JavaScript中几乎无处不在,在你处理用户的输入数据的时候,在读取或设置DOM对象的属性时,在操作cookie时,当然还有更多。JavaScript的核心部分提供了一组属性和方法用于通用的字符串操作,如分割字符串,改变字符串的大小写,操作子字符串等。
三、任务内容
1、String对象属性
属性名称 | 作用 | 示例 | 结果 |
---|---|---|---|
length | 获取字符串入的长度 | 'abcd'.length | 4 |
2、String对象的常用方法
方法名称 | 作用 | 示例 | 结果 |
---|---|---|---|
charAt() | 获取指定位置的字符 | 'abcd'.charAt(2) | c |
indexOf() | 检索指定的字符串值在字符串中首次出现的位置 | 'abcd'.indexOf('a') | 0 |
lastIndexOf() | 从后往前查询所要搜索的字符串在原字符串中第一次出现的位置(索引),找不到则返回-1 | 'abcdabc'.lastIndexOf('a') | 4 |
search() | 检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串 | 'abcd'.search('c') | 2 |
match() | 字符串内检索指定的值,或找到一个或多个正则表达式的匹配 | 'abcdabc'.match('a') | ['a', index: 0, input: 'abcdabc'] |
substring() | 字符串截取方法,它可以接收两个参数,分别是要截取的开始位置和结束位置,它将返回一个新的字符串 [ ) | 'abcdabc'.substring(1, 4) | bcd |
slice() | 与substring()方法非常类似,它传入的两个参数也分别对应着开始位置和结束位置。而区别在于,slice()中的参数可以为负值 | 'abcdabc'.slice(1, 4) | bcd |
replace() | 用来进行字符串替换操作,它可以接收两个参数,前者为被替换的子字符串,后者为用来替换的文本 | 'abcd'.replace('a', 'A') | Abcd |
split() | 于把一个字符串分割成字符串数组 | 'abcd'.split('') | ['a', 'b', 'c', 'd'] |
toLowerCase() | 可以把字符串中的大写字母转换为小写 | 'Abcd'.toLowerCase() | abcd |
toUpperCase() | 可以把字符串中的小写字母转换为大写 | 'Abcd'.toUpperCase() | ABCD |
数组常见方法与属性
三、任务内容
1、数组定义
// 直接使用中括号就能定义一个数组,数组中的值的类型不必相同,数组中可以嵌套数组
var arr = [1, 2, 5, 'init', ['apple', 2, 4]]
2、数组中值的访问与修改
var arr = [1, 2, 5, 'init', ['apple', 2, 4]] // 可以使用下标(或者叫索引)来取数组中的值。下标是从0开始的
arr[0] // 取下标为0的值,即1
arr[3] // 取下标为3的值,即'init'
// 我们可以给数组中某一个下标的值进行重新赋值,即修改该下标的值
arr[0] = 'name' // 将字符串'name'赋值给数组arr下标为0的位置,此时arr[0]的值就为'name'了,而不是1了
3、数组常见属性
3.1 length
访问一个数组的length属性,返回该数组的长度,即该数组元素的个数
var arr = [1, 2, 5, 'init', ['apple', 2, 4]]
arr.length // 返回数组arr的长度,即5
4、数组常见方法
4.1 forEach()
对数组的每个元素执行一次给定的函数
var array1 = ['a', 'b', 'c']
array1.forEach( function(element) {
console.log(element)
})
// 预期输出
// "a"
// "b"
// "c"
4.2 indexOf()
返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。第二个参数是第几个二此元素。
var beasts = ['ant', 'bison', 'camel', 'duck', 'bison']
console.log(beasts.indexOf('bison')) // 预期输出: 1
// start from index 2
console.log(beasts.indexOf('bison', 2)) // 预期输出: 4
console.log(beasts.indexOf('giraffe')) // 预期输出: -1
4.3 join()
将一个数组的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
var elements = ['Fire', 'Air', 'Water']
console.log(elements.join()) // 预期输出: "Fire,Air,Water"
console.log(elements.join('')) // 预期输出: "FireAirWater"
console.log(elements.join('-')) // 预期输出: "Fire-Air-Water"
4.4 map()
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
var array1 = [1, 4, 9, 16]; // 传入一个回调函数给map方法
var map1 = array1.map(function (x) { return x * 2 });
console.log(map1); // 预期输出: Array [2, 8, 18, 32]
4.5 pop()
从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
var plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];
console.log(plants.pop()); // 预期输出: "tomato"
console.log(plants); // 预期输出: Array ["broccoli", "cauliflower", "cabbage", "kale"]
plants.pop();
console.log(plants); // 预期输出: Array ["broccoli", "cauliflower", "cabbage"]
4.6 push()
将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
var animals = ['pigs', 'goats', 'sheep'];
var count = animals.push('cows');
console.log(count); // 预期输出: 4
console.log(animals); // 预期输出: Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals); // 预期输出: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
4.7 reverse()
将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
var array1 = ['one', 'two', 'three'];
console.log('array1:', array1); // 预期输出: "array1:" Array ["one", "two", "three"]
var reversed = array1.reverse();
console.log('reversed:', reversed); // 预期输出: "reversed:" Array ["three", "two", "one"]
// 注意:该方法会修改原数组
console.log('array1:', array1); // 预期输出: "array1:" Array ["three", "two", "one"]
4.8 shift()
从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
var array1 = [1, 2, 3];
var firstElement = array1.shift();
console.log(array1); // 预期输出: Array [2, 3]
console.log(firstElement); // 预期输出: 1
4.9 slice()
返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2)); // 预期输出: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4)); // 预期输出: Array ["camel", "duck"]
console.log(animals.slice(1, 5)); // 预期输出: Array ["bison", "camel", "duck", "elephant"]
console.log(animals.slice(-2)); // 预期输出: Array ["duck", "elephant"]
console.log(animals.slice(2, -1)); // 预期输出: Array ["camel", "duck"]
4.10 sort()
对数组的元素进行排序,并返回数组。(默认转换成字符串)
var months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months); // 预期输出: Array ["Dec", "Feb", "Jan", "March"]
var array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1); // 预期输出: Array [1, 100000, 21, 30, 4]
// 如果sort()方法调用的时候没有传入回调函数,会将数组转成字符串然后进行大小比较并升序排列,
//字符串的大小比较是按照字典顺序进行的。所以10000会比21小。
// 如果sort()方法调用的时候传入了回调函数,会按回调函数的返回值来决定相邻两个元素的排序,
//例如:
var array1 = [1, 30, 4, 21, 100000];
array1.sort(function (item1, item2) {
return item1 - item2
});
console.log(array1); // 预期输出: Array [1, 4, 21, 30, 100000]
// 这里面的item, item2参数就是array1里面相邻的两个元素
// 如果这个回调函数返回的结果大于0,那么item2将排在item1的前面
// 如果这个回调函数返回的结果小于0,那么item1将排在item2的前面
// 如果这个回调函数返回的是0,那么item1和item2的位置不变
4.11 unshift()
将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
var array1 = [1, 2, 3];
console.log(array1.unshift(4, 5)); // 预期输出: 5
console.log(array1); // 预期输出: Array [4, 5, 1, 2, 3]
Web进阶
DOM节点操作(上)
二、任务背景
DOM(Document Object Model——文档对象模型)是用来处理HTML和XML的跨平台API。它允许运行在浏览器中的代码访问文档节点并与之交互,了解并掌握DOM操作是Web开发中的必经之路。
三、任务内容
1、DOM结构及节点
整个HTML的结构都可以由类似上图的树结构表示,整个树结构由节点组成
-
document对象指代整个文档节点, 它是文档内其他节点的访问入口,提供了操作其他节点的方法
-
节点可以分为元素节点、文本节点和属性节点
-
节点之间有层级关系,父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。 父节点拥有子节点,同级的子节点被称为同胞(兄弟或姐妹)
2、常用节点获取方法和属性
要进行DOM操作,首先要获取到需要操作的节点或节点集合,接下来以下面的示例代码为基础,介绍常用的DOM获取方法和属性。
<div class="box" id="container">
<p class="item" title="111">项目1</p>
<p class="item">项目2</p>
<p>项目3</p>
<input type="text" value="123">
</div>
注:复制示例代码到HTML文件中,并在浏览器内打开这个HTML文件。(Chrome浏览器中右键选择“检查”可打开控制台,选择控制台的Console可运行代码,回车查看结果)。
名称 | 描述 |
---|---|
getElementById() | 获取带有指定id的节点 |
getElementsByTagName() | 获取带有指定标签名的节点集合 |
querySelector() | 获取指定选择器或选择器组匹配的第一个节点 |
querySelectorAll() | 获取指定选择器或选择器组匹配的所有节点集合 |
上表介绍了获取元素节点方法的基本定义,接下来我们使用具体示例介绍这些方法的具体使用方式(代码示例截图均为
Chrome浏览器
控制台运行结果)。
2.1 getElementById()代码示例
-
获取id为container的节点
document.getElementById('container')
2.2 getElementsByTagName()代码示例
-
获取所有p元素节点
document.getElementsByTagName('p')
这里获取到的是一个节点集合,节点集合无法直接用于DOM操作。可以使用索引获取节点集合中的某个元素节点(后续的节点集合也可使用这种方法)
document.getElementsByTagName('p')[0]
2.3 querySelector()代码示例
-
获取被选择器
.box .item
匹配的第一个节点
document.querySelector('.box .item')
除了函数方法,我们还可以使用属性来获取节点信息,下表介绍了一些获取元素节点信息常用的属性。
名称 | 描述 |
---|---|
innerHTML | 返回元素内包含的所有HTML内容(文本和标签),类型为字符串 |
parentNode | 返回指定节点的父节点 |
children | 返回指定元素的子元素节点集合 |
firstElementChild | 返回指定元素的第一个子元素节点 |
lastElementChild | 返回指定元素的最后一个子元素节点 |
2.4 innerHTML代码示例
-
获取第一个类名为
item
的元素内容
document.querySelector('.box .item').innerHTML
2.5 parentNode代码示例
-
获取
input
元素节点的父节点
document.querySelector('input').parentNode
2.6 children代码示例
-
获取类名为
box
的元素的子节点集合
document.querySelector('.box').children
3、常用的节点属性获取方式
名称 | 描述 |
---|---|
getAttribute() | 返回元素一个指定的属性值 |
直接使用属性名称获取 | 适用于部分属性(如:title ,value ,href ) |
方式1 getAttribute()代码示例
-
获取input元素的value属性值
document.querySelector('input').getAttribute('value')
方式2 某些元素的属性值可以直接使用属性名获取
-
获取input元素的value属性值
document.querySelector('input').value
两种方式区别
-
方式1获取结果类型为String,方式2获取结果可以为不同类型
-
获取到的结果未必相同,如:a元素的href属性
-
属性有默认值时,方式1只能获取到初始默认值,方式2可以获取到实时更新的值,如:input元素的value属性
DOM节点操作(下)
二、任务背景
通过上一节学习了常用的DOM获取方法和属性后,我们就可以对DOM节点进行操作以达到交互效果,交互效果主要涉及修改,删除,添加三种DOM操作。
三、任务内容
1、DOM修改
名称 | 描述 |
---|---|
innerHTML | innerHTML 除了获取元素内容,也可通过赋值用于修改元素中内容。如果修改内容中包含html字符串 会被解析成html元素 |
setAttribute(name,value) | 设置指定元素上的某个属性值。如果属性已经存在,则更新该值;否则,使用指定的名称和值添加一个新的属性 |
通过属性名更改属性 | 对元素属性重新赋值可更改对应属性值 |
1.1 innerHTML代码示例
改变p元素内容
// 更改为文字
document.querySelector('p').innerHTML = '测试项目'
// 更改为html内容(p元素中内容替换为span元素)
document.querySelector('p').innerHTML = '<span>测试项目</span>'
1.2 setAttribute(name, value)代码示例
参数:name为属性名,value为属性值
改变input的type属性
document.querySelector('input').setAttribute('type', 'button')
1.3 通过属性名更改属性
改变input的type属性
document.querySelector('input').type = 'button'
2、DOM添加
名称 | 描述 |
---|---|
createElement(tagName) | 创建一个由标签名称tagName 指定的HTML元素 |
appendChild(node) | 将一个节点插入到指定父节点的子节点列表的末尾处 |
insertAdjacentHTML(position, text) | 将指定文本解析为HTML字符串,插入到指定位置(IE不友好) |
2.1 createElement(tagName)代码示例
创建一个
<div>
元素
newDiv = document.createElement('div')
// 可以直接对创建完的元素进行操作,如:修改元素内文字
newDiv.innerHTML = '我是新元素'
2.2 appendChild(node)代码示例
创建一个新元素
<p>
,然后添加到<div>
的最尾部:(先后顺序)
var p = document.createElement('p');
document.querySelector('div').appendChild(p)
2.3 insertAdjacentHTML(position, text)代码示例
-
position(内容相对当前元素位置):
-
'beforebegin':元素自身的前面
-
'afterbegin':插入元素内部的第一个子节点之前
-
'beforeend':插入元素内部的最后一个子节点之后
-
'afterend':元素自身的后面
-
将一个新元素
<p>
插入到<div>
的最尾部:
// 执行添加
var div = document.querySelector('div')
div.insertAdjacentHTML('beforeend', '<p></p>')
3、DOM删除
名称 | 描述 |
---|---|
removeChild(child) | 删除选定的子节点,需要指定其父元素 |
remove() | 删除选定节点(IE不友好) |
3.1 removeChild(child)
<div>
<p>项目1</p>
<p>项目2</p>
<div>
<script>
// 删除div中的第一个p元素
var parent = document.querySelector('div')
var child = document.querySelector('p')
parent.removeChild(child)
</script>
3.2 remove()
<div>
<p>项目1</p>
<p>项目2</p>
<div>
<script>
// 删除div中的第一个p元素
var p1 = document.querySelector('p')
p1.remove()
</script>
DOM控制CSS样式
二、任务背景
为了实现网页交互效果,我们经常需要控制DOM的CSS样式,了解并掌握如何控制CSS是Web开发中的重要技能之一。
三、任务内容
1、通过style属性控制样式
style属性可以设置或返回元素的内联样式
-
语法:element.style.property = value
-
property为CSS属性名,如:color,margin。如果属性名原来包含“-”,则需转换为小驼峰形式,如:backgroundColor,marginLeft。
var box = document.querySelector('div')
box.style.color = "#fff" // 将元素中文字设置为白色
box.style.marginLeft = "100px" // 将元素左外边距设置为100px
2、通过classList控制样式
classList属性返回一个元素类属性集合(这里可以简单理解为类名的集合),通过使用classList中的方法可以方便的访问和控制元素类名,达到控制样式的目的
classList常用方法介绍
名称 | 描述 |
---|---|
add(class1, class2, …) | 添加一个或多个类名 |
remove(class1, class2, …) | 移除一个或多个类名 |
replace(oldClass, newClass) | 替换类名 |
contains(class) | 判定类名是否存在,返回布尔值 |
| 如果类名存在,则移除它,否则添加它,第二个参数代表无论类名是否存在,强制添加(true )或删除(false ) |
<div class="box">classList test</div>
<script>
var box = document.querySelector('.box')
box.classList.add('box1', 'box2') // [box] => [box, box1, box2]
box.classList.remove('box1', 'box2') // [box, box1, box2] => [box]
box.classList.replace('box', 'box2') // [box] => [box2]
box.classList.contains('box1') // 当前元素不包含类名box1,返回false
box.classList.toggle('active') // [box2] => [box2, active]
</script>
二、任务背景
当我们需要更改一个标签的文字或内容时,这时就需要了解节点写入的知识,学会节点写入可以帮助我们更加精确的控制网页内容,节点写入的方式有很多种,这里介绍常用的几种方法。
三、任务内容
1、节点写入常用方式
名称 | 描述 |
---|---|
innerHTML | 返回元素中的html内容 ,通过赋值,可设置元素中的html内容 |
innerText | 返回元素中的文本内容,通过赋值,可设置元素中的文本内容 |
document.write() | 将html字符串 写入到文档中 |
1.1 innerHTML
-
在div中写入h1元素
<body>
<div></div>
</body>
<script>
document.querySelector('div').innerHTML = '<h1>我是新内容</h1>'
</script>
如果写入内容中包含html标签字符串,会被解析成对应的html标签
1.2 innerText
-
在div中写入字符串
<body>
<div></div>
</body>
<script>
document.querySelector('div').innerText = '<h1>我是新内容</h1>'
</script>
html标签字符串不会被解析,会被当作普通字符串写入
1.3 document.write()
document.write('我是新内容')
document.write('<h1>我是新内容</h1>')
和innerHTML类似,写入内容如果包含html标签字符串,会被解析成对应的html标签。document.write()根据运行时机,会写入文档不同的位置
事件基础(节点写入)
二、任务背景
当我们需要更改一个标签的文字或内容时,这时就需要了解节点写入的知识,学会节点写入可以帮助我们更加精确的控制网页内容,节点写入的方式有很多种,这里介绍常用的几种方法。
三、任务内容
1、节点写入常用方式
1.1 事件定义
用户与浏览器交互的方法,规定了浏览器在什么时刻执行什么事情
事件举例:鼠标单击,双击,键盘输入,页面或图像载入
1.2 事件三要素(事件源,事件,事件处理程序)
-
事件源:谁触发的,一般指某个元素节点
-
事件:怎么触发的
-
事件处理程序:触发后发生了什么事
2、事件绑定
事件源要与事件绑定后,才能触发对应事件。下面以鼠标点击事件为例,介绍事件的三种绑定方式。
2.1 方式一:行内事件属性赋值
<button onclick="alert('行内事件属性赋值')">点击按钮</button>
2.2 方式二:事件属性赋值
var btn = document.querySelector('button');
btn.onclick = function() {
alert('事件属性赋值')
}
2.3 方式三:事件监听
addEventListener(type, listener, useCapture)
-
type: 事件类型
-
listener: 监听器(处理程序)
-
useCapture: 默认为false,设置为true时,不会因冒泡触发监听器,一般不写
const btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('事件监听')
})
事件属性赋值与事件监听区别:
-
事件属性多次赋值,只会执行最后一次事件处理程序;事件监听可以添加多个监听器,执行多个事件处理程序;
-
事件属性赋值兼容IE8及以下浏览器,而事件监听最低兼容到IE9浏览器
鼠标及键盘事件
三、任务内容
1、常用鼠标事件
名称 | 描述 |
---|---|
click | 单击鼠标左键触发。焦点在按钮并按了Enter键时,也会触发 |
contextmenu | 右键点击(右键菜单显示前触发) |
dblclick | 双击左键触发 |
mouseenter | 指针移至元素范围内触发一次 |
mouseleave | 指针移出元素范围外触发一次 |
mouseover | 指针移至元素或其子元素内,可能触发多次 |
mouseout | 指针移出元素,或者移至其子元素内,可能触发多次 |
代码示例:
var btn = document.querySelector('button')
btn.addEventListener('mouseenter', function() { // 鼠标移入文字为红色
this.style.color = 'red'
})
btn.addEventListener('click', function() { // 鼠标单击文字为蓝色
this.style.color = 'blue'
})
btn.addEventListener('mouseleave', function() { // 鼠标移出文字为黑色
this.style.color = 'black'
})
事件处理程序中的this指代当前操作元素
2、常用键盘事件
名称 | 描述 |
---|---|
keydown | 按下任意按键,按住可连续触发 |
| 按下按键(包括字母,文字和Enter )触发,按住可连续触发,不能监听一些特殊按键(ALT、CTRL、SHIFT、ESC、方向键等 ) |
keyup | 释放任意按键 |
键盘事件经常用于表单元素中,如:
input
输入框
代码示例:
var input = document.querySelector('input')
input.addEventListener('keydown', function() {
console.log('keydown', this.value) // 获取上一次输入值
})
input.addEventListener('keypress', function() {
console.log('keypress', this.value) // 获取上一次输入值
})
input.addEventListener('keyup', function() {
console.log('keyup', this.value) // 获取当前输入值
})
使用时注意触发顺序(keydown
->keypress
->keyup
),不同的键盘事件触发时机不同,返回的结果有区别
3、常用键盘事件属性
使用键盘事件属性可以精确的控制键盘操作,如:回车触发,方向键触发
名称 | 描述 |
---|---|
| keyCode 属性返回keypress 事件触发的键的值的字符代码,或者keydown 或keyup 事件的键盘代码。字符代码 - 表示 ASCII 字符的数字键盘代码 - 表示键盘上真实键的数字 |
charCode | 返回keypress 事件触发时按下的字符键的字符Unicode值,用于keydown 或keyup 时总是返回0 |
key | 返回按键的标识符(字母区分大小写)。keypress ,keyup ,keydown 返回值相同 |
代码示例:
// 以输入a为例,分别查看三种事件返回结果
var input = document.querySelector('input')
input.addEventListener('keydown', function(event) {
console.log(event.keyCode) // 65
console.log(event.charCode) // 0
console.log(event.key) // a
})
input.addEventListener('keypress', function(event) {
console.log(event.keyCode) // 97
console.log(event.charCode) // 97
console.log(event.key) // a
})
input.addEventListener('keyup', function(event) {
console.log(event.keyCode) // 65
console.log(event.charCode) // 0
console.log(event.key) // a
})
可以看到,三种事件中,只有key属性返回的结果保持统一,如果不考虑IE8以下浏览器兼容性,推荐使用key来代替keyCode和charCode
窗口事件
二、任务背景
窗口事件在浏览器窗口发生变化时触发,其中包括窗口大小更改,加载窗口,关闭窗口,窗口滚动等,掌握如何处理窗口事件可以帮助我们实现更加丰富的交互效果。
三、任务内容
1、常用鼠标事件
名称 | 描述 |
---|---|
load | 当整个页面及所有依赖资源(如样式表和图片)都已完成加载时,将触发load事件 |
| window、document 和它们的资源即将卸载时触发。当事件属性 returnValue 被赋值为非空字符串时,会弹出一个对话框,让用户确认是否离开页面(示例如下)。否则,事件被静默处理。一些浏览器实现仅在框架或内置框架接收到用户手势或交互时才显示对话框 |
resize | 窗口大小改变时触发 |
scroll | 元素内发生滚动时触发 |
3.1.1 load事件代码示例
<script>
/* 输出div中文字内容 */
// 方式一
window.addEventListener('load', function() {
console.log(document.querySelector('.box').innerHTML)
})
// 方式二
window.onload = function() {
console.log(document.querySelector('.box').innerHTML)
}
</script>
<div class="box">主要内容</div>
此处JS代码在元素之前,所以应该将代码放在load事件中,等待元素加载完成后再获取其内容。
使用onload绑定事件时,注意一个页面不要存在多个onload,这样会只会运行最后一个onload中的代码,推荐使用addEventListener绑定事件。
1.2 beforeunload事件代码示例
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "confirm close window ?"
// 兼容WebKit与非WebKit内核浏览器
(e || window.event).returnValue = confirmationMessage
return confirmationMessage
})
根据returnValue或return的值可自定义对话框信息(只对IE有效)
1.3 resize事件代码示例
/* 调整浏览器窗口时,获取可视窗口宽高 */
window.addEventListener("resize", function (e) {
console.log(window.innerWidth) // 可视窗口宽
console.log(window.innerHeight) // 可视窗口高
})
多用于检测不同屏幕尺寸,自适应布局。Edge浏览器得打开检查才行。
1.4 scroll事件代码示例
/* 获取滚动条垂直滚动距离 */
window.addEventListener("scroll", function () {
var myTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop; // 兼容写法
console.log(myTop);
})
常用于检测滚动条滚动距离
BOM window对象
二、任务背景
BOM即浏览器对象模型(Browser Object Model),它提供了页面与浏览器窗口进行交互的对象接口。BOM由一系列的相关对象组成,window作为BOM的顶层对象,所有其他全局对象都是window的子对象,甚至DOM也是其子对象之一。学会了window对象及其子对象的常用属性方法,基本就掌握了BOM的大部分知识。
三、任务内容
1、BOM结构
window
对象作为BOM的顶级对象,本身包含一些全局属性和方法,其子对象也有其特有的属性和方法
使用window子对象时,可以使用完整语法,也可以忽略window,如:
window.alert()
与alert()
效果相同
2、window对象
名称 | 描述 |
---|---|
open() | 打开一个新浏览器窗口 |
alert() | 显示警告框 |
close() | 关闭当前浏览器窗口 |
scrollTo() | 可把内容滑动到指定坐标 |
scrollBy() | 可将内容滑动指定的距离(相对于当前位置) |
innerWidth | 返回窗口的网页显示区域宽度 |
innerHeight | 返回窗口的网页显示区域高度 |
2.1 open(url, name, features, replace)
-
url
: 打开指定页面的url,如果没有则打开空白页-
name
: 指定target
属性或窗口名称,支持以下值:-
_blank
–- url加载到新窗口(默认) -
_parent
–- url加载到父框架 -
_self
–- url替换当前页面 -
_top
–- url替换任何可加载的框架集 -
name
-- 窗口名称
-
-
-
features
: 设置新打开窗口的功能样式(如:width=500) -
replace
-
true
–- url替换浏览历史中的当前条目 -
false
–- 在浏览历史中创建新条目
-
// 新窗口打开csdn首页
open('https://www.csdn.net/')
// 当前窗口打开csdn首页
open('https://www.csdn.net/', '_self')
// 新窗口打开csdn首页,并设置窗口宽高500px
open('https://www.csdn.net/', '_blank', 'width=500,height=500')
2.2 scrollTo(xpos, ypos)
-
xpos
:距离网页左上角x坐标 -
ypos
:距离网页左上角y坐标
<style>
.box { height: 3000px; }
</style>
<div class="box">
<p>我是顶部</p>
</div>
<script>
window.addEventListener('load', function() {
scrollTo(0, 500) // 页面加载后,滚动到距离顶部500px
})
</script>
3、location对象
location对象包含当前url信息,经常用于网址判断,url跳转
名称 | 描述 |
---|---|
href | 返回当前完整网址 |
host | 返回主机名和端口号,通常指完整域名 |
protocol | 返回网址协议 |
port | 返回端口号 |
pathname | 返回网址路径部分 |
search | 返回网址中的?及?后的字符串(查询部分),通常指查询参数 |
hash | 返回网址中的#及#后的字符串,通常指锚点名称 |
assign(url) | 在当前页面打开指定新url(增加浏览记录) |
reload() | 重新加载当前页面 |
replace(url) | 打开新url替换当前页面(替换当前浏览记录) |
3.1 获取网址信息
// 以https://www.csdn.net/nav/python?param1=111¶m2=222#first为例,
查看输出结果
console.log(location.href)
// “https://www.csdn.net/nav/python?param1=111¶m2=222#first”
console.log(location.host) // “www.csdn.net”
console.log(location.protocol) // “https://”
console.log(location.pathname) // “/nav/python”
console.log(location.search) // “?param1=111¶m2=222”
console.log(location.hash) // “#first”
3.2 通过给href属性赋值url字符串的方式,可以跳转到对应url
location.href = 'https://www.csdn.net'
4、history对象
history对象包含用户浏览器的历史记录,但是不可读取,经常用于页面跳转
名称 | 描述 | 示例 |
---|---|---|
back() | 返回历史记录的上一个url | history.back() |
forward() | 返回历史记录的下一个url | history.forward() |
go(n) | 返回相对于当前记录的第n个url n>0,表前进;n<0,表后退;n=0,刷新当前页 | history.go(-1) history.go(1) |
5、navigator对象
navigator对象包含浏览器相关信息,经常用于判断设备类型,浏览器兼容性
名称 | 描述 |
---|---|
platform | 返回操作系统类型 |
userAgent | 返回用户代理头的值 |
判断是否为谷歌内核:
navigator.userAgent.toLowerCase().indexOf('chrome')
// 返回-1时不是chrome内核,大于-1时是chrome内核
6、screen对象
screen对象包含用户屏幕的信息
名称 | 描述 |
---|---|
availWidth | 返回屏幕的宽度(不包括windows任务栏) |
availHeight | 返回屏幕的高度(不包括windows任务栏) |
width | 返回屏幕的总宽度 |
height | 返回屏幕的总高度 |
BOM 定时器
二、任务背景
当你需要延时或每隔一段时间执行代码时,这时你就需要学习定时器的知识了,定时器是JS动效的核心,也可用来实现轮询等效果,掌握定时器使用方法是Web开发的重要技能之一。
三、任务内容
1、定时器方法
方法名 | 定义 | 清除定时器方法 |
---|---|---|
| 指定的毫秒数后调用函数或计算表达式 |
|
setInterval() | 按照指定的周期(毫秒)来调用函数或计算表达式 | clearInterval() |
1.1 setTimeout(代码字符串或函数, 等待的毫秒数, 参数1, 参数2…)
setTimeout()
可执行代码字符串,如:a+b,但不推荐使用,有安全风险;
定时器到期时,可以通过
setTimeout()
的额外参数(参数1, 参数2…)给执行函数传递参数(IE9及以下浏览器不支持此语法);
定时器清除方法
clearTimeout(id)
,id为setTimeout()
的返回值;
示例:
<p class="info"></p>
<button class="btn">清除定时器</button>
<script>
var info = document.querySelector('.info')
var btn = document.querySelector('.btn')
var t1 = setTimeout(function() {
info.innerHTML = '已经5秒了'
}, 5000);
// 点击按钮可清除定时器
var btn = document.querySelector('.btn')
btn.addEventListener('click', function() {
clearTimeout(t1)
info.innerHTML = '定时器已清除'
})
</script>
1.2 setInterval(代码字符串或函数, 运行间隔毫秒数,参数1, 参数2…)
语法与
setTimeout()
相似,区别是setInterval()
第二个参数为运行间隔;
由于
setInterval()
是循环执行,如果没有特殊需求,则必须限制执行次数,使用clearInterval(id)
清除定时器;
示例:
<p class="info"></p>
<script>
var info = document.querySelector('.info')
var num = 0
var t1 = setInterval(function() { // 每隔1秒显示当前时间,5次后停止
info.innerHTML = '当前时间:' + String(new Date())
if (num >= 4) { clear() }
num++
}, 1000)
// 清除定时器
function clear() {
clearInterval(t1)
info.innerHTML = '定时器已清除'
}
</script>