Luwang
文章54
标签57
分类25

UV
PV
wallleap
每日一句
:D 获取中...

欣赏音乐
文章列表
JavaScript基础学习笔记

JavaScript基础学习笔记

一、JavaScript简介

1、简介

什么是语言

  • 计算机就是一个由人来控制的机器,人让它干什么,它就得干什么。
  • 我们要学习的语言就是人和计算机交流的工具,人类通过语言来控制、操作计算机。
  • 编程语言和我们说的中文、英文本质上没有区别,只是语法比较特殊。
  • 语言的发展
    • 纸带机:机器语言
    • 汇编语言:符号语言
    • 现代语言:高级语言

JavaScript起源

  • JavaScript诞生于1995年,它的出现除妖是用于处理网页中的前端验证
  • 所谓的前端验证,就是指检查用户输入的内容是否符合一定的规则
  • 比如:用户名的长度,密码的长度,邮箱的格式等

JavaScript简史

  • JavaScript是由网景公司发明,起初命名为LiveScript,后来由于SUN公司的介入更名为了JavaScript
  • 1996年微软公司在其最新的IE3浏览器中引入了自己对JavaScript的实现JScript
  • 于是在市面上存在两个版本的JavaScript,一个网景公司的JavaScript和微软的JScript
  • 为了确保不同的浏览器上运行的JavaScript标准一致,所以几个公司共同定制了JS的标准名命名为ECMAScript

时间表

年份 事件
1995年 网景公司开发了JavaScript
1996年 微软发布了和JavaScript兼容的JScript
1997年 ECMAScript第1版(ECMA-262)
1998年 ECMAScript第2版
1998年 DOM Level1的制定
1998年 新型语言DHTML登场
1999年 ECMASript第3版
2000年 DOM Level2 的制定
2002年 ISO/IEC 16262:2002的确立
2004年 DOM Level3的制定
2005年 AJAX登场
2009年 ECMAScrpt第5版
2009年 新型语言HTML5登场

实现

  • ECMAScript是一个标准,而这个标准需要由各个厂商去实现。
  • 不同的浏览器厂商对该标准会有不同的实现。
浏览器 JavaScript实现方式
FireFox SpiderMonkey
Internet Explorer JScript/Chakra
Safari JavaScriptCore
Chrome v8
Carakan Carakan
  • 我们已经知道ECMAScript是JavaScript标准,所以一般情况下这两个词我们认为是一个意思。
  • 但是实际上JavaScript的含义却要更大一些。
  • 一个完整的JavaScript实现应该由以下三个部分构成:

image-20200812081312883

学习内容

  • 我们已经知道了一 个完整的JavaScript实现包含了三个部分:ECMAScript、DOM和BOM。
  • 由此我们也知道了我们所要学习的内容就是这三部分:
    • ECMAScript
    • DOM
    • BOM

JS的特点

  • 解释型语言
  • 类似于C和Java的语法结构
  • 动态语言
  • 基于原型的面向对象

2、写法

(1) JS代码需要写到script标签中

例如:

<script type=”text/javascript”>
   alert(“Hello”); // 警告框
   document.write(“hahhh”); // 向body中输出一个内容
   console.log(“OK”); // 向控制台输出一个内容
</script>

自上而下顺序执行

(2) JS代码编写位置

  • 写到标签属性中

可以将js代码编写到便签的onclick属性中,当我们点击按钮时,js代码才会执行

<button onclick="alert('点我干嘛~')">点我一下</button>

可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码

<a href="javascript:alert('让你点你就点??');">点我一下</a>
<a href="javascript:;">点我一下</a>

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

  • 写到script标签中
<script type="text/javascript">
  alert('我是script标签中的代码')
</script>
  • 写到js文件中,再引入

可以将js代码编写到外部js文件中,然后通过script标签引入,写到外部文件中可以在不同的页面中同时引用,也可以利用感到浏览器的缓存机制。——推荐使用的方式

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

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

二、ECMAScript

1、注释

// 单行注释
/*
  多行注释,注释中的内容不会被执行,但是可以在源代码中查看
*/

要养成良好的编写注释的习惯,也可以通过注释来对代码进行一些简单的调试

2、说明

  • js代码中严格区分大小写

  • js中每一条语句以分号(;)结尾

    如果不写分号,浏览器会自动添加,但是会消耗一些系统资源(也不会很大),而且有些时候,浏览器会加错分号,所以在开发中分号必须写

关于是否应该写分号可以看下这篇文章:……查找中……

引用下尤雨溪大佬讲的:

没有应该不应该,只有你自己喜欢不喜欢。

至于什么时候加分号。真正会导致上下行解析出问题的 token 有 5 个:括号,方括号,正则开头的斜杠,加号,减号。我还从没见过实际代码中用正则、加号、减号作为行首的情况,所以总结下来就是一句话:

一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。

我以前也都是每行必加的,但就像某位老师讲的,用过了才知道,“不加分号是真的爽啊”

  • js中回忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化

3、字面量和变量

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

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

  • 变量 变量可以用来保存字面量,而且变量的值是可以任意改变的,变量更方便我们使用,所以在开发中都是通过变量去保存一个字面量,而很少直接使用字面量

在js中使用var关键字来声明一个变量,为变量赋值

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

声明和赋值同时进行

var b=789;

也可以通过变量对字面量进行描述

var age = 23;

4、标识符

在js中所有的可以由我们自主命名的都可以称为标识符

如:变量名、函数名、属性名

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

  • 标识符中可以含有字母、数字、_$

  • 标识符不能以数字开头

  • 标识符不能是ES中的关键字或保留字

image-20200812084202495

  • 其他不建议使用的标识符

image-20200812084250806

  • 标识符一般都采用驼峰命名法 helloWorld

  • js底层保存标识符时,实际上是采用Unicode编码,所以理论上讲,所有的utf-8中含有的内容都可以作为标识符

5、数据类型

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

在js中一共有六种数据类型

  • String 字符串

  • Number 数值

  • Boolean 布尔值

  • Null 空值

  • Undefined 未定义

  • Object 对象

  • 前五种属于基本数据类型Object属于引用数据类型

(1) String

  • 在js中字符串需要使用引号引一起 var str=”hello”;

  • 使用双引号或单引号都可以,但是不要混着用

  • 引号不能嵌套,双引号中不能放双引号,单引号中不能放单引号,但是单/双引号中可以放双/单引号

  • 在字符串中,可以使用\作为转义字符,当表示一些特殊符号时,可以使用\进行转义 \” \’ \n \t \\

(2) Number

  • 在js中所有的数值都是Number类型

  • 包括整数和浮点数(小数)

  • 可以使用运算符typeof来检查一个变量的类型

    console.log(typeof a);
    console.log(Number.MAX_VALUE);
  • Number.MAX_VALUE 数字的最大值,超过了这个值回返回Infinity,表示正无穷 -Infinity 负无穷

  • NAN,表示Not A Number,是一个特殊的数字

  • Number.MIN_VALUE 大于0的最小值

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

  • 浮点数计算,可能得到一个不精确的值,不要进行对精确度要求高的计算

(3) Boolean

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

  • true真

  • false假

(4) Null

null专门用来表示一个为空的对象

(5) undefined

声明了一个变量但是没有赋值时,它的值就是undefined

6、强制类型转换

强制类型转换:将一个数据类型转换成其他的数据类型

String Number Boolean

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

var a = 123;
a = a.toString();
  • 该方法不会影响到原变量,它会将转换的结果返回,所以可以直接用该变量接收

  • 但是注意:nullundefined这两个值没有toString()方法,如果调用它们的方法,会报错

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

var a = true
a=String(a);
  • 对于NumberBoolean实际上就是调用toString()方法
  • 但是对于nullundefined,就不会调用toString()方法,它会将null直接转换成"null"

(3) 使用Number()函数

var a = true
a = Number(a);
  • 字符串—>数字
    • 如果是纯数字的字符串,则直接将其转换为数字
    • 如果字符串中有非数字的内容,则转换为NaN
    • 如果字符串是一个空串或者是一个全是空格的字符,转换为0
  • 布尔值—>数字
    • true 转成 1
    • false 转成 0
  • Null—>数字 0
  • undefined—>数字 NaN

(4) 对字符串,parseInt()把一个字符串转换为一个整数,可取整

可以将字符串中的有效的整数内容取出来,然后转换为Number

console.log(parseInt('123a123')) // 123
console.log(parseInt('a123')) // NaN

(5) parseFloat()把一个字符串转换为小数

var a = parseFloat('123.5px'); 
console.log(a) // 123.5

16进制 0x10 8进制 070 2进制 0b10

/* 像'070'这种字符串,有些浏览器会当成八进制解析,有些会当成十进制 */
var a = '070'
/* 可以在parseInt()中传递第二个参数,来指定数字的进制 */
console.log(parseInt(a, 8)) // 56
console.log(parseInt(a, 10)) // 70

(6) 使用Boolean()函数将其他数据类型转换为Boolean

  • 数字 —> 布尔值 除了0和NaN,其他的都是true
  • 字符串 —> 布尔值 除了空串,其他都是true
  • null和undefined都会转换为false

7、运算符

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

比如:typeof就是一个运算符,可以来获得一个值的类型,它会将该值的类型以字符串的形式返回

(1) 算术运算符:

  • 当对非Number类型的值进行运算时,会将这些值转换为Number然后再运算
  • 任何值和NaN做运算都得NaN
  • +可以对两个值进行加法运算,并将结果返回。如果对两个字符串进行加法运算,则会做拼串,将两个字符串拼接成一个字符串,并返回。任何的值和字符串做加法运算,都会先转换为字符串,然后再和字符串做拼串的操作,我们可以让任意的数据类型+””使其转换为字符串(隐式转换)。
  • -可以对两个值进行减法运算,并将结果返回
  • * 可以对两个值进行乘法运算
  • /可以对两个值进行除法运算
  • % 取模运算(取余数)

(2) 一元运算符 只需要一个操作数

  • + 正号 正号不会对数字产生任何影响

  • -负号 负号可以对数字进行负号的取反

对于非Number类型的值,它会先转换为Number,然后再运算,可以对一个其它的数据类型使用+,将其转换为Number,它的原理和Number()函数一样

(3) 自增和自减

自增++ 可以使变量在自身的基础上增加1,原变量的值改变

后++(a++) 前++(++a) 都会立即使原变量的值自增1,但是两个值不同,后++为原值,前++为自增后的值,都改变了a的值,但是自身的看情况。自减--类似,只是变为了减一。

var a = 5
console.log(a, a++, a, ++a, a) // 5 5 6 7 7
console.log(a, a--, a, --a, a) // 7 7 6 5 5

(4) 逻辑运算符 逻辑判断

  • ! 对一个值进行非运算,对布尔值进行取反操作
    • 取反 true变false、false变true
    • 如果对一个值进行两次取反,它不会变化
    • 如果对非布尔值进行运算,则会将其转换为布尔值,然后再取反,所以我们可以利用这个特点,来讲一个其他的数据类型转换为布尔值(可以为一个任意数据类型取两次反,来将其转换为布尔值),原理和Boolean()函数一样
var a = true
a=!a
console.log(a) // false
  • && 对符号两侧的值进行与运算并返回结果

    运算规则

    • 两个值只要有一个为false就返回false,只有两个值都为true时才会返回true

    • js中的与属于短路的与,如果第一个值为false,就不会再看第二个值了

// 如果两个值都是true则返回true
var result = true && true
console.log(result) // true
// 只要有一个false,就返回false
result = true && false
console.log(result) // false
console.log(false && true) // false
console.log(false && false) // false
// 第一个值为true,会检查第二个值
true && alert('我会弹出来哦')
// 第一个值为false,不会检查第二个值
false && alert('不会弹出来')
  • || 可以对符号两侧的值进行或运算并返回结果

    运算规则

    • 两个值中只要有一个true就返回true,如果两个值都为false,才返回false

    • js中的或属于短路的或,如果第一个值为true,就不会看第二个值

// 两个都是false,则返回false
console.log(false || false)
// 只要有一个true,就返回true
console.log(true || false)
console.log(false || true)
console.log(true || true)
// 第一个值为false,会检查第二个值
false || alert('123')
// 第一个值为true,则不会检查第二个值
true || alert('123')
  • && || 的非布尔值情况

    • 对于非布尔值进行与或运算时,会先将其转换为布尔值,再运算,并且返回原值
    • 与运算:如果第一个值为true,则必然返回第二个值。 如果第一个值为false,则直接返回第一个值
    // true && true
    // 与运算:如果两个值都为true,则返回后边的
    var result = 5 && 6
    console.log(result) // 6
    // 与运算:如果两个值中有false,则返回靠前的false
    // false && true
    result = 0 && 2
    console.log(result) // 0
    result = 2 && 0
    console.log(result) // 0
    // false && false
    result = NaN && 0
    result = 0 && NaN
    console.log(result) // 0
    • 或运算:如果第一个值为true,则直接返回回一个值。 如果第一个值为false,则返回第二个值
    // true || true , true || false
    // 如果第一个值为true,则直接返回第一个值
    console.log(2 || 1) // 2
    console.log(2 || NaN) // 2
    console.log(2 || 0) // 2
    // 如果第一个值为false,则直接返回第二个值
    console.log(NaN || 1) // 1
    console.log(NaN || 0) // 0
    console.log(0 || NaN) // NaN

(5) 赋值运算符=

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

复合运算+=-=*=/=%=

var a = 10
a += 5 // a = a + 5
a -= 5 // a = a - 5
a *= 2 // a = a * 2
a /= 2 // a = a / 2
a %= 3 // a = a % 3

(6) 关系运算符

可以比较两个值之间的大小关系

如果关系成立它会返回true,如果关系不成立则返回false

  • > 大于号

    • 判断符号左侧的值是否大于右侧的
    • 如果关系成立则返回true,如果关系不成立则返回false
    var result = 5 > 10 // false
    result = 5 > 4 // true
    result = 5 > 5 // false
  • >= 大于等于 是否大于或等于

  • < 小于号

  • <= 小于等于

非数值的情况

  • 对于非数值进行比较时,会将其转换为数字然后再比较
console.log(1 > true) // false
console.log(1 >= true) // true
console.log(1 > '0') // true
console.log(10 > null) // true
// 任何值和NaN做任何比较都是false
console.log(10 <= "hello") // false
console.log(1000000000 > NaN) // false
console.log(true > false) // true
  • 如果符号两侧的值都是字符串时,不会将其转换为数字进行比较,而是会分别比较字符串中字符的Unicode编码
// 比较练歌字符串时,比较的是字符串的字符编码
console.log('a' < 'b') // true
// 比较字符编码时是一位一位进行比较的,如果两位一样则比较下一位,所以可以借用它对英文进行排序
console.log('abc' < 'bcd') // true
// 比较中文时没有意义
console.log("我" > "你") // true
// 如果比较两个字符串型的数字,可能会得到不可预测的结果
console.log('1222222222' < '5') // true
// 因此在比较练歌字符串型的数字时,一定要转型
console.log('1222222222' < +'5') // false

(7) 相等运算符

  • 使用==来做相等运算

相等运算符用来比较两个值是否相等,如果相等会返回true,否则返回false

如果两个进行比较的值类型不同,则会自动进行类型转换,将其转换为相同的类型,然后再比较

console.log(1 == 1); //true
var a=10;
console.log(a == 4); //false
console.log("1" == 1); //true
console.log(true == "1"); //true
console.log(null == 0); //false

由于undefined衍生自null,所以这两个值做相等判断时,会返回ture

console.log(undefined == null) // true

NaN不和任何值相等,包括它本身

console.log(NaN == "1") // false
console.log(NaN == NaN) // false

因此需要通过其他方式判断:isNaN()函数就是用来判断一个值是否是NaN的

var a = 'abc'
a = Number(a)
console.log(a, isNaN(a)) // NaN, true
console.log(isNaN(NaN)) // true
  • 使用!=来做不相等运算

不相等运算符用来判断两个值是否不相等,如果不相等会返回true,否则返回false

不相等运算符也会对变量进行自动类型转换,如果转换后相等它也会返回false

  • 使用===来做全等运算

用来判断两个值是否全等,它和相等类似,不同的是他不会做自动类型转换,如果两个值的类型不同,直接返回false

  • 使用!==来做不全等运算

用来判断两个值是否不全等,和不等类似,不同的是它不会做自动类型转换

(8) 条件运算符,也叫三元运算符

条件表达式?语句1:语句2

执行的流程:

首先对条件表达式进行求值,如果该值为true,则执行语句1,并返回执行结果;如果该值为false,则执行语句2,并返回执行结果。

非布尔值会先转换为布尔值

var a = 30
var b = 20
var c = 10
a > b ? alert('a大') : alert("b大")

// 获取a和b中的较大值
var max = a > b ? a : b
// 获取a、b、c中的最大值
max = max > c ? max : c

// 也可以放到一起,但是不推荐使用,不方便阅读
var max = a > b ? (a > c ? a : c) : (b > c ? b :c)

(9) 逗号运算符

使用,可以分割多个语句,一般可以在声明多个变量时使用

// 使用逗号运算符同时声明多个变量
var a, b, c
// 可以同时声明多个变量并赋值
var a = 1, b = 2, c = 3
alert(b)

和数学中一样,在js中运算符也有优先级,例如先乘除后加减

在JS中有一个运算符优先的表,在表中越靠上优先级越高,优先级越高越优先运算,如果优先级一样,则从左往右计算,可以利用()改变优先级

运算符的优先级

8、编码

在字符串中使用转义字符输入Unicode编码:\u四位编码

console.log('\u2620')

在网页中使用Unicode编码:&#编码;这里的编码需要的是十进制

<h1 style="font-size: 200px;">&#9760</h1>

9、语句

  • 前面我们说的表达式、运算符等内容可以理解成是一门语言中的单词、短语
  • 语句(statement)就是我们这个语言中一句一句完整的话了
  • 语句是一个程序的基本单位,js的程序就是由一条一条语句构成的,每一条语句使用;结尾
  • js中的语句默认是由上至下顺序执行的,但是我们也可以通过一些流程控制语句来控制语句的执行顺序
  • 在js中可以使用{}来为语句进行分组,同一个{}中的语句我们称为是一组语句,它们要么都执行,要么都不执行,一个{}中的语句我们也称为一个代码块,在代码块的后边就不用再编写;
  • js中的代码块,只具有分组的作用,没有其他的用途,代码块中的内容,在外部是完全可见的
{
    alert('hello');
  console.log('你好');
  document.write("语句");
}

流程控制语句

  • JS中的程序是从上到下一行一行执行的。
  • 通过流程控制语句可以控制程序执行流程,使程序可以根据一定的条件来选择执行。
  • 语句的分类:
    1. 条件判断语句
    2. 条件分支语句
    3. 循环语句

(1) 条件判断语句

使用条件判断语句可以在执行某个语句之前进行判断,如果条件成立才会执行语句,条件不成立则语句不执行。

if语句

语法一:

if(条件表达式){
    语句……
}

if语句在执行时,会先对条件表达式进行求值判断,如果条件表达式的值为true,则执行if后的语句,如果条件表达式的值为false,则不会执行if后的语句。

if语句只能控制紧随其后的那个语句,如果希望if语句可以控制多条语句,可以将这些语句统一放到代码块中。

语法二:

if(条件表达式){
    语句……
}else{
    语句……
}

if…else…语句

当该语句执行时,会先对if后的条件表达式进行求值判断如果该值为true,则执行if后的语句,如果该值为false,则执行else后的语句。

语法三:

if(条件表达式){
    语句……
}else if(条件表达式){
    语句……
}else if(条件表达式){
    语句……
}else{
    语句……
}

if…else if…else…

当该语句执行时,会从上到下依次对条件表达式进行求值判断,如果值为true,则执行当前语句,如果值为false,则继续向下判断。

补充一个知识点:

prompt()可以弹出一个提示框。该提示框中会带有一个文本框,用户可以在文本恒中输入一段内容,该函数需要一个字符串作为参数,该字符串将会作为提示框的提示文字。用户输入的内容将会作为函数的返回值返回,可以定义一 个变量来按收该内容。

var score = prompt("请输入成绩:")
// 判断是否合法
if(score > 100 || score < 0 || isNaN(socre)){
  alert("请输入0~100的整数")
}

(2) 条件分支语句

switch(条件表达式){
    case 表达式:
        语句……
        break;
  case 表达式:
        语句……
        break;
    default:
        语句……
        break;
}

switch…case..语句
在执行时会值次将case后的表达式的值和switch后的条件表达式的值进行全等比较。
如果比较结果为true,则从当前case处开始执行代码。当前case后的所有的代码都会执行,我们可以在case的语句后加上一个break关键字,这样可以确保只会执行当前case后的语句,而不会执行其他的case。
如果比较结果为false,则继续向下比较。
如果所有的比较结果都为false,则只执行default后的语句。

switch语句和If语句的功能实际上有重复的,使用switch可以在现if的功能,同样使用if也可以实现switch的功能, 所以我们使用时,可以根据自己的习惯选择。

/*
switch(parseInt(score/10)){
    case 10:
    case 9:
    case 8:
        console.log("优秀");
        break;
    case 7:
    case 6:
        console.log("合格");
        break;
    default:
        console.log("不合格");
        break;
}
*/
switch(true){
  case score >= 60:
    console.log("合格");
    break;
  default:
    console.log("不合格");
    break;
}

(3) 循环语句

通过循环语句可以反复地执行一段代码多次

while循环

  • 语法:
while(条件表达式){
  语句……
}
  • while语句在执行时,先对条件表达式进行求值判断,如果值为true,则执行循环体,循环体执行完毕以后,继续对表达式进行判断,如果为true,则继续执行循环体,以此类推,如果值为false则终止循环
// 像这种条件表达式写死为true的循环,叫做死循环。该循环不会停止,除非浏览器关闭,死循环在开发时慎用。可以使用break来终止循环。
while(true){
  alert(n++)
  if(n == 10){
    break
  }
}
// 创建一个循环,往往需要三个步骤:
// 1、初始化一个变量
var i = 1
// 2、在循环中设置一个条件表达式
while(i < 300){
  // 3、定义一个更新表达式,每次更新初始化变量
  document.write(i++ + "<br />")
}

do…while循环

  • 语法:
do{
    语句……
}while(条件表达式)
  • 执行流程:

do…while语句在执行时,会先执行循环体,循环体执行完毕以后,再对while后的条件表达式进行判断,如果结果为true,则连续执行循环体,执行完毕后继续判断以此类推,如果结果为false则终止循环

实际上while和do…while这两个语句功能相似,不同的是while是先判断后执行,而do…while可以保证循环体至少执行一次,而while不能

do{
  document.write(i++ + '<br />')
}while(i <= 10)

while(true){
  var score = prompt('请输入成绩:')
  if(score >= 0 && score <= 100){
    alert('成绩合法')
    break
    }
  alert('请输入有效的分数!')
}

for循环

for语句,也是一个循环语句,也称为for循环

在for循环中,提供了专门的位置用来放三个表达式:

  1. 初始化表达式
  2. 条件表达式
  3. 更新表达式
  • 语法:
for(初始化表达式; 条件表达式; 更新表达式){
    语句……
}
  • 执行流程:

①执行初始化表达式,初始化变量(初始化表达式只会执行一次)

②执行条件表达式,判断是否执行循环。

​ 如果为true,则执行循环 ③

​ 如果为false,终止循环

④执行更新表达式,更新表达式执行完毕继续重复 ③

// for循环中的三个部分都可以省略,也可以写在外部
var i = 0
for(; i<10;){
  alert(i++)
}
// 如果在for循环中不写任何的表达式,只写两个分号,即for(;;),此时是一个死循环
for(var i=100; i<1000; i++){
    var th = parseInt(i/100) 
  var te = parseInt((i-th*100)/10)
  var on = i%10
  // 判断i是否是水仙花数
  if(th*th*th + te*te*te + on*on*on == i)
    console.log(i)
}

补充:break和continue

  • break关键字可以用来退出switch或循环语句,不能在if语句中使用break和continue,break关键字会立即终止离他最近的那阿哥循环语句

可以为循环语句创建一个label,用来标识当前的循环label: 循环语句。使用break时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。

outer:
for(var i=0; i<5; i++){
  console.log("@外层循环"+i)
  for(var j=0; j<5; j++){
    break outer // 终止外层循环(外层循环都没执行,内层循环自然也执行不了了)
    console.log("@内层循环"+j)
  }
}
  • continue关键字可以用来跳过本次循环,通用continue也是默认只会对离他最近的循环起作用
for(var i=0; i<5; i++){
  if(i==2){
    continue;
  }
  console.log(i) // 0 1 3 4
}

// 当然,也可以用来跳过指定的
outer: for(var i=0; i<5; i++){
  console.log("@外层循环"+i)
  for(var j=0; j<5; j++){
    if(j==1){
      // continue
      continue outer
    }
    console.log("@内层循环"+j)
  }
}
/*
 测试某段代码的性能:
* 在代码执行前,开始计时。console.time("计时器的名字")可以用来开启一个计时器,它需要一个字符串作为参数,这个字符串将会作为计时器的标识
* 在代码结束后终止计时器,console.timeEnd("计时器的名字")用来停止一个计时器,需要一个计时器的名字作为参数
*/
console.time('test')
for(var i=2; i<=10000; i++){
  var flag = true
  for(var j=2; j<i; j++){
    if(i%j == 0){
      flag = false
      // break
    }
    if(flag){
      // console.log(i)
    }
  }
}
console.timeEnd('test')

可以通过Math.sqrt()对一个数进行开方:

var result = Math.sqrt(4)

10、对象

五种基本数据类型:

String字符串、Number数值、Boolean布尔值、Null空值、Undefined未定义

我们以后看到的值只要不是这五种,全都是对象(Object)

基本数据类型都是单一的值”helloe”、123、true,值和值之间没有任何的联系

在js中表示一个人的信息(name gender age):

var name = "张三"
var gender = "男"
var age = 18

如果使用基本数据类型的数据,我们所创建的变量都是独立的,不能成为一个整体

对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。

对象的分类:

  1. 内建对象
    • 由ES标准中定义的对象,在任何的ES的实现中都可以使用
    • 比如:Math、String、Number、Boolean、Function、Object……
  2. 宿主对象
    • 由JS运行环境提供的对象,目前来讲主要指由浏览器提供的对象
    • 比如BOM、DOM
  3. 自定义对象
    • 由开发人员自己创建的对象
  • 创建对象

使用new关键字调用的函数,是构造函数constructor,构造函数是专门用来创建对象的函数。使用typeof检查一个对象时,会返回object。

var obj = new Object()
console.log(obj, typeof(obj))
  • 添加属性

在对象中保存的值称为属性

向对象添加属性,语法:对象.属性名=属性值;

// 向obj中添加一个name属性
obj.name = "张三"
// 向obj中添加一个gender属性
obj.gender = "男"
// 向obj中添加一个age属性
obj.age = 18
console.log(obj)
  • 读取属性

读取对象中的属性,语法:对象.属性名

如果读取对象中没有的属性,不会报错,而是会返回undefined

console.log(obj.gender)
console.log(obj.hello)
  • 修改属性值

修改对象的属性值,语法:对象.属性名=新值

obj.name = "tom"
console.log(obj.name)
  • 删除属性

删除对象的属性,语法:delete 对象.属性名

delete obj.name
console.log(obj.name)

属性名

  • 对象的属性名不强制要求遵守标识符的规范,什么乱七八糟的名字都可以取
  • 但是我们使用的时候还是尽量按照标识符的规范去做
  • 如果想要使用特殊的属性名,不能采用.的方式来操作,需要使用另一种方式,语法:对象["属性名"]=属性值,读取时也需要采用这种方式对象.["属性名"]。使用[]这种形式去操作属性,更加地灵活,在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性(变量的时候也只能采用这种方式)。
obj["nihao"] = "你好"
var n = "nihao"
console.log(obj[n])

属性值

  • js对象的属性值,可以是任意的数据类型,甚至也可以是一个对象
var obj1 = new Object()
obj1.name = "对象"
obj1.obj2 = new Object()
obj1["2"] = null
obj1["num"] = 12345
var a = u
obj1[a] = undefined

in运算符

  • 通过该运算符可以检查一个对象中时候含有指定的属性,如果有则返回true,没有则返回false
  • 语法:"属性名" in 对象
console.log("name" in obj1)
console.log("test" in obj1)

基本数据类型和引用数据类型

基本数据类型:StringNumberBooleanNullUndefined

引用数据类型:Object

js中的变量都是保存到栈内存中的

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

image-20200812163822217

  • 对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当修改其中一个的变量属性时,另一个也会受到影响。
var obj = new Object()
obj.name = "张三"
var obj2 = obj
obj.name = "李四"
console.log(obj.name)
console.log(obj2.name)

image-20200812164415240

new会在堆内存中开辟空间

obj2=null,这样obj2就没有指向0x123这个地址了

当比较两个基本数据类型的值时,就是比较值。

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

var c = 10
var d = 10
console.log(c == d)

var obj3 = new Object()
var obj4 = new Object()
obj3.name = "张三"
obj4.name = "张三"
console.log(obj3, obj4, obj3==obj4)

对象字面量

/* 创建一个对象 */
// var obj = new Object()
/* 使用对象字面量来创建一个对象 */
var obj = {}
console.log(typeof obj)
obj.name = "张三"
console.log(obj.name)

使用对象字面量,可以在创建对象时,直接指定对象中的属性,语法:{属性名:属性值,属性名:属性值……}

var obj2 = {name:"张三", age: 18, gender: "男"}
console.log(obj2)
var obj3 = {
  name: "李四",
  age: 23,
  gender: "男"
}

对象字面量的属性名可以加引号也可以不加,建议不加,如果要使用一些特殊的名字,则必须加引号。

属性名和属性值是一组一组的名值对结构,名和值之间使用:连接,多个名值对之间使用,隔开,如果一个属性之后没有其他的属性了,就不要写,

11、函数

(1) 函数function

  • 函数也是一个对象
  • 函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)
  • 函数中可以保存一些代码在需要的时候再调用
  • 使用typeof检查一个函数对象时,会返回function
// 创建一个函数对象
var fun = new Function()
console.log(typeof fun)

(2) 创建函数和调用函数

  • 在创建一个函数对象的时候,可以将要封装的代码以字符串的形式传递给构造函数
  • 封装到函数的代码不会立即执行
  • 函数中的代码会在函数调用的时候执行
  • 调用函数语法:函数对象()
  • 当调用函数时,函数中封装的代码会按照顺序执行
  • 调用几次就会执行几次
var fun = new Function("console.log('这是一个函数哦')")
fun()
fun()

我们在实际开发中很少使用构造函数来创建一个函数对象,而是使用其他方式,例如以下两种(事实上学完ES6后这两种方式也很少使用了)

使用函数声明来创建一个函数

语法:

function 函数名([形参1, 形参2...形参N]){
    语句……
}

其中[]代表可选

function fun2(arg){
  console.log("调用了这个" + arg + "函数了~")
}
// console.log(fun2)
fun2("fun2")

使用函数表达式来创建一个函数

语法:

var 函数名 = ffunction([形参1, 形参2...形参N]){
    语句……
}
var fun3 = function(){
  console.log('fun3')
}
fun3()

(3) 函数的参数

  • 可以在定义函数的时候,在函数的()中指定一个或多个形参(形式参数),多个形参之间使用,隔开,声明形参就相当于在函数内部声明了对应的变量,但是并没有赋值。

  • 在调用函数的时候,可以在()中指定实参(实际参数),实参将会赋值给函数中对应的形参。

    • 调用函数时解析器不会检查实参的类型,所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查(函数的实参可以是任意的数据类型)。
    • 调用函数时,解析器也不会检查实参的数量,多余的实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
/*
 * 定义一个用来求两个数和的函数
*/
function sum(a, b){
  console.log(a+b)
}
sum(1,2)
sum(123,456)

(4) 返回值

可以使用return来设置函数的返回值

语法:return 值

return后的值将会作为函数的执行结果返回,可以定义一个变量来接收该结果

function sum(a, b, c){
  var d = a + b + c
  return d
}
var result = sum(4,7,8)

在函数中return后的语句都不会执行

如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return,也是返回undefined

return后可以跟任意类型的值(返回值可以是任意的类型),可以是一个对象,可以是一个函数……

在函数内部可以再声明一个函数,可以这样调用——fun()()

总结:使用break可以退出当前循环,使用continue跳过当次循环,使用return可以结束整个函数。

(5) 立即执行函数(匿名函数)——只想调用一次

函数定义完,立即被调用。

(function(){
  alert("我是一个匿名函数~~~");
})();

如果不喜欢写分号的,记得上面说过的规则,开头是()[]需要加上分号:

;(function(){
  alert("我是一个匿名函数~~~")
})()

(6) 函数与方法

函数也可以成为对象的属性,如果一个函数作为一个对象的属性保存,那么我们称这个函数时这个对象的方法(method),调用这个函数就说调用对象的方法。
但是它只是名称上的区别没有其他的区别。

var obj = new Object()
obj.name = "张三"
obj.age = 21
obj.sayName = function(){
  console.log(obj.name)
}
// console.log(obj.sayName)
obj.sayName()

调用方法:obj.sayName()

调用函数:fun()

var obj2 = {
  name: "李四",
  age: 18,
  sayName: fuction(){
        console.log(obj2.name)    
    }
}
obj.sayName()

12、for…in

使用for…in语句可以枚举对象中的属性

语法:

for(var 变量 in 对象){

}

for…in语句,对象中有几个属性,循环体就会执行几次,每次执行时,会将对象中的恶一个属性的名字赋值给变量

for(var index in obj){
    console.log("属性名:"+index)
  console.log("属性值:"+obj[index])
}

13、作用域scope

作用域指一个变量的作用的范围

在js中一共有两种作用域:全局作用域和函数作用域

  • 全局作用域

    • 直接编写在script标签中的js代码,都在全局作用域
    • 全局作用域在页面打开时创建,页面关闭时销毁。
    • 在全局作用域中有一个全局对象window,代表的是一个浏览器的窗口,它由浏览器创建,我们可以直接使用
    • 在全局作用域中,创建的变量都会作为window对象的属性保存;创建的函数都会作为window对象的方法保存
    var a = 10
    console.log(window.a)
    function fun(){
      console.log("fun()")
    }
    window.fun()
    • 全局作用域中的变量都是全局变量,在页面的任意的部分都是可以访问到的。
  • 函数作用域
    • 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
    • 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的
    • 在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量
    • 当前函数作用域操作一个变量时,它会现在自身作用域中寻找,如果有就直接使用;如果没有就往上一级作用域中去找,知道找到全局作用域;如果全局作用域中依然没有找到,则会报错ReferenceError
    • 在函数中要访问全局变量可以使用window对象
    • 在函数作用域中也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前声明。函数声明也会在函数中所有的代码执行之前声明
    • 在函数中,不使用var声明的变量都会成为全局变量
    • 定义形参就相当于在函数作用域中声明了变量

14、声明提前

变量的声明提前

  • 使用var关键字声明的变量,会在所有的代码执行之前被声明(即使放在使用的之后)但提前声明并不会同时赋值
// 没有var a时
console.log(a) // 报错Uncaught ReferenceError: a is not defined
--------------------------------------------------------------
// 提前声明,相当于在这里 var a
console.log(a) // undefined
var a = 1     // 这里a=1
console.log(a) // 1
  • 但是如果声明变量时不使用var关键字,则变量不会被声明提前

函数的声明提前

  • 使用函数声明形式创建的函数function 函数(){},它会在所有的代码执行之前就被创建
fun() // 声明提前,输出fun()
function fun(){
    console.log("fun()")
}
  • 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用
var fun2 = function(){
  console.log("我不会被提前声明")
}

15、this

解析器在调用函数时每次都会向函数内部传递一个隐含的参数

这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式 的不同,this会指向不同的对象。

  1. 以函数的形式调用,this永远都是window
  2. 以方法的形式调用,this就是调用方法的那个对象
  3. 当以构造函数的形式调用时,this就是新创建的那个对象

在后面的学习中将慢慢补全this是什么

function fun(){
    console.log(this.name)
}

16、使用工厂方法创建对象

通过该方法可以大批量的创建对象

function createPerson(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 zbj = createPerson("猪八戒",1030,"男")
var lcg = createPerson("李长庚",11030,"男")
var ce = createPerson("嫦娥",18,"女")
ce.sayName()

使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型,这就导致我们无法区分出多种不同类型的对象

17、构造函数

构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。

构造函数和普通函数的区别就是调用方法的不同,普通函数时直接调用,而构造函数需要使用new关键字调用

function Person(){}
var per = new Person()
console.log(per)

构造函数的执行流程:

  • 立刻创建一个新的对象

  • 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象

  • 逐行执行函数中的代码

  • 将新建的对象作为返回值返回

function Person(name, age, gender){
  this.name = name
  this.age = age
  this.gender = gender
  this.sayName = function(){
    alert(this.name)
  }
}
var zbj = new Person("猪八戒",1030,"男")
var lcg = new Person("李长庚",11030,"男")
var ce = new Person("嫦娥",18,"女")
console.log(zbj)
console.log(lcg)
console.log(ce)

使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象,称为是该类的实例

18、instanceof

使用instanceof可以检查一个对象是否是一个类的实例

语法:对象 instanceof 构造函数

如果是,则返回true,否则返回false

console.log(lcg instanceof Person) // true
console.log(dog instanceof Person) // false

注意:

所有的对象都是Object的后代,所以任何对象和Object做instanceof检查时都会返回true

console.log(dog instanceof Object)

缺陷

创建一个Person构造函数,在Person构造函数中, 为每一个对象都得加了一个sayName方法。
目前我们的方法是在构造固数内部创建的,也就是构造函数每执行一次就会创建一个新的sayName方法,也就是说实例的sayName都是唯一的。
这样就导致了构造函数执行一-次就会创建一个新的方法,执行10000次就会创建10000个新的方法,面10000个方法都是一 模一样的,这是完全没有必要,完全可以使所有的对象共享同一个方法。

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("张三", 21, "男")
var per2 = new Person("李四", 18, "男")

将函数定义在全局作用域中,污染了全局作用域的命名空间,而且也不安全

19、原型prototype

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象

如果函数作为普通函数调用,prototype没有任何作用

当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__来访问该属性

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中

当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用

// 向MyClass的原型中添加属性a
MyClass.prototype.a = 123
// 向mc中添加a属性
mc.a = "我是mc中的a"

image-20200812192849700

mc、mc2、mc3是通过MyClass创建的对象,完整代码如下

function MyClass(){

}
MyClass.prototype.a = 123
var mc = new MyClass()
var mc2 = new MyClass()
var mc3 = new MyClass()
mc.a = "我是mc中的a"
console.log(mc.a) // 由于mc中自己有a,因此输出自己的 我是mc中的a
console.log(mc2.a)
console.log(mc3.a) // 这两个自己没有a,因此会到原型中去找,找到了则输出 123

建议:以后我们创建构造函数时,可以将这些对象共有的属性和方法。 统一添加加到构造函教的原型对象中,这样不用分别为每一个对像添加,也不会影响到到全局作用城,就可以使每个对象都具有这些属性和方法了

function Person(name, age, gender){
  this.name = name
  this.age = age
  this.gender = gender
}
// 向原型中添加sayName方法
Person.prototype.sayName = function(){
    alert(this.name)
}

使用in检查对象中是否含有某个属性是,如果对象中没有,但是原型中有,也会返回true

console.log("a" in mc2) // true

可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,该方法只有当对象自身中含有属性时,才会返回true

console.log(mc.hasOwnProperty("age")) // false
console.log(mc.hasOwnProperty("a")) // true
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true

原型对象也是对象,所以它也有原型,当我们使用一个对象的属性或方法时,会先在自身中寻找,自身中如果有,则直接使用;如果没有则去原型对象中寻找,如果原型对象中有,则使用;如果没有则去原型的原型中寻找,直到找到0bject对象的原型,Object对象的原型没有原型,如果在Object原型中仍然没有找到,则返回undefined。

image-20200812195159809

当我们直接在页面中打印一个对象时,实际上输出的是对象的toString()方法的返回值

function Person(name, age, gender){
  this.name = name
  this.age = age
  this.gender = gender
}
var per = new Person("张三", 21, "男")
var result = per.toString()
console.log("result="+result) // result=[object Object]
console.log(per.__proto__.__proto__.hasOwnProperty("toString")) // true

如果我么希望在输出对象时不输出[object Object],可以为对象添加一个toString方法

Person.prototype.toString = function(){
  return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]"
}

20、垃圾回收(GC)

  • 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生的垃圾
  • 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理
  • 在js中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作

image-20200812201503886

  • 因此,我们需要做的只是将不再使用的对象设置为null即可

21、数组

  • 数组(Array)也是一个对象
  • 它和普通对象功能类似,也是用来存储一些值的
  • 不同的是普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引操作元素的
  • 索引:从0开始的整数
  • 数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据

image-20200812202046775

/* 创建数组对象 */
var arr = new Array()
console.log(typeof arr) // object
// 使用构造函数创建数组时,可以同时添加元素,将要添加的元素作为构造函数的参数传递,元素之间用逗号隔开
var arr1 = new Array(10,20,30)
console.log(arr1)
/* 向数组中添加元素:数组[索引]=值 */
arr[0] = 10
arr[1] = 20
console.log(arr) // [10, 20]
/* 读取数组中的元素:数组[索引]
 * 如果读取不存在的索引,不会报错,而是返回undefined
*/
console.log(arr[0]) // 10
/* 获取数组的长度,使用length属性来获取
 * 语法:数组.length
 * 对于连续的数组,使用length可以获取到数组的长度(元素的个数)
 * 对于非连续的数组,使用length会获取到数组的最大索引+1  尽量不要创建非连续的数组
*/
console.log(arr.length) // 2
/* 修改length
 * 如果修改的length大于原长度,则多出的部分会空出来
 * 如果修改的length小于原长度,则多出的元素会被删除
*/
arr.length = 10
/* 向数组的最后一个位置添加元素
 * 语法:数组[数组.length] = 值
*/
arr[arr.length] = 30
arr[arr.length] = 40
arr[arr.length] = 50

使用字面量来创建数组

/* 使用字面量来创建数组
 * 语法:[]
*/
var arr = []
console.log(typeof arr, arr instanceof Array) // object true
/* 使用字面量床架数组时,可以在创建时就指定数组中的元素 */
var arr1 = [1,2,3,4,5,6]
console.log(arr[3])
// 数组中的元素可以是任意的数据类型
arr = ["hello",1,true,null,undefined]
console.log(arr)
// 也可以是对象
var obj = {name:"张三"} 
arr[arr.length] = obj
// 可以是函数
arr = [function(){alert(1)}, function(){alert(2)}]
arr[0]()
// 数组中也可以放数组,如下这种数组称为二维数组
arr = [[1,2,3], [3,4,5], [5,6,7]]
console.log(arr[1])

22、数组的方法

方法 描述
concat() 连接两个或更多的数组,并返回结果。
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reverse() 颠倒数组中元素的顺序。
shift() 删除并返回数组的第一个元素
slice() 从某个已有的数组返回选定的元素
sort() 对数组的元素进行排序
splice() 删除元素,并向数组添加新元素。
toSource() 返回该对象的源代码。
toString() 把数组转换为字符串,并返回结果。
toLocaleString() 把数组转换为本地数组,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值

push()

  • 该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度
  • 可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾
  • 该方法会将数组新的长度作为返回值返回
var result = arr.push("HTML", "CSS", "JavaScript")
console.log(arr, result)

pop()

  • 该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
result = arr.pop()
console.log(arr, result)

unshift()

  • 向数组开头添加一个或多个元素,并返回新的数组长度
  • 向前边插入元素以后,其他的元素索引会依次调整
console.log(arr)
arr.unshift("HTTP")
console.log(arr)

shift()

  • 可以删除数组的第一个元素,并将被删除的元素作为返回值返回
result = arr.shift()
console.log(arr, result)

数组的遍历

for循环

/* 所谓的遍历数组,就是将数组中的元素都取出来
 * arr[0]
 * arr[1]
 * ...
 * arr[lenght-1]
*/
for(var i=0; i<arr.length; i++){
  console.log(arr[i])
}

forEach

一般我们都是使用for循环去遍历数组,js中还为我们提供了一个方法,用来遍历数组forEach()

这个方法只支持IE8以上的浏览器,IE8及以下的浏览器均不支持该方法,还是使用for

forEach( )方法需要一个函数作为参数

  • 像这种函数,由我们创建但是不由我们调用但最后执行了的,我们称为回调函数

  • 数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素
    以实参的形式传递进来, 我们可以来定义形参,来读取这些内容

  • 浏览器会在回调函数中传递三个参数:

    • 第一个参数,就是当前正在遍历的元素
    • 第二个参数,就是当前正在遍历的元素的索引
    • 第三个参数,就是正在遍历的数组
    arr.forEach(function(value, index, obj){
      console.log(value, index)
    })

slice()

  • 可以用来从数组提取指定元素
  • 该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回
  • 参数,
    1. 数取开始的位置的索引,包含开始索引
    2. 截取結東的位置的索引,不包含结束索引
      • 第二个参数可以省略不写,此时会截取从开始索引往后的所有元素
      • 索引可以传递一个负值, 如果传递一个负值,则从后往前计算,-1——倒数第一个
var result = arr.slice(1, 4)
result = arr.slice(3)
result = arr.slice(1, -2)

splice()

  • 可以用于删除数组中的指定元素
  • 使用splice()会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
  • 参数,
    • 第一个,表示开始位置的索引
    • 第二个,表示删除的数量
    • 第三个及以后,可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
var arr = ["HTTP","HTML","CSS","JavaScript","jQuery","Less"]
var result = arr.splice(3,0,"BootStrap")

去除数组中重复的数字

for(var i=0; i<arr.length; i++){
  // console.log(i)
  for(var j=i+1; j<arr.length; j++){
    if(arr[i] == arr[j]){
      arr.splice(j,1)
      j--
  }
}

concat()

  • 可以连接两个或多个数组,并将新的数组返回
  • 该方法不会对原数组产生影响
var result = arr.concat(arr2)
console.log(result)
result = arr.concat(arr2,arr3,"ES6","模块化","WebPack","AngularJS","React","VUE")

join()

  • 可以将数组转换为一个字符串
  • 该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
  • 在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
result = arr.join() // 不传,默认用逗号分隔
result = arr.join("") // 想让它们直接连接需要传空串(不是空格)
result = arr.join("-") // 传什么就用什么连接

reverse()

  • 用来反转数组(前面的元素到后面,后面的元素到前面)
  • 该方法会直接修改原数组
arr = ["a","b","c","d"]
arr.reverse()

sort()

  • 可以用来对数组中的元素进行排序
  • 也会影响原数组,默认会按照Unicode编码进行排序
arr.sort() // 排序
arr.reverse() // 搭配起来进行反向排序
  • 即使对于纯数字的数组,使用sort( )排序时,也会按照Unicode编码来排序,所以对数字进排序时,可能会得到错误的结果。
  • 我们可以自己来指定排序的规则:我们可以在sort( )添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数,使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边
  • 浏览器会根据回调函数的返回值来决定元素的顺序,
    • 如果返回一个大于0的值,则元素会交换位置
    • 如果返回一个小于0的值,则元素位置不变
    • 如果返回一个0,则认为两个元素相等,也不交换位置
  • 如果需要升序排列,则返回a-b,如果需要降序排列,则返回b-a
arr.sort(function(a,b){
  /* if(a>b){
    return 1
  }else if(a<b){
    return -1
  }else{
    return 0
  } */
  return a-b
})

23、函数的方法

call()和apply()

  • 这两个方法都是函数对象的方法,需要通过函数对象来调用
  • 当对函数调用这两个方法时,都会调用函数执行
function fun(){
  alert("fun()")
}
fun.apply()
fun.call()
fun()
  • 在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this
function fun(){
    alert(this.name)
}
var obj = {
  name: "obj",
  sayName:function(){
    alert(this.name)
  }
}
// fun.call(obj)
fun.apply(obj)
  • 传递单个参数时没什么不同,但是多个参数:
    • call()方法可以将实参在对象之后依次传递
    • apply()方法需要将实参封装到一个数组中统一传递
fun.call(obj,2,3)
fun.apply(obj,[2,3])

这里this又多了一种情况:

  1. 使用call()和apply()调用时,this是指定的那个对象

24、arguments

在调用函数时,浏览器每次都会传递进两个隐含的参数:

  1. 函数的上下文对象 this

  2. 封装实参的对象arguments

    • arguments是一个类数组对象,它可以通过索引来操作数据,也可以获取长度
    function fun(){
      // console.log(arguments instanceof Array) // false
      console.log(Array.isArray(arguments)) // false
    }
    fun()
    • 在调用函数时,我们所传递的实参都会在arguments中保存
    • arguments.length可以用来获取实参的长度
    • 我们即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦
      • arguments[0] 表示第一个实参
      • arguments[1] 表示第二个实参……
    • 它里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象
    console.log(arguments.callee === fun) // true
    • 由于是个伪数组(类数组),因此不支持数组的方法,比如forEach
 /*
函数参数可选,可以利用arguments来判断
 arr:数组
 length:长度,可选参数
 callback:回调函数
*/
function(){
  var arr = arguments[0]
  if(arguments.length==2){
    var fun = arguments[1]
    fun()
  }
  if(arguments.length==3){
    var length = arguments[1]
    var fun = arguments[2]
    fun()
  }
}

25、Date()对象

  • 在js中使用Date对象来表示一个时间
// 创建一个Date对象
var d = new Date()
console.log(d) // Mon Apr 13 2020 09:09:04 GMT+0800 (中国标准时间)

如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间

创建一个指定的时间对象,需要在构造函数中传递一个表示时间的字符串作为参数

日期的格式: 月份/日/年 时:分:秒

var d2 = new Date("4/16/2020 09:09:04") 
console.log(d2) // Thu Apr 16 2020 09:09:04 GMT+0800 (中国标准时间)
方法 描述
Date() 返回当日的日期和时间。
getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay() 从 Date 对象返回一周中的某一天 (0 ~ 6)。
getMonth() 从 Date 对象返回月份 (0 ~ 11)。
getFullYear() 从 Date 对象以四位数字返回年份。
getYear() 请使用 getFullYear() 方法代替。
getHours() 返回 Date 对象的小时 (0 ~ 23)。
getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。
getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。
getTime() 返回 1970 年 1 月 1 日至今的毫秒数。
getTimezoneOffset() 返回本地时间与格林威治标准时间 (GMT) 的分钟差。
getUTCDate() 根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。
getUTCDay() 根据世界时从 Date 对象返回周中的一天 (0 ~ 6)。
getUTCMonth() 根据世界时从 Date 对象返回月份 (0 ~ 11)。
getUTCFullYear() 根据世界时从 Date 对象返回四位数的年份。
getUTCHours() 根据世界时返回 Date 对象的小时 (0 ~ 23)。
getUTCMinutes() 根据世界时返回 Date 对象的分钟 (0 ~ 59)。
getUTCSeconds() 根据世界时返回 Date 对象的秒钟 (0 ~ 59)。
getUTCMilliseconds() 根据世界时返回 Date 对象的毫秒(0 ~ 999)。
parse() 返回1970年1月1日午夜到指定日期(字符串)的毫秒数。
setDate() 设置 Date 对象中月的某一天 (1 ~ 31)。
setMonth() 设置 Date 对象中月份 (0 ~ 11)。
setFullYear() 设置 Date 对象中的年份(四位数字)。
setYear() 请使用 setFullYear() 方法代替。
setHours() 设置 Date 对象中的小时 (0 ~ 23)。
setMinutes() 设置 Date 对象中的分钟 (0 ~ 59)。
setSeconds() 设置 Date 对象中的秒钟 (0 ~ 59)。
setMilliseconds() 设置 Date 对象中的毫秒 (0 ~ 999)。
setTime() 以毫秒设置 Date 对象。
setUTCDate() 根据世界时设置 Date 对象中月份的一天 (1 ~ 31)。
setUTCMonth() 根据世界时设置 Date 对象中的月份 (0 ~ 11)。
setUTCFullYear() 根据世界时设置 Date 对象中的年份(四位数字)。
setUTCHours() 根据世界时设置 Date 对象中的小时 (0 ~ 23)。
setUTCMinutes() 根据世界时设置 Date 对象中的分钟 (0 ~ 59)。
setUTCSeconds() 根据世界时设置 Date 对象中的秒钟 (0 ~ 59)。
setUTCMilliseconds() 根据世界时设置 Date 对象中的毫秒 (0 ~ 999)。
toSource() 返回该对象的源代码。
toString() 把 Date 对象转换为字符串。
toTimeString() 把 Date 对象的时间部分转换为字符串。
toDateString() 把 Date 对象的日期部分转换为字符串。
toGMTString() 请使用 toUTCString() 方法代替。
toUTCString() 根据世界时,把 Date 对象转换为字符串。
toLocaleString() 根据本地时间格式,把 Date 对象转换为字符串。
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串。
UTC() 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。
valueOf() 返回 Date 对象的原始值。

getTime()

  • 获取当前日期对象的时间戳
  • 时间戳,指的是从格林威治标准时间的1970年1月1日 0时0分0秒到当前日期所花费的毫秒数(1秒=1000毫秒)
var time = d2.getTime()
console.log(time) // 1586999344000
  • 计算机底层在保存时间时使用的是时间戳,可以利用时间关系进行换算
console.log(time/1000/60/60/25/365)
  • 以前利用过console.time()、console.timeEnd()测试代码的执行性能,现在可以利用Date的函数实现
// 获取当前的时间戳
var start  = Date.now()
for(var i=0; i<100; i++){
  console.log(i)
}
var end = Date.now()
console.log("执行了:"+(end-start)+"毫秒")

26、Math对象

Math 对象用于执行数学任务。

Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。它属于一个工具类,无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。

Math 对象属性

属性 描述
E 返回算术常量 e,即自然对数的底数(约等于2.718)。
LN2 返回 2 的自然对数(约等于0.693)。
LN10 返回 10 的自然对数(约等于2.302)。
LOG2E 返回以 2 为底的 e 的对数(约等于 1.414)。
LOG10E 返回以 10 为底的 e 的对数(约等于0.434)。
PI 返回圆周率(约等于3.14159)。
SQRT1_2 返回返回 2 的平方根的倒数(约等于 0.707)。
SQRT2 返回 2 的平方根(约等于 1.414)。

Math 对象方法

方法 描述
abs(x) 返回数的绝对值。
acos(x) 返回数的反余弦值。
asin(x) 返回数的反正弦值。
atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x) 返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。
ceil(x) 对数进行上舍入。
cos(x) 返回数的余弦。
exp(x) 返回 e 的指数。
floor(x) 对数进行下舍入。
log(x) 返回数的自然对数(底为e)。
max(x,y) 返回 x 和 y 中的最高值。
min(x,y) 返回 x 和 y 中的最低值。
pow(x,y) 返回 x 的 y 次幂。
random() 返回 0 ~ 1 之间的随机数。
round(x) 把数四舍五入为最接近的整数。
sin(x) 返回数的正弦。
sqrt(x) 返回数的平方根。
tan(x) 返回角的正切。
toSource() 返回该对象的源代码。
valueOf() 返回 Math 对象的原始值。

Math.random()

  • 可以用来生成一个0~1之间的随机数

console.log(Math.random())

  • 生成一个0~10的随机数

Math.random()*10 –> 整数 Math.round(Math.random()*10)

  • 生成一个0~x之间的随机整数

Math.round(Math.random()*x)

  • 生成一个x~y之间的随机整数

Math.round(Math.random()*(y-x)+x)

Math.max() 可以获取多个数中的最大值

Math.min() 可以获取多个数中的最小值

var max = Math.max(10,45,5,30,100,50)
var min = Math.min(10,45,5,30,100,50)
console.log(max,min)

Math.pow(x,y) 返回x的y次幂

Math.sqrt(x) 返回x的平方根

console.log(Math.pow(2,3)) // 8
console.log(Math.sqrt(2)) // 1.4142135623730951

27、包装类

基本数据类型:String Number Boolean Null Undefined

引用数据类型:Object

在js中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象

  • String() 可以将基本数据类型字符串转换为String对象
  • Number() 可以将基本数据类型的数字转换为Number对象
  • Boolean() 可以将基本数据类型的布尔值转换为Boolean对象
var num = new Number(3)
console.log(typeof num) // object

但是往意,我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象, 在做一些比较时可能会带来一些不 可预期的结果

方法和属性只能添加给对象,不能添加给基本数据类型

当我们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法,调用完以后,再将其转换为基本数据类型

28、字符串相关

创建一个字符串

var str = "Hello JavaScript"

在底层字符串是以字符数组的形式保存的 ['H',"e","l","l","o"." ","J","a"]

console.log(str[1])

length属性

  • 可以用来获取字符串的长度
console.log(str.length)

charAt()

  • 可以返回字符串中指定位置的字符
  • 根据索引获取指定的字符
var result = str.charAt(6)
console.log(result) // J

charCodeAt()

  • 获取指定位置字符的字符编码(Unicode编码)
console.log(str.charCodeAt(0)) // 72

String.formCharCode()

  • 根据字符编码去获取字符
result = String.fromCharCode(20045) // 乍

concat()

  • 可以用来连接两个或多个字符串
  • 作用和+一样
result = str.concat("hello","javascript")

indexof()

  • 该方法可以检索一个字符串中是否含有指定内容
  • 如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有找到指定的内容,则会返回-1
  • 可以指定第二个参数,表示开始查找的位置
result = str.indexOf("h",1)

lastIndexOf()

  • 该方法的用法和indexOf()一样,不同的是indexOf是从前往后找,而lastIndexOf是从后往前找
  • 也可以指定开始查找的位置

slice()

  • 可以从字符串中截取指定的内容
  • 不会影响原字符串,而是将截取到的内容返回
  • 参数
    • 第一个,开始位置的索引(包括开始位置)
    • 第二个,结束位置的索引(不包括结束位置)
      • 如果省略第二个参数,则会截取到后边所有的
      • 也可以传递一个负数作为参数,负数的话将会从后边计算
str = "abcdefghijklmn"
result = str.slice(1)
result = str.slice(1,3)
result = str.slice(3,-3)

substring()

  • 可以用来截取一个字符串,和slice()类似
  • 参数:
    • 第一个,开始截取位置的索引(包括开始位置)
    • 第二个:结束位置的索引(不包括结束位置)
    • 不同的是这个方法不能接受负值作为参数。如果传递了一个负值,则默认使用0
    • 而且他还会自动调整參数的位置,如果第二个参数小于第-一个, 则自动交换
result = str.substring(0,1);

substr()

  • 用来截取字符串
  • 参数
    • 截取开始位置的索引
    • 截取的长度
result = str.substr(3,2)

image-20200813100825993

split()

  • 可以将一个字符串拆分为一个数组
  • 参数
    • 需要一个字符串作为参数,将会根据这个字符串去拆分为数组
    • 如果传递一个空串作为参数,则会将每个字符都拆分为数组中的一个元素
str = "string"
result = str.split("") // ["s", "t", "r", "i", "n", "g"]
str = "abc,bcd,efg,hij"
result = str.split(",") // ["abc", "bcd", "efg", "hij"]
console.log(Array.isArray(result)) // true

toUpperCase()

  • 将一个字符串转换为大写并返回
str = "aBcdefg"
result = str.toUpperCase() // ABCDEFG

toLowerCase()

  • 将一个字符串转换为小写并返回
result = result.toLowerCase() // abcdefg

字符串和正则相关方法(正则表达式看下一节)

splite()

  • 可以将一个字符串拆分为一个数组
  • 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
// 根据任意字母来将字符串财富
var result = str.split(/[A-z]/)
  • 这个方法即使不指定全局匹配,也会全部拆分

search()

  • 可以搜索字符串中是否含有指定内容
  • 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到则返回-1
  • 它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
str = "hello hello aec afc"
// 搜索字符串中是否含有abc或aec或afc
result = str.search(/a[bef]c/)
  • search()只会查找第一个,即使设置全局匹配也没用

match()

  • 可以根据正则表打死,从一个字符串中将符合条件的内容提取出来
  • 默认情况下match只会找到第一个符合要求的内容,找到以后就停止检索,我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容了
str = "1a2b3c4d5e6f7g8h9i"
result = str.match(/[A-z]/g)
  • 可以为一个正则表达式设置多个匹配模式,且顺序无所谓
result = str.match(/[A-z]/ig)
  • match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果

replace()

  • 可以将字符串中指定内容替换为新的内容
  • 参数
    1. 被替换的内容,可以接受一个正则表达式作为参数
    2. 新的内容
  • 默认只会替换一个
result = str.replace(/a/gi "@_@")

29、正则表达式

GitHub上有个很好的学习教程learn-regex翻译版

  • 正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式,来检查一个字符串是否符合规则,将字符串中符合规则的内容提取出来

  • 创建正则表达式的对象

    • 语法: var 变量 = new RegExp("正则表达式","匹配模式")
    • 使用typeof检查正则对象,会返回object
    var reg = new RegExp("a")
    var str = "a"
    console.log(typeof reg)
  • 正则表达式的方法 test()

    • 使用这个方法可以检查一个字符串是否符合正则表达式的规则,如果符合则返回true,否则返回false
    var result = reg.test(str)
    console.log(result)
    console.log(reg.test("Abcbc"))
  • 在构造函数中可以传递一个匹配模式作为第二个参数,可以是:

    • i 忽略大小写
    • g 全局匹配模式
  • 使用字面量来创建正则表达式,语法:var 变量 = /正则表达式/匹配模式

// var reg = new RegExp("a","i")
reg = /a/i
console.log(typeof reg)
console.log(reg.test("abc"))

使用字面量的方式创建更加简单,使用构造函数创建更加灵活

  • 使用|表示或者的意思
// 创建一个正则表达式,检查一个字符串中是否含有a或b
reg = /a|b/
  • []里的内容也是或的关系 [ab]==a|b
    • [a-z] 任意小写字母
    • [A-Z] 任意大写字母
    • [A-z] 任意字母
    • [0-9] 任意数字
reg = /[ab]/
// 检查一个字符串中是否含有abc或adc或aec
reg = /a[bde]c/
  • [^ ]除了
reg = /[^ab]/
console.log(reg.test("abc"))
  • 量词
    • 通过量词可以设置一个内容出现的次数
    • 量词只对她前边的一个内容起作用
  • {n} 正好出现n次
  • {n,m} 出现m~n次
  • {n,} 出现m次以上
reg = /a{3}/
console.log(reg.test("aaabc"))
reg = /(ab){3}/
reg = /ab{1,3}c/
reg = /a{2,}/
  • + 至少一个,相当于{1,}
  • * 0个或多个,相当于{0,}
  • ? 0个或1个,相当于{0,1}
reg = /ab+c/
reg = /ab*c/
reg = /ab?c/
  • ^ 表示开头
  • $ 表示结尾
reg = /^a/
reg = /a$/
  • 在表达式中同时使用^$则要求字符串必须完全符合正则表达式
reg = /^a$/
console.log(reg.test("a"))
reg = /^a|a$/
  • .表示任意字符
// 在正则表达式中使用\作为转义字符 \.表示.
var reg = /\./
console.log(reg.test("b."))
reg = /\\/
console.log(reg.test("b.\\"))
// 使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\则需要使用\\来代替
reg = new RegExp("\\.")
reg = new RegExp("\\\\")
  • \w 任意字母、数字、下划线(_) [A-z0-9_]
  • \W 除了字母、数字、下划线(_) [^A-z0-9_]
  • \d 任意的数字
  • \D 除了数字
  • \s 空格
  • \S 除了空格
  • \b 单词边界
  • \B 除了单词边界
reg = /\bchild\b/
console.log(reg.test("child ren"))
  • 创建一个正则表达式,用来检查一个字符串是否是合法手机号
/*
手机号的规则: 1 3 511111111 
1.以1开头
2.第二位3-9任意数字
3.三位以后任意数字9个
^1 [3-9] [0-9]{9}$
*/
var phoneStr = "13511111111"
var phoneReg = /^1[3-9][0-9]{9}$/
  • 去除首尾的空格
// 开头
str = str.replace(/^\s*/, "")
// 结尾
str = str.replace(/\s*$/, "")
// 开头和结尾 /^\s*|\s*$/g
str = str.replace(/^\s*|\s*$/g, "")
  • 合法电子邮件
/*
hello  .host  @  abc .com.cn
任意字母数字下划线  .任意字母数字下划线 @  任意字母数字 .任意字母(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}$/
var email = "[email protected]"
console.log(emailReg.test(email))

三、DOM

1、什么是DOM

  • 全称Document Object Model 文档对象模型

  • JS中通过DOM来对HTML文档进行操作。只要了解了DOM就可以随心所欲地操作WEB页面。

  • 文档:表示的就是整个HTML网页文档

  • 对象:表示将网页中的每一个部分都转换为了一个对象

  • 模型:使用模型来表示对象之间的关系,这样方便我们获取对象

  • 文档对象模型

    image-20200813113819936

2、节点

  • 节点Node,是构成我么网页的最基本的组成部分,网页中的每一个部分都可以称为是一个节点。比如:html标签、属性、文本、注释、整个文档等都是一个个节点。
  • 虽然都是节点,但实际上他们的具体类型是不同的。比如:标签称为元素节点、属性称为属性节点、文本称为文本节点、文档称为文档节点

image-20200813114229455

  • 节点的类型不同,属性和方法也都不尽相同

image-20200813115713878

3、节点分类和DOM查询

(1) 节点分类

  • 文档节点(document)

    • 文档节点document ,代表的是整个HTML文档,网页中的所有节点都是它的子节点。
    • document对象作为window对象的属性存在的,我们不用获取可以直接使用。
    • 通过该对象我们可以在整个文档访问内查找节对象,并可以通过该对象创建各种节点对象。
  • 元素节点(Element)

    • HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。
    • 浏览器会将页面中所有的标签都转换为一个元素节点,我们可以通过document的方法来获取元素节点。
    • 比如: document.getElementById)根据id属性值获取-个元素节点对象。
  • 文本节点(Text)

    • 文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。
    • 它包括可以字面解释的纯文本内容。
    • 文本节点一般是作为元素节点的子节点存在的。
    • 获取文本节点时, 一般先要获取元素节点,再通过元素节点获取文本
      节点。
    • 例如: 元素节点.firstChild; 获取元素节点的第一个子节点,一般为文本节点
  • 属性节点(Attr)

    • 属性节点表示的是标签中的一个一个的属性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。
    • 可以通过元素节点来获取指定的属性节点。
    • 例如: 元素节点.getAttributeNode("属性名");
    • 注意:我们一般不使用属性节点。

(2) 获取元素节点

通过document对象调用

  • getElementById() 通过id属性获取一个元素节点对象
  • getElementsByTagName() 通过标签名获取一组元素节点对象
  • getElementsByName() 通过name属性获取一组元素节点对象
var btn = document.getElementById("btn")
var lis = document.getElementsTagName("li")
var gender = document.getElementsByName("gender") // <input name="gender" type="radio" value="男" />

(3) 获取元素节点的子节点

通过具体的元素节点调用

  • getElementsByTagName() 方法,返回当前节点的指定标签名后代节点
// 查找#city下的所有li节点
var list = city.getElementsByTagName("li")
  • childNodes 属性,表示当前节点的所有子节点

childNodes属性会获取包括文本节点在内的所有节点,包括DOM标签与标签间空白也会当成文本节点

// 返回#city的所有子节点
var cns = city.childNodes

children属性可以获取当前元素的所有子元素

var cns2 = city.children
  • firstChild 属性,表示当前节点的第一个子节点(包括空白文本节点)
var phone = document.getElementById("phone")
// 返回#phone的第一个子节点
phone.childNodes[0]
var fir = phone.firstChild

firstElementChild获取当前元素的第一个子元素,但是不支持IE8及以下的浏览器

fir = phone.firestElementChild
  • lastChild 属性,表示当前节点的最后一个子节点

(4) 获取父节点和兄弟节点

通过具体的节点调用

  • parentNode 属性,表示当前节点的父节点
  • previousSibling 属性,表示当前节点的前一个兄弟节点
  • nextSiblig 属性,表示当前节点的后一个兄弟节点
<button id="btn">我是一个按钮</button>
<script type="text/javascript">
  // 浏览器已经为我们提供文档节点对象,这个对象是window属性,可以在页面中直接使用,文档节点代表的是整个网页
  // console.log(document)
  var btn = document.getElementById('btn')
  // 修改按钮的文字
  btn.innerHTML = "I'm Button"
</script>

(5) DOM查询的其他方法

  • querySelector() 该方法需要一个选择器作为参数,可以根据一个CSS选择器来查询一个元素节点对象,IE8中也可以使用,总是会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个

  • querySelectorAll() 该方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回,即使符合条件的元素之后一个,它也会返回数组

  • 获取body标签 document.getElementsByTagName("body")[0] ,其实在document中有一个属性,它保存的就是body的引用document.body

  • document.documentElement保存的是html根标签

  • document.all代表页面中所有元素,document.getElementsByTagName("*")

  • getElementsByClassName()可以根据元素的class属性值查询一组元素节点对象,但是该方法不支持IE8及以下的浏览器

var btn = document.querySelector("#btn")
var body = document.body
var html = document.documentElement
var all = document.all
var box = document.getElementsByClassName("box")[0]

3、事件

  • 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间/交互行为。

  • JavaScript与HTML之间的交互是通过事件实现的。

  • 对于Web应用来说,有下面这些代表性的事件:点击某个元素、将鼠标移动至某个
    元素上方、按下键盘上某个键、关闭窗口等等。

  • 可以在事件对应的属性中设置一些js代码,这样当事件被触发时,这些代码将会执行。

事件句柄 此事件发生在何时…
onabort 图像的加载被中断。
onblur 元素失去焦点。
onchange 域的内容被改变。
onclick 当用户点击某个对象时调用的事件句柄。
ondblclick 当用户双击某个对象时调用的事件句柄。
onerror 在加载文档或图像时发生错误。
onfocus 元素获得焦点。
onkeydown 某个键盘按键被按下。
onkeypress 某个键盘按键被按下并松开。
onkeyup 某个键盘按键被松开。
onload 一张页面或一幅图像完成加载。
onmousedown 鼠标按钮被按下。
onmousemove 鼠标被移动。
onmouseout 鼠标从某元素移开。
onmouseover 鼠标移到某元素之上。
onmouseup 鼠标按键被松开。
onreset 重置按钮被点击。
onresize 窗口或框架被重新调整大小。
onselect 文本被选中。
onsubmit 确认按钮被点击。
onunload 用户退出页面。
<button id="btn" onclick="alert('点我干嘛')">我是一个按钮</button>

这种写法结构和行为耦合,不方便维护,不推荐使用

4、onclick

可以为按钮的对应事件绑定处理函数的形式来响应事件,这样当事件被触发时,其对应的函数将会被调用

<button id="btn">我是一个按钮</button>
<script>
  // 获取按钮对象
  var btn = document.getElementById('btn')
  // 绑定一个单击事件
  btn.onclick = function(){
    alert('你还点')
  }
</script>

像这种单击事件绑定的函数,我们称为单击响应函数

4、文档加载 onload

浏览器在加载一个页面时,是按照自上向下的顺序加载的,读取到一行就运行一行,如果将script标签写到页面的上边,在代码执行时,页面还没有加载,页面没有加载DOM对象也没有加载,会导致无法获取到DOM对象

将js代码编写到页面的下方就是为了可以在页面加载完毕以后再执行js代码

但是,一定要放在上面呢,js也提供了一个事件

onload事件会在整个页面加载完成之后才触发

为window绑定一个onload事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行时,所有的DOM对象已经加载完毕了

window.onload = function(){
  var btn = document.getElementById("btn")
  btn.onclick = function(){
    alert("hello")
  }
}

在这里来做几个练习呗

  1. 城市选择

image-20200814082609725

要求完成右边按钮的功能

// 查找#bj节点
btn01.onclick = function(){
  var bj = document.getElementById("bj")
}
// 查找所有li节点
btn02.onclick = function(){
  var lis = document.getElementsByTagName("li")
}
// 查找name为gender的所有节点
btn03.onclick = function(){
  var gNodes = document.getElementsByName("gender")
}
// 查找#city下所有li节点
btn04.onclick = function(){
  var cNodes = document.getElementById("city").getElementsByTagName("li")
}
// 返回#city的所有子节点
btn05.onclick = function(){
  var cAllNodes = document.getElementById("city").childNodes
}
// 返回#phone的第一个子节点
btn06.onclick = function(){
  var firstPNode = document.getElementById("#phone").firstChild
}
// 返回#bj的父节点
btn07.onclick = function(){
  var bParentNode = document.getElementById("bj").parentNode
}
// 返回#android的前一个兄弟节点
btn08.onclick = function(){
  var androidBro = document.getElementById("android").previousSibling
}
// 返回#username的value属性值
btn09.onclick = function(){
  var userNameValue = document.getElementById("username").value
}
// 设置Eusername的value属性值
btn10.onclick = function(){
  document.getElementById('username').value = "用户名"
}
// 返回#bj的文本值
btn11.onclick = function(){
  var bjText = document.getElementById("bj").innerText
}

它们的功能相似,可以封装为一个函数(只是提醒一下,这里不一定更方便)

function myClick(element, callback){
  document.getElementById(element).onclick = callback
}
myClick("btn04",function(){
  var cNodes = document.getElementById("city").getElementsByTagName("li")
  console.log(cNodes)
})
  1. 图片切换

image-20200814095504361

<style>
  *{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  img{
    width: 533px;
    height: 300px;
  }
  #wrapper{
    position: relative;
    margin: 50px auto;
    width: 533px;
    height: 300px;
  }
  #wrapper button{
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto 0;
    width: 60px;
    height: 30px;
    text-align: center;
    line-height: 30px;
    background-color: rgba(0, 0, 0, .3);
    color: white;
    border: none;
    outline: none;
    cursor: pointer;
  }
  #wrapper #prev{
    left: 0;
  }
  #wrapper #next{
    right: 0;
  }
  #wrapper button:hover{
    background-color: rgba(0, 0, 0, .8);
  }
  #wrapper #info{
    width: 533px;
    background-color: rgba(0, 0, 0, .3);
    color: whitesmoke;
    text-align: center;
    position: absolute;
    top: 0;
  }
</style>
<div id="wrapper">
  <img src="./img/1.jpg" alt="图片">
  <button id="prev">上一张</button>
  <button id="next">下一张</button>
  <p id="info"></p>
</div>
<script type="text/javascript">
  window.onload = function(){
    /*
     * 点击按钮切换图片
     *  1、找到按钮
     *  2、给按钮添加单击响应事件
     *  3、在单击函数中修改img的src
    */
    var prev = document.getElementById("prev")
    var next = document.getElementById("next")
    var img = document.getElementsByTagName("img")[0]
    var info = document.getElementById("info")
    var imgArr = ["img/1.jpg", "img/2.jpg", "img/3.jpg", "img/4.jpg", "img/5.jpg"]
    var index = 0
    info.innerText = "一共 " +imgArr.length+" 张图片,现在显示的是第 " +(index+1)+" 张"
    // console.log(img)
    prev.onclick = function(){
      // alert("上一张")
      index--
      if(index < 0){
        index = imgArr.length-1
      }
      img.src = imgArr[index]
      // console.log(imgArr[index]);
      info.innerText = "一共 " +imgArr.length+" 张图片,现在显示的是第 " +(index+1)+" 张"
    }
    next.onclick = function(){
      // alert("下一张")
      index++
      if(index > imgArr.length-1){
        index = 0
      }
      img.src = imgArr[index]
      // console.log(imgArr[index]);
      info.innerText = "一共 " +imgArr.length+" 张图片,现在显示的是第 " +(index+1)+" 张"
    }
  }
</script>
  1. 全选
<form action="" method="post">
  你喜欢的运动是?<label id="control"><input type="checkbox" id="checkAllBox">全选/全不选</label><br>
  <input type="checkbox" name="items" value="足球">足球
  <input type="checkbox" name="items" value="篮球">篮球
  <input type="checkbox" name="items" value="羽毛球">羽毛球
  <input type="checkbox" name="items" value="乒乓球">乒乓球<br>
  <input type="button" id="checkedAllBtn" value="全选">
  <input type="button" id="checkedNoBtn" value="全不选">
  <input type="button" id="checkedRevBtn" value="反选">
  <input type="button" id="sendBtn" value="提交">
</form>
<script>
  window.onload = function(){
    var items = document.getElementsByName("items")
    // 在js中可以直接使用id名
    /* 1、全选 */
    checkedAllBtn.onclick = function(){
      // alert('全选')
      // 设置四个多选框变成选中状态
      for(var i=0; i<items.length; i++){
        // 多选框的checked属性
        items[i].checked = true
      }
      // checkAllBox状态
      checkAllBox.checked = true
    }
    // 2、全不选
    checkedNoBtn.onclick = function(){
      for(var i=0; i<items.length; i++){
        items[i].checked = false
      }
      // checkAllBox状态
      checkAllBox.checked = false
    }
    // 3、反选
    checkedRevBtn.onclick = function(){
      for(var i=0; i<items.length; i++){
        items[i].checked = !items[i].checked
      }
      // checkAllBox状态
      checkAllBox.checked = true
      for(var j=0; j<items.length; j++){
        // 只要有一个不是选中状态,则不是全选
        if(!items[j].checked){
          checkAllBox.checked = false
          // 进入判断就说明已经false了,不需要再执行
          break
        }
      }
    }
    // 4、发送
    sendBtn.onclick = function(){
      for(var i=0; i<items.length; i++){
        if(items[i].checked === true){
          alert(items[i].value)
        }
      }
    }
    // 5、全选/全不选
    checkAllBox.onclick = function(){
      for(var i=0; i<items.length; i++){
        // items[i].checked = checkAllBox.checked
        items[i].checked = this.checked
      }
    }
    // checkAllBox状态
    for(var i=0; i<items.length; i++){
      items[i].onclick = function(){
        checkAllBox.checked = true
        for(var j=0; j<items.length; j++){
          // 只要有一个不是选中状态,则不是全选
          if(!items[j].checked){
            checkAllBox.checked = false
            // 进入判断就说明已经false了,不需要再执行
            break
          }
        }
      }
    }
  }
</script>

反选可以修改下代码,减少一个循环

// 3、反选
checkedRevBtn.onclick = function(){
  //将checkedAllBox设置为选中状态
  checkAllBox.checked = true;
  for(var i=0; i<items.length ; i++){
    // 反选
    items[i].checked = !items[i].checked;
    // checkBox状态
    if(!items[i].checked){
      checkAllBox.checked = false;
    }
  }
}

上面又用到了this:

在事件的响应函数中,响应函数是给谁绑定的this就是谁

5、DOM对象的其他属性、方法

下面的属性和方法可用于所有 HTML 元素上:

属性 / 方法 描述
element.accessKey 设置或返回元素的快捷键。
element.appendChild() 向元素添加新的子节点,作为最后一个子节点。
element.attributes 返回元素属性的 NamedNodeMap。
element.childNodes 返回元素子节点的 NodeList。
element.className 设置或返回元素的 class 属性。
element.clientHeight 返回元素的可见高度。
element.clientWidth 返回元素的可见宽度。
element.cloneNode() 克隆元素。
element.compareDocumentPosition() 比较两个元素的文档位置。
element.contentEditable 设置或返回元素的文本方向。
element.dir 设置或返回元素的内容是否可编辑。
element.firstChild 返回元素的首个子。
element.getAttribute() 返回元素节点的指定属性值。
element.getAttributeNode() 返回指定的属性节点。
element.getElementsByTagName() 返回拥有指定标签名的所有子元素的集合。
element.getFeature() 返回实现了指定特性的 API 的某个对象。
element.getUserData() 返回关联元素上键的对象。
element.hasAttribute() 如果元素拥有指定属性,则返回true,否则返回 false。
element.hasAttributes() 如果元素拥有属性,则返回 true,否则返回 false。
element.hasChildNodes() 如果元素拥有子节点,则返回 true,否则 false。
element.id 设置或返回元素的 id。
element.innerHTML 设置或返回元素的内容。
element.insertBefore() 在指定的已有的子节点之前插入新节点。
element.isContentEditable 设置或返回元素的内容。
element.isDefaultNamespace() 如果指定的 namespaceURI 是默认的,则返回 true,否则返回 false。
element.isEqualNode() 检查两个元素是否相等。
element.isSameNode() 检查两个元素是否是相同的节点。
element.isSupported() 如果元素支持指定特性,则返回 true。
element.lang 设置或返回元素的语言代码。
element.lastChild 返回元素的最后一个子元素。
element.namespaceURI 返回元素的 namespace URI。
element.nextSibling 返回位于相同节点树层级的下一个节点。
element.nodeName 返回元素的名称。
element.nodeType 返回元素的节点类型。
element.nodeValue 设置或返回元素值。
element.normalize() 合并元素中相邻的文本节点,并移除空的文本节点。
element.offsetHeight 返回元素的高度。
element.offsetWidth 返回元素的宽度。
element.offsetLeft 返回元素的水平偏移位置。
element.offsetParent 返回元素的偏移容器。
element.offsetTop 返回元素的垂直偏移位置。
element.ownerDocument 返回元素的根元素(文档对象)。
element.parentNode 返回元素的父节点。
element.previousSibling 返回位于相同节点树层级的前一个元素。
element.removeAttribute() 从元素中移除指定属性。
element.removeAttributeNode() 移除指定的属性节点,并返回被移除的节点。
element.removeChild() 从元素中移除子节点。
element.replaceChild() 替换元素中的子节点。
element.scrollHeight 返回元素的整体高度。
element.scrollLeft 返回元素左边缘与视图之间的距离。
element.scrollTop 返回元素上边缘与视图之间的距离。
element.scrollWidth 返回元素的整体宽度。
element.setAttribute() 把指定属性设置或更改为指定值。
element.setAttributeNode() 设置或更改指定属性节点。
element.setIdAttribute()
element.setIdAttributeNode()
element.setUserData() 把对象关联到元素上的键。
element.style 设置或返回元素的 style 属性。
element.tabIndex 设置或返回元素的 tab 键控制次序。
element.tagName 返回元素的标签名。
element.textContent 设置或返回节点及其后代的文本内容。
element.title 设置或返回元素的 title 属性。
element.toString() 把元素转换为字符串。
nodelist.item() 返回 NodeList 中位于指定下标的节点。
nodelist.length 返回 NodeList 中的节点数。

DOM查询学完了,接着就可以操作对象了(增删改)

增:

apperndChild() 向父节点添加一个新的子节点,父元素.appendChild(子节点)

insertBefore() 在指定的子节点前插入新的子节点,父节点.inserBefore("要插入的子节点","指定的子节点")

createElement() 创建元素节点,需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回

createTextNode() 创建文本节点,需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回

createAttribute() 创建属性节点

删:

removeChild() 删除子节点,父节点.removeChild(子节点)—>子节点.parentNode.removeChild(子节点)

改:

replaceChild() 使用指定的子节点替换已有子节点,父节点.replaceChild(新节点,旧节点)

setAttribute() 把指定属性设置或修改为指定的值

innerHTML 用于获取元素内部的HMTL代码,对于自结束标签,这个属性没有意义

如果要读取元素节点属性,可以直接使用元素.属性名,例如 元素.id、元素.name、元素.value,注意 class属性不能采用这种方式,读取class属性时需要使用 元素.className

innerTex t这个属性可以获取到元素内部的文本内容,和innerHTML类似,不同的是它会自动将html去除

可以使用innerHTML完成DOM的增删改操作

练习:

  1. 城市节点修改

image-20200814113430625

<style>
  *{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  body {
    width: 800px;
    margin-left: auto;
    margin-right: auto;
  }
  button {
    width: 300px;
    margin-bottom: 10px;
  }
  #btnList {
    float:left;
  }
  #total{
    width: 450px;
    float:left;
  }
  ul{
    list-style-type: none;
    margin: 0px;
    padding: 0px;
  }
  .inner li{
    border-style: solid;
    border-width: 1px;
    padding: 5px;
    margin: 5px;
    background-color: #99ff99;
    float:left;
  }
  .inner{
    width:400px;
    border-style: solid;
    border-width: 1px;
    margin-bottom: 10px;
    padding: 10px;
    float: left;
  }
</style>
<div id="total">
  <div class="inner">
    <p>
      你喜欢哪个城市?
    </p>
    <ul id="city">
      <li id="bj">北京</li>
      <li>上海</li>
      <li>东京</li>
      <li>首尔</li>
    </ul>
  </div>
</div>
<div id="btnList">
  <div><button id="btn01">创建一个"广州"节点,添加到#city下</button></div>
  <div><button id="btn02">将"广州"节点插入到#bj前面</button></div>
  <div><button id="btn03">使用"广州"节点替换#bj节点</button></div>
  <div><button id="btn04">删除#bj节点</button></div>
  <div><button id="btn05">读取#city内的HTML代码</button></div>
  <div><button id="btn06">设置#bj内的HTML代码</button></div>
  <div><button id="btn07">将HTML代码"广州"节点,添加到#city下</button></div>
</div>
<script>
  function myClick(element, fun){
    var btn = document.getElementById(element)
    btn.onclick = fun
  }
  // 创建一个"广州"节点,添加到#city下
  myClick("btn01", function(){
    // 创建
    var li = document.createElement("li")
    var gzText = document.createTextNode("广州")
    // 插入
    // li.appendChild(gzText)
    li.innerHTML = "广州"
    city.appendChild(li)
  })
  // 将"广州"节点插入到#bj前面
  myClick("btn02", function(){
    // 创建
    var li = document.createElement("li")
    var gzText = document.createTextNode("广州")
    // 插入
    li.appendChild(gzText)
    city.insertBefore(li,bj)
  })
  // 使用"广州"节点替换#bj节点
  myClick("btn03", function(){
    // 创建
    var li = document.createElement("li")
    var gzText = document.createTextNode("广州")
    // 插入
    li.appendChild(gzText)
    city.replaceChild(li,bj)
  })
  // 删除#bj节点
  myClick("btn04", function(){
    // city.removeChild(bj)
    bj.parentNode.removeChild(bj)
  })
  // 读取#city内的HTML代码
  myClick("btn05", function(){
    alert(city.innerHTML)
  })
  // 设置#bj内的HTML代码
  myClick("btn06", function(){
    bj.innerHTML = "北平"
  })
  // 创建一个"广州"节点,添加到#city下
  myClick("btn07", function(){
    city.innerHTML += "<li>广州</>"
  })
</script>
  1. 员工记录

image-20200814112357578

HTML和CSS部分

<style>
  #total {
    width: 450px;
    margin-left: auto;
    margin-right: auto;
  }
  ul {
    list-style-type: none;
  }
  li {
    border-style: solid;
    border-width: 1px;
    padding: 5px;
    margin: 5px;
    background-color: #99ff99;
    float: left;
  }
  .inner {
    width: 400px;
    border-style: solid;
    border-width: 1px;
    margin: 10px;
    padding: 10px;
    float: left;
  }
  #employeeTable {
    border-spacing: 1px;
    background-color: black;
    margin: 80px auto 10px auto;
  }
  th,td {
    background-color: white;
  }
  #formDiv {
    width: 250px;
    border-style: solid;
    border-width: 1px;
    margin: 50px auto 10px auto;
    padding: 10px;
  }
  #formDiv input {
    width: 100%;
  }
  .word {
    width: 40px;
  }
  .inp {
    width: 200px;
  }
</style>
<table id="employeeTable">
  <tr>
    <th>Name</th>
    <th>Email</th>
    <th>Salary</th>
    <th>&nbsp;</th>
  </tr>
  <tr>
    <td>Tom</td>
    <td>[email protected]</td>
    <td>5000</td>
    <!-- <td><a href="javascript:;">Delete</a></td> -->
    <td><a href="deleteEmp?id=001">Delete</a></td>
  </tr>
  <tr>
    <td>Jerry</td>
    <td>[email protected]</td>
    <td>8000</td>
    <td><a href="deleteEmp?id=002">Delete</a></td>
  </tr>
  <tr>
    <td>Bob</td>
    <td>[email protected]</td>
    <td>10000</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" value="abc">
          Submit
        </button>
      </td>
    </tr>
  </table>
</div>

取消a的默认行为

<a href="javascript:;"></a>
a.onclick=function(){
  return false
}

for循环会在页面加载完成之后立即执行难,而响应函数会在超链接被点击时才执行,等它执行,循环已经结束了

var allA = document.getElementsByTagName("a")
for(var i=0; i<allA.length; i++){
  allA[i].onclick = function(){
    alert(i) // 一直是3
    return false
  }
}

可以用this来解决,添加之后删除,由于绑定删除是之前的,因此需要单独绑定

删除和添加员工

<script>
  /* 删除员工 */
  var allA = document.getElementsByTagName("a")
  for(var i=0; i<allA.length; i++){
    allA[i].onclick = function(){
      var tr = this.parentNode.parentNode
      // var name = tr.getElementsByTagName("td")[0].innerText
      var name = tr.children[0].innerHTML
      // alert("确认删除吗?")
      /* window对象中的方法,找到confirm,这是用于弹出一个带有确认和取消按钮的提示框,字符串(提示文字)作为参数,点击确认返回true,点击取消返回false */
      var flag = confirm("确认删除" +name+ "吗?") // firstChild会找第一个节点,空格也是
      if(flag){
        tr.parentNode.removeChild(tr)
      }
      // 取消默认行为
      return false
    }
  }
  /* 添加员工 */
  addEmpButton.onclick = function(){
    var name = document.getElementById("empName").value
    var email = document.getElementById("email").value
    var salary = document.getElementById("salary").value
    // console.log(name,email,salary)
    /*
    <tr>
      <td>Bob</td>
      <td>[email protected]</td>
      <td>10000</td>
      <td><a href="deleteEmp?id=003">Delete</a></td>
    </tr>
    */
    var tr = document.createElement("tr")
    var nameTd = document.createElement("td")
    var emailTd = document.createElement("td")
    var salaryTd = document.createElement("td")
    var aTd = document.createElement("td")
    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.appendChild(delText)
    a.href = "javascript:;"
    a.onclick = function(){
      var tr = this.parentNode.parentNode
      var name = tr.children[0].innerHTML
      var flag = confirm("确认删除" +name+ "吗?")
      if(flag){
        tr.parentNode.removeChild(tr)
      }
      return false
    }
    aTd.appendChild(a)
    // 将td添加到tr中
    tr.appendChild(nameTd)
    tr.appendChild(emailTd)
    tr.appendChild(salaryTd)
    tr.appendChild(aTd)
    // 插入到table
    // employeeTable.appendChild(tr) // 事实上tr在tbody中
    employeeTable.getElementsByTagName("tbody")[0].appendChild(tr)
  }
</script>

由于删除的有相同代码,可以提出来

function delA(){
  var tr = this.parentNode.parentNode
  // var name = tr.getElementsByTagName("td")[0].innerText
  var name = tr.children[0].innerHTML
  // alert("确认删除吗?")
  /* window对象中的方法,找到confirm,这是用于弹出一个带有确认和取消按钮的提示框,字符串(提示文字)作为参数,点击确认返回true,点击取消返回false */
  var flag = confirm("确认删除" +name+ "吗?") // firstChild会找第一个节点,空格也是
  if(flag){
    tr.parentNode.removeChild(tr)
  }
  // 取消默认行为
  return false
}
删除员工中
allA[i].onclick = delA
添加员工中
a.onclick = delA

增加的使用appendChild和innerHTML配合更简单一点

/* 添加员工 */
addEmpButton.onclick = function(){
  var name = document.getElementById("empName").value
  var email = document.getElementById("email").value
  var salary = document.getElementById("salary").value

  var tr = document.createElement("tr")
  tr.innerHTML = "<td>"+name+"</td>"+
                "<td>"+email+"</td>"+
                "<td>"+salary+"</td>"+
                "<td><a href='javascript:;'>Delete</a></td>"
  var a = tr.getElementsByTagName("a")[0]
  a.onclick = delA
  var tbody = employeeTable.getElementsByTagName("tbody")[0]
  tbody.appendChild(tr)
  // tbody.innerHTML += tr // 这样就不太合适了,会影响前面已有的
}

6、DOM操作CSS

通过js修改元素的样式

  • 语法:元素.style.样式名=样式值

  • 注意:如果CSS的样式名中含有-,这种名称在js中是不合法的,需要将这种样式名修改为驼峰命名,去掉-,然后将-后的字母大写

var box1 = document.getElementById("box1")
var btn01 = document.getElementById("btn01")
btn01.onclick = function(){
  // 修改box1的宽度
  box1.style.width = "300px"
  // 修改背景颜色
  box1.style.backgroundColor = "yellow"
}
  • 通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过js修改的样式往往会立即显示;但如果在样式中写了!important,则此时样式会有最高的优先级,即使通过js也不能覆盖该样式,此时将会导致js修改样式失败,所以在写CSS样式的时候尽量不要加!important

js读取样式

  • 语法:元素.style.样式名
var btn02 = document.getElementById("btn02")
btn02.onclick = function(){
  // 读取box1的样式
  alert(box1.style.height, box1.style.width)
}
  • 通过style属性设置和读取的都是内联样式,无法读取样式表中的样式

js获取当前显示的样式

  • 语法:元素.currentStyle.样式
  • 它可以用来读取当前元素正在显示的样式,如果当前元素没有设置该样式,则获取它的默认值
window.onload = function(){
  btn01.onclick = function(){
    alert(box1.currentStyle.width)
    alert(box1.currentStyle.backgroundColor)
  }
}
  • currentStyle只有IE浏览器支持,其他的浏览器都不支持

在其他浏览器中可以使用

getComputedStyle()这个方法来获取元素当前的样式,这个方法是window的方法,可以直接使用

需要两个参数

第一个:要获取样式的元素

第二个:可以传递一个伪元素,一般都传null

这个方法会返回一个对象,对象中封装了当前元素对应的样式

可以通过对象.样式名来读取样式,如果获取的样式没有设置,则会获取到真实的值,而不是默认值。比如:没有设置width,它不会获取到auto,而是一个长度

这个方法不支持IE8及以下的浏览器

// var obj = getComputedStyle(box1, null)
alert(getComputedStyle(box1,null).backgroundColor)

通过currentStyle和getComputedStyle()读取到的样式都是只读的,不能修改,如果要修改必须通过style属性

/* 定义一个函数,用来获取指定元素的当前的样式
* 参数:
*  obj 要获取样式的元素
*  name 要获取的样式名
*/
/* function getStyle(obj, name){
    if(window.getComputedStyle){
    // 正常浏览器的方式,具有getComputedStyle()方法
    return getComputedStyle(obj, null)[name]
  }else{
    // IE8的方式,没有getComputedStyle()方法
    return obj.currentStyle[name]
  }
} */
/* // 不建议用下面这个 IE11会优先使用current,虽然都能用
function getStyle(obj, name){
    if(obj.currentStyle){
    return obj.currentStyle[name]
  }else{
    return getComputedStyle(obj, null)[name]
  }
}*/
function getStyle(obj, name){
    return window.getComputedStyle ? getComputedStyle(obj, null)[name] : obj.currentStyle[name]
}

clientWidth、clientHeight

这两个属性可以获取元素的可见宽度和高度

这些属性都是不带px的,返回都是一个数字,可以直接进行计算

会获取元素宽度和高度,包括内容区和内边距

这些属性都是只读的,不能修改

btn01.onclick = function(){
  alert(box1.clientWidth)
}

offsetWidth、offsetHeight

获取元素的整个的宽度和高度,包括内容区、内边距和边框

alert(box1.offsetWidth)

offsetParent

可以用来获取当前元素的定位父元素

会获取到离当前元素最近的开启了定位的祖先元素,如果所有的祖先元素都没开启定位,则返回body

var op = box1.offsetParent
alert(op.id)

offsetLeft

当前元素相对于其定位父元素的水平偏移量

offsetTop

当前元素相对于其定位父元素的垂直偏移量

设置了overflow:auto;,高度和长度都太大,会出现滚动条

scrollWidth、scrollHeight

可以获取元素整个滚动区域的宽、高度

alert(box4.clientHeight, box4.scrollHeight)

scrollLeft

可以获取水平滚动条滚动的距离

scrollTop

可以获取垂直滚动条滚动的距离

alert(box4.scrollLeft)
alert(box4.scrollTop)

7、其他事件

onscroll

该事件会在元素的滚动条滚动时触发

阅读协议:

image-20200814143324153

<style type="text/css">
  #info{
    width: 300px;
    height: 500px;
    background-color: #bfa;
    overflow: auto;
  }
</style>
<h3>欢迎亲爱的用户注册</h3>
<p id="info">
  Lorem ipsum, dolor sit amet consectetur adipisicing elit. Amet, doloremque. Ea tempora consequuntur mollitia corrupti. Commodi iusto ducimus deleniti, ratione quam, harum fugit autem omnis nihil dolorem fuga, sequi eligendi excepturi expedita tenetur accusamus! In eaque voluptate inventore commodi a? Unde provident tempore, dolorem deserunt numquam reiciendis eum vero. Aut ipsum, dolorem doloribus nemo molestiae exercitationem deserunt amet quod voluptatibus expedita ex architecto, cum culpa fuga dolore. Ratione perspiciatis soluta, facilis temporibus, error laudantium nostrum facere doloremque natus sint cum esse incidunt officiis eum officia velit ab illo perferendis distinctio enim voluptas tempore? Reiciendis, itaque cupiditate? Totam mollitia tenetur labore neque possimus vero porro modi iure atque reiciendis fugit iste, omnis, magnam rem animi adipisci tempore repellendus iusto fugiat voluptatum consequuntur excepturi. Similique vel praesentium quo quam at. Veniam, neque nostrum, minima ex assumenda perferendis aliquam cum, molestiae culpa repellat explicabo? Sapiente, placeat eligendi voluptas velit beatae accusantium minus culpa reprehenderit similique, corporis eum neque tempore expedita iure, adipisci molestias. Quidem, sapiente temporibus deserunt nobis architecto incidunt ipsam. Provident distinctio accusamus quaerat inventore ex, omnis excepturi temporibus quod alias possimus maxime nesciunt odio aperiam error quia? Neque rem eos a perferendis repellat repudiandae reprehenderit reiciendis molestiae ullam! Nihil, illum odio!
</p>
<!-- 如果为表单项添加disabled="disabled" 则表单项将变成不可用的状态 -->
<input type="checkbox" disabled="disabled" />我已仔细阅读协议,一定遵守
<input type="submit" value="注册" disabled="disabled" />
<script type="text/javascript">
  window.onload = function(){
    /*
      * 当垂直滚动条滚动到底时使表单项可用
      */
    //获取id为info的p元素
    var info = document.getElementById("info")
    //获取两个表单项
    var inputs = document.getElementsByTagName("input")
    //为info绑定一个滚动条滚动的事件
    info.onscroll = function(){
      //检查垂直滚动条是否滚动到底
      if(info.scrollHeight - info.scrollTop == info.clientHeight){
        //滚动条滚动到底,使表单项可用
        /*
          * disabled属性可以设置一个元素是否禁用,
          *     如果设置为true,则元素禁用
          *     如果设置为false,则元素可用
          */
        inputs[0].disabled = false
        inputs[0].onclick = function(){ // 只有到底了才能能点复选框,点了复选框才能点按钮
          if(inputs[0].checked){
            inputs[1].disabled = false
          }
        }
      }
    }
  }
</script>

onmousemove

该事件会在鼠标在元素中移动时被触发

事件对象:当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,在事件对象中封装了当前事件相关的一切信息。比如,鼠标坐标、键盘哪个按键被按下、鼠标滚轮滚动的方向……

<style>
  #areaDiv{
    position: relative;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0,0,0,.2);
  }
  #showMsg{
    position: absolute;
    width: 160px;
    height: 20px;
    line-height: 20px;
    text-align: left;
    background-color: rgba(0,0,0,.5);
    left: 0;
    top: 0;
  }
</style>
<div id="areaDiv"></div>
<div id="showMsg"></div>
<script>
  /* 当鼠标在areaDiv中移动时,在showMsg中来显示鼠标的坐标 */
  areaDiv.onmousemove = function(event){
    /*
     * clientX可以获取鼠标指针的水平坐标
     * clientY可以获取鼠标指针的垂直坐标
    */
    var x = event.clientX
    var y = event.clientY
    showMsg.innerHTML = "(x = " + x + ", y = " + y +")"
    showMsg.style.left = x + 10 + "px"
    showMsg.style.top = y + 10 + "px"
  }
</script>

在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的

/*var x = window.event.clientX
var y = window.event.clientY*/
/*if(!event){
  event = window.event
}*/
envent = event || window.event

上面也涉及到了跟随鼠标的,下面来详细说一下

<style type="text/css">
  #box1{
    width: 100px;
    height: 100px;
    background-color: red;
    position: absolute;
  }
</style>
<script type="text/javascript">
  window.onload = function(){
    /*
     * 使div可以跟随鼠标移动
     */
    //绑定鼠标移动事件
    document.onmousemove = function(event){  
      //解决兼容问题
      event = event || window.event
      //获取滚动条滚动的距离
      /*
       * chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取
       * 火狐等浏览器认为浏览器的滚动条是html的,
       */
      var st = document.body.scrollTop || document.documentElement.scrollTop
      var sl = document.body.scrollLeft || document.documentElement.scrollLeft
      //var st = document.documentElement.scrollTop;
      //获取到鼠标的坐标
      /*
       * clientX和clientY
       *     用于获取鼠标在当前的可见窗口的坐标
       * div的偏移量,是相对于整个页面的
       * 
       * pageX和pageY可以获取鼠标相对于当前页面的坐标
       *     但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
       */
      var left = event.clientX
      var top = event.clientY

      //设置div的偏移量
      box1.style.left = left + sl + "px"
      box1.style.top = top + st + "px"
    };    
  };
</script>
<body style="height: 1000px;width: 2000px;">
  <div id="box1"></div>
</body>

8、事件的冒泡(Bubble)

image-20200814152059578

所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发

// body>#box1>span#s1
s1.onclick = function(){
  alert("我是span的单击响应函数")
}
box1.onclick = function(){
  alert("我是div的单击响应函数")
}
document.body.onclick = function(){
  alert("我是body的单击响应函数")
}

点一下span,span、div、body的单击响应函数都会被触发

在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡

s1.onclick = function(e){
  event = e || window.event
  alert("我是span的单击响应函数")
  // 取消冒泡,可以将事件对象的cancelBubble设置为true,即可取消冒泡
  event.cancelBubble = true
}
box1.onclick = function(e){
  e = e || window.event
  alert("我是div的单击响应函数")
  e.cancelBubble = true
}

9、事件的委派

<script type="text/javascript">
  window.onload = function(){
    var u1 = document.getElementById("u1")
    //点击按钮以后添加超链接
    var btn01 = document.getElementById("btn01")
    btn01.onclick = function(){
      //创建一个li
      var li = document.createElement("li")
      li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
      //将li添加到ul中
      u1.appendChild(li)
    }
    /*
      * 为每一个超链接都绑定一个单击响应函数
      * 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定
      */
    //获取所有的a
    var allA = document.getElementsByTagName("a")
      //遍历
      for(var i=0 ; i<allA.length ; i++){
        allA[i].onclick = function(){
          alert("我是a的单击响应函数!!!")
      }
    }
  }
</script>
<button id="btn01">添加超链接</button>
<ul id="u1" style="background-color: #bfa;">
  <li>
    <p>我是p元素</p>
  </li>
  <li><a href="javascript:;" class="link">超链接一</a></li>
  <li><a href="javascript:;" class="link">超链接二</a></li>
  <li><a href="javascript:;" class="link">超链接三</a></li>
</ul>

事件的委派
指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。

事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能

/*
* 我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
* 我们可以尝试将其绑定给元素的共同的祖先元素
*/
//为ul绑定一个单击响应函数
u1.onclick = function(event){
  event = event || window.event
  /*
   * target
   *     - event中的target表示的触发事件的对象
  */
  //alert(event.target);
  //如果触发事件的对象是我们期望的元素,则执行否则不执行
  if(event.target.className == "link"){
    alert("我是ul的单击响应函数")
  }  
}

10、事件的绑定

使用 对象.事件 = 函数 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,能绑定多个,如果绑定了多个,则后边会覆盖掉前边的

/*
* 点击按钮以后弹出一个内容
*/
//获取按钮对象
var btn01 = document.getElementById("btn01")
//为btn01绑定一个单击响应函数
btn01.onclick = function(){
  alert(1)
}
//为btn01绑定第二个响应函数
btn01.onclick = function(){
  alert(2)
}

addEventListener()

  • 通过这个方法也可以为元素绑定响应函数

  • 参数:

  1. 事件的字符串,不要on

  2. 回调函数,当事件触发时该函数会被调用

  3. 是否在捕获阶段触发事件,需要一个布尔值,一般都传false

使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照函数的绑定顺序执行

这个方法不支持IE8及以下的浏览器

btn01.addEventListener("click",function(){
  alert(1);
},false);
btn01.addEventListener("click",function(){
  alert(2);
},false);
btn01.addEventListener("click",function(){
  alert(3);
},false);

attachEvent()

  • 在IE8中可以使用attachEvent()来绑定事件

  • 参数:

    1. 事件的字符串,要on
    2. 回调函数
  • 这个方法也可以同时为一个事件绑定多个处理函数,不同的是它是后绑定先执行,执行顺序和addEventListener()相反(顺序实在有要求可以反着写)

btn01.attachEvent("onclick",function(){
  alert(1)
})
btn01.attachEvent("onclick",function(){
  alert(2)
})
btn01.attachEvent("onclick",function(){
  alert(3)
})
btn01.addEventListener("click",function(){
  alert(this)
},false)
btn01.attachEvent("onclick",function(){
  alert(this)
})

定义一个函数,用来为指定元素绑定响应函数

  • 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)
    })
  }
}
// 借助function由浏览器调用变成自己调用,就能使用call
// 传入实参
bind(btn01 , "click" , function(){
  alert(this);
})

11、事件的传播

关于事件的传播网景公司和微软公司有不同的理解

  • 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行
  • 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后再向内传播给后代元素

事件传播

W3C综合了两个公司的方案,将事件传播分为了三个阶段:

  1. 捕获阶段——在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
  2. 目标阶段——事件捕获到目标元素,捕获结果开始在目标元素上触发事件
  3. 冒泡阶段——事件从目标元素向它的祖先元素传递,一次触发祖先元素上的事件

W3C事件传播

如果希望在捕获阶段就触发事件,可以在addEventListener()的第三个参数设置为true,一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false

obj.addEventListener(eventStr,callback,true)

IE8及以下的浏览器中没有捕获阶段

12、鼠标事件

onmousedown、onmousemove、onmouseup

拖拽

还记得H5新添加的那个拖拽API嘛,那个非常好用的对吧,可是在H5还没出来的时候咋实现的呢

<style>
  #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>
<div id="box1"></div>
<div id="box2"></div>
<script type="text/javascript">
  window.onload = function(){
    /*
    * 拖拽box1元素
    *  - 拖拽的流程
    *         1.当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
    *         2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
    *         3.当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
    */
    //获取box1
    var box1 = document.getElementById("box1")
    //为box1绑定一个鼠标按下事件
    //当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
    box1.onmousedown = function(event){
      event = event || window.event
      //div的偏移量 鼠标.clentX - 元素.offsetLeft
      //div的偏移量 鼠标.clentY - 元素.offsetTop
      var ol = event.clientX - box1.offsetLeft
      var ot = event.clientY - box1.offsetTop
      //为document绑定一个onmousemove事件
      document.onmousemove = function(event){
        event = event || window.event
        //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
        //获取鼠标的坐标
        var left = event.clientX - ol
        var top = event.clientY - ot
        //修改box1的位置
        box1.style.left = left+"px"
        box1.style.top = top+"px"
      }
      //为document绑定一个鼠标松开事件
      document.onmouseup = function(){
        //当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
        //取消document的onmousemove事件(移到同样是`position: absolute`的另一个盒子上时,会被另一个覆盖,松开鼠标会触发另一个盒子的onmouseup,因此需要给document绑定)
        document.onmousemove = null
        //取消document的onmouseup事件
        document.onmouseup = null
      }
    }
  }
</script>

onmouseup使用过了直接就不需要了,可以直接取消,这样onmouseup就变成一次性事件了。

点击box光标会变到鼠标左上角,需要求出box的偏移量,在按下时求出,移动时减去这个偏移量就是鼠标所处的位置了。(如果有滚动条还要进行处理)

box1.onmousedown = function(event){
    /* 设置box1捕获所有鼠标按下的事件
     * setCapture()
     *  - 当调用一个元素的setCapture()方法后,这个元素将会把下一次所有的鼠标按下相关的事件捕获到自己身上
     *     - 只有IE支持,但是在火狐中调用时不会报错,
     *         而如果使用chrome调用,会报错
     */
  // 只需要设置一次,不需要一直捕获,在up中释放
  // 做判断,有就用(IE),没有就不用
    /*if(box1.setCapture){
        box1.setCapture()
    }*/
    box1.setCapture && box1.setCapture()
    event = event || window.event
    //div的偏移量 鼠标.clentX - 元素.offsetLeft
    //div的偏移量 鼠标.clentY - 元素.offsetTop
    var ol = event.clientX - box1.offsetLeft
    var ot = event.clientY - box1.offsetTop
    //为document绑定一个onmousemove事件
    document.onmousemove = function(event){
        event = event || window.event
        //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
        //获取鼠标的坐标
        var left = event.clientX - ol
        var top = event.clientY - ot
        //修改box1的位置
        box1.style.left = left+"px"
        box1.style.top = top+"px"
    }
    //为document绑定一个鼠标松开事件
    document.onmouseup = function(){
        //当鼠标松开时,被拖拽元素固定在当前位置    onmouseup
        //取消document的onmousemove事件
        document.onmousemove = null
        //取消document的onmouseup事件
        document.onmouseup = null
        //当鼠标松开时,取消对事件的捕获
        box1.releaseCapture && box1.releaseCapture()
    }
    /*
     * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
     *     此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
     *     如果不希望发生这个行为,则可以通过return false来取消默认行为
     * 但是这招对IE8不起作用(IE8用capture,其他用这个)
     */
    return false
}

封装

/*
* 提取一个专门用来设置拖拽的函数
* 参数:开启拖拽的元素
*/
function drag(obj){
//当鼠标在被拖拽元素上按下时,开始拖拽  onmousedown
obj.onmousedown = function(event){
    obj.setCapture && obj.setCapture()
    event = event || window.event
    var ol = event.clientX - obj.offsetLeft
    var ot = event.clientY - obj.offsetTop
    //为document绑定一个onmousemove事件
    document.onmousemove = function(event){
        event = event || window.event
        var left = event.clientX - ol
        var top = event.clientY - ot
        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
}

var box1 = document.getElementById("box1")
var box2 = document.getElementById("box2")
var img1 = document.getElementById("img1")
//开启box1的拖拽
drag(box1)
//开启box2的
drag(box2)
drag(img1)  // <img src="img/an.jpg" id="img1" style="position: absolute;"/>

鼠标滚轮事件

onmousewheel(火狐用DOMMouseScroll)

<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变短
        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>
<body style="height: 2000px;">
<div id="box1"></div>
</body>

13、键盘事件

onkeydown

  • 按键被按下

  • 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发

  • 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。

onkeyup

  • 按键被松开
    • 键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

可以通过keyCode来获取按键的编码
通过它可以判断哪个按键被按下
除了keyCode,事件对象中还提供了几个属性
altKey ctrlKey shiftKey
这个三个用来判断alt ctrl 和 shift是否被按下
如果按下则返回true,否则返回false

window.onload = function(){
  document.onkeydown = function(event){
    event = event || window.event
    /*
        * 可以通过keyCode来获取按键的编码,通过它可以判断哪个按键被按下
        * 除了keyCode,事件对象中还提供了几个属性 altKey、    ctrlKey、shiftKey
        */
    //console.log(event.keyCode)
    //判断一个y是否被按下
    //判断y和ctrl是否同时被按下
    if(event.keyCode === 89 && event.ctrlKey){
      console.log("ctrl和y都被按下了")
    }
  }
  /*document.onkeyup = function(){
            console.log("按键松开了")
    }*/
  //获取input
  var input = document.getElementsByTagName("input")[0] // <input type="text" />
  input.onkeydown = function(event){        
    event = event || window.event
    //console.log(event.keyCode)
    //数字 48 - 57
    //使文本框中不能输入数字
    if(event.keyCode >= 48 && event.keyCode <= 57){
      //在文本框中输入内容,属于onkeydown的默认行为
      //如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中
      return false
    }
  }
}

通过按键移动盒子

<style type="text/css">
    #box1{
        width: 100px;
        height: 100px;
        background-color: red;
        position: absolute;
    }
</style>
<script type="text/javascript">
    //使div可以根据不同的方向键向不同的方向移动
    /*
     * 按左键,div向左移
     * 按右键,div向右移
     * ……
     */
    window.onload = function(){
        //为document绑定一个按键按下的事件
        document.onkeydown = function(event){
            event = event || window.event
            //定义一个变量,来表示移动的速度
            var speed = 10
            //当用户按了ctrl以后,速度加快
            if(event.ctrlKey){
                speed = 500
            }

            /*
             * 37 左
             * 38 上
             * 39 右
             * 40 下
             */
            switch(event.keyCode){
                case 37
                    //alert("向左"); left值减小
                    box1.style.left = box1.offsetLeft - speed + "px"
                    break
                case 39:
                    //alert("向右");
                    box1.style.left = box1.offsetLeft + speed + "px"
                    break
                case 38:
                    //alert("向上");
                    box1.style.top = box1.offsetTop - speed + "px"
                    break
                case 40:
                    //alert("向下");
                    box1.style.top = box1.offsetTop + speed + "px"
                    break
            }
        }
    }
</script>
<div id="box1"></div>

还存在问题:会有卡顿

四、BOM

BOM(浏览器对象模型)可以使我们通过js来操作浏览器

在BOM中为我们提供了一组对象,用来完成对浏览器的操作

BOM对象:

  • window——代表的是整个浏览器窗口,同时也是网页中的全局对象
  • navigator——代表的是当前浏览器的信息,通过该对象可以识别不同的浏览器
  • location——代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转网页
  • history——代表浏览器的历史记录,可以通过该对象来操作浏览器的而历史记录(由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效)
  • screen——代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

console.log(window)
// console.log(navigator)
console.log(window.navigator)
console.log(location)
console.log(screen)

1、Navigator

  • 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
  • 由于历史原因,Navigator对象中的大部分属性已经不能帮助我们识别浏览器了
属性 描述
appCodeName 返回浏览器的代码名。
appMinorVersion 返回浏览器的次级版本。
appName 返回浏览器的名称。
appVersion 返回浏览器的平台和版本信息。
browserLanguage 返回当前浏览器的语言。
cookieEnabled 返回指明浏览器中是否启用 cookie 的布尔值。
cpuClass 返回浏览器系统的 CPU 等级。
onLine 返回指明系统是否处于脱机模式的布尔值。
platform 返回运行浏览器的操作系统平台。
systemLanguage 返回 OS 使用的默认语言。
userAgent 返回由客户机发送服务器的 user-agent 头部的值。
userLanguage 返回 OS 的自然语言设置。
方法 描述
javaEnabled() 规定浏览器是否启用 Java。
taintEnabled() 规定浏览器是否启用数据污点 (data tainting)。
alert(navigator.appName)
  • 一般我们只会使用userAgent来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent
console.log(navigator.userAgent)
火狐的userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0"
Chrome的userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
IE11
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0; rv:11.0) like Gecko"
IE10
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0)"
IE9
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0)"
IE8
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0)"

根据UA来判断

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("woc,你是IE")
}

如果通过userAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息

比如:ActiveXObject

if("ActiveXObject" in window){
    alert("你是IE,我已经抓住你了~~~");
}else{
    alert("你不是IE~~~");
}

/*alert("ActiveXObject" in window);*/

if(/firefox/i.test(ua)){
  alert("你是火狐")
}else if(/chrome/i.test(ua)){
  alert("你是Chrome")
}else if(/msie/i.test(ua)){
  alert("woc,你是IE")
} else if("ActiveXObject" in window){
    alert("你是IE11,还好");
}

2、History

  • History对象可以用来操作浏览器向前或向后翻页
属性 描述
length 返回浏览器历史列表中的 URL 数量。
方法 描述
back() 加载 history 列表中的前一个 URL。
forward() 加载 history 列表中的下一个 URL。
go() 加载 history 列表中的某个具体页面。
// length属性可以获取到当前访问的链接数量
alert(history.length)
// back()可以用来回退到上一个页面,作用和浏览器的回退按钮一样
history.back()
// forward()可以跳转到下一个页面,作用和浏览器的前进按钮一样
history.forward()
/*
 go()可以用来跳转到指定的页面,需要一个整数作为参数
 * 1:表示向前跳转一个页面,相当于forward()
 * 2:表示向前跳转两个页面
 * -1:表示向后跳转一个页面
 * -2:表示向后跳转 两个页面
*/
history.go(-2)

3、Location

如果直接打印location,则可以获取到地址栏中的信息(当前页面的完整路径)

alert(location)

如果直接将location属性修改为一个完整的路径或相对路径,则我们的页面会自动跳转到该路径,并且会生成响应的历史记录

location = "http://www.baidu.com"
location = "./index.html"
属性 描述
hash 设置或返回从井号 (#) 开始的 URL(锚)。
host 设置或返回主机名和当前 URL 的端口号。
hostname 设置或返回当前 URL 的主机名。
href 设置或返回完整的 URL。
pathname 设置或返回当前 URL 的路径部分。
port 设置或返回当前 URL 的端口号。
protocol 设置或返回当前 URL 的协议。
search 设置或返回从问号 (?) 开始的 URL(查询部分)。
属性 描述
assign() 加载新的文档。
reload() 重新加载当前文档。
replace() 用新的文档替换当前文档。
// assign()用来跳转到其他的页面,作用和直接修改location一样
location.assign("http://www.baidu.com");

/*
 * reload()
 *     - 用于重新加载当前页面,作用和刷新按钮一样
 *     - 如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面
 */
location.reload(true);

/*
 * replace()
 *     - 可以使用一个新的页面替换当前页面,调用完毕也会跳转页面
 *         不会生成历史记录,不能使用回退按钮回退
 */
location.replace("index.html");

4、Screen

属性 描述
availHeight 返回显示屏幕的高度 (除 Windows 任务栏之外)。
availWidth 返回显示屏幕的宽度 (除 Windows 任务栏之外)。
bufferDepth 设置或返回调色板的比特深度。
colorDepth 返回目标设备或缓冲器上的调色板的比特深度。
deviceXDPI 返回显示屏幕的每英寸水平点数。
deviceYDPI 返回显示屏幕的每英寸垂直点数。
fontSmoothingEnabled 返回用户是否在显示控制面板中启用了字体平滑。
height 返回显示屏幕的高度。
logicalXDPI 返回显示屏幕每英寸的水平方向的常规点数。
logicalYDPI 返回显示屏幕每英寸的垂直方向的常规点数。
pixelDepth 返回显示屏幕的颜色分辨率(比特每像素)。
updateInterval 设置或返回屏幕的刷新率。
width 返回显示器屏幕的宽度。

5、Window

属性 描述
closed 返回窗口是否已被关闭。
defaultStatus 设置或返回窗口状态栏中的默认文本。
document 对 Document 对象的只读引用。请参阅 Document 对象
history 对 History 对象的只读引用。请参数 History 对象
innerheight 返回窗口的文档显示区的高度。
innerwidth 返回窗口的文档显示区的宽度。
length 设置或返回窗口中的框架数量。
location 用于窗口或框架的 Location 对象。请参阅 Location 对象
name 设置或返回窗口的名称。
Navigator 对 Navigator 对象的只读引用。请参数 Navigator 对象
opener 返回对创建此窗口的窗口的引用。
outerheight 返回窗口的外部高度。
outerwidth 返回窗口的外部宽度。
pageXOffset 设置或返回当前页面相对于窗口显示区左上角的 X 位置。
pageYOffset 设置或返回当前页面相对于窗口显示区左上角的 Y 位置。
parent 返回父窗口。
Screen 对 Screen 对象的只读引用。请参数 Screen 对象
self 返回对当前窗口的引用。等价于 Window 属性。
status 设置窗口状态栏的文本。
top 返回最顶层的先辈窗口。
window window 属性等价于 self 属性,它包含了对窗口自身的引用。
screenLef/tscreenTop/screenX/screenY 只读整数。声明了窗口的左上角在屏幕上的的 x 坐标和 y 坐标。IE、Safari 和 Opera 支持 screenLeft 和 screenTop,而 Firefox 和 Safari 支持 screenX 和 screenY。
方法 描述
alert() 显示带有一段消息和一个确认按钮的警告框。
blur() 把键盘焦点从顶层窗口移开。
clearInterval() 取消由 setInterval() 设置的 timeout。
clearTimeout() 取消由 setTimeout() 方法设置的 timeout。
close() 关闭浏览器窗口。
confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。
createPopup() 创建一个 pop-up 窗口。
focus() 把键盘焦点给予一个窗口。
moveBy() 可相对窗口的当前坐标把它移动指定的像素。
moveTo() 把窗口的左上角移动到一个指定的坐标。
open() 打开一个新的浏览器窗口或查找一个已命名的窗口。
print() 打印当前窗口的内容。
prompt() 显示可提示用户输入的对话框。
resizeBy() 按照指定的像素调整窗口的大小。
resizeTo() 把窗口的大小调整到指定的宽度和高度。
scrollBy() 按照指定的像素值来滚动内容。
scrollTo() 把内容滚动到指定的坐标。
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。
setTimeout() 在指定的毫秒数后调用函数或计算表达式。

定时器:

  • 循环定时器

js的程序执行速度是非常快的,如果洗完过一段程序,可以每隔一段事件执行一次,可以使用定时调用

setInterval()定时调用

可以将一个函数,每隔一段事件执行一次

参数有两个:

第一个是回调函数,该函数会每隔一段时间调用一次

第二个是每次调用间隔的时间,单位是毫秒

返回值:

返回一个Number类型的数据,这个数字用来作为定时器的唯一标识

clearInterval()可以用来关闭一个定时器,方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

  • 延时定时器

setTimeout()延时调用,延时调用一个函数不马上执行,而是隔一段时间以后在执行,而且只会执行一次

延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次

延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择

  1. count自动增加
<h1 id="count"></h1>
<script>
    /*// 执行太快
  for(var i=0 ; i<10000 ; i++){
      count.innerHTML = i
      alert("hello")
  }*/
  var num = 1
  var timer = setInterval(function(){
    count.innerHTML = num++
        if(num == 11){
            //关闭定时器
            clearInterval(timer)
        }            
    },1000)        
    //console.log(timer)
</script>
  1. 自动切换图片
<script type="text/javascript">
  window.onload = function(){
    /*
      * 使图片可以自动切换
      */
    //获取img标签
    var img = document.getElementById("img")
    //创建一个数组来保存图片的路径
    var imgArr = ["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg","img/5.jpg"]
    //创建一个变量,用来保存当前图片的索引
    var index = 0
    //定义一个变量,用来保存定时器的标识
    var timer
    //为btn01绑定一个单击响应函数
    var startBtn = document.getElementById("startBtn")
    startBtn.onclick = function(){
      /*
        * 目前,我们每点击一次按钮,就会开启一个定时器,
        *     点击多次就会开启多个定时器,这就导致图片的切换速度过快,
        *     并且我们只能关闭最后一次开启的定时器
        */
      //在开启定时器之前,需要将当前元素上的其他定时器关闭
      clearInterval(timer)
      /*
        * 开启一个定时器,来自动切换图片
        */
      timer = setInterval(function(){
        //使索引自增
        index++
        //判断索引是否超过最大索引
        /*if(index >= imgArr.length){
          //则将index设置为0
          index = 0;
        }*/
        index %= imgArr.length
        //修改img的src属性
        img.src = imgArr[index]
      },1000)
    }
    //为stopBtn绑定一个单击响应函数
    var stopBtn = document.getElementById("stopBtn")
    stopBtn.onclick = function(){
      //点击按钮以后,停止图片的自动切换,关闭定时器
      /*
        * clearInterval()可以接收任意参数,
        *     如果参数是一个有效的定时器的标识,则停止对应的定时器
        *     如果参数不是一个有效的标识,则什么也不做
        */
      clearInterval(timer)
    }
  }
</script>
<img id="img" src="img/1.jpg"/>
<br /><br />
<button id="startBtn">开始</button>
<button id="stopBtn">停止</button>
  1. 解决按键移动box卡顿问题
<style type="text/css">
  #box1{
    width: 100px;
    height: 100px;
    background-color: red;
    position: absolute;
  }
</style>
<script type="text/javascript">
  //使div可以根据不同的方向键向不同的方向移动
  /*
    * 按左键,div向左移
    * 按右键,div向右移
    * 。。。
    */
  window.onload = function(){ 
    //定义一个变量,来表示移动的速度
    var speed = 10
    //创建一个变量表示方向
    //通过修改dir来影响移动的方向
    var dir = 0
    //开启一个定时器,来控制div的移动
    setInterval(function(){
      /*
        * 37 左
        * 38 上
        * 39 右
        * 40 下
        */
      switch(dir){
        case 37:
          //alert("向左"); left值减小
          box1.style.left = box1.offsetLeft - speed + "px"
          break
        case 39:
          //alert("向右");
          box1.style.left = box1.offsetLeft + speed + "px"
          break
        case 38:
          //alert("向上");
          box1.style.top = box1.offsetTop - speed + "px"
          break
        case 40:
          //alert("向下");
          box1.style.top = box1.offsetTop + speed + "px"
          break
      }
    },30)
    //为document绑定一个按键按下的事件
    document.onkeydown = function(event){
      event = event || window.event
      //当用户按了ctrl以后,速度加快
      if(event.ctrlKey){
        speed = 500
      }else{
        speed = 10
      }
      //使dir等于按键的值
      dir = event.keyCode
    };
    //当按键松开时,div不再移动
    document.onkeyup = function(){
      //设置方向为0
      dir = 0
    }  
  }
</script>
<div id="box1"></div>

延时调用

/*setInterval(function(){
    console.log(num++);
},3000);*/
var timer = setTimeout(function(){
    console.log(num++)
},3000)
//使用clearTimeout()来关闭一个延时调用
clearTimeout(timer);
  1. 盒子移动
<style type="text/css"> 
  *{
    margin: 0;
    padding: 0;
  } 
  #box1{
    width: 100px;
    height: 100px;
    margin-top: 50px;
    background-color: red;
    position: absolute;
    left: 0;
  }
</style>
<script type="text/javascript">
  window.onload = function(){
    //获取box1
    var box1 = document.getElementById("box1")
    //获取btn01
    var btn01 = document.getElementById("btn01")
    //定义一个变量,用来保存定时器的标识
    var timer
    //点击按钮以后,使box1向右移动(left值增大)
    btn01.onclick = function(){
      //关闭上一个定时器
      clearInterval(timer)
      //开启一个定时器,用来执行动画效果
      timer = setInterval(function(){
        //获取box1的原来的left值
        var oldValue = parseInt(getStyle(box1,"left"))
        //在旧值的基础上增加
        var newValue = oldValue + 1
        //判断newValue是否大于800
        if(newValue > 800){
          newValue = 800
        }
        //将新值设置给box1
        box1.style.left = newValue + "px"
        //当元素移动到800px时,使其停止执行动画
        if(newValue == 800){
          //达到目标,关闭定时器
          clearInterval(timer)
        }
      },30)
    }
  }
  /*
    * 定义一个函数,用来获取指定元素的当前的样式
    * 参数:
    *         obj 要获取样式的元素
    *         name 要获取的样式名
    */
  function getStyle(obj , name){
    if(window.getComputedStyle){
      //正常浏览器的方式,具有getComputedStyle()方法
      return getComputedStyle(obj , null)[name]
    }else{
      //IE8的方式,没有getComputedStyle()方法
      return obj.currentStyle[name]
    }
  }
</script>
<button id="btn01">点击按钮以后box1向右移动</button>
<div id="box1"></div>
<div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>
  1. 封装一个移动函数
<script type="text/javascript">
  window.onload = function(){
    //获取box1
    var box1 = document.getElementById("box1")
    //获取btn01
    var btn01 = document.getElementById("btn01")
    //获取btn02
    var btn02 = document.getElementById("btn02")
    //点击按钮以后,使box1向右移动(left值增大)
    btn01.onclick = function(){
      move(box1 , 800 , 10)
    }
    //点击按钮以后,使box1向左移动(left值减小)
    btn02.onclick = function(){
      move(box1 , 0 , 10)
    }
  }
  //定义一个变量,用来保存定时器的标识
  var timer
  //尝试创建一个可以执行简单动画的函数
  /*
    * 参数:
    *     obj:要执行动画的对象
    *     target:执行动画的目标位置
    *     speed:移动的速度(正数向右移动,负数向左移动)
    */
  function move(obj , target ,speed){
    //关闭上一个定时器
    clearInterval(timer)
    //获取元素目前的位置
    var current = parseInt(getStyle(obj,"left"))
    //判断速度的正负值
    //如果从0 向 800移动,则speed为正
    //如果从800向0移动,则speed为负
    if(current > target){
      //此时速度应为负值
      speed = -speed
    }
    //开启一个定时器,用来执行动画效果
    timer = setInterval(function(){
      //获取box1的原来的left值
      var oldValue = parseInt(getStyle(obj,"left"))
      //在旧值的基础上增加
      var newValue = oldValue + speed
      //判断newValue是否大于800
      //从800 向 0移动
      //向左移动时,需要判断newValue是否小于target
      //向右移动时,需要判断newValue是否大于target
      if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)){
        newValue = target
      }
      //将新值设置给box1
      obj.style.left = newValue + "px"
      //当元素移动到0px时,使其停止执行动画
      if(newValue == target){
        //达到目标,关闭定时器
        clearInterval(timer)
      }
    },30)
  }
  /*
    * 定义一个函数,用来获取指定元素的当前的样式
    * 参数:
    *         obj 要获取样式的元素
    *         name 要获取的样式名
    */
  function getStyle(obj , name){
    if(window.getComputedStyle){
      //正常浏览器的方式,具有getComputedStyle()方法
      return getComputedStyle(obj , null)[name]
    }else{
      //IE8的方式,没有getComputedStyle()方法
      return obj.currentStyle[name]
    }
  }
</script>
<button id="btn01">点击按钮以后box1向右移动</button>
<button id="btn02">点击按钮以后box1向左移动</button>
<div id="box1"></div>
<div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>

封装move.js

//尝试创建一个可以执行简单动画的函数
/*
 * 参数:
 *     obj:要执行动画的对象
 *     attr:要执行动画的样式,比如:left top width height
 *     target:执行动画的目标位置
 *     speed:移动的速度(正数向右移动,负数向左移动)
 *  callback:回调函数,这个函数将会在动画执行完毕以后执行
 */
function move(obj, attr, target, speed, callback) {
    //关闭上一个定时器
    clearInterval(obj.timer)
    //获取元素目前的位置
    var current = parseInt(getStyle(obj, attr))
    //判断速度的正负值
    //如果从0 向 800移动,则speed为正
    //如果从800向0移动,则speed为负
    if(current > target) {
        //此时速度应为负值
        speed = -speed
    }
    //开启一个定时器,用来执行动画效果
    //向执行动画的对象中添加一个timer属性,用来保存它自己的定时器的标识
    obj.timer = setInterval(function() {
        //获取box1的原来的left值
        var oldValue = parseInt(getStyle(obj, attr))
        //在旧值的基础上增加
        var newValue = oldValue + speed
        //判断newValue是否大于800
        //从800 向 0移动
        //向左移动时,需要判断newValue是否小于target
        //向右移动时,需要判断newValue是否大于target
        if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
            newValue = target
        }
        //将新值设置给box1
        obj.style[attr] = newValue + "px"
        //当元素移动到0px时,使其停止执行动画
        if(newValue == target) {
            //达到目标,关闭定时器
            clearInterval(obj.timer)
            //动画执行完毕,调用回调函数
            callback && callback()
        }

    }, 30)
}

/*
 * 定义一个函数,用来获取指定元素的当前的样式
 * 参数:
 *         obj 要获取样式的元素
 *         name 要获取的样式名
 */
function getStyle(obj, name) {
    if(window.getComputedStyle) {
        //正常浏览器的方式,具有getComputedStyle()方法
        return getComputedStyle(obj, null)[name]
    } else {
        //IE8的方式,没有getComputedStyle()方法
        return obj.currentStyle[name]
    }
}

调用

<style type="text/css">
  *{
    margin: 0;
    padding: 0;
  }  
  #box1{
    margin-top: 50px;
    width: 100px;
    height: 100px;
    background-color: red;
    position: absolute;
    left: 0;
  }
  #box2{
    width: 100px;
    height: 100px;
    background-color: yellow;
    position: absolute;
    left: 0;
    top: 200px;
  }
</style>
<script type="text/javascript" src="js/move.js"></script>
<script type="text/javascript">
  window.onload = function(){
    //点击按钮以后,使box1向右移动(left值增大)
    btn01.onclick = function(){
      move(box1 ,"left", 800 , 20)
    }
    //点击按钮以后,使box1向左移动(left值减小)
    btn02.onclick = function(){
      move(box1 ,"left", 0 , 10)
    }
    //获取btn03
    var btn03 = document.getElementById("btn03")
    btn03.onclick = function(){
      move(box2 , "left",800 , 10)
    }
    //测试按钮
    var btn04 = document.getElementById("btn04");
    btn04.onclick = function(){
      //move(box2 ,"width", 800 , 10);
      //move(box2 ,"top", 800 , 10);
      //move(box2 ,"height", 800 , 10);
      move(box2 , "width" , 800 , 10 , function(){
        move(box2 , "height" , 400 , 10 , function(){
          move(box2 , "top" , 0 , 10 , function(){
            move(box2 , "width" , 100 , 10 , function(){

            })
          })
        })
      })
    }
  }
</script>
<button id="btn01">点击按钮以后box1向右移动</button>
<button id="btn02">点击按钮以后box1向左移动</button>
<button id="btn03">点击按钮以后box2向右移动</button>
<button id="btn04">测试按钮</button>
<div id="box1"></div>
<div id="box2"></div>
<div style="width: 0; height: 1000px; border-left:1px black solid; position: absolute; left: 800px;top:0;"></div>
  1. 轮播图
<style>
*{
    margin: 0;
    padding: 0;
}

/*
 * 设置outer的样式
 */
#outer{
    /*设置宽和高*/
    width: 520px;
    height: 333px;
    /*居中*/
    margin: 50px auto;
    /*设置背景颜色*/
    background-color: greenyellow;
    /*设置padding*/
    padding: 10px 0;
    /*开启相对定位*/
    position: relative;
    /*裁剪溢出的内容*/
    overflow: hidden;
}

/*设置imgList*/
#imgList{
    /*去除项目符号*/
    list-style: none;
    /*设置ul的宽度*/
    /*width: 2600px;*/
    /*开启绝对定位*/
    position: absolute;
    /*设置偏移量*/
    /*
     * 每向左移动520px,就会显示到下一张图片
     */
    left: 0px;
}

/*设置图片中的li*/
#imgList li{
    /*设置浮动*/
    float: left;
    /*设置左右外边距*/
    margin: 0 10px;
}

/*设置导航按钮*/
#navDiv{
    /*开启绝对定位*/
    position: absolute;
    /*设置位置*/
    bottom: 15px;
    /*设置left值
         outer宽度  520
         navDiv宽度 25*5 = 125
             520 - 125 = 395/2 = 197.5
     * */
    /*left: 197px;*/
}

#navDiv a{
    /*设置超链接浮动*/
    float: left;
    /*设置超链接的宽和高*/
    width: 15px;
    height: 15px;
    /*设置背景颜色*/
    background-color: red;
    /*设置左右外边距*/
    margin: 0 5px;
    /*设置透明*/
    opacity: 0.5;
    /*兼容IE8透明*/
    filter: alpha(opacity=50);
}

/*设置鼠标移入的效果*/
#navDiv a:hover{
    background-color: black;
}
</style>
<!-- 创建一个外部的div,来作为大的容器 -->
<div id="outer">
    <!-- 创建一个ul,用于放置图片 -->
    <ul id="imgList">
        <li><img src="img/1.jpg"/></li>
        <li><img src="img/2.jpg"/></li>
        <li><img src="img/3.jpg"/></li>
        <li><img src="img/4.jpg"/></li>
        <li><img src="img/5.jpg"/></li>
    <!-- 由于需要流畅衔接,故在最后加一张 -->
    <li><img src="img/1.jpg"/></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>

js



        <!--引用工具-->
        <script type="text/javascript" src="js/move.js"></script>
        <script type="text/javascript">
            window.onload = function(){
                //获取imgList
                var imgList = document.getElementById("imgList");
                //获取页面中所有的img标签
                var imgArr = document.getElementsByTagName("img");
                //设置imgList的宽度
                imgList.style.width = 520*imgArr.length+"px";


                /*设置导航按钮居中*/
                //获取navDiv
                var navDiv = document.getElementById("navDiv");
                //获取outer
                var outer = document.getElementById("outer");
                //设置navDiv的left值
                navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";

                //默认显示图片的索引
                var index = 0;
                //获取所有的a
                var allA = document.getElementsByTagName("a");
                //设置默认选中的效果
                allA[index].style.backgroundColor = "black";

                /*
                     点击超链接切换到指定的图片
                         点击第一个超链接,显示第一个图片
                         点击第二个超链接,显示第二个图片
                 * */

                //为所有的超链接都绑定单击响应函数
                for(var i=0; i<allA.length ; i++){

                    //为每一个超链接都添加一个num属性
                    allA[i].num = i;

                    //为超链接绑定单击响应函数
                    allA[i].onclick = function(){

                        //关闭自动切换的定时器
                        clearInterval(timer);
                        //获取点击超链接的索引,并将其设置为index
                        index = this.num;

                        //切换图片
                        /*
                         * 第一张  0 0
                         * 第二张  1 -520
                         * 第三张  2 -1040
                         */
                        //imgList.style.left = -520*index + "px";
                        //设置选中的a
                        setA();

                        //使用move函数来切换图片
                        move(imgList , "left" , -520*index , 20 , function(){
                            //动画执行完毕,开启自动切换
                            autoChange();
                        });

                    };
                }


                //开启自动切换图片
                autoChange();


                //创建一个方法用来设置选中的a
                function setA(){

                    //判断当前索引是否是最后一张图片
                    if(index >= imgArr.length - 1){
                        //则将index设置为0
                        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 %= imgArr.length;

                        //执行动画,切换图片
                        move(imgList , "left" , -520*index , 20 , function(){
                            //修改导航按钮
                            setA();
                        });

                    },3000);

                }


            };

        </script>

类的操作实现样式修改

我们可以通过修改元素的class属性来间接地修改样式,这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器只需要重新渲染页面一次,性能比较好,并且这种方式,可以使表现和行为进一步地分离

box.className = "b2" // 修改类名为b2
box.className += "b3"  // 在原有类的基础上加

定义函数,用来对一个元素中class进行操作

/* 添加添加指定的class属性值
参数:
obj: 要添加class属性的元素
cn: 要添加的class值
*/
/*function addClass(obj, cn){
  obj.className += " "+cn
}
addClass(box, "b2")
*/
// 有了就不需要添加了
function addClass(obj, cn){
  if(!hasClass(obj, cn)){
    obj.className += " "+cn
  }
}
/*
判断一个元素中是否含有指定的class属性值,如果有则返回true,没有则返回false
*/
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")
  obj.className = obj.className.replace(reg, "")
}
/*
toggleClass用来切换一个类,如果有,则删除;没有则添加
*/
function toggleClass(obj, cn){
  if(hasClass(obj, cn)){
    removeClass(obj, cn)
  }else{
    addClass(obj, cn)
  }
}

二级菜单

<style type="text/css">
    * {
        margin: 0;
        padding: 0;
        list-style-type: none;
    }
    a,img {
        border: 0;
        text-decoration: none;
    }
    body {
        font: 12px/180% Arial, Helvetica, sans-serif, "新宋体";
    }
    div.sdmenu {
        width: 150px;
        margin: 0 auto;
        font-family: Arial, sans-serif;
        font-size: 12px;
        padding-bottom: 10px;
        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;
        line-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: #066 url(linkarrow.gif) no-repeat right center;
        color: #fff;
        text-decoration: none;
    }
</style>
<div id="my_menu" class="sdmenu">
    <div>
        <span class="menuSpan">在线工具</span>
        <a href="javascript:;">图像优化</a>
        <a href="javascript:;">收藏夹图标生成器</a>
        <a href="javascript:;">邮件</a>
        <a href="javascript:;">htaccess密码</a>
        <a href="javascript:;">梯度图像</a>
        <a href="javascript:;">按钮生成器</a>
    </div>
    <div class="collapsed">
        <span class="menuSpan">支持我们</span>
        <a href="javascript:;">推荐我们</a>
        <a href="javascript:;">链接我们</a>
        <a href="javascript:;">网络资源</a>
    </div>
    <div class="collapsed">
        <span class="menuSpan">合作伙伴</span>
        <a href="javascript:;">JavaScript工具包</a>
        <a href="javascript:;">CSS驱动</a>
        <a href="javascript:;">CodingForums</a>
        <a href="javascript:;">CSS例子</a>
    </div>
    <div class="collapsed">
        <span class="menuSpan">测试电流</span>
        <a href="javascript:;">Test</a>
        <a href="javascript:;">2</a>
        <a href="javascript:;">Lorem</a>
        <a href="javascript:;">Lorem ipsum dolor sit amet</a>
    </div>
</div>

使这个菜单在点击时能够把二级菜单展示出来,点击另一个span,关掉该项打开点击的项

image-20200815084145224

<script type="text/javascript" src="js/move.js"></script>
<script type="text/javascript" src="js/class.js"></script>
<script type="text/javascript">
    window.onload = function(){
        /*
         * 我们的每一个菜单都是一个div
         *     当div具有collapsed这个类时,div就是折叠的状态
         *     当div没有这个类是,div就是展开的状态
         */
        /*
         * 点击菜单,切换菜单的显示状态
         */
        //获取所有的class为menuSpan的元素
        var menuSpan = document.querySelectorAll(".menuSpan");
        //定义一个变量,来保存当前打开的菜单
        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()不需要有移除的功能
                    //toggleClass(openDiv , "collapsed")
                    //切换菜单的显示状态
                    toggleMenu(openDiv)
                }
                //修改openDiv为当前打开的菜单
                openDiv = parentDiv
            }
        }
        /*
         * 用来切换菜单折叠和显示状态
         */
        function toggleMenu(obj){
            //在切换类之前,获取元素的高度
            var begin = obj.offsetHeight
            //切换parentDiv的显示
            toggleClass(obj , "collapsed")
            //在切换类之后获取一个高度
            var end = obj.offsetHeight
            //动画效果就是将高度从begin向end过渡
            //将元素的高度重置为begin
            obj.style.height = begin + "px"
            //执行动画,从bengin向end过渡
            move(obj,"height",end,10,function(){
                //动画执行完毕,内联样式已经没有存在的意义了,删除之
                obj.style.height = ""
            })
        }
    }
</script>

五、JSON

JSON

  • JS中的对象只有JS自己认识,其他的语言都不认识
  • JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
  • JavaScript Object Notation JS对象表示法
  • JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,其他的和JS语法一致
  • JSON分类:
    1. 对象 {}
    2. 数组 []
  • JSON中允许的值:
    1. 字符串
    2. 数值
    3. 布尔值
    4. null
    5. 对象
    6. 数组
//创建一个对象
var arr = '[1,2,3,"hello",true,null]'
var obj2 = '{"arr":[1,2,3]}'
var arr2 ='[{"name":"孙悟空","age":18,"gender":"男"},{"name":"孙悟空","age":18,"gender":"男"}]'

将JSON字符串转换为JS中的对象

  • 在JS中,为我们提供了一个工具类,就叫JSON
  • 这个对象可以帮助我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON

json –> js对象

  • JSON.parse()
  • 可以将以JSON字符串转换为js对象
  • 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回
var json = '{"name":"孙悟空","age":18,"gender":"男"}'
var o = JSON.parse(json)
var o2 = JSON.parse(arr)
console.log(o.gender)
console.log(o2[1])

JS对象 —> JSON

  • JSON.stringify()
  • 可以将一个JS对象转换为JSON字符串
  • 需要一个js对象作为参数,会返回一个JSON字符串
var obj3 = {name:"猪八戒" , age:28 , gender:"男"}
var str = JSON.stringify(obj3)
console.log(str)

JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理

<script src="https://cdn.bootcdn.net/ajax/libs/json2/20110223/json2.js"></script>

eval()

  • 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回
  • 如果使用eval()执行的字符串中含有{},它会将{}当成是代码块
  • 如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
  • eval()这个函数的功能很强大,可以直接执行一个字符串中的js代码,
  • 但是在开发中尽量不要使用,首先它的执行性能比较差,然后它还具有安全隐患
var str = '{"name":"孙悟空","age":18,"gender":"男"}'
var obj = eval("("+str+")")
console.log(obj)
给你的hexo加上一个炫酷的捐赠动画

给你的hexo加上一个炫酷的捐赠动画

先看下效果

donate

CSS学习笔记

CSS学习笔记

一、CSS简介

1、层叠样式表(Cascading Style Sheeets)

  • CSS可以用来为网页创建样式表,通过样式表可以对网页进行装饰

  • 可以将网页想象成是一层一层的结构,层次高的将会覆盖层次低的。

  • CSS可以分别为网页的各个层次设置样式

2、使用

  • 内联样式:将css样式编写到元素的style属性当中
<p style=”color:red;font-size:13px;”></p>

内联样式只对当前的元素中的内容起作用,不方便复用,结构与表现耦合,不方便后期维护,不推荐使用(可在测试样式时使用)

  • 将CSS样式编写到head中的style标签中,通过CSS选择器选中指定元素,可以同时为这些元素一起设置样式,这样可以是样式进一步的复用
<style type=”text/css”>
p {
  color:red;
  Font-size:13px;
}
</style>

将样式编写到style标签,可以是表现和结构进一步分离,推荐使用

  • 将样式编写到外部的css文件中,然后通过link标签将外部的css文件引入到当前页面中,这样外部文件中的css样式表将会应用到当前页面中
<link rel="stylesheet" type="text/css" href="style.css">

完全使结构和表现分离,可以让样式表在不同的页面中使用,最大限度的使样式可以进行复用,将样式统一写在样式表中,然后通过link标签引入,可以利用浏览器的缓存加快用户访问的速度,提高用户体验,最推荐使用

3、注释

// 单行注释

/* 注释内容 */

注:style中的不是html内容了

4、语法

选择器 声明块

  • 选择器:通过选择器可以选中页面中指定的元素,并且将声明块中的样式应用到选择器对应的元素上

  • 声明块:声明块紧跟在选择器的后边,使用一对{}括起来,声明块中实际上就是一组一组的名值对结构,这一组一组额名值对我们称为声明,在一个声明块中可以写多个声明,多个声明之间使用;隔开,声明的样式名和样式值之间使用:连接

    例如:

div{
  width: 200px;
  height: 200px;
}

5、块、内联元素

  • 块元素:独占一行的元素
<div>
   I’m div!
</div>

无论内容有多少,都会占一整行

div、p、h1、br…

div标签没有任何语义,就是一个纯粹的块元素,并且不会为它里面的元素设置任何的默认样式,div元素主要用来对页面进行布局的

  • 内联元素(行内元素):只占自身大小的元素,不会占用一行
<span>
  I’m span.
</span>

a、img、iframe、span

span没有任何的语义,span标签用来选中文字,然后为文字设置样式

Ps:块元素主要用来做页面中的布局,内联元素主要用来选中文本设置样式

一般情况下只使用块元素去包含内联元素,而不会使用内联元素去包含块元素,a元素可以包含除它本身之外的任意元素,p元素不可以包含任何的块元素

6、元素之间的关系

  • 父元素:直接包含子元素的元素

  • 子元素:直接被父元素包含的元素

  • 祖先元素:直接或间接包含后代元素的元素,父元素也是祖先元素

  • 后代元素:直接或间接被祖先元素包含的元素,子元素也是后代元素

  • 兄弟元素:拥有相同父元素的元素

二、选择器

由于选择器使用是基本的,因此就不和CSS3分开讲了

1、元素选择器:可以选中页面中的所有指定元素

语法:标签名{}

P{
  Color: red;
}
h1{
  Font-size:25px;
}

2、id选择器:通过元素的id属性值选中唯一的一个元素

语法:#id属性值{}

<p id=”p1”>hello</p>
<style>
  #p {
     Font-size:16px;
  }
</style>

3、类选择器:通过元素的class属性值选中一组元素

语法:.class属性值{}

<p class=”p2”>111</p>
<p class=”p2”>222</p>
<style>
    .p{
      font-size:16px;
    }
</style>

可以同时为一个元素设置多个class属性值,多个值之间使用空格隔开

<p class=”p2 111”>111</p>
<style>
    .111{
      font-size:20px;
    }
</style>

4、选择器分组(并集选择器):同时选中多个选择器对应的元素

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

#p1,.p2,h1{
  background-color:yellow;
}

5、通配选择器:选中页面中的所有元素

语法:*{}

*{ 
    margin:0; 
    padding:0;
}

6、复合选择器(交集选择器):选中同时满足多个选择器的元素

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

<span class="p3"></span>
<style>
    span.p3{
      background-color:yellow;
    }
</style>

Id一般不使用

7、后代元素选择器:选中指定元素的指定后代元素

语法:祖先元素 后代元素{}

<div>
  <p>
      <span>hello</span>
      <span>nihao</span>
  </p>
  <span>hello</span>
</div>
<style>
    div span{color:greenyellow;}
    div p span{font-size:50px;}
</style>

8、子元素选择器:选中指定父元素的指定子元素

语法:父元素>子元素{}

div>span{background-color:red;}

IE6及以下的不兼容

9、伪类选择器

伪类专门用来表示元素的一种的特殊的状态,例如访问过的超链接、获取焦点的文本框

当需要为处在这些特殊状态的元素设置样式时,就可以使用伪类

eg:

  • 正常(未访问过的) a:link

  • 访问过的 a:visited –浏览器通过历史记录来判断一个连接是否访问过。由于涉及到用户的隐私问题,故使用这个伪类只能设置字体的颜色(IE6能设置背景颜色)。

  • 鼠标滑过 a:hover

  • 正在点击 a:active (点击不松手)

后两个伪类其他元素也能设置(IE6不支持除a之外的元素设置)

  • 获取焦点 :focus
<input type="text" />
<style>
    input:focus{background-color: yellow;}
</style>
  • 指定元素前 :before 指定元素最前边的部分 一般需要结合属性content一起使用,添加内容
p:before{content:”最前边加的”;}
  • 指定元素后 :after 结束元素的最后的部分(结束标签前)

  • 选中的元素 ::selection 例如选中文字

火狐中可p::-moz-selection{background-color: orange;}

10、伪元素(选择特殊的位置)

段落定义

  • 文本的第一个字母或字 ::first-letter
/* 首字下沉 */
p::first-letter{
  font-size: 20px;
  float: left;  /* 文本环绕 */
}
  • 文本第一行::first-line

如果同时设置了first-letter,则无法影响这个字/字母

  • ::selection 可改变选中文本的样式,只能设置显示的样式,不能改变内容大小
  • ::before::after伪元素

i. 是一个行内元素,如果想要设置宽高需要转换为块(display:block float:** position:**)

ii. 必须添加content,即使没有内容,也要加上content: “”

iii. E:beforeE:after在旧版本里是伪类,在新版本中是伪元素,新版本中单冒号的会被自动识别为E::beforE::after,按伪元素来对待,这样做的目的是兼容性处理

iv. E::before:定义在一个元素的内容之前插入content属性定义的内容与样式

v. E::after:定义在一个元素的内容之后插入content属性定义的内容与样式

vi. 注意:

a) IE6、IE7与IE8(怪异模式Quirks Mode)不支持此伪元素

b) CSS2中E:beforeE:after属于伪类,并且没有伪元素的概念,CSS3中提出伪元素的概念E::beforeE::after,并且归属到了伪元素当中,伪类中就不再存在E:beforeE:after伪类

c) 功能完全等同于一个DOM元素,但是不会在DOM树中生成

11、属性选择器

title属性可以给任何标签指定,光标移动到元素上时,元素中的title属性的值将会作为提示文字显示。

作用:可以根据元素中的属性或属性值来选取指定元素

语法:元素(可以是元素选择器、类选择器、id选择器等)后跟

  • [属性名] 选取含有指定属性的元素

    E[attr]: 查找拥有attr属性的E标签

  • [属性名=”属性值”] 选取含有指定属性值的元素

    E[attr=value]: 查找拥有attr属性且属性值为value的E标签(严格匹配)

  • [属性名^=”属性值”] 选取属性值以指定内容开头的元素

    E[attr^=value]: 查找拥有attr属性且属性值是以value开头的E标签

  • [属性名*=”属性值”] 选取属性值包含指定内容的元素

    E[attr*=value]: 查找拥有attr属性且属性值中包含value(可以在任何位置)的E标签

  • [属性名$=”属性值”] 选取属性值以指定内容结尾的元素

    E[attr$=value]: 查找拥有attr属性且属性值是以value结尾的E标签

eg:

p[title] {background-color:green;}
p[title=hello] {background-color:yellow;} // 也可给title值加上双引号
p[title^=”ab”] {background-color:purple;} // 以ab开头的
p[title$=”c”] {background-color:pink;} // 以c结尾的
p[title*=”c”] {background-color:purple;} // 包含c的

12、子元素选择器

  • 父元素>子元素 : 比如div>a代表选择div下的子元素a

其他子元素选择器(相对于父元素的结构伪类)

  • :first-child:选择该元素父标签下第一个子标签

E:first-child: 查找E元素的父元素下的第一个E元素

  • :last-child:选择该元素父标签下最后一个子标签

E:last-child: 查找E元素中最后一个指定类型的子元素

  • :nth-child(n):选择指定位置的子元素,里面的n可以传
    • 数字:从1开始的数字,选择该元素父标签下的第几个子标签
    • n的表达式:n代表所有的该标签,2n代表父标签下偶数个子标签,3n代表选择第三个……,3n-1
    • even/odd:偶数/奇数

E:nth-child(n): 指定索引位置,n是从1开始的数字 也可以是偶数:even 奇数:odd

上面这三个是既需要满足最后一个,又得是这个标签,例如:

// p*3+ul>(span{span1}+li{$}*6+span{span2})
li:first-child{font-size: 30px;}  // 选择不到,因为li的父元素ul下第一个子元素是span,不满足li
span:last-child{color: green;} // 可以选择到,因为span的父元素ul下最后一个子元素是span
li:nth-child(2){background-color: red;} // 1的话选择不到,2能选择到<li>1</li>(在父元素下第二个,且为li标签)
body > p:first-child{color: red;} // body子元素p如果p是在第一个元素则选中,若p前还有其他类型的元素,则选不到了(所有元素中排)
P:last-child{color: green;}  // 如果最后一个p后面还有其他元素则选择不到
P:nth-child(2){background-color:yellow;} // 任意位置,传值,可以设置数字、even(偶数)、odd(奇数)
  • :first-of-type
  • :last-of-type
  • :nth-of-tyle(n) 这三个分别表示同类型中的第一个、最后一个、第几个

E:nth-of-type(n): (限定类型) n也可以是数字、even、odd、还可以是n(代表默认取值范围为0~子元素的长度)、还可以利用n取前几个(-n+5就是代表前5个,当n<=0时无效)

这三个选择指定类型的子元素,推荐使用这个

  • :nth-last-of-tyle(n)

E:nth-last-of-type(n): 同上(-n+5代表最后5个) (n——索引、关键字、表达式)

p:first-of-type{font-size: 20px;} // 所有p中的第一个(同一类型中排)
  • E:empty: 选中没有任何子节点的E元素(空格也算子元素)

  • E:target: 可以为锚点目标元素添加样式,当目标元素被触发为当前锚链接的目标时,调用此伪类样式

<style>
  h2:target{
    color: red;
  }
</style>
<a href="#title1">跳转到title1</a>
<a href="#title2">跳转到title2</a>
<h2 id="title1">title1</h2>
<p>……</p>
<h2 id="title2">title2</h2>
<p>……</p>

13、兄弟元素选择器(兄弟伪类)

(1) 后一个兄弟选择器

作用:选中一个元素后紧跟着的指定的兄弟元素

语法:前一个+后一个

span+p{} // span后紧挨着的p

(2) 选中后边的所有兄弟元素

语法:前一个~后边所有

span~p{}

14、否定伪类

作用:可以从已选中的元素中剔除出某些元素

语法: :not(选择器)

p:not(.hello){} // 选择所有不带hello类的p标签

三、样式的继承

和儿子继承父亲的遗产一样,在CSS中,祖先元素上的样式,也会被他的后代元素所继承。eg:

<p>
    这个是p中文字
  <span>p中的span</span>
</p>

利用继承,可以将一些基本的样式设置给祖先元素,这样所有的后代元素将会自动继承这些样式。但是并不是所有的样式都会被子元素所继承,例如背景相关边框相关定位相关的样式都不会被继承

四、选择器的优先级

当使用不同的选择器,选中同一个元素并且设置相同的样式时,这时样式之间产生了冲突,最终到底采用哪个选择器定义歌样式,由选择器的优先级(权重)决定,优先级高的优先显示。

1、优先级的规则

内联样式,优先级 1000

id选择器,优先级 100

类和伪类,优先级 10

元素选择器,优先级 1

通配*,优先级 0

继承的样式,没有优先级

当选择器中包含多种选择器时,需要将多种选择器的优先级相加然后再比较,但是注意,选择器优先级计算不会超过他的最大的数量级。如果选择器优先级一样,则使用靠后的样式(会覆盖前一个)。

并集选择器的优先级是单独计算的。

可以在样式的最后,添加一个!important,则此时该样式将会获得一个最高的优先级。

p{
  color: skyblue !important;
}

2、伪类的顺序

涉及到a的伪类一共有四个

这四个选择器的优先级是一样的

active应写在hover后面,前两个要写在后两个前面,即下面的顺序:

a:link{}

a:visited{}

a:hover{}

a:active{}

五、HTML中一些标签

HTML中有些标签需要拿出来讲解一下

1、文本标签

下面两个强调

  • <strong></strong>内容上的强调 显示为粗体

  • <em></em> 语气上的强调 显示为斜体

下面两个无语义,单纯加粗、斜体

  • <b></b> 内容以粗体显示
  • <i></i> 内容以斜体显示

大小

  • <small></small> small标签中的内容会比他的父元素中的文字要小一些,在H5中表示一些细则一类的内容,比如:合同中的小字、网站的版权声明等

  • big无语义,淘汰

    引用

  • <cite></cite>网页中所有的加书名号的内容,表示参考的内容

  • q标签表示短的引用(行内引用) 自动加双引号

  • blockquote标签表示一个长引用(块级引用)

    上下标

  • sup 设置上标

  • sub 设置下标

文字上的线

  • del 表示删除的内容 自动添加删除线

  • ins表示一个插入的内容 自动添加下划线

    代码片段

  • pre标签是一个预格式标签,将会将代码中的格式保存,不会忽略多个空格

  • code专门用来表示代码,一般结合precode来表示一段代码

2、列表

(1) 无序列表

ul标签来创建一个无序列表

使用liul中创建一个一个的列表项,一个li就是一个列表项

<ul type=”disc”>
  <li>北京</li>
  <li>上海</li>
</ul>

通过type属性可以修改无序列表的项目符号。默认的项目符号一般都不使用!非要加项目符号,采用为li设置背景方式实现。

  • disc 默认,实心的原点

  • square 实心方块

  • circle 空心圆球

去掉项目符号:

ul{
  list-style: none;
}

导航栏中的一般都是用的无序列表

ulli都是块元素

(2) 有序列表

ol来创建一个有序列表

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

有序列表使用有序的序号作为项目符号。

type属性可以指定序号的类型

  • 默认值,使用阿拉伯数字

  • a/A,小/大写

  • i/I,罗马数字

列表之间都是可以相互嵌套的,可以在无序列表中放有序列表,也可以在有序中放无序。当然嵌套的ulol都是放在li中。

(3) 定义列表

用来对一些词汇或内容进行定义

使用dl创建

dl中有两个子标签

dt:被定义的内容 dd:对定义的内容进行描述

<dl>
 <dt>胡萝卜<dt>
 <dd>蔬菜</dd>
 <dd>好吃</dd>
 <dd>含维生素E</dd>
 <dt>西瓜</dt>
 <dd>水果</dd>
</dl>

制作下拉菜单的时候可以用

3、表格

表格在日常生活中使用的非常多,比如excel就是专门用来创建表格的工具,表格就是用来表示一些格式化的数据的,比如:课程表、银行对账单等

在网页中也可以来创建出不同的表格

在HTML中使用table标签来创建一个表格

table标签中使用tr来表示表格中的一行,有几行就写几个tr

tr中需要使用td来创建一个单元格,有几个单元格就写几个td

可以使用th标签来表示表头中的内容,它的用法和td一样,不同的是它会有一些默认效果

使用<td colspan="2"></td>横向合并单元格

使用<td rowspan="2"></td>纵向合并单元格

直接用案例来看表格样式:

<style>
  table{
    width: 500px;
    margin: 30px auto;
    /* 设置边框 */
    border: 1px solid silver;
    /* 
     * table和td边框之间默认有一个距离,通过border-spacing属性可以设置这个距离
     */
     border-spacing: 10px;
     /* 
      * border-collapse可以用来设置表格的边框合并,如果设置了边框合并,则border-spacing自动失效
      */
     border-collapse: collapse;
  }
  /* 设置隔行变色 */
  tr:nth-child(even){
    background-color: skyblue;
  }
  /* 鼠标移入tr后,改变颜色 */
  tr:hover{
    background-color: #ff0;
  }
</style>
<table>
  <tr>
    <th>姓名</th>
    <th>性别</th>
    <th>年龄</th>
    <th>地址</th>
  </tr>
  <tr>
    <td>孙悟空</td>
    <td rowspan="2">男</td>
    <td>未知</td>
    <td>花果山</td>
  </tr>
  <tr>
    <td>猪八戒</td>
    <td>未知</td>
    <td>高老庄</td>
  </tr>
</table>

长表格

有一些情况下表格是非常长的,这时就需要将表格分为三个部分,表头、表格的主体、表格底部,分别用三个标签theadtbodytfoot表示

这三个标签的作用就是区分表格的不同部分,它们都是table的子标签,都需要直接写到table中,tr需要写在这些标签当中

标签theadtbodytfoot中的内容,永远会显示在表格的头部、中间、底部

如果表格中没有写tbody,浏览器会自动在表格中添加tbody,并且将所有的tr都放到tbody中,所以注意tr并不是table的子元素,而是tbody的子元素,通过table>tr无法选中行,需要通过tbody>tr

表格的列数由td最多的那行决定

表格是可以嵌套的,可以在td中再嵌套一个表格

使用表格布局–了解即可

以前表格很多情况实际上是用来对页面进行布局的,但是这种方式早已被CSS所淘汰了

演示一个吧:

<style>
  *{
    margin: 0;
    padding: 0;
  }
  table{
    width: 1200px;
    margin: 0 auto;
    border: none;
    border-spacing: 0;
  }
  .header, .footer{
    width: 1200px;
    height: 200px;
    background-color: yellow;
  }
  .nav{
    width: 200px;
    height: 516px;
    background-color: green;
  }
  .content{
    width: 780px;
    height: 516px;
    margin: 10px;
    background-color: skyblue;
  }
  .aside{
    width: 200px;
    height: 516px;
    background-color: pink;
  }
</style>
<table>
  <tr>
    <td colspan="3"><div class="header"></div></td>
  </tr>
  <tr>
    <td><div class="nav"></div></td>
    <td><div class="content"></div></td>
    <td><div class="aside"></div></td>
  </tr>
  <tr>
    <td colspan="3"><div class="footer"></div></td>
  </tr>
</table>

image-20200811172342416

写起来是真的很方便啊,但是改起来会想哭的

4、表单

表单的作用就是用来将用户信息提交给服务器的,比如:百度搜索框、登录这些操作都需要填写表单

使用form标签创建表单,form标签中必须制定一个action属性,该属性指向的是一个服务器的地址,当我们提交表单时将会提交到action属性对应的地址

使用form创建的仅仅是一个空白的表单,我们还需要向form中添加不同的表单项

  • 使用input来创建一个文本框,它的type属性是text,如果希望表单项中的数据提交到服务器中,还需要给表单项指定一个name属性,name表示提交内容的名字。用户填写的信息会负载url地址的后面以查询字符串的形式发送给服务器。在文本框中指定value属性值,将会作为默认值

url地址?查询字符串

属性名=属性值&属性名=属性值

  • 使用input创建密码框,它的type值为password
  • 使用input来创建单选按钮,它的type属性使用radio。单选按钮通过name属性进行分组,name属性值相同的是一组按钮。像这种需要用户选择,但是不需要用户直接填写内容的表单项,还必须指定一个value属性,这样被选中的表单项的value属性值将会最终提交给服务器
  • 使用input创建一个多选框,它的type属性使用checkbox
  • 使用select创建一个下拉列表,在下拉列表中使用option标签来创建一个个列表项.下拉列表的name属性指定给selectvalue属性指定给option

multiple=”multiple”可以选中多个

select中可以使用optgroup对选项进行分组,同一个optgroup中的选项是一组,通过label属性来指定分组的名字

如果希望在单选按钮或者是多选框中指定默认选中的选项,可以在想选中的项中,添加checked=”checked”属性

下拉列表可以通过在option中添加selected=”selected”将选项设置为默认选中

  • 使用textarea创建一个文本域
  • 提交按钮可以将表单中的信息提交给服务器,使用input创建一个提交按钮,它的type属性是submit,在提交按钮中,可以通过value属性来指定按钮上的文字

<input type="reset" />重置按钮,点击之后表单中的内容都会恢复为默认值

<input type="button" value="按钮">单纯的按钮,这个按钮没有任何功能,只能被点击,一般js设置功能

<button type="submit">提交</button>

<button type="reset">重置</button>

<button type="button">按钮</button>

这种方式和使用input类似,但是更灵活

  • 在HTML中提供了一个标签,专门用来选中表单中的提示文字的label标签,该标签可以指定一个for属性,该属性的值需要指定一个表单项的id值
  • 可以使用fieldset对表单项进行分组,在fieldset中使用legend子标签来指定组名

    <form action=”target.html”>
    <fieldset>
      <legend>用户信息</legend>
      <label for="usrname">用户名:</label><input type="text" name="username" id="usrname" /><br />
      <label>联系电话:<input type="text" name="num" /> </label><br />
      密码:<input type="password" name="pwd" /><br />
      性别:<input type="radio" name="gender" value="male" />
      <input type="radio" name="gender" value="female" checked="checked" />女<br />
    </fieldset>
    <fieldset>
      <legend>爱好</legend>
      爱好:<input type="checkbox" name="hobby" value="lq" />篮球
      <input type="checkbox" name="hobby" value="zq" />足球
      <input type="checkbox" name="hobby" value="pq" checked="checked" />排球
      <input type="checkbox" name="hobby" value="ymq" checked="checked" />羽毛球
      喜欢的明星:<select name="star">
        <optgroup lable="女明星">
          <option value="lxr">林心如</option>
          <option value="ym" selected="selected">杨幂</option>
          <option value="fbb">范冰冰</option>
        </optgroup>
        <optgroup label="男明星">
          <option value="lxr">林心如</option>
          <option value="ym" selected="selected">杨幂</option>
          <option value="fbb">范冰冰</option>
        </optgroup>
      </select>
    </fieldset>
    自我介绍:<textarea name="info"></textarea>
    <input type="submit" value="提交" />
    <input type="reset" />
    <input type="button" value="按钮">
    </form>

六、文本格式化

1、单位

  • px 像素

一个像素就相当于我们屏幕中的一个小点,我们的屏幕实际上就是由这些像素点构成的。但是这些像素点,是不能直接看见。不同显示器一个像素的大小也不相同,显示效果越好越清晰,像素就越小,反之像素越大

  • 百分比

根据其父元素的样式计算该值。

自适应页面常使用百分比作为单位。

  • em

em相对当前元素的字体大小来计算的

1em=1font-size

当设置字体相关的样式时,经常会使用em

2、颜色

CSS3中的颜色也到这里讲

  • 预设常量值:

    颜色单词 red、blue、green、orange……

  • RGB

    各颜色浓度

    rgb(红, 绿, 蓝),取值在0~255之间,还可以按百分比取

    rgb(255,0,0) rgb(200,0,0) rgb(0%,100%,0%)

  • HEX

    和上面类似,但以十六进制显示 ,前两位表示红,中间两位表示绿,最后两位表示蓝(00~ff)

    #FFFFFF 重复的两位可简写 #ff00aa #f0a

  • HSL

    H:Hue(色调、色相),0或360表示红色、120表示绿色、240表示蓝色。0~360,过渡也是红橙黄绿青蓝紫

    S:Saturation(饱和度)。0.0%~100.0%

    L:Lightness(亮度)。0.0%~100.0%,50%是平衡值 brightness

    rgb、hsl、HEX表示颜色,都是按橙黄绿紫顺序过去的,因此改变该颜色值,可以调到相邻的另一种颜色,比如rgb(255, 0, 0)表示红色,那么取一半

  • rgba rgba(128,128,0, .5)

  • hsla hsla(120, 1%, 50%, .5)

这两个只是多了一个透明通道alpha,都是在最后一个参数,取值0~1,这样设置的透明度不会影响子元素

后面讲的opacity:透明度 0~1 设置父容器,则父容器中的所有子元素也会透明

单词透明transparent不可调节透明度,始终完全透明

3、字体

(1) 字体颜色

格式:color: 颜色值;

例如:color: red;color: rgb(255, 0, 0);color: #f00;

(2) 字体大小

格式:font-size: 大小;

基本上填数值,而不使用large、small等属性值

font-size: 20px;

默认大小16px 并不是文字本身的大小 在页面中,每个文字都是处在一个看不见的框中 设置的实际上是格的高度,一般文字都要比这个格要小一些,有时会比格大 根据字体不同,显示效果也不同

(3) 字体

格式:font-family: 字体;

font-family: "微软雅黑";

如果浏览器支持该字体,则以该字体显示,不支持则用默认字体 可指定多个,font-family: arial, 宋体 ;优先使用前面字体,没有则尝试下一个 浏览器使用的字体默认使用计算机中字体 在开发中,字体用的少,尽量不要使用 。字体在后面还会讲到。

字体分类:(浏览器会自动选择大分类的一种字体)

  • serif(衬线字体):有粗细变化
  • sans-serif(非衬线字体):无粗细变化
  • monospace(等宽字体):上下同宽
  • cursive 草书字体
  • fantasy 虚幻字体

指定字体类型:font-family: sans-serif;

一般会将字体的大分类,指定为font-family中的最后一个字体。

font-family: arial, 微软雅黑, 华文彩云, serif; (前面字体找不到

找后面的)

(4) 字体样式

格式:font-style: 样式;

可选值:

  • normal正常字体
  • italic斜体
  • oblique斜体
  • inherit继承父元素样式
  • initial默认
  • unset不设置(正常)

(5)文本粗细

格式:font-weight: 样式值;

可选值:

  • normal 正常
  • bold 加粗
  • lighter 定义更细的字符
  • border 更粗一点
  • 100、200、300……900 定义由粗到细的字符。400 等同于 normal,而 700 等同于 bold。

(6) 小型大写字母

格式:font-variant: 样式值;

可选值:

  • normal 正常
  • small-caps 设置为小型大写字母字体

(7) font简写

font: italic small-caps bold 60px “微软雅黑”;

使用这个font属性最后两个属性值有顺序(位置必须倒一、倒二),且必须有这两个属性值。

(8) 行间距

通过设置行高 行高越大、行间距越大

line-height: 40px;

行高类似于单线本,两线之间的高度就是行高

网页中的文字实际上也是写在一个看不见的行中,文字会默认在行高中垂直居中 行间距=行高-字体大小

line-height: 120%;相对于字体大小

line-height: 1.5;

对于单行文本来说,可以将行高设置为和父元素高度一致,可以使单行文本在父元素中垂直居中

font的完整缩写font: font-style font-variant font-weight font-size/line-height font-family

font: 30px/40px “宋体”;字体大小/行高 字体

4、文本

(1) 大小写

格式:text-transform: 值;

可选值:

  • none 默认值,定义带有小写字母和大写字母的标准的文本
  • capitalize 文本中每个单词开头字母大写
  • uppercase 所有字母大写
  • lowercase 所有字母小写

(2) 文本修饰

  • text-decoration-line: 线的位置;
    • none 没有线
    • overline 文字上方
    • line-through 穿过文字
    • underline 文字下方
  • text-decoration-style: 线的样式;
    • none 默认的样式,一条直线
    • dashed 虚线
    • dotted 点
    • solid 直线
    • wavy 波浪线
  • text-decoration-color: 颜色值;
  • 其他的不重要

可以简写:text-decoration: underline dashed red;

(3) 字母间距

letter-spacing: 10px;

(4) 单词间距

word-spacing: 1em;

(5) 文本对齐

text-align: 值;

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

(6) 首行缩进 text-indent: 2em;

可用于隐藏文字text-indent: -99999px;

七、、盒子模型(框模型 Box Module)

1、盒子

  • CSS处理网页时,它认为每个元素都包含在一个不可见的盒子里
  • 我们只需要将相应的盒子摆放到网页中相应的位置即可完成网页的布局

2、盒子模型

一个盒子具有内容区(content)、内边距(padding)、边框(border)、外边距(margin)

盒模型

盒模型包括标准盒模型(W3C盒模型)和怪异盒模型(IE盒模型)

  • 标准盒模型width指的是内容区域content的宽度;height指的是内容区域content的高度。

标准盒模型下盒子的大小 = content + border + padding + margin

  • 怪异盒模型width指的是内容、边框、内边距总的宽度(content + border + padding);height指的是内容、边框、内边距总的高度

怪异盒模型下盒子的大小=width(content + border + padding) + margin

在默认情况下,CSS设置的盒子宽度仅仅是内容区的宽度,而非盒子的宽度。同样的高度类似。真正的盒子的宽度(在页面上呈现出来的宽度)和高度,需要加上一些其他的属性。

很明显,这种盒模型不直观,很容易出错,造成网页中其他元素的错位。

CSS3中可以通过box-sizing来指定盒模型,即可指定为

  • content-box:标准盒模型
  • border-box:IE盒模型

(1) widthheight 设置内容区的宽高

(2) border-widthborder-colorborder-style 设置边框宽、颜色、样式

  • border-width: 10px 2px 3px 5px; 四个值:上、右、下、左 (顺时针)

  • border-width: 10px 2px 3px; 三个值:上、左右、下

  • border-width: 10px 3px; 两个值:上下、左右

  • border-width: 10px ; 一个值:上下左右

  • 除此之外,还可以分别设置每边的宽:border-xxx-width: 10px; 其中xxx表示toprightbottomleft

  • border-color: red blue green pink; 与上方类似(四个值、三个值……)

  • 单独一边的颜色border-xxx-color: red; 其中xxx表示toprightbottomleft

  • border-style: none;

    • solid实线
    • dotted点状
    • dashed虚线
    • double双线
  • border-style: solid dotted dashed double;

  • 某一边的样式border-xxx-style: solid; 其中xxx表示toprightbottomleft

大部分浏览器中,边框的宽度和颜色都是有默认值的,而边框的样式默认值都是none

  • 简写 border: 10px red solid; 没顺序要求,不能分别指定四边

  • 单独指定边:border-xxx: 10px red solid; 其中xxx表示toprightbottomleft

(3) 内边距:指的是从边框到内容的距离

  • padding-xxx: 10px; 分别指定四个内边距 ,其中xxx表示toprightbottomleft

  • padding: 10px 20px 30px 40px;和上面类似(四个值、三个值……)

盒子可见框的大小由内容区、内边距、边框决定

(4) 外边距是当前盒子与其他盒子之间的距离,不会影响可见框的大小,而是影响盒子的位置

  • 分别设置四面外边距margin-xxx: 10px; 其中xxx表示toprightbottomleft

还可以设置为auto,一般设置在水平方向,如margin: 0 auto;

如果只给左右设置auto,那么那侧值会变成最大

  • 垂直方向,外边距默认就是0

  • 如果左右同时设置为auto,两侧外边距会设置为相同值,就可以使元素自动在父元素中居中 margin: 0 auto;

※ 垂直外边距的重叠

  • 在网页中垂直方向相邻外边距会发生外边距的重叠,即兄弟元素之间相邻外边距会取最大值而不是取和。

  • 如果父子元素的垂直外边距相邻了,则子元素的外边距会设置给父元素

可以使用boder和padding隔开相邻,但需要将其长度从内容宽高中去掉

浏览器为了在页面中没有样式时,也可以有一个比较好的现实效果,所以为很多的元素都设置了一些默认的margin和padding,而我们往往都是不需要的,因此要去掉

清除浏览器的默认样式:

*{
    margin: 0; 
    padding:0;
}

内联元素盒子 <span></span>

内联元素不能设置宽高,可以设置水平方向的内边距,可以设置垂直方向的内边距(但不会影响页面布局),可以设置边框(垂直的还是不会影响页面布局),支持水平方向外边距,不支持垂直外边距

通过display样式可以修改元素的类型

可选值:

  • Inline: 内联元素

  • block: 块元素

  • inline-block: 行内块元素(有两者的特点,支持宽高,不独占一行)例如img

  • none:不会显示,并且元素不会在页面中继续占有位置

还有隐藏元素的方式

visibility: visible;隐藏和显示 (默认显示)

  • hidden 隐藏 不显示但还是占位置

    opcity: 0;透明度为0

子元素默认是存在于父元素的内容区中,理论上子元素的最大可以等于父元素内容区的大小。如果子元素的大小超过了父元素的内容区,则超过的大小会在父元素以外的位置显示,超出父元素的内容,我们称为溢出的内容。通过overflow可以设置父元素如何处理溢出内容。

overflow: visible;默认在外面显示

  • hidden 溢出内容会被修剪,不会显示

  • scroll 为父元素添加滚动条,可以通过滑动滚动条查看,不论是否溢出均会添加滚动条

  • auto 根据需求自动添加滚动条

八、布局

1、概念

文档:就是一个网页

文档流:处在网页的最底层,它表示的是一个页面中的位置。我们创建的元素默认都处在文档流中。

元素在文档流中的特点:

块元素:独占一行(自上向下排列)。块元素默认宽度是父元素的100%。块元素的默认高度被内容/子元素撑开。

内联元素:只占自身大小,会默认自左向右排列。如果一行中不足以容纳所有的内联元素,则换到下一行,继续自左向右。在文档流中,内联元素的宽度和高度默认都被内容撑开。

当元素的宽度的值设置为auto时,此时指定内边距不会影响可见框的大小,但是会自动修改宽度,以适应内边距。

块元素在文档流中默认垂直排列,自上向下依次排开。

如果希望块元素在页面中水平排列,可以使块元素脱离文档流

2、浮动

float: none; 默认值,不浮动

  • left 元素脱离文档流,向左侧浮动

  • right 脱离文档流,向页面右侧浮动

当为一个元素设置浮动以后,元素会立即脱离文档流,元素脱离文档流以后,它下边的元素会立即向上移动。

元素浮动以后,会尽量向页面的左上或者右上浮动,直到遇到父元素的边框或其他的浮动元素。

如果浮动元素上边是一个没有浮动的块元素,则浮动元素不会超过块元素。

浮动的元素不会超过他上边的兄弟元素,最多和他一边齐

浮动的元素不会盖住文字,文字会自动环绕在浮动元素的周围,所以我们可以使用浮动来设置文字环绕图片的效果。

块元素脱离文档流以后,高度和宽度都被内容撑开。内联元素脱离文档流以后,会变成块元素。浮动之后不区分内联、块元素。

学完盒模型和浮动就可以完成大部分的布局了,布局分为固定布局和自适应布局

  • 固定布局:网页大小固定不变,不随设备不同改变
  • 自适应布局(响应):根据浏览器屏幕不同,布局发生改变

利用浮动进行简单布局

img

注:盒子套盒子,垂直摆放div,水平摆放float,看好宽高不越界,水平居中margin: 0 auto;

img

我们做一下上面这个效果:

<style>
  *{
    margin: 0;
    padding: 0;
  }
  body{
    min-width: 1200px;
  }
  .container{
    width: 1200px;
    margin: 0 auto;
  }
  header{
    width: 100%;
    height: 18vh;
    background-color: green;
  }
  footer{
    width: 100%;
    height: 18vh;
    background-color: #ddd;
  }
  main{
    width: 100%;
    height: 62vh;
    background-color: orange;
    margin: 1vh 0;
  }
  nav{
    float: left;
    width: 250px;
    height: 100%;
    background-color: skyblue;
  }
  article{
    float: left;
    width: 680px;
    height: 100%;
    background-color: #fffe03;
    margin: 0 10px;
  }
  aside{
    float: left;
    width: 250px;
    height: 100%;
    background-color: pink;
  }
</style>
<div class="container">
  <header></header>
  <main>
    <nav></nav>
    <article></article>
    <aside></aside>
  </main>
  <footer></footer>
</div>

甚至还可以嵌套更多:

img

3、高度塌陷问题

(1) 问题说明

在文档流中,父元素的高度默认被子元素撑开,即父元素不设置高度,子元素多高,父元素就有多高。但是当为子元素设置浮动以后,子元素会完全脱离文档流,此时将会导致子元素无法撑起父元素的高度,导致父元素高度塌陷,父元素下的所有元素都会向上移动,这样会导致网页布局混乱

可以将父元素写死,但是父元素的高度将不能自动适应子元素的高度,不建议使用

(2) BFC

根据W3C标准,页面中元素都有一个隐含的属性交Block Formatting Contex(BFC,块级格式化上下文),该属性可以设置打开,默认关闭

当开启元素的BFC以后,元素将会具有如下的特性:

  • 父元素的垂直外边距不会和子元素重叠

  • 该元素不会被浮动元素所覆盖

  • 该元素可以包含浮动的子元素

间接开启BFC

  • 设置元素浮动 父元素、子元素都浮动 使用这种方式,可以撑开父元素,但是父元素的宽度会丢失,也会导致下边的元素上移,不推荐

  • 设置元素绝对定位

  • 设置元素为inline-block 宽度也会丢失,不推荐

  • 将元素的overflow设置一个非visible的值

overflow: auto;

overflow设置为hidden是副作用最小的开启BFC的方式。IE6不支持,IE6具有另一个隐含属性hasLayout,与BFC类似,开启hasLayout副作用最小的zoom设置为1即可 放大1倍

zoom只在IE中支持,由于css不对的那条将会直接忽略,因此可以两种都写上

利用float写导航条

<style>
  *{
    margin: 0;
    padding: 0;
  }
  .nav{
    width: 1000px;
    margin: 50px auto;
    list-style: none;
    background-color: #bfa;
    overflow: auto;
    zoom: 1;
  }
  .nav li{
    float: left;
    width: 249px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    background-color: #6495ed;

  }
  .nav li:not(:last-of-type){
    border-right: 1px solid #ddd;
  }
  .nav li a{
    display: block;
    width: 100%;
    height: 100%;
    text-decoration: none;
    font-weight: bold;
  }
  .nav li a:hover{
    background-color: #cc0000;
  }
</style>
<ul class="nav">
  <li><a href="#">首页</a></li>
  <li><a href="#">新闻</a></li>
  <li><a href="#">联系</a></li>
  <li><a href="#">关于</a></li>
</ul>

4、清除浮动

有时希望清除其他元素浮动对当前元素产生的影响,可以使用clear

clear: none;默认值,不清除浮动影响

  • left 清除左侧浮动元素对当前元素的影响

  • right 清除右侧……

  • both 清除两侧……实际是清除对它影响最大的那个

可以在高度塌陷的父元素的最后,添加一个撑开父元素的空白div,对其进行清除浮动,但是添加了一个无用的结构,因此可以借用伪类:

.clearfix:after{
  content:””;
    display: block;
    clear:both;
}
.clearfix{zoom:1;} /*IE6*/

父元素多加一个类名clearfix

5、高度塌陷最终解决方案

经过修改后的clearfix是一个多功能的,既可以解决高度塌陷,又可以确保父元素和子元素的垂直外边距不会重叠

为父元素添加类名clearfix

<div class="parent clearfix">
  <div class="child"></div>
</div>

添加样式

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

6、定位

定位:将指定的元素摆放到页面的任意位置

position: static;默认值,元素没有开启定位

  • relative 开启元素的相对定位

  • absolute 绝对定位

  • fixed 固定定位

当开启了元素的定位,可以通过left、right、top、bottom四个属性来设置元素的偏移量,通常偏移量只使用两个就可以对一个元素进行定位,水平一个+垂直一个

相对定位

  • 开启了相对定位,而不设置偏移量时,元素不会发生任何变化

  • 相对定位是相对于元素在文档流中原来的位置进行定位

  • 相对定位的元素不会脱离文档流

  • 相对定位会使元素提升一个层级(覆盖底下的)

  • 相对定位不会改变元素的性质,块还是块,内联还是内联

绝对定位

  • 开启绝对定位会使元素脱离文档流

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

  • 绝对定位是相对于离他最近的开启了定位的祖先元素进行定位的(一般情况,开启了子元素的绝对定位,会同时开启父元素的相对定位);如果所有的祖先元素没有开启定位,则相对于浏览器窗口进行定位

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

  • 绝对定位会改变元素的性质,内联元素变成块元素,块元素的宽度和高度默认都被内容撑开

固定定位

固定定位也是一种绝对定位,它的大部分特点都和绝对定位一样,不同的是:

  • 固定定位永远都会相对于浏览器窗口进行定位

  • 固定定位会固定在浏览器窗口的某个位置,不会随滚动条滚动

IE6不支持固定定位

元素的层级

如果定位元素的层级是一样的,则下边的元素会盖住上边的

通过z-index属性可以用来设置元素的层级

可以为z-index指定一个正整数作为值,该值将会作为当前元素的层级,层级越高,越优先显示

  • 对于没有开启定位的元素不能使用z-index

  • 父元素的层级再高,也不会盖住子元素

九、背景

1、设置元素的透明背景

opacity: 1;0~1之间的值

  • 0完全透明
  • 1完全不透明
  • 0.5半透明

IE8及以下的浏览器不支持,可以使用filter: alpha(opacity=50); 透明度0~100

2、背景颜色

background-color: red;

3、背景图

(1) 添加背景图片

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

  • 如果背景图片大于元素,默认会显示图片的左上角

  • 如果背景图片与元素一样大,则背景图片将会完全显示

  • 如果背景图片小于元素大小,则会默认将背景图片平铺以充满元素

  • 可以同时为一个元素指定背景颜色和背景图片,这样背景颜色将会作为背景图片的底色,一般情况下设置背景图片时都会同时指定一个背景颜色

(2) 图片平铺

background-repeat: repert; 默认值,背景图片会双方向重复(平铺)

  • no-repeat 背景图片不会重复

  • repeat-x 背景图片沿水平方向重复

  • repeat-y 背景图片沿垂直方向重复

  • round 会将图片缩放之后进行平铺

  • space 产生相同的间距

(3) 图片位置

background-position: 0% 0%; 默认值,图片在左上角显示,水平 垂直

  • center center 只给一个值,第二个值默认为center

  • 1% 1% 左上角是0% 0%,右下角是100% 100%,只给一个值,第二个值默认为50%

  • 10px 0px 只设置一个值,另一个值将是50%

(4) 图片滚动

background-attachment: scroll; 默认值,背景图片随着页面一起滚动

  • fixed; 背景图片固定在某个位置,不随页面滚动。背景图片定位永远相对于浏览器窗口。

    /* 容器滚动时,背景图片动作 */
    background-attachment: fixed; 背景图片位置固定不变
    background-attachment: scroll; 跟随滚动
    /* 当前容器滚动时 */
    background-attachment: scroll; 不会随内容一起滚动
    background-attachment: local; 跟随滚动

在IE6中对图片格式png24支持度不高,如皋使用的图片格式是png24,则会导致透明效果无法正常显示。

  • 可以使用png8代替png24,图片清晰度会下降。

  • 使用JavaScript解决,在body标签的最后引入js文件

<!--[if IE 6]>
<script src="https://cdn.bootcdn.net/ajax/libs/dd_belatedpng/0.0.8/dd_belatedpng.min.js"></script>
<script>
    DD_belatedPNG.fixed(“div,img”); // 选择器
</script>
<![endif]-->

4、精灵/雪碧图(CSS-Sprite)

先看需求:给超链接和按钮设置背景图片、宽高、:link:hover:active

设置完成之后会发现第一次切换图片的时候,会发现图片有一个非常快的闪烁,这个闪烁会造成一次不佳的用户体验。

产生问题的原因:

背景图片是以外部资源的形式加载进网页的,浏览器每加载一个外部资源就需要单独地发送一次请求,但是我们外部资源并不是同时加载,浏览器会在资源被使用时才去加载资源。在这个案例中,一上来浏览器只会加载link.png,由于hover和active的状态没有马上出发,所以hover.png、active.png并不是立即加载的;只有当hover、active被触发时浏览器才去加载hover.png、active.png;由于加载图片需要一定的时间,所以在加载和显示过程会有一段时间,背景图片无法显示,导致出现闪烁的情况。

解决方案:图片整合技术(CSS-Sprite),将所有的小的背景素材放到同一张图片中,利用background-position进行位置调整得到想要的素材。

优点:

  • 将多个图片整合为一张图片,浏览器只需要发送一次请求,可以同时加载多个图片,提高访问效率,优化了用户体验

  • 减小了图片的总大小

5、背景图片简写属性

例如:

background-color: #bfa; /* 设置一个背景颜色 */
background-image: url(img/pic.png); /* 设置一个背景图片 */
background-repeat: no-repeat; /* 设置背景图片是否平铺 */
background-position: center center; /* 设置背景图片的位置 */
background-attachment: fixed; /* 设置背景图片不随滚动条滚动 */

简写

background: #bfa url(../img/1.png) center center no-repeat fixed;

没有顺序要求,没有数量要求,不设置采用默认值

十、CSS Hack

有一些情况,有一些特殊的代码我们只需要在某些特定的浏览器中执行,而在其他的浏览器中不需要执行,这时就可以使用CSS Hack来解决该问题

CSS Hack实际上指的是一个特殊的代码,这段代码只在某些浏览器中可以识别,而其他浏览器都不能识别,通过这种方式,来为一些浏览器设置特殊的代码

1、条件Hack

img

条件Hack只对IE浏览器有效,其他的浏览器都会将它识别为注释,IE10及以上的浏览器已经不支持这种方式

<!--[if IE]>
  <p>这是IE6</p>
<![endif]-->
<!--[if IE 6]>
  <p>这是IE6</p>
<![endif]-->
<!--[if IE 8]>
  <p>这是IE8</p>
<![endif]-->
<!--[if lte IE 9]>
  <p>您使用的浏览器是IE及以下的</p>
<![endif]-->

lt 小于 gt大于 lte小于等于

可以利用条件Hack,为IE浏览器单独引入样式

<link rel="stylesheet" href="style.css">
<!--[if IE 8]>
  <link rel="stylesheet" href="style-ie8.css">
<![endif]-->

2、属性级Hack

img

img

3、选择符级Hack

img

CSS Hack不到万不得已的情况尽量不要使用

十一、CSS3中其他属性

上面提到过CSS3中的选择器、盒模型、颜色,这里讲一下其他的

1、文本阴影(text-shadow)

text-shadow: none | <length> none | [<shadow>,]*<shadow> 或 none | <color> [,<color>]*

即:

text-shadow: [颜色(color) x轴(X Offset) y轴(Y Offset) 模糊半径(Blur)],[颜色 x轴 y轴 模糊半径],……

text-shadow: [x轴 y轴 模糊半径 颜色],[x轴 y轴 模糊半径 颜色],……

例如:

div{
  text-shadow: -2px -2px 5px red;
  /* text-shadow: 0px 0px 30px #fff;
  text-shadow: 0px 0px 30px #fff,
               0px 0px 50px red,
               0px 0px 70px #fff;
  text-shadow: 0px 1px 0px #fff;
  text-shadow: -1px -1px 0px #fff,
               -2px -2px 0px #eee,
               -3px -3px 0px #ddd,
               -4px -4px 0px #ccc;
  text-shadow:  0 0 8px hsla(30,100%,40%,1); */
}

2、边框圆角

border-radius: 值;

单独设置,border-xxx-radius设置不同方向

整合写为border-radius: 左上 右上 右下 左上;

两个值:左上/右下 右上/左下;

三个值:左上 右上/左下 右下;

设置不同方向的半径值 水平/垂直

border-radius: 100px/50px;

border-radius: 100px 80px 50px 30px/20px 30px 40px 50px;

3、渐变

渐变是CSS3中比较丰富多彩的一个特性,通过渐变我们可以实现许多绚丽的效果,有效减少图片的使用数量,并且具有很强的适应性和可扩展性。

(1) 线性渐变

linear-gradient([<point> || <angle>,]?<stop>,<stop>[,<stop>]]*)

  • 第一个参数表示线性渐变的方向
    • to left:设置渐变从右到左,相当于270deg
    • to right:设置渐变从左到右,相当于90deg
    • to top:设置渐变从下到上,相当于0deg
    • to bottom:设置渐变从下到上,相当于180deg,这个是默认值,等同于留空不写
    • 还可以指定度数,如45deg
  • 第二个参数是起点颜色,可以指定颜色的位置
  • 第三个参数是终点颜色,可以在后面添加更多的参数,表示多种颜色的渐变

例如:

background: linear-gradient(40deg, red 0%, red 10%, orange 12%, orange 15%, yellow 25%, green, blue, pink 60%);

image-20200811185824969

(2) 径向渐变

radial-gradient([[<shape>||<size>] [at <position>]? , | at <postition>,]?<color-stop>[,<color-stop>]+)

  • position:确定圆心的位置。如果提供两个参数,第一个表示横坐标,第二个表示纵坐标;如果只提供一个,第二值默认为50%,即center
  • shape:渐变的形状,ellipse表示椭圆形,circle表示圆形。默认为ellipse,如果元素的形状为正方形,啧ellipse和circle显示一样
  • size:渐变的大小,即渐变到哪里停止,它有四个值。closest-side:最近边,farthest-side:最远边,closest-corner:最近角,farthest-corner:最远角。默认是最远角farthest-corner
  • color:指定颜色
background: radial-gradient(red, blue)
background: radial-gradient(ellipse, red, blue) 或者circle(在非正方形中有区别,circle不会压缩、ellipse会压缩) 形状
background: radial-gradient(at 50px 50px, red, blue) 位置(坐标)
background: radial-gradient(circle closest-corner at 50px 50px, red, blue) 大小
background: radial-gradient(red, red 50%, blue 50%, blue)

(3) 重复渐变

background: repeating-linear-gradient(45deg, #fff 0%, #fff 10%, #000 10%, #000 20%)

background: repeating-radial-gradient(circle at center center, #fff 0%, #fff 10%, #000 10%, #000 20%)

4、 背景样式

设置背景图片的大小

background-size: auto(原始图片大小) || number(数值) || percentage(百分比) || cover(放大铺满) || contain(缩小铺满)

background-size: 300px 500px 同时设置宽高,建议保持与图片同比例,否则会造成图片失真变形

background-size: 300px; 只设置宽度,高度auto也是一种选择(图片会保持比例自动缩放)

设置百分比是参照父容器可放置内容区域的百分比background-size: 50% 50%

设置contain:按比例调整图片大小,使用图片宽高自适应整个元素的背景区域,使图片全部包含在容器中

  • 图片大于容器:有可能造成容器的空白区域,将图片缩小
  • 图片小于容器:有可能造成容器的空白区域,将图片放大

设置cover:与contain刚好相反,背景图片会按比例缩放至适应整个背景区域,如果背景区域不足以包含所有背景图片,图片内容会溢出

  • 图片大于容器:等比例缩小,会填满整个背景区域,有可能造成图片的某些区域不可见
  • 图片小于容器:等比例放大,填满整个背景区域,图片有可能造成某个方向上内容的溢出

一般轮播图就使用cover,方便在不同分辨率下显示完全

精灵图的部分使其居中并且放大,提升相应区域

5、边框背景图片

如下图所示,将图片等分为9个区域,将会和div平分为九个区域之后的格子一一对应

image-20200811202119076

div {
  margin: 20px auto;
  width: 300px;
  height: 300px;
  border: 54px solid red;
  /* 添加边框图片 */
  /* border-image-source:可以指定边框图片的路径,默认知识填充到容器的四个角 */
  border-image-source: url('img/borderbg.jpg');
  /* 让它成为九宫格:border-imgage-slice:设置四个方向上的裁切距离, fill:做内容的内部填充 */
  border-image-slice: 54 fill;
}

image-20200811202856670

image-20200811202921067

image-20200811202929582

image-20200811202942535

案例:按钮变形(上、右、下、左不变形,中间拉伸)

image-20200811203001861

image-20200811203012987

如果是纹理、渐变的背景,需要设置round或repeat(纯色可以默认stretch)

image-20200811203026219

6、 过渡

通过过渡transition,我们可以在不使用Flash 动画或JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果.要实现这一点,必须规定两项内容: 1.规定希望把效果添加到哪个CSS属性上,2.规定效果的时长

(1) 语法:

transition: property duration timing-function delay;

(2)参数说明:

transition属性是-一个简写属性,用于设置四个过渡属性:

描述
transition-property 规定设置过渡效果的CSS属性的名称
transition-duration 规定完成过渡效果费多少秒或毫秒
transition-timing-function 规定速度效果的速度曲线
transition-delay 定义过渡效果何时开始

(3) 补充说明tansition-timing-function:属性规定过渡效果的速度曲线

描述
linear 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。
ease 规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezier(0.25,0.1,0.25,1))。
ease-in 规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))。
ease-out 规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))。
ease-in-out 规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))。
cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。

cubic-bezier 函数可以到这个网站上查看

steps(<integer>[,start| end]?) <integer>:用于指定间隔个数(该值只能是正整数) 第二个参数可选,默认是end,表示开始值保持一次,若参数为start,表示开始值不保持

step-start: 直接位于结束处。相当于steps(1,start)

step-end: 位于开始处经过时间间隔后结束。相当于steps(1,end)

(4) eg: 点击之后移动到某位置,显示移动过程

image-20200811205701467

简写:transition: 属性名称 过渡时间 时间函数 延迟

transition: left 2s linear 0s;

image-20200811205843859

(5) 使用建议

因为transition最早是由webkit内核河克确提出来的,moila和opera都量最近版本才支持这个属性,而IE浏览器是不支持,另外由于各大现代浏览器firefox、Safari、Chrome、Opera都还不支持W3C的标准,所以在应用transition时有必要加上各自的前缀

-moz-transition: all 5s ease 1s;
-webkit-transition: all 1s ease 1s;
-o-transition: all 1s ease 1s;
transition: all 1s ease 1s;

7、 Transform

通过CSS3 transform 转换,我们能够对元素进行移动、缩放、旋转、斜切等操作。

(1) 2D移动translate()

使用translate()函数,你可以把元素从原来的位置移动,移动参照元素左上角原点

  • 语法: translate(tx) I translate(tx,tE)

  • tx是一个代表X轴(横坐标)移动的向量长度,当其值为正值时,元素向X轴右方向移动,反之其值为负值时,元素向X轴左方向移动。

  • ty是一个代表 Y轴(纵向标)移动的向量长度,当其值为正值时,元素向Y轴下方向移动,反之其值为负值时,元素向Y轴上方向移动。如果ty没有显式设置时,相当于ty=0。

  • 也可以使用translateX(x)或者translateY(ty)

    image-20200811211226225

(2) 2D缩放: scale()

缩放scale()函数让元素根据中心原点对对象进行缩放。
默认的值1,因此0.01到0.99之间的任何值都会使一个元素缩小;而任何大
于或等于1.01 的值都会让元素显得更大。缩放是参照元素中心点。

  • 语法: scale(sx|ty) | scale(sx,sy)

  • sx: 用来指定横向坐标(X轴)方向的缩放向量,如果值为0.01~0.99之间,会让对象在X轴方向缩小,如果值大于或等于1.01,对象在Y轴方向放大。

  • sy: 用来指定纵向坐标(Y轴)方向的缩放量,如果值为0.01~0.99之间,会让对象在Y轴方向缩小,如果值大于或等于1.01,对象在Y轴方向放大

  • 也可以使用scaleX(sx)或者scaleY(sy)

    image-20200811211647763

(3)2D旋转: rotate()

旋转rotate()函数通过指定的角度参数对元素根据对象原点指定一个2D旋转。它主要在二维空间内进行操作,接受一个角度值,用来指定旋转的幅度。如果这个值为正值,元素相对原点中心顺时针旋转;如果这个值为负值,元素相对原点中心逆时针旋转

  • 语法: rotate(a)

  • a: 代表的是一个旋转的角度值。 其取值可以是正的,也可以是负的。
    如果取值为正值时,元素默认之下相对元素中心点顺时针旋转;如果
    取值为负值时,元素默认之下相对元素中心点逆时针旋转

    image-20200811211906427

(4) 2D斜切: skew()

能够让元素倾斜显示。它可以将一个对象以其中心位置围绕看X轴和Y轴按照一定的角度倾斜。这与rotate()函数的旋转不同,rotate()函数只是旋转,而不会改变元素的形状。skew()函数不会旋转,而只会改变元素的形状

  • 语法:skew(ax) | skew(ax,ay)

  • ax:用来指定元素水平方向(X轴方向)倾鈄的角度。

  • ay:用来指定元素垂直方向(Y轴方向)倾斜的角度。如果未显式的设置这个值,其默认为

  • 也可以使用 skewX(sx)或者skewY(sy)

    image-20200811212118202

    image-20200811212126747

    image-20200811212137749

同时设置多个transform属性值

transform: translateX(700px) rotate(-90deg);

注意书写顺序

image-20200811212257492

备注:可利用定位和translate实现任意元素居中

定位中left、top的百分比是参照父容器的宽高

translate的百分比是参照元素本身的宽高

8、3D转换

三维变换使用基于二维变换相同的属性,可以让我们基于三个坐标方向对元素进行变换。

(1) 3D移动
方法:translate3d(x, y, z)使元素在这三个维度中移动,也可以分开写.如:
translateX(length),translateY(length),translateZ(length)

image-20200811212648882

(2) 3D缩放
scale3d(number,number,numben)使元素在这三个纬度中缩故,也可分开写,
如: scaleX(),scaleY(),scalZ()

image-20200811212836030

(3) 3D旋转

  • rotate3d(x, y, z, angle) ,指定需要进行旋转的坐标轴

  • rotatX(angle) 是元素依照x轴旋转;

  • rotateY(angle) 是元素依照y轴旋转;

  • rotateZ(angle) 是元素依照z轴旋转

    image-20200811213003421

9、透视/景深

左手法则:大拇指指向当前坐标轴的下方向,手指环绕的方向就是正方向

  • perspective(length) 为一个元素设置三维透视的距高。仅作用于元素的后代,而
    不是其元素本身。当perspective:none/0时,相当于没有设perspetive(length), 比如你要建立一个小立方体,长宽高都是200px,如果你的perspective< 200px,那就相当于站在盒子里面看的结果,如果perspective非常大那就是站在非常远的地方看(立方体已经成了小正方形了) , 意味着perspective属性指定了观察者与z=0平面的距离,使具有三维位置变换的元素产生透视效果
  • perspective-origin属性规定了镜头在平面上的位置,默认是放在元素的中心
  • tasom-style:使被蠡换的子元素保留其3D转换需要设置在父元素中
描述
flat 子元素将不保留其3D位置中面方式。
preseve-3d 子元素将保留其3D位置-立体方式。

10、 动画

image-20200811213731091

image-20200811213739261

image-20200811213748177

image-20200811213755937

image-20200811213806970

image-20200811213814634

11、 Web字体、字体图标

开发人员可以为自己的网页指定特殊的字体,无序考虑用户电脑上是否安装了此特殊字体

(1) 字体格式

不同浏览器所支持的字体格式不同

image-20200811204305599

获取这些种类的字体文件:

https://www.iconfont.cn/webfont?spm=a313x.7781069.1998910419.d81ec59f2#!/webfont/index

选中一种字体-本地下载-解压-根据demo在自己的项目中使用字体

<script>
    @font-face{
       font-family: ‘字体名’,
       src: url(‘路径/字体文件’);
       src: url(‘路径/字体文件’) format(‘格式’),
       url……
    }
    .myFont{
       font-family: 上面的字体名’
    }
</script>
<span class=”myFont>之前生成的文字</span>

注意:

  • 得自定义想生成对应字体文件的内容

  • 使用网络资源生成web字体

  • 使用:

    • 定义自定义字体
    • 定义样式使用自定义字体
    • 指定样式,调用样式

(2) 字体图标

常见的就是把网页常用的一些小图标,借助工具生成一个字体包,然后就可以像使用文字一样使用图标了

优点

  • 将所有图标打包成字体库,减少请求
  • 具有矢量性,可保证清晰度
  • 使用灵活,便于维护

fonticon或者fontawsome

十二、多列布局和弹性(伸缩)布局

1、 多列布局

image-20200811203753419

image-20200811203746127

image-20200811203736789

image-20200811203728192

2、 伸缩布局

传统布局方式的局限:

image-20200811203622593

image-20200811203601481

image-20200811203545505

image-20200811203527386

d中的所有属性都是在子元素中设置的

image-20200811203444454

image-20200811203454106

image-20200811203501719

image-20200811203509539

案例:弹性导航栏

image-20200811203409255

案例:宽高自动适应

image-20200811203320408

<div class="layout">
  <header>header</header>
  <main>
    <aside>left</aside>
    <article>right</article>
  </main>
  <footer>footer</footer>
</div>
<style>
*{
  margin: 0;
  padding: 0;
}
.layout{
  width: 500px;
  height: 600px;
  background-color: #ccc;
  margin: 10px auto;
  /* 设置父容器为伸缩盒子 */
  display: flex;
  /* 修改主轴方向 */
  flex-direction: column;
}
header{
  width: 100%;
  height: 60px;
  background-color: red;
}
main{
  width: 100%;
  background-color: green;
  /* 让当前伸缩项占据父容器的剩余空间 */
  flex: 1;
  /* 让main称为弹性盒子 */
  display: flex;
}
main > aside{
  height: 100%;
  flex: 1;
  background-color: pink;
}
main > article{
  height: 100%;
  flex: 3;
  background-color: purple;
}
footer{
  width: 100%;
  height: 80px;
  background-color: blue;
}
</style>

jQuery全屏滚动插件

http://www.jq22.com/jquery-info1124

十三、其他

1、重置样式表和默认样式表

img

2、对元素id和class还有文件的命名规范

img

3、cursor: point; 设置指针

4、解决IE6双边距

img

img

5、利用jsCssZip对CSS、js压缩

valine评论系统使用

valine评论系统使用

最开始用这个评论是在使用Sakura主题的时候,但是那个时候没认真看教程

觉得它没有邮件提醒功能、而且有的时候还会报错,就没使用了

改用的来必力和gitment,gitment使用起来挺方便的,能够邮件提醒,而且报的错误也能解决

emmmm……一直到现在,想接着用valine,然后搜了很多篇教程,发现valine还是非常好用的

手动配图:真香.gif

然后接下来就讲下怎样添加valine,对其进行美化和添加评论功能吧

Markdown语法大全

Markdown语法大全

这位老哥写的已经挺全了,刚好有一些语法忘记了,留个档

使用Markdown Here对微信公众号文章进行排版

使用Markdown Here对微信公众号文章进行排版

今天讲下微信公众号图文排版

HTML学习笔记

HTML学习笔记

一、HTML简介

1、HTML

全称为超文本标记语言(Hypetext Markup Language)

  • 其中超文本是相对纯文本来说的,HTML除了纯文本内容(文字、字符)还可以包括图片、音频、视频

  • 负责网页三要素中的结构

  • 使用标签(记)的形式来标识网页中的不同组成部分 <标签名>

    开始标签

    结束标签

  • 超文本标识——超链接

2、网页标准格式

一个简单的网页可以只有文本内容,也就是内容只写入纯文本,文件名后缀为.html.htm,浏览器将会把文本内容自动加到body标签中,基本内容如下

  • <html></html> 根标签 有且只有一个 网页内容写到里面

  • html两个子标签:

    • <head></head> 设置网页头部信息 不会在网页中直接显示 给浏览器看 解析网页

    • <body></body> 网页主体 页面中可见部分写在这

    • head子标签:

      • <title></title>网页标题 将在浏览器标签栏显示

标签关系——父标签、子标签、兄弟标签、祖先标签、后代标签

<html>
   <head>
      <title></title>
   </head>
   <body>
     文本内容在这
   </body>
</html>

3、发展

  • 1993年6月:HTML第一个版本发布
  • 1995年11月:HTML2.0
  • 1997年1月:HTML3.2(W3C推荐)
  • 1999年12月:HTML4.01(W3C推荐)
  • 2000年底:XHTML1.0(W3C推荐)
  • 2014年10月:HTML5(W3C推荐)

html xml xhtml html5

二、HTML5标准

(1)Doctype 使用版本

声明必须是 HTML 文档的第一行,位于 标签之前。

声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。

在 HTML 4.01 中,<!DOCTYPE> 声明引用 DTD,因为 HTML 4.01 基于 SGML。DTD 规定了标记语言的规则,这样浏览器才能正确地呈现内容。

HTML5 不基于 SGML,所以不需要引用 DTD。

提示:请始终向 HTML 文档添加 <!DOCTYPE> 声明,这样浏览器才能获知文档类型。

  • HTML4

    • 过渡版

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3.org/TR/html4/loose.dtd">
  • 严格版

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
  • 框架版

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/frameset.dtd">
  • XHTML

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • HTML5

    html4.01和xhtml的文档声明这么麻烦,还好我们只要使用HTML5就OK了

    <!DOCTYPE html>

    不写文档声明,有些浏览器会进入怪异模式(解析网页是出现异常)

(2)一个最基本的HTML5页面

<!DOCTYPE html>
<html lang="en"> <!-- en英文、zh中文 -->
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>网页标题</title>
</head>
<body>
  <h1>网页正文</h1>
</body>
</html>
  • Doctype 文档声明,必须放在html标签前面,且之前不能放置内容,即使是注释
  • html、head、body、title 根标签、头部标签、主体标签、网页标题,html中的lang属性规定元素内容的语言,当然,这个属性其他标签也有
  • meta元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词,这里charset设定的字符集为UTF-8,viewport主要针对移动端

三、语法规范

  • HTML中不区分大小写,一般使用小写

  • 注释不能嵌套

  • 标签必须结构完整,要么成对出现,要么自结束标签(浏览器尽最大努力正确解析页面,修正不符合语法规范的内容,但是有些情况会修正错)

  • HTML标签可以嵌套,但是不能交叉嵌套

  • 属性必须有值,且值必须加引号(单引号、双引号都可以)

四、概念

1、标记

又称标签,标签注重的是语义化,即什么标签做什么事(比如一个标题那么就用h$包裹)

2、元素

一个完整的标签(包含标签括起来的内容)

3、标签分类

(1)

  • 单标签:又称自结束标签,例如<img src='../img/1.png' />,推荐在后面的>之前加上/,将标签闭合
  • 双标签:具有开始标签和结束标签,内容写在开始标签和结束标签之间

(2)

  • 替换
  • 非替换

(3)

  • 有内容:
  • 空元素:没有闭合的标签,例如后面讲的link、hr、br、img等标签

(4)(这个需要掌握,一般说HTML标签,就按这个分)

  • 行内元素:b、big、i、small、tt、abbr、acronym、cite、code、dfn、em、kbd、strong、samp、var、a、bbdo、br、img、map、object、q、script、span、sub、sup、button、input、label、select、textarea——只占据它对应标签的边框所包含的空间
  • 块级元素:address、article、aside、audio、blockquote、canvas、dd、div、dl、fieldset、figcaption、figure、footer、form、h1-6、header、hgroup、hr、noscript、ol、output、p、pre、section、table、tfoot、ul、video——独占一行
  • 行内块元素:input、td

这个是常用的分类(然而MDN中并没有分行块元素),CSS中还会再提到

可以看下HTML行内元素、块状元素、行内块状元素的区别标签,HTML元素分类特点

其中img标签以前一直说的是行块标签,可是现在到浏览器中查看显示的是display: inline,可身为内联元素又可以设置高宽(这不就是行块元素特点嘛)

4、注释

HTML文档中的注释使用<!-- -->包裹,写在这里面的内容浏览器能够识别,但是不会在页面中渲染显示出来

<!-- 
注释内容,不会在页面中显示 好的注释习惯 简单明了
功能:
作者:
日期:
-->

5、属性

标签的属性(开始标签中 属性名=”属性值”)

例如:

<p align="center" style="font-size: 14px;">文字</p>
  • p就是标签名,这是一个段落标签

  • alignstyle就是这个标签的属性名

  • 属性名等号后的就是属性值,属性值需要用引号引起来,属性名和属性值一般成对出现(如果属性值为BOOL类型,有些可以省略属性值,只写属性名)

  • lang属性

  • title属性

6、路径

绝对路径:相对于根目录

相对路径:相对于当前资源所在目录的位置

../ 上层路径

./ 当前路径

/ 下层

eg:

  • /
    • img
      • picture1.webp
    • css
      • base.css
      • index.css
    • js
      • script.js
    • html
      • blog.html
    • favicon.ico
    • index.html
  • index.html中引用script.js——./js/script.js或者js/script.js
  • index.html中引用favicon.ico——/favicon.ico,一般都是放在根目录,引用的时候使用绝对目录
  • blog.html中引用picture1.webp——../img/picture1.webp

7、进制

满几进一

  • 二进制:满二进一,由0、1组成,例如11111110这八位表示2^0^ *0+2^1^ *1+2^2^+2^3^+2^4^+2^5^+2^6^+2^7^,即十进制254
  • 八进制:满八进一,由0~7组成,例如O12表示十进制10(8^0^2+8^1^1)
  • 十进制:满十进一,由0~9组成
  • 十六进制:由0~9、A~F组成,例如oX1e表示十进制30

8、单位

  • 1,看情况,有的是1=100%,有的1指的是1px
  • % 百分比,相同百分比参照物不同,得到的结果不同
  • px 像素,有物理像素、CSS像素、设备像素
  • vw/vh 1vw等于视口(PC端浏览器可视区域/移动端涉及3个)宽/高度的1%
  • em 1em为一个字体大小
  • rem 根标签的字体大小

五、标签

1、根标签html

一个HTML文档的根(顶级元素),所以它也被称为根元素。所有其他元素必须是此元素的后代。

通过lang属性指定整个页面的语言

<html lang="en">
  ……
</html>

2、头标签head

规定文档相关的配置信息(元数据),包括文档的标题,引用的文档样式和脚本等。

  • title:网页标题
<title>网页标题</title>
  • meta: 设置网页元信息(meta-information),比如网页字符集、针对搜索引擎和更新频度的描述和关键词,是一个单标签:

    • 编码

      乱码问题原因:计算机只认识0、1,计算机中保存的内容需要转化为二进制编码来保存,读取内容时需要转换成正确的内容—-编码、解码 编码和解码采用的字符集不同

      常见字符集:ASCII、ISO-8859-1、GBK、GB2312(中文系统的默认编码)、UTF-8(万国码)

      解决:在中文系统的浏览器中,默认的都是GB2312编码,更改编码Unicode,解码 head中告诉浏览采用的编码字符集

      <meta charset=”utf-8”/>  #编写使用的编码、字符集一致
  • 重定向

    <meta http-equiv=”refresh” conternt=”秒数;url=网址” />
  • 网页关键字

    <meta name="keywords" content="关键字内容1,2,3" />
  • 网页描述

    <meta name="description" content="描述" />

    搜索引擎在检索页面时,会同时检索页面中的关键字和描述,但是不会影响页面在搜索引擎中的排名

  • 与移动开发有关

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  • link:定义文档与外部资源的关系

    属性 
    href -- 指定需要加载的资源的地址URI 
    media -- 媒体类型
    rel -- 指定链接类型,设定是指对象和链接目标的关系,可选值, link还可以用Shortcut Icon等
    rev -- 指定链接类型 
    type -- 指定所连接文档的MIME类型,css的MIME是type/css,一般使用type="text/css" 

    其中rel和href是必须要设置的

    • 引入CSS样式

      <link rel="stylesheet" href="style.css">
  • 引入网页icon图标

    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
  • 很久以前,网速非常慢,网站主要就是分享文章的,就可以标识文档开始(告知搜索引擎)、文档上一页(浏览器可以回退)、下一页(浏览器可以提前加载此页)

    <link rel="start" type="text/html" href="http://www.dreamdu.com/xhtml/" />
    <link rel="prev" type="text/html" href="http://www.dreamdu.com/xhtml/alternate/" />
    <link rel="next" type="text/html" href="http://www.dreamdu.com/xhtml/attribute_rel/" />

    如果还想了解lin标签的话,自己可以到html中link的用法去看下

  • style:包含文档的样式信息或者文档的部分内容。默认情况下,该标签的样式信息通常是CSS的格式。

3、文档主体标签body

body 元素定义文档的主体。

body 元素包含文档的所有内容(比如文本、超链接、图像、表格和列表等等)

document.body属性提供了可以轻松访问文档的 body 元素的脚本。

4、脚本

  • noscript:如果页面上的脚本类型不受支持或者当前在浏览器中关闭了脚本,则在 HTML<noscript>元素中定义脚本未被执行时的替代内容。
  • script:HTML <script> 元素用于嵌入或引用可执行脚本。

六、常用标签

1、标题标签

一共有六级 h1 h2 h3 h4 h5 h6

<h1>这是一级标题</h1>

不关心显示的大小 注重标签语义 h1最重要,表示网页中的主要内容

对于搜索引擎来说,h1的重要性仅次于title

建议只使用h1-h3

2、段落标签

<p>这是一个段落</p>

表示一个段落/自然段,独占一行,两段之间有间隔

在HTML中,字符之间多个空格当成一个空格解析,换行也当成空格

<center>需要居中的元素</center>

3、换行

<br />

4、水平线(分割线)

<hr />

5、容器

div表示一个盒子或容器

span没有特定的语义,通常用于样式的应用

6、文字标记

<b>:加粗

<strong>:强调

bstrong的区别就在于前者是物理元素,仅表示加粗,后者是逻辑元素,表示强调的意思,<b>是在html中的标签,而在xhtml中只能使用<strong>,后者兼容性更好。

<i>:斜体,现在主要用于文本图标

<em>:次级强调

文字标记 语义
<blockquote> 长引用
<q> 短引用
<abbr> 缩写
<address> 作者联系信息
<pre> 预格式化的文本,常用于程序代码
<code> 定义计算机代码文本。
<del> 删除的文本
<sub> 上标
<sup> 下标

7、超链接

a标签可以将包含内容设置为超链接,设置了href属性后点击内容可跳转到相应的页面

<a href="目标地址" target="_blank">链接</a>

常用属性:

  • href:

    • url:设置为链接之后可以跳转到该页面 <a href="https://wallleap.cn">wallleap</a>
    • #id:跳转到这个id名处 <h1 id="title"></h1>,如果跳转的地方是一个超链接也可设置name属性,之后点击这个链接<a href="#title">转到title</a>,就能跳转到这个地方,也可以加到链接后:<a href="https://a.c#title">跳转锚点</a>
    • mailto:打开默认邮件应用发送邮件到该邮箱 <a href="mailto:[email protected]">发送邮件</a>,也可以设置好主题、内容:<a href="mailto:[email protected]?subject=Re:wallleap.cn%20某文章&body=发送自wallleap">发送邮件</a>
  • target:

    • _self:默认
    • _blank:设置为内联框架的名称,可以在内联框架中打开页面
    • _top

提示:如果不使用 href 属性,则不可以使用如下属性:download, hreflang, media, rel, target 以及 type 属性。

提示:被链接页面通常显示在当前浏览器窗口中,除非您规定了另一个目标(target 属性)。

提示:请使用 CSS 来设置链接的样式。

8、图片标签

<img src="路径" alt="图片描述" width="200px" height="200px" />

alt:图片不能显示时,对图片描述;搜索引擎根据alt搜索图片

宽度和高度只设置一个,另一个也会等比例变化,同时指定按照值变化,自适应页面不设置宽高值

图片格式:

  • JEPG(JPG)支持颜色多,可压缩,不支持透明;

  • GIF支持颜色少,支持简单的透明,支持动态图;

  • PNG支持颜色多,支持复杂的透明;

  • webp提供了有损压缩与无损压缩(可逆压缩)的图片文件格式,

  • base64:当图片很小时(一般小于8kb),或者需要先加载的图片,可以转为base64

效果不一致,使用效果好的;效果一致,使用小的。

9、列表标记

1)ul、ol、li

<ol>
  <li>巴西</li>
  <li>阿根廷</li>
  <li>德国</li>
</ol>
  1. 巴西
  2. 阿根廷
  3. 德国
<ul>
  <li>巴西</li>
  <li>阿根廷</li>
  <li>德国</li>
</ul>
  • 巴西
  • 阿根廷
  • 德国

2)dl、dt、dd

<dl>
  <dt>计算机</dt>
  <dd>用来计算的仪器 ... ...</dd>
  <dt>显示器</dt>
  <dd>以视觉方式显示信息的装置 ... ...</dd>
</dl>

捕获.JPG

image-20200810164726876

ul:无序列表,li子元素显示为默认的黑色圆点,也可通过参数自定义列表的符号,常用于新闻列表展示

ol:有序列表,可以在列表前增加序号,如1,2,3,4;适用于排行榜;

dl:自定义列表,可以包括标题及内容,可适合用制作风箱结构;

9、表格标签

table:表格,适合于超过两行以上的数据呈现

一个表格<table>是由每行<tr>组成的,每行是由列<td>组成的。

所以我们要记住,一个表格是由行组成的(行是由列组成的),而不是由行和列组成的。(td是嵌套在tr中的)

<table>下的 <caption>标签、 <thead>标签、<tbody>标签、<tfoot>标签

  • <caption>——表格的标题,一般是table的第一个子元素(零个或一个)
  • <colgroup>——表格列组标签,用来定义表中的一组列表(零个或多个)
  • <thead>——表头,表格的最上面一行(零个或一个)
    • <tr>定义表格中的行
      • <th>定义表格内的表头单元格(列),此元素内部的文本通常会呈现为粗体。
  • <tbody>——表的主体部分(零个或多个)
    • <tr>
      • <th>表头列(如果没有<thead>就需要写上,显示在最上方;有<thead>可以tr*3>th+td*2这种形式,位于最左一列)
    • <tr>
      • <td>
  • <tfoot>——汇总行(零个或一个)

注:

1、如果写了theadtbodytfoot这三个部分,代码顺序书写可以随意,浏览器显示的时候还是按照theadtbodytfoot的顺序依次来显示内容。如果不写thead、tbody、tfoot,那么浏览器解析并显示表格内容的时候是从按照代码的从上到下的顺序来显示。

2、当表格非常大内容非常多的时候,如果用theadtbodytfoot标签的话,那么数据可以边获取边显示。如果不写,则必须等表格的内容全部从服务器获取完成才能显示出来。

3、tbody标签是“必须的”(并不是要求一定写),即使你在代码中并没有写,在浏览器渲染之后trtd还是会在tbody

属性:表格中的属性差不多都是不推荐使用的(可以写样式),但由于开发的时候写属性更方便一点,因此列出来

表格<table>的属性:

  • border:边框,单位px。
  • style="border-collapse:collapse;":单元格的线和表格的边框线合并。
  • width:宽度,单位px。
  • height:高度,单位px。
  • bordercolor:表格的边框颜色。
  • align表格的水平对齐方式,属性值可以填:leftrightcenter
    注意:这里不是设置表格里内容的对齐方式,如果想设置内容的对齐方式,要对单元格标签<td>进行设置)
  • cellpadding:单元格内容到边的距离,单位px。默认情况下,文字是紧挨着左边那条线的,即默认情况下的值为0。
    注意不是单元格内容到四条边的距离,而是到一条边的距离,默认是与左边那条线的距离。如果设置属性dir="rtl"(在下面有讲),那就指的是内容到右边那条线的距离。
  • cellspacing:单元格和单元格之间的距离(外边距),单位px。默认情况下的值为0。
  • bgcolor="#99cc66":表格的背景颜色。
  • background="路径src/...":背景图片。
    背景图片的优先级大于背景颜色。
  • bordercolorlight:表格的上、左边框,以及单元格的右、下边框的颜色。
  • bordercolordark:表格的右、下边框,以及单元格的上、左的边框的颜色。
    这两个属性的目的是为了设置3D的效果。
  • dir:公有属性,单元格内容的排列方式(direction)。 可以 取值:ltr:从左到右(left-to-right,默认),rtl:从右到左(right-to-left) 既然说dir是共有属性,如果把这个属性放在任意标签中,那表明这个标签的位置可能会从右开始排列。

<tr>属性:

  • dir:公有属性,设置这一行单元格内容的排列方式。可以取值:ltr:从左到右(left-to-right,默认),rtl:从右到左(right-to-left)
  • bgcolor:设置这一行的单元格的背景色。
    注:没有background属性,即:无法设置这一行的背景图片,如果非要设置,可以用css实现。
  • height:一行的高度
  • align="center":一行的内容水平居中显示,取值:leftcenterright
  • valign="center":一行的内容垂直居中,取值:topmiddlebottom

单元格(列)td/th属性:

  • align:内容的横向对齐方式,属性值可以填:leftcenterright
  • valign:内容的纵向对齐方式,属性值可以填:topmiddlebottom
  • width:宽度——绝对值或者相对值(%)
  • height:单元格的高度
  • bgcolor:设置这个单元格的背景色
  • background:设置这个单元格的背景图片

单元格合并:如果要将两个单元格合并,那肯定就要删掉一个单元格。

  • colspan:横向合并。例如colspan="2"表示当前单元格在水平方向上要占据两个单元格的位置。
  • rowspan:纵向合并。例如rowspan="2"表示当前单元格在垂直方向上要占据两个单元格的位置。

下面用几个例子讲解表格(这些代码只是演示上面的知识,开发中千万别这样用/手动狗头)

例子1:表格由行tr组成,行由列td组成

<!-- 注:table标签一定要有 -->
<table border="1"> <!-- 为了看的更清楚一点,加上border属性(开发中不推荐)——给表格加上边框 -->
  <tr>
    <td>孙悟空</td><td>未知</td><td>男</td><td>花果山</td>  <!-- 由于代码有点长,这里把td写到一行 -->
  </tr>
  <tr>
    <td>猪八戒</td><td>未知</td><td>男</td><td>高老庄</td>
  </tr>
  <tr>
    <td>沙和尚</td><td>未知</td><td>男</td><td>流沙河</td>
  </tr>
  <tr>
    <td>唐三藏</td><td>23</td><td>男</td><td>东土大唐</td>
  </tr>
  <tr>
    <td>白龙马</td><td>未知</td><td>男</td><td>鹰愁涧</td>
  </tr>
</table>

image-20200810160009152

例子2:没有加theadth来做表头、table部分属性

<table border="1" width="400" height="200" bordercolor="skyblue" align="center" cellpadding="10px" cellspacing="5" dir="ltr">
  <tr>
    <th>姓名</th><th>年龄</th><th>性别</th><th>地点</th>
  </tr>
  <tr>
    <td>孙悟空</td><td>未知</td><td>男</td><td>花果山</td>
  </tr>
  <tr>
    <td>猪八戒</td><td>未知</td><td>男</td><td>高老庄</td>
  </tr>
  <tr>
    <td>沙和尚</td><td>未知</td><td>男</td><td>流沙河</td>
  </tr>
  <tr>
    <td>唐三藏</td><td>23</td><td>男</td><td>东土大唐</td>
  </tr>
  <tr>
    <td>白龙马</td><td>未知</td><td>男</td><td>鹰愁涧</td>
  </tr>
</table>

image-20200810161835381

例子3:有theadtbody中不设置th、table部分属性+tr属性

<table border="1" width="500" bordercolor="skyblue" style="border-collapse:collapse;" dir="rtl">
  <thead>
    <tr height="50" valign="bottom">
      <th>姓名</th><th>年龄</th><th>性别</th><th>地点</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>孙悟空</td><td>未知</td><td>男</td><td>花果山</td>
    </tr>
    <tr>
      <td>猪八戒</td><td>未知</td><td>男</td><td>高老庄</td>
    </tr>
    <tr>
      <td>沙和尚</td><td>未知</td><td>男</td><td>流沙河</td>
    </tr>
    <tr>
      <td>唐三藏</td><td>23</td><td>男</td><td>东土大唐</td>
    </tr>
    <tr>
      <td>白龙马</td><td>未知</td><td>男</td><td>鹰愁涧</td>
    </tr>
  </tbody>
  <tfoot>
    <tr align="center">
      <td>取经四人一马组</td><td>以前全都是仙佛来着</td><td>单身汉</td><td>前几集就凑齐了</td> <!-- 汇总行-->
    </tr>
  </tfoot>
</table>

image-20200810162232527

例子4:加上其他几个标签,有theadtbody中设置th、th/td属性

<table border="1" width="550" bordercolor="skyblue" style="border-collapse:collapse;">
  <caption>取经四人组</caption>
  <colgroup> <!-- 就是把列分组,每组可以加个类名这样的 -->
    <col style="background-color: bisque;">
    <col span="3" style="background-color: rosybrown;">
    <col span="2" style="background-color: silver;">
  </colgroup>
  <thead>
    <tr>
      <th width="100" height="50">物种</th><th>姓名</th><th>年龄</th><th>性别</th><th>地点</th>
    </tr>
  </thead>
  <tfoot>
    <tr align="center">
      <th>说明</th><td>取经四人一马组</td><td>以前全都是仙佛来着</td><td>单身汉</td><td>前几集就凑齐了</td> <!-- 汇总行-->
    </tr>
  </tfoot> <!-- 只要写了这三个,顺序无所谓,仍按照thead->tbody->tfoot -->
  <tbody>
    <tr>
      <th>猴子</th><td>孙悟空</td><td>未知</td><td>男</td><td>花果山</td>
    </tr>
    <tr>
      <th>猪头</th><td>猪八戒</td><td>未知</td><td>男</td><td>高老庄</td>
    </tr>
    <tr>
      <th>河妖?</th><td>沙和尚</td><td>未知</td><td>男</td><td>流沙河</td>
    </tr>
    <tr>
      <th>金蝉</th><td>唐三藏</td><td>23</td><td>男</td><td>东土大唐</td>
    </tr>
    <tr>
      <th>白龙</th><td>白龙马</td><td>未知</td><td>男</td><td>鹰愁涧</td>
    </tr>
  </tbody>
</table>

image-20200810163541447

例子5:单元格合并

<table bgcolor="#ccc" border="1" width="550" bordercolor="red" style="border-collapse:collapse;">
  <tbody>
    <tr bgcolor="yellow">
      <th>姓名</th><th>年龄</th><th>性别</th><th>地点</th><th>前世工作地点</th>
    </tr>
    <tr>
      <td>孙悟空</td><td rowspan="3">未知</td><td rowspan="5">男</td><td>花果山</td><td bgcolor="yellowgreen" rowspan="3">天庭</td>
    </tr>
    <tr>
      <td>猪八戒</td><td>高老庄</td>
    </tr>
    <tr>
      <td>沙和尚</td><td>流沙河</td>
    </tr>
    <tr>
      <td>唐三藏</td><td>23</td><td>东土大唐</td><td>雷音寺</td>
    </tr>
    <tr>
      <td>白龙马</td><td>未知</td><td>鹰愁涧</td><td>西海</td>
    </tr>
    <tr>
      <td colspan="5" align="center">西天取经</td>
    </tr>
  </tbody>
</table>

image-20200810164636116

表格布局:还是在很久以前,表格用来做页面布局,还没学到CSS,提下这个概念,知道有这个东东就行。

10、表单

1)表单标记

<form action="表单提交的处理程序地址" method="表单提交方式(post/get)" name="表单名称"></form>

form元素将所有的表单包含起来,也相应于表单的作用域。

getpost提交方式的区别:get请求把表单的数据显式地放在URL中,并且对长度和数据值编码有所限制;post请求把表单数据放在HTTP请求体中,没有长度限制。

2)文本框

<input type="text" name="控件名称" value="文本框输入值" placeholder="提示信息" disabled readonly required auotfocus />

3)密码框

<input type="password" name="控件名称" placeholder="提示信息"/>

4)单选按钮:同一组单选按钮使用同一命名

<input type="radio" name="控件名称" value="控件值" checked />

5)复选按钮

<input type="checkbox" name="控件名称" value="控件值" checked />

6)下拉列表

<select name="控件名称" multiple="multiple" size="数值">    <option value="控件值" selected>选项</option></select>

7)多行文本框

<textarea name="控件名称" cols="列数" rows="行数"></textarea>

8)隐藏控件

<input type="hidden" name="控件名称" value="控件值" />

9)普通按钮

<input type="button" value="按钮文字" /><button type="button">按钮文字</button>

10)发送按钮

<input type="submit" value="按钮文字" /><button type="submit">按钮文字</button>

11)重置按钮

<input type="reset" value="按钮文字"><button type="reset">按钮文字</button>

表单实例:

<form action="" method="post">
  <fieldset>
    <legend>表单演示</legend>
    <p> <label for="username">姓名:</label><input type="text" name="username" id="username" placeholder="请输入姓名"
        required="required" /> </p>
    <p> <label for="pwd">密码:</label><input type="password" name="pwd" id="pwd" placeholder="请输入密码" /> </p>
    <p> 性别: <label><input type="radio" name="sex" value="1" checked="checked" />男</label> <label><input type="radio"
          name="sex" value="0" />女</label> </p>
    <p> 爱好: <label><input type="checkbox" name="basketball" value="basketball" />篮球</label> <label><input
          type="checkbox" name="football" value="football" />足球</label> </p>
    <p> <label for="bloodtype">血型:</label> <select name="bloodtype" id="bloodtype">
        <option value="A">A型</option>
        <option value="B">B型</option>
        <option value="AB">AB型</option>
        <option value="O">O型</option>
      </select> </p>
    <p> <label for="intro">介绍</label> <textarea name="intro" cols="30" rows="3" id="intro"></textarea> </p> <input
      type="submit" value="提交按钮" /> <input type="reset" value="重置按钮" /> <input type="button" value="自定义按钮" />
  </fieldset>
</form>

11、转义字符(字符实体)

&实体名字;

< &lt;

> &gt;

空格 &nbsp;

版权&copy;

浏览器解析到实体时,会自动将其转换为相应字符。

特殊字符 描述 字符的代码
空格符 &nbsp;
< 小于号 &lt;
> 大于号 &gt;
& 和号 &amp;
人民币 &yen;
© 版权 &copy;
® 注册商标 &reg;
° 摄氏度 &deg;
± 正负号 &plusmn;
× 乘号 &times;
÷ 除号 &divide;
² 平方2(上标2) &sup2
³ 立方3(上标3) &sup3

12、框架网页

框架集和内联框架的作用类似,都是用于在一个页面中引入其他的外部的页面,框架集可以同时引入多个页面,而内联框架只能引入一个。在H5标准中,推荐使用框架集,而不使用内联框架。

将浏览器窗口分解为多个小窗口,每个小窗口均可以显示各自的网页

<frameset rows="" cols="">:框架网页集,rows为横向分隔,cols为纵向分隔,值可以是具体数值也可以是百分比,这两属性frameset必须选择一个,并且需要在属性中指定每一部分所占的大小。注意frameset标记是和body标记同级的标记,不能将frameset标记包含在body标记中,否则将无法看到框架网页的效果。

<frame name="" scr="" />:指定每一个小窗口的名称和链接的网页,窗口的名称可以用于超级链接的target属性。

frameset中也可以再嵌套frameset

水平分隔两个窗口,每个窗口各占50%

可引入一个外部的页面

<iframe src=”路径” width=”” heigh=”” name=”名称”></iframe>

framesetiframe一样,它里面的内容都不会被搜索引擎所检索,所以如果搜索引擎检索到的页面是一个框架页的话,它是不能去判断里边的内容的.

内嵌框架<iframe>:可以在一个浏览器窗口种同时显式多个页面文档

在现实开发中,不推荐使用,使用框架集意味着页面中不能有自己的内容,只能引入其他的页面,而我们每单独加载一个页面,浏览器都需要重新发送一次请求,引入几个页面就需要发送几次请求,用户的体验比较差,如果非得用建议使用frameset而不是iframe

<frameset rows=”20%, *,30%”>
  <frame src="header.html" />
  <frameset cols="20%,40%,40%">
    <frame src="body1.html">
    <frame src="body2.html">
    <frame src="body3.html">
  </frameset>
  <frame src="footer.html">
</frameset>

七、HTML5新增标签

1、新增语义化标签

以前布局,我们基本用div来做,但是div对于搜索引擎来说,是没有语义的。

image-20200810172730433

标签名 作用
header 表示页眉
nav 表示导航
article 文章
section 章节
main 文档主要内容
aside 侧边栏
hgroup 头/标题组
footer 文档或页的页脚

image-20200810174704025

<header>header</header>
<nav>nav</nav>
<main>
  main
  <article>
    article
    <section>section</section>
  </article>
  <aside>aside</aside>
</main>
<footer>footer</footer>

兼容性解决:

  • IE9:行级元素在设置宽度的时候是失效的(需要将这些标签转换为块级元素)
header, nav, main, article, section, aside, footer{
  display: block;
}
  • IE8:完全不支持语义标签(不支持HTML5)

    • 方法一:手动创建标签
    <script>
      /* 手动创建标签:默认的标签的类型都是行级元素 */
      document.createElement("header")
      document.createElement("nav")
      document.createElement("main")
      document.createElement("article")
      document.createElement("aside")
      document.createElement("footer")
    </script>
  • 方法二:引入第三方插件html5shiv.min.js

    <script src="https://cdn.bootcdn.net/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>

2、列表

HTML5中,对ol、dl进行了改良

  • ol:添加了startreversed属性
    • start:可以指定列表编号从多少开始
    • reversed:列表反向排序
<ol start="3">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ol>
<ol start=9 reversed>
  <li>列表值1</li>
  <li>列表值2</li>
  <li>列表值3</li>
  <li>列表值4</li>
  <li>列表值5</li>
</ol>
  • dl:重新定义,dl标签包含多个带名字列表项;每一项包含至少一条带名字的dt元素,用来表示术语;dt后紧跟一个或多个dd元素,用来表示定义。在一个元素内不允许有相同名字的dt元素,不允许有重复的术语。

    • 可以用于解释术语
    <dl>
      <dt><dfn>RSS</dfn></dt>
      <dd>RSS也叫聚合RSS,是在线共享内容的一种简易方式(也叫聚合内容)……</dd>
      <dt><dfn>博客</dfn></dt>
      <dd>博客,又译为网络日志,部落格或部落阁等,是一种通常由个人管理……</dd>
    </dl>
  • 可以表示辅助信息

    <dl>
    <dt>作者</dt>
    <dd>xxx</dd>
    <dt>出版社</dt>
    <dd>xxx出版社</dd>
    <dt>类别</dt>
    <dd>文学</dd>
    </dl>

3、表单

(1) 表单新增的type属性

  • email提供了默认的电子邮箱的完整验证,要求必须包含@符号,同时必须包含服务器名称,如果不能满足验证,则会阻止当前的数据提交(submit)
邮箱:<input type="email">
  • tel并不是用来实现验证,它的本质目的是为了能够在移动端打开数字键盘,意味着限制了用户只能输入数字。
电话:<input type="tel">
  • url 验证只能输入合法的网址,必须包含http://
网址:<input type="url">
  • number 只能输入数字(包含小数点),不能输入其他的字符
    • max:最大值,min:最小值,value:默认值
数量:<input type="number">
<input type="number" value="60" min="0" max="100">
  • search 可以提供更人性化的输入体验
搜索框:<input type="search">
  • range 范围
范围:<input type="range" min="0" max="100" value="50">
  • color颜色
颜色:<input type="color">
  • 日期时间相关
时间:<input type="time"> <!-- 时分秒 -->
日期:<input type="date"> <!-- 年月日 -->
日期时间:<input type="datetime"> <!-- 目前大多数浏览器都不支持,只有Safari -->
日期时间:<input type="datetime-local"> <!-- 日期和时间 -->
月份:<input type="month">
星期:<input type="week">

(2) 表单新增的其他属性

  • placeholder 提示文本,提示占位

  • autofocus 自动获取焦点

  • autocomplete:自动完成 on off

    必须成功提交过:提交过才会记录

    当前添加autocomplete的元素必须有name属性

  • required 必须输入,如果没有输入则会阻止当前数据提交

  • pattern:正则表达式验证

  • multiple 可以选择多个文件,在email中,设置multiple属性之后可以输入多个邮箱地址,以逗号分隔

  • form 指定表单id,会随着该表单一起提交

<form action="" id="myFrm">
  用户名:<input type="text" name="username" placeholder="请输入用户名" autofocus autocomplete="on">
  手机号:<input type="tel" required pattern="^(\+86)?1\d{10)$">
  文件:<input type="file" name="photo" multiple>
  邮箱:<input type="email" multiple>
  <input type="submit" value="提交">
</form>
地址:<input type="text" name="address" form="myFrm">

(3) 新增表单元素

  • datalist创建选项列表
  • option创建选择,属性:value具体的值,label提示信息,辅助值

注意:

  • 需要在input中加入list属性,值为datalist的id名

  • datalist在不同浏览器下表现不同,很少使用

  • option可以是单标签,也可以是双标签

  • 当input的类型为url时,option的value必须带http前缀

选择:<input type="text" list="selectors">
<datalist id="selectors">
  <option value="HTML" label="结构" />
  <option value="CSS" label="表现"></option>
  <option value="JavaScript" label="行为"></option>
</datalist>
网址:<input type="url" list="urls">
<datalist id="urls">
  <option value="https://www.baidu.com" label="百度" />
  <option value="http://www.sohu.com" label="搜狐"></option>
  <option value="http://www.163.com" label="网易"></option>
</datalist>

image-20200810190152657

<form action="">
  用户名:<input type="text" name="username" ><br>
  密码:<input type="password" name="pwd" ><br>
  加密:<keygen></keygen><br>
  <input type="submit" value="提交">
</form>

<!-- 显示输出信息:只能显示不能修改
1、语义性更强
2、值需要你去设置,不能自动计算
-->
<output>总金额:¥100.00</output>

(4) 新增的表单事件

  • oninput:监听当前指定元素内容的改变,只要内容改变(添加内容/删除内容)就会触发这个事件(鼠标粘贴的也能触发)

对比:onkeyup:键盘弹起的时候触发,每一个键的弹起都会触发一次

  • oninvalid:当验证不通过时触发
<form action="">
  用户名:<input type="text" name="username" id="username">
  电话:<input type="tel" name="phone" pattern="^1\d{10}$" id="phone">
  <input type="submit" value="提交">
</form>
<script>
  document.getElementById('username').oninput = function(){
    console.log(this.value);
  }
  document.getElementById('phone').oninvalid = function(){
    // 设置默认的提示信息
    this.setCustomValidity('请输入合法的11位手机号')
  }
</script>

4、进度条

  • progress
    • max:最大值
    • value:当前进度值
  • meter度量器——衡量当前进度值
    • high:规定的较高的值
    • low:规定的较低的值
    • max:最大值
    • min:最小值
    • value:当前度量值
<progress max="100" value="50"></progress>
<meter max="100" min="0" high="80" low="40" value="10"></meter>
<meter max="100" min="0" high="80" low="40" value="50"></meter>
<meter max="100" min="0" high="80" low="40" value="90"></meter>

5、多媒体标签——音视频

embed:直接插入视频文件,本质调用本机上已经安装的软件,有兼容性

flash插件:安装flash,学习flash增加使用成本,苹果设备不支持flash

新增:

  • audio:音频
    • src: 播放的音频文件的路径
    • controls: 音频播放器的控制面板
    • autoplay: 自动播放
    • loop: 循环
<audio src="../mp3/a.mp3" controls autoplay loop></audio>
  • video:视频

    • src: 播放的视频文件的路径

    • controls: 视频播放器的控制面板

    • autoplay: 自动播放

    • loop: 循环

    • width: 宽度

    • height: 高度 设置宽高时,一般只会设置其一,使其等比缩放,如果同时设置宽度和高度,视频并不会真的调整到该大小,除非设置的刚好是等比例的

    • poster: 当视频还没有完全下载,或者用户还没有点击播放前的默认显示的封面,默认显示的是当前视频文件的第一幅画面

<video src="../medeas/1.mp4" width="800" controls poster="../imgs/1.png" autoplay></video>

因为不同浏览器支持的音视频文件的格式不一样,因此需要考虑到浏览器是否支持,可以准备多个格式的视频文件,让浏览器自动选择:source

<video controls>
  <source src="../medias/1.flv" type="video/flv">
  <source src="../medias/1.mp4" type="video/mp4">
    您的浏览器不支持视频播放,请更换浏览器!
</video>

image-20200810191653266

image-20200810191740565

image-20200810191752979

文件API、拖放API

八、H5中的DOM操作

1、获取DOM元素

query:查询 selector:选择器

  • document.querySelector()只能获取单个元素,如果获取的元素不止一个,那么只会返回满足条件的第一个元素

  • document.querySelectorAll()获取满足条件的所有元素——数组

2、操作类样式

classList当前元素的所有样式列表——数组

  • .add为元素添加指定类名,一次只能添加一个

  • .remove为元素溢出指定名称的类样式,一次只能移除一个

  • .toggle切换元素的样式,如果元素之前没有指定名称的样式则添加,如果有则移除

  • .contains判断元素是否包含指定名称的样式,返回true/false

document.querySelector(‘li’).classList.add(‘red’)
document.querySelectorAll(‘li’)[1].classList.remove(‘blue’)
document.querySelectorAll(‘li’)[2].classList.toggle(‘green’)
console.log(document.querySelectorAll(‘li’)[2].classList.contains(‘green’))
console.log(document.querySelectorAll(‘li’)[2].classList.item(0))

以前:

document.querySelector(‘li’).className=‘red underline’

3、自定义属性

定义:

  • data-开头

  • data-后必须至少有一个字符,多个单词使用-连接

  • 建议小写、无特殊符号、非纯数字

// 定义 data-单词-单词
<p data-test-a='AreYouOK'>test</p>
<script>
window.onload = function(){
  var p = document.querySelector('p')
  // 获取自定义属性值
  var value = p.dataset['testA'] // 将data-后面的单词使用camel命名法连接
  console.log(value);
}
</script>

九、常用API

1、网络状态改变事件

  • ononline: 网络连通的时候触发这个事件

  • onoffline: 网络断开时触发

// window.ononline = function () {}
window.addEventListener("online", function(){
  // 操作
  alert('网络连通了~')
})
// window.onoffline = function(){}
window.addEventListener("offline", function(){
  // 操作
  alert('网络断开了~')
})

2、全屏接口的使用

  • requireFullscreen(): 开启全屏显示

不同浏览器需要添加不同的前缀:Chrome: webkit fireFox: moz ie: ms opera: o

  • cancelFullScreen(): 退出全屏显示 只能使用document来实现

  • fullscreenElement: 是否是全屏状态 只能使用document来实现

<div>
  <img src="" alt="">
  <input type="button" id="full" value="全屏">
  <input type="button" id="cancelFull" value="退出全屏">
  <input type="button" id="isFull" value="是否全屏">
</div>
<script>
window.onload = function(){
  var div = document.querySelector('div')
  document.querySelector('#full').onclick = function(){
    if(div.requestFullscreen){
      div.requestFullscreen()
    }else if(div.webkitRequestFullscreen){
      div.webkitRequestFullscreen()
    }else if(div.mozRequestFullscreen){
      div.mozRequestFullscreen()
    }else if(div.msRequestFullscreen){
      div.msRequestFullscreen()
    }else if(div.oRequestFullscreen){
      div.oRequestFullscreen()
    }
  }
  document.querySelector('#cancelFull').onclick = function(){
    if(document.cancelFullScreen){
      document.cancelFullScreen()
    }else if(document.webkitCancelFullScreen){
      document.webkitCancelFullScreen()
    }else if(document.mozCancelFullScreen){
      document.mozCancelFullScreen()
    }else if(document.msCancelFullScreen){
      document.msCancelFullScreen()
    }else if(document.oCancelFullScreen){
      document.oCancelFullScreen()
    }
  }
  document.querySelector('#isFull').onclick = function(){
    if(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullscreenElement || document.msFullscreenElement){
      alert('true')
    }else{
      alert('false')
    }
  }
}
</script>

3、文件读取API

FileReader:读取文件内容

  • readAsText(): 读取文本文件(可以使用Txt打开的文件),返回文本字符串,默认编码是UTF-8

  • readAsBinaryString(): 读取任意类型的文件。返回二进制字符串,这个方法不是用来读取文件展示给用户的,而是存储文件。例如:读取文件的内容,获取二进制数据,传递给后台,后台接收了数据之后,再将数据存储

  • readAsDataURL(): 没有返回值,参数是文件

读取文件获取一段以data开头的字符串,这段字符串的本质就是DataURL。DataURL是一种将文件(这个文件一般就是指图像或者能够嵌入到文档的文件格式)嵌入到文档的方案,将资源转换为base64编码的字符串形式,并且将这些内容直接存储在url中à优化网站的加载速度和执行效率

<!-- 展示图片,src:指定路径(资源定位--url),src请求得是外部文件,一般是服务器资源,意味着它需要向服务器发送请求,它占用服务器资源 -->
<img src="../imgs/1.jpg" alt="">
  • abort(): 中断读取

FileReader提供一个完整的事件模型,用来捕获读取文件时的状态

  • onabort: 读取文件中断时触发

  • onerror: 读取错误时触发

  • onload: 文件读取成功完成时触发

  • onloadend: 读取完成时触发,无论成功还是失败

  • onloadstart: 开始读取时触发

  • onprogress: 读取文件过程中持续触发

<!-- 实时预览图片 
及时:onchange()
预览:readAsDataURL()
-->
<form action="">
  文件;<input type="file" name="myFile" id="myFile" onchange="getFileContent();"><br>
  <input type="submit">
</form>
<img src="" alt="">
<script>
  function getFileContent(){
    var reader = new FileReader()
    var file = document.getElementById('myFile').files[0]
    reader.readAsDataURL(file)
    reader.onload = function(){
      // console.log(reader.result);
      document.querySelector('img').src = reader.result
    }
  }
</script>

4、拖拽接口

为元素添加属性:draggable=”true”,图片和超链接默认就能拖拽

拖拽事件:

  • (被)拖拽元素

    • ondrag: 拖动整个过程都会调用
    • ondragstart: 当拖动开始时调用
    • ondragleave: 当鼠标离开拖拽元素时调用
    • ondragend: 当拖拽结束时调用
  • 目标元素

    • ondragenter: 当拖拽元素进入时调用
    • ondragover: 当停留在目标元素上时调用
    • ondrop: 当在目标元素上松开鼠标时调用 浏览器默认会阻止这个事件,我们必须在ondragover中阻止浏览器的默认行为
    • ondragleave: 当鼠标离开目标元素时调用
<style>
    .box1,.box2{
      width: 200px;
      height: 200px;
      background-color: #ddd;
      border: 1px solid red;
      float: left;
      margin-left: 30px;
    }
    #pe{
      width: 100%;
      background-color: orange;
    }
  </style>
<div class="box1">
  <p id="pe" draggable="true">拖动我啊</p>
</div>
<div class="box2"></div>
<script>
var p = document.querySelector('#pe')
var box2 = document.querySelector('.box2')
var box1 = document.querySelector('.box1')
p.ondragstart = function(){
  console.log('p ondragstart')

}
p.ondragend = function(){
  console.log('p ondragend')
}
p.ondragleave = function(){
  // console.log('p ondragleave')
}
p.ondrag = function(){
  // console.log('p ondrag')
}

box2.ondragenter = function(){
  console.log('box2 ondragenter')
}
box2.ondragover = function(e){
  // console.log('box2 ondragover')
  // 阻止浏览器默认行为,使ondrop事件能被触发
  e.preventDefault()
}
box2.ondrop = function(){
  // console.log('box2 ondrop')
  box2.appendChild(p)
}
box2.ondragleave = function(){
  console.log('box2 ondragleave')
}

box1.ondragover = function(e){
  // 阻止浏览器默认行为,使ondrop事件能被触发
  e.preventDefault()
}
box1.ondrop = function(){
  box1.appendChild(p)
}
</script>

改进:利用事件捕获
<div class="box1">
  <p id="pe" draggable="true">拖动我啊</p>
  <p id="p2" draggable="true">拖动我啊</p>
</div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4" draggable="true"></div>
<script>
// var obj = null // 被拖拽元素,全局变量不安全
document.ondragstart = function(e){
  /* 通过事件捕获来获取当前被拖拽的子元素 */
  // console.log(e.target);
  e.target.style.opacity = 0.5
  e.target.parentNode.style.borderWidth = '5px'
  // obj = e.target
  /*
    通过dataTransfer来实现数据的存储与获取
  * setData(format, data)
  ** 数据类型:text/html  text/uri-list
  ** 数据:一般来说是字符串值
  */
  e.dataTransfer.setData('text/html', e.target.id)
}
document.ondragend = function(e){
  e.target.style.opacity = 1
  e.target.parentNode.style.borderWidth = '1px'
}
document.ondragleave = function(e){
}
document.ondrag = function(e){
}

document.ondragenter = function(e){
  console.log(e.target);

}
document.ondragover = function(e){
  // 阻止浏览器默认行为,使ondrop事件能被触发
  e.preventDefault()
}
document.ondrop = function(e){
  // e.target.appendChild(obj)
  /*
   通过e.dataTransfer.setData存储的数据,只能在drop事件中获取

  */
  var id = e.dataTransfer.getData('text/html')
  console.log(id);
  e.target.appendChild(document.getElementById(id))
}
document.ondragleave = function(e){
}
</script>

5、地理定位API

image-20200810193305180

示例:

<div class="map"></div>
<script>
var map = document.querySelector('.map')
function getLocation(){
  if(navigator.geolocation){
    navigator.geolocation.getCurrentPosition(showPosition, showError, {})
  }else{
    map.innerHTML = "Geolocation is not supported by this browser"
  }
}
function showPosition(position){
  map.innerHTML = 'Latitude:' + position.coords.latitude + "<br />Logitude:" + position.coords.longitude
}
function showError(error){
  ……
}
getLocation()
</script>

百度地图API:http://lbsyun.baidu.com/jsdemo.htm#a1_2

6、通信API

Web Sockets是H5提供的在Web应用程序中客户端与服务器端之间进行的非HTTP的通信机制。

  • 建立与服务器之间的通信连接
var webSocket = new WebSocket("ws://localhost:9000/socket")

调用的是WebSocket对应,参数url必须以wswss开头

  • 发送数据
webSocket.send("data")
  • 监听
// 通过获取onmessage事件句柄来接收服务器传过来的数据
webSocket.onmessage = function(event){
  var data = event.data
  ...
}
// 通过获取onopen事件句柄来监听socket的打开事件
webSocket.onopen = function(event){
  // 开始通信时的处理
}
// 通过获取onclose事件句柄来监听socket的关闭事件
webSocket.onclose = function(event){
  // 通信结束时的处理
}
  • 关闭socket
webSocket.close()

可以通过读取readyState的属性值来获取WebSocket对象的状态,主要有:

  • CONNECTING(0),表示正在连接
  • OPEN(1),表示已建立连接
  • CLOSING(2),表示正在关闭连接
  • CLOSED(2),表示已关闭连接

十、web存储

1、sessionStorage的使用

可以存储数据到本地,存储的容量5MB左右。这个数据本质是存储在当前页面的内存中;它的生命周期为关闭当前页面,关闭页面,数据会自动清除;

  • setItem(key, value): 存储数据,以键值对方式存储

  • getItem(key): 获取数据,通过指定名称的key获取对应的value值,如果找不到对应名称的key,那么就会获取null

  • removeItem(key): 删除数据,通过指定名称key删除对应的值,如果key值错误,不会报错,也不会删除数据

  • clear(): 清空所有存储的内容

<input type="text" id="username"><br>
<input type="button" value="设置数据" id="setData">
<input type="button" value="获取数据" id="getData">
<input type="button" value="删除数据" id="removeData">
<script type="text/javascript">
  document.querySelector('#setData').onclick = function(){
    var name = document.querySelector('#username').value
    // 存储数据
    window.sessionStorage.setItem("username", name)
  }
  document.querySelector('#getData').onclick = function(){
    // 获取数据
    var name = window.sessionStorage.getItem('username')
    alert(name)
  }
  document.querySelector('#removeData').onclick = function(){
    // 删除数据
    window.sessionStorage.removeItem('username')
  }
</script>

调试器查看

image-20200810193553627

2、localStorage的使用

存储的内容大概20MB;不同浏览器不能共享数据,但是在同一浏览器的不同窗口中可以共享数据;永久生效,它的数据是存储在硬盘上,并不会随着页面或者浏览器的关闭而清除

  • setItem(key, value): 存储数据,以键值对方式存储

  • getItem(key): 获取数据,通过指定名称的key获取对应的value值,如果找不到对应名称的key,那么就会获取null

  • removeItem(key): 删除数据,通过指定名称key删除对应的值,如果key值错误,不会报错,也不会删除数据

  • clear(): 清空所有存储的内容

<input type="text" id="username"><br>
<input type="button" value="设置数据" id="setData">
<input type="button" value="获取数据" id="getData">
<input type="button" value="删除数据" id="removeData">
<script type="text/javascript">
  document.querySelector('#setData').onclick = function(){
    var name = document.querySelector('#username').value
    // 存储数据
    window.localStorage.setItem("username", name)
  }
  document.querySelector('#getData').onclick = function(){
    // 获取数据
    var name = window.localStorage.getItem('username')
    alert(name)
  }
  document.querySelector('#removeData').onclick = function(){
    // 删除数据
    window.localStorage.removeItem('username')
  }
</script>

十一、应用程序缓存

概念:使用HTML5,通过创建cache manifest文件,可以轻松地创建web应用的离线版本

优势:

  • 可配置需要缓存的资源

  • 网络无连接应用仍可用

  • 本地读取缓存资源,提升访问速度,增强用户体验

  • 减少请求,缓解服务器负担

Cache Manifest基础:

  • 如需启用应用程序缓存,要在文档的html标签中包含manifest属性:
<!DOCTYPE html>
<html  manifest="demo.appcache">
  ……
</html>

manifest=”应用程序缓存清单文件的路径”

  • 每个指定了manifest的页面在用户对其访问时都会被缓存,如果未指定manifest属性,则页面不会被缓存(除非在manifest文件中直接指定了该页面)

  • Manifest文件的建议个文件扩展名为appcache,这个文件的本质是一个文本文件

  • 注意:manifest文件需要配置正确的MIME-type,即”text/cache-manifest”,必须在web服务器上进行配置

demo.appcache

CACHE MANIFEST
# 注释 上面必须是当前文件的第一句

# 需要缓存的文件清单列表
CACHE:
./imgs/1.jpg
./imgs/2.jpg

# 配置每一次都需要重新从服务器获取的文件清单列表
NETWORK:
./imgs/3.jpg

# 配置如果文件无法获取则使用指定的文件进行替代
FALLBACK:
./imgs/4.jpg ./imgs/loader.gif

# /代表所有文件

最后,列出一下已弃用的标签

image-20200810171332092

H5中还有两个知识点需要单独学习的:

Web Worker 使用教程

学习HTML5 Canvas这一篇文章就够了

扩展文章

HTML 元素参考

html中link的用法

html5新标签总结

HTML5 新元素

怎样拥有两个独立的Chrome

怎样拥有两个独立的Chrome

1、问题起源

  • 由于自己日常使用的Chrome安装了太多插件,调试的时候受插件的影响,很难进行识别,因此需要一个单独用于开发调试的Chrome
  • Chrome默认安装到C盘,移动到其他盘之后,再进行安装打开的仍是同一个浏览器

2、解决方法

主要就是利用Chrome的多用户会生成一个独立的、相互隔离的浏览器

方法一、自己指定存放数据路径(推荐)

1、进入Chrome所在目录(可以通过默认的快捷方式右击-属性-打开文件所在位置),接着右击Chrome,选择创建快捷方式

创建快捷方式

2、对创建的图标进行命名,右键属性

属性

3、目标字段:添加--user-data-dir参数,设置一个目标存放数据,笔者设置的是D:\ChromeData\WebChrome

修改目标

4、确定(可以换一个图标再点确定!)

方法二、直接生成新用户快捷方式

打开谷歌浏览器,点击如下的图标

点击图标

点击添加

点击添加

输入任意用户名,默认勾选添加快捷方式,点击添加

image-20200716092240575

之后就可以使用独立的Chrome了

image-20200716092343187

而且,你可以在开发工具中指定Chrome路径为你创建的快捷方式的路径,之后默认就会以该浏览器打开网页了

IDE指定Chromepath

参考文档:

web入门基础知识

web入门基础知识

1、 软件开发架构:

  • C/S架构:客户端/服务器——用户需要下载安装客户端软件使用,服务器负责处理软件的业务逻辑、同时更新、不能跨平台、通信采用自有协议(相对安全),客户端功能强大,可以减轻服务器端压力,但是客户端维护开发成本高(胖客户端)

  • ✪ B/S架构:浏览器/服务器端——本质上也是C/S,使用浏览器作为软件的客户端,通过浏览器访问网页的形式来使用软件、软件不需要安装(使用浏览器访问指定的网址)、客户端不需要更新、可跨平台使用、通信采用通用的HTTP协议(相对不安全),客户端维护成本低,可跨平台,但服务器负担重,缺点是客户端功能较简单,用户体验不如C/S(瘦客户端)

2、软件开发流程

  1. 网页设计师根据需求设计网页(PS)
  2. 前端工程师将设计做成静态网页(HTML+CSS)
  3. 后台工程师将静态网页修改为动态网页(JSP\PHP\Python\ASP) 提供接口 JS Nodejs

image-20200705094201933

3、技术

  • 前端:HTML(结构)、CSS(表现)、JavaScript(行为)——(W3C标准)

    由浏览器负责解释执行,分别描述页面的结构、控制页面内中元素的样式、响应用户操作

  • 后端:ASP、PHP、JSP、NodeJS等

    由服务器负责执行

  • 静态网页:由前端技术实现(扩展名:.htm或.html)
  • 动态网页:由前端和后台(服务器端)技术共同实现(扩展名:.asp或.php或.jsp)

4、工具

  • 浏览器:Firefox、Chrome、IE

  • 编辑器:Sublime Text、VS code

  • 调试工具:FireBug

  • 图片工具:Photoshop

  • IDE(集成开发工具):DW、WebStorm、Hbuilder

  • IE6浏览器兼容测试:ietester

5、万维网联盟(W3C)

万维网联盟(W3C):World Wid Web Consortium 定义网页相关标准(HTML、CSS、DOM、HTTP、XML等)

WHATWG:网页超文本应用技术工作小组 推动网络HTML5标准

6、文档

W3School离线手册

CSS

Unicode

正则表达式

……

7、其他

(1)HTTP

HTTP(Hyper Text Transfer Protocol,超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式。

HTTP是基于客户/服务器模式,且面向连接的。典型的HTTP事务处理有如下的过程:

(1)客户与服务器建立连接;

(2)客户向服务器提出请求;

(3)服务器接受请求,并根据请求返回相应的文件作为应答;

(4)客户与服务器关闭连接。

状态码

消息 描述
100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。
消息 描述
200 OK 请求成功(其后是对GET和POST请求的应答文档。)
201 Created 请求被创建完成,同时新的资源被创建。
202 Accepted 供处理的请求已被接受,但是处理未完成。
203 Non-authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。
204 No Content 没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content 没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它。
消息 描述
300 Multiple Choices 多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently 所请求的页面已经转移至新的url。
302 Found 所请求的页面已经临时转移至新的url。
303 See Other 所请求的页面可在别的url下被找到。
304 Not Modified 未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Unused 此代码被用于前一版本。目前已不再使用,但是代码依然被保留。
307 Temporary Redirect 被请求的页面已经临时移至新的url。
消息 描述
400 Bad Request 服务器未能理解请求。
401 Unauthorized 被请求的页面需要用户名和密码。
401.1 登录失败。
401.2 服务器配置导致登录失败。
401.3 由于 ACL 对资源的限制而未获得授权。
401.4 筛选器授权失败。
401.5 ISAPI/CGI 应用程序授权失败。
401.7 访问被 Web 服务器上的 URL 授权策略拒绝。这个错误代码为 IIS 6.0 所专用。
402 Payment Required 此代码尚无法使用。
403 Forbidden 对被请求页面的访问被禁止。
403.1 执行访问被禁止。
403.2 读访问被禁止。
403.3 写访问被禁止。
403.4 要求 SSL。
403.5 要求 SSL 128。
403.6 IP 地址被拒绝。
403.7 要求客户端证书。
403.8 站点访问被拒绝。
403.9 用户数过多。
403.10 配置无效。
403.11 密码更改。
403.12 拒绝访问映射表。
403.13 客户端证书被吊销。
403.14 拒绝目录列表。
403.15 超出客户端访问许可。
403.16 客户端证书不受信任或无效。
403.17 客户端证书已过期或尚未生效。
403.18 在当前的应用程序池中不能执行所请求的 URL。这个错误代码为 IIS 6.0 所专用。
403.19 不能为这个应用程序池中的客户端执行 CGI。这个错误代码为 IIS 6.0 所专用。
403.20 Passport 登录失败。这个错误代码为 IIS 6.0 所专用。
404 Not Found 服务器无法找到被请求的页面。
404.0 (无)–没有找到文件或目录。
404.1 无法在所请求的端口上访问 Web 站点。
404.2 Web 服务扩展锁定策略阻止本请求。
404.3 MIME 映射策略阻止本请求。
405 Method Not Allowed 请求中指定的方法不被允许。
406 Not Acceptable 服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required 用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout 请求超出了服务器的等待时间。
409 Conflict 由于冲突,请求无法被完成。
410 Gone 被请求的页面不可用。
411 Length Required “Content-Length” 未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed 请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large 由于所请求的实体的太大,服务器不会接受请求。
414 Request-url Too Long 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
415 Unsupported Media Type 由于媒介类型不被支持,服务器不会接受请求。
416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头。
417 Expectation Failed 执行失败。
423 锁定的错误。
消息 描述
500 Internal Server Error 请求未完成。服务器遇到不可预知的情况。
500.12 应用程序正忙于在 Web 服务器上重新启动。
500.13 Web 服务器太忙。
500.15 不允许直接请求 Global.asa。
500.16 UNC 授权凭据不正确。这个错误代码为 IIS 6.0 所专用。
500.18 URL 授权存储不能打开。这个错误代码为 IIS 6.0 所专用。
500.100 内部 ASP 错误。
501 Not Implemented 请求未完成。服务器不支持所请求的功能。
502 Bad Gateway 请求未完成。服务器从上游服务器收到一个无效的响应。
502.1 CGI 应用程序超时。 ·
502.2 CGI 应用程序出错。
503 Service Unavailable 请求未完成。服务器临时过载或宕机。
504 Gateway Timeout 网关超时。
505 HTTP Version Not Supported 服务器不支持请求中指明的HTTP协议版本。

(2)IP地址与ARP

IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

  • 公有地址(Public address)由Inter NIC(Internet Network Information Center因特网信息中心)负责。这些IP地址分配给注册并向Inter NIC提出申请的组织机构。通过它直接访问因特网。

  • 私有地址(Private address)属于非注册地址,专门为组织机构内部使用。

以下列出留用的内部私有地址

私有地址段
A类 10.0.0.0–10.255.255.255
B类 172.16.0.0–172.31.255.255
C类 192.168.0.0–192.168.255.255

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议

(3)URL与DNS

在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位符),它是WWW的统一资源定位标志,就是指网络地址。

也可认为由4部分组成:协议、主机、端口、路径

URL的一般语法格式为:protocol :// hostname[:port] / path / [;parameters][?query]#fragment

例如:https://loacalhost:3000/test

ftp://192.168.10.100/

域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换。

(4)浏览器

  • 发展历程

1992年,托尼哟翰逊(Tony Johnson)发布了Midas,它允许用户浏览UNIX和VMS网页上的文档。

1993年,NCSA发布了Mosaic浏览器。

1994年,网景公司(Netscape)发布了Navigator浏览器。

1995年,IE浏览器(Internet Explorer)的发布掀起了“浏览器之战”。

1996年,网景公司的Navigator浏览器所占有的浏览器市场份额达86%。微软公司开始将IE浏览器整合到OS(操作系统)中。

1996年9月,Opera浏览器面世。

1998年,网景公司启动其开源产品,开始推出Mozilla。这一年的下半年,网景公司被AOL(美国在线服务公司)收购。

2002年,Firefox(火狐)浏览器面世。

2003年,苹果公司发布Safari浏览器。

2004年,IE浏览器所占有的市场份额达到了历史顶峰-92%。自此以后,其市场份额开始下滑。

2006年6月,Firefox 3的发布创下了吉尼斯世界纪录——一天有800万人下载。

2006年10月,专为Windows XP、Windows Server 2003和Windows Vista而设计的IE 7面世。

2008年,谷歌公司发布Chrome浏览器。

2009年,专为Windows 7、Windows Server 2003与2008、Windows Vista和WindowsXP设计的IE 8面世。同年,Firefox 3.5面世。它是第一款支持多点触控的浏览器。

2010年,谷歌公司发布了Chrome 5.0浏览器。它是第一款稳定支持三个平台的浏览器,还是第一款有书签同步功能(bookmark synchronization)的浏览器。

2011年,微软发布IE 9,IE 9采用了新的JavaScript引擎Chakra,使网页加载速度更快,同时利用显卡GPU加速文字和图形的渲染,使CPU的负担大大减轻。另外,IE 9开始支持HTML5和CSS3。

2012年,Windows 8正式上市后,IE 10问世。

2013年,随着Windows 8.1的正式发布,IE 11问世。IE 11在IE 10的基础上再次扩大对HTML5和CSS3的支持,如支持HTML5拖放、HTML5全屏、CSS边框图、视频码率控制、视频字幕隐藏、媒体加密、WebGL等,使得IE 11全面支持HTML5新特性 [7] 。

  • 浏览器的种类很多,但是主流的内核只有四种,各种不同的浏览器,就是在主流内核的基础上,添加不同的功能构成 。

1、Trident内核

代表产品为Internet Explorer,又称其为IE内核。Trident(又称为MSHTML),是微软开发的一种排版引擎。使用Trident渲染引擎的浏览器有:IE、傲游、世界之窗浏览器、Avant、腾讯TT、Netscape 8、NetCaptor、Sleipnir、GOSURF、GreenBrowser和KKman等 。

2、Gecko内核

代表作品为Mozilla Firefox。Gecko是一套开放源代码的、以C++编写的网页排版引擎,是最流行的排版引擎之一,仅次于Trident。使用它的最著名浏览器有Firefox、Netscape6至9 。

3、WebKit内核

代表作品有Safari、Chrome。WebKit是一个开源项目,包含了来自KDE项目和苹果公司的一些组件,主要用于Mac OS系统,它的特点在于源码结构清晰、渲染速度极快。缺点是对网页代码的兼容性不高,导致一些编写不标准的网页无法正常显示。

4、Presto内核

代表作品Opera。Presto是由Opera Software开发的浏览器排版引擎,供Opera 7.0及以上使用。它取代了1日版Opera 4至6版本使用的Elektra排版引擎,包括加入动态功能,例如网页或其部分可随着DOM及Script语法的事件而重新排版 。

  • 主流的浏览器分为IE、Chrome、Firefox、Safari等几大类,它们具有以下特点:

1、IE浏览器。IE浏览器是微软推出的Windows系统自带的浏览器,它的内核是由微软独立开发的,简称IE内核,该浏览器只支持Windows平台。国内大部分的浏览器,都是在IE内核基础上提供了一些插件,如360浏览器、搜狗浏览器等。

2、Chrome浏览器。Chrome浏览器由Google在开源项目的基础上进行独立开发的一款浏览器,市场占有率第一,而且它提供了很多方便开发者使用的插件,因此该浏览器也是本书开发的主要浏览器。Chrome浏览器不仅支持Windows平台,还支持Linux、Mac系统,同时它也提供了移动端的应用(如Android和iOS平台)。

3、Firefox浏览器。Firefox浏览器是开源组织提供的一款开源的浏览器,它开源了浏览器的源码,同时也提供了很多插件,方便了用户的使用,支持Windows平台、Llnux平台和Mac平台 。

4、Safari浏览器。Safari浏览器主要是Apple公司为Mac系统量身打造的一款浏览器,主要应用在Mac和iOS系统中 。

5、欧朋(Opera)浏览器。

  • 移动端浏览器

1、内置浏览器

手机操作系统厂商开发

2、可下载浏览器

独立于操作系统,QQ浏览器、UC浏览器

3、webview

独立程序,留给原生应用的一个操作系统浏览接口

4、代理浏览器

在服务端完成渲染,返回一个压缩页面

5、混合浏览器

代理浏览器、完备浏览器(在浏览器上渲染页面)结合——省流模式

(O)其他文章

web入门基础知识

浏览器简介

What really happens when you navigate to a URL

HTTP必知必会 Vscode 小白使用介绍

前端vscode常用快捷键总结

Vscode前端开发插件大全

VsCode中使用Emmet神器快速编写HTML代码

Sakura美化

Sakura美化