JS-Pink

一、JavaScript基础

1.基本的输入输出语句

方法 说明 归属
alert(mesg) 浏览器弹出警示框 浏览器
console.log(mesg) 浏览器控制台打印输出信息 浏览器
prompt(info) 浏览器弹出输入框,用户可以输入 浏览器
<script>
		//输入框
		prompt("用户输入");
		//弹出警示框
		alert("警示框")
		//控制台输出打印
		console.log("用户看不到");
script>

2.变量

2.1 变量的基本使用

变量声明用关键字var(variable缩写)

<script>
    //获取用户输入值并保存在变量中
    var name=prompt("输入你的名字")
    //将变量中的值通过警示框显示
    alert(name)
script>

2.2 变量的语法扩展

变量值可以被覆盖,变量名可以一次声明多个,多个变量名之间使用 ","号分隔开来

声明变量的特殊情况

<script>
    //只声明不赋值
    var sex;
    console.log(sex); //报错为 undefined未定义的,程序也不知道里面有什么
    //不声明不赋值
    console.log(test); //报错为 test变量没有被定义
    //不声明只赋值
    tel=110;
	console.log(tel) //没有报错正常显示
script>

2.2 变量名的命名规范

  • 由字母、数字、下划线、美元符号组成
  • 变量名称严格区分大小写
  • 不能以数字开头
  • 不能是关键字
  • 变量名必须有意义,name有特殊含义不建议使用
  • 遵守驼峰命名法

3. 数据类型

3.1 数据类型存在的意义

​ 在计算机中,不同的数据所需占用的存储空间是不同的,为了方便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型

3.2 变量的数据类型

JavaSCript是一种弱类型或者说是动态语言,这个意味着不用提前声明变量的类型,程序运行过程中数据类型会被自动确认

//程序运行到等号的右端才能确定age变量的数据类型
var age =10; //age 是数字类型
age = "18"; //age 是字符串类型,可以动态变化

3.3 数据类型的分类

JS将数据分为两大类:

  1. 简单数据类型(Number、String、Null、Boolean、undefined)
  2. 复杂数据类型(Object)

3.3.1 简单数据类型

3.3.1.1 数字型Number

1>八进制与十六进制

<script>
    var number =010; //八进制
    console.log(number); //打印出十进制    ---8
    number =0x15; //十六进制
    console.log(number); //打印出十进制    ---21
script>

2>数字最大值与最小值(了解即可)

//数字型的最大值与最小值
console.log(Number.MAX_VALUE);
console.log(Number.MIN_VALUE);

Number.MAX_VALUE : 1.7976931348623157e+308

Number.MIN_VALUE : 5e-324

3>数字的三个特殊值(了解即可)

//三个特殊值
console.log(Infinity);//单词代表无穷大
console.log(-Infinity); //无穷小
console.log(NaN); //非数值

4>isNaN()方法判断是否为一个数字

//判断数值是否是一个非数字,是数字返回一个false,非数字返回一个true
console.log(isNaN(10));
console.log(isNaN('210abc'));
3.3.1.2 字符串型

1>建议使用单引号,因为HTML中属性为双引号;引号嵌套使用要 "外双内单、外单内双"规则

转义字符要放在引号里面

转义符 解释说明
\n 换行符,相当于newLine的意思
\\ 斜杠 \
\’ ’ 单引号
\" " 双引号
\t tab 缩进
\b 空格,b是blank的意思

2>字符串的长度 :—>每个字符串都一个length属性可以获得字符串的长度

3>字符串的拼接:—>与Java相同

4>字符串拼接加强

<script>
    var age = prompt("请输入您的年龄:");
    var str ='您今年已经'+age+'岁了..';//字符串加强拼接
    alert(str)
script>
3.3.1.3 布尔型

当布尔类型的数据参与数学运算时,true的值为1,false的值为0

<script>
    console.log(true+1); //2
    console.log(false+1);//1
script>
3.3.1.4 null与undefined

undefined与字符串相加会被拼接成一个字符串,与数字相加为 NaN;

null与字符串相加会被拼接为一个字符串,与数字1相加结果为1;

3.3.2 复杂数据类型

3.4 获取变量类型

<script>
    var age = 18;
    console.log(typeof age); //number类型
    var name ='张三';
    console.log(typeof name);//字符串类型
    var flag=true;
    console.log(typeof flag);//布尔类型
    var define=undefined;
    console.log(typeof define);//undefinde类型
    var value =null;
    console.log(typeof value);//object类型
    </object>
script>

3.5 数据类型转换

​ 使用表单、prompt获取过来的数据默认都是字符串类型,不能直接进行简单的数学运算,需要对数据类型进行转变。通俗来讲就是把一种数据类型的变量转换为另一种数据类型

转换的方法有多重,掌握最重要的一种,其他了解即可

3.5.1 转换为字符串

方式 说明 案例
toString 转换为字符串 ;var num =1;alert(num.toString);
String()强制转换 转换为字符串 var num =1;alert(String(num));
“+”拼接字符串 转换为字符串 var num =1;alert(num+"");

3.5.2 转换为数字型(重点)

方式 说明 案例
parseInt(string) 转换为数字 parseInt(‘18’);
parseFloat(String) 转换为数字 parseFloat(‘15.01’);
Number() 转换为数字 Number(‘12’);
<script>
    //转换为整数型
    var num='18';
    console.log(parseInt(num)); //18
    num='18.01';
    console.log(parseInt(num)); //18
    num='18px';
    console.log(parseInt(num)); //18
    num='max18';
    console.log(parseInt(num)); //NaN
-----------------------------------------
    //转换为浮点型
    var num='18';
    console.log(parseFloat(num)); //18
    num='18.01';
    console.log(parseFloat(num)); //18.01
    num='18px';
    console.log(parseFloat(num)); //18
    num='max18';
    console.log(parseFloat(num)); //NaN
script>

隐式转换

<script>
    var year=prompt("请输入你的出生年份:");
    var age=2020 - year; //隐式转换
    alert("今年你已经"+age+"岁了");
script>

3.5.3 转换为布尔型

方式 说明 案例
Boolean函数 其他类型转换为布尔型 Boolean(‘true’)
  • 代表为空、否定的值会被转化为false,例如’’、0、NaN、null、undefined
  • 其余具体的值转换为true

3.6 编译型语言与解释性语言

编译型语言:将全部代码编译之后产生一个中间文件供计算机阅读

解释性语言:遇到一行解释一行运行一行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUVNufvb-1607239291398)(img/image-20201108202203236.png)]

4 标识符、关键字、保留字

4.1 标识符

开发人员为变量、属性、参数、函数取的名字

4.2 关键字

JavaScript本身已经使用了的字,不能再用它充当变量名、方法名

4.3 保留字

实际为预留的“关键字”,虽然现在不是关键字,未来可能成为关键字

5.运算符

5.1 算数运算符

四则运算

注:浮点型运算的精度不及整数型,浮点型之间不要进行相等判断

5.2 递增递减运算符

自增自减运算符只能与变量搭配使用,单独使用时前置自加与后置自加效果相同,与其他代码联用时要注意

<script>
    var e = 10 ;
    var f = e++ + ++e;
    console.log(f);//22
script>

5.3 比较运算符

两个数据进行比较时使用的运算符,返回一个布尔类型的值

运算符名称 说明 案例 结果
< 小于号
> 大于号
>= 大于等于
<= 小于等于
== 等号(会转型) 37==‘37’ true
!= 不等号 37!=37 false
=== ==! 全等,要求值和数据类型一致 37=‘37’ false

5.4 逻辑运算符

逻辑 符号 规律
逻辑与 && 两边都为true结果为true
逻辑或 || 两边都为false结果为false
逻辑非 ! 结果取反

5.5 短路运算

当有多个表达式时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式值成为短路运算

5.5.1 逻辑与中断

console.log(表达式1 && 表达式2) :如果表达式1为真,则返回表达式2;如果表达式1为假,返回表达式1

<script>
    console.log(''&&123&&456);//返回为空
    console.log(0&&123&&456);//0
    console.log(123&&456);//456
script>

5.5.2 逻辑或中断

console.log(表达式1 && 表达式2) :如果表达式1为真,则返回表达式1;如果表达式1为假,返回表达式2

console.log(''||123||456);//123
console.log(0||123||456);//123
console.log(123||456||789);//123

5.5.3 逻辑中断影响程序结果

<script>
    var num=0;
    console.log(123||num++);
    console.log(num);//0
script>

5.6 赋值运算符

+=、-=、*=、/=、%=

5.7 运算符优先级

括号优先级最高,逻辑运算符优先级较低

6.流程控制-分支

6.1 流程控制

流程控制就是控制我们的代码按照什么结构来执行

流程控制主要有三种结构:顺序结构、分支结构、循环结构

6.2 顺序流程控制

代码从上打下按照顺序就行执行

6.3 分支流程控制

由上到下执行代码的过程中,按照不同的条件执行不同的代码得到不同的结果

JavaScript提供了两种分支结构语句:if、switch语句

6.3.1 if语句

6.3.2 if…else语句

6.3.3 if…else if…else语句

6.3.4 三元表达式

<script>
    var time=prompt("请输入你的数字:");
    var result = time >= 10 ? time : '0'+time; //比较数字大小使用了隐式转换
    alert(result);
script>

6.3.5 switch语句

<script>
    var fruit = prompt("请输入水果名");
    switch(fruit){
      
        case '苹果':
            alert('3.5/斤');
            break;
        case '香蕉':
            alert('4.5/斤');
            break;
        default:
            alert("没有此水果")
    }
script>

7.流程控制-循环

7.1 循环

JavaScript中主要有三种类型的循环语句:for、while、do…while

7.2 for循环

7.3 while循环

7.4 do…while循环

7.5 continue break

二、JavaScript数组

1.数组的概念

数组是指一组数据的集合,其中每一个数据被称为元素,在数组中可以存放任意类型的数据,数组是一种将一组数据存储在单个变量名下的优雅方式

2.数组的创建

<script>
    //创建数组的第一种方式
    var arr1=new Array();
    //创建数组的第二种方式
    var arr2=[1,2,'3',true]; //存放数据没有限制
script>

3.获取数组中的数据

数组可以通过索引来访问、修改对应的数组元素

4.遍历数组

通过循环将数组中的元素取出来

5.数组新增元素

5.1 修改数组长度

<script>
    //修改数组长度
    var arr=['1','2','3'];
    arr.length=5;
    console.log(arr[3]);//empty
    console.log(arr[4]);//empty
script>

5.2 修改数组索引

//修改数组索引,如果数值不存在则追加,如果存在则覆盖
var arr=['1','2','3'];
arr[3]='4';
arr[4]='5';
console.log(arr[3]);
console.log(arr[4]);

如果将字符串直接赋值给数组变量,则数据类型发生变化由数组变为了字符串

6. 翻转数组

<script>
    var arr=['1','2','3'];
    var newarray=[];
    //i的值存的是数组中的最后一个元素的索引
    for(var i =arr.length-1;i>=0;i--){
      
        //将旧数组的最后一个元素赋予新数组的第一个位置
        newarray[newarray.length] = arr[i];
    }
    console.log(newarray);
script>

7.冒泡排序法

外层for循环控制趟数,内部for循环控制交换次数

三、JavaScript函数

1.函数的概念

在JS代码中,会有许多相同的代码或者功能相似,代码需要被大量复用,此时函数的作用就体现出来了

2.函数的使用

函数的使用分为两步,声明函数和调用函数

3.函数的参数

3.1 形参

形式上的参数

3.2 实参

实际上的参数

3.3 函数形参与实参个数不匹配

参数个数 结果
实参个数==形参个数 结果正常执行
实参个数 > 形参个数 只取到形参的个数
实参个数 < 形参个数 多出的参数为underfined,结果为NaN

4.函数的返回值

个别情况我们希望函数能给调用者一个执行结果或者叫返回值

4.1 return语句

通过return value;语句可以将结果或者值返回给调用者

4.2 return终止语句

return后的语句不会被执行

4.3 return返回值

return只能返回一个值,如果逗号分隔多个值,以最后一个为准,可以将返回的多个值放到数组中,return [value1,value2…];

4.4 返回值为undefined

函数都是有返回值的:

  1. 如果有return,则返回return后面的值
  2. 如果没有return,则返回undefined

5.arguments的使用

5.1 基本使用

arguments是函数的内置对象,内部可以存储传递的所有实参,当不确定有多少个实参传递的时候,可以通过此对象来获取

<script>
    //arguments对象可以接受所有的参数
    function fn(){
      
        console.log(arguments);
    }
    fn(1,2,3,5);
script>

arguments展示形式是一个伪数组,因此可以进行遍历,伪数组的特点:

  • 具有length属性
  • 按照索引方式存储数据
  • 不具有数组的push、pop方法
<script>
    //只有函数才有arguments对象
    function fn(){
      
        for(var arr=0;arr<arguments.length;arr++){
      
            console.log(arguments[arr]);
        }
    }
    fn(1,2,3,5);
    fn('3','2','1','0');
script>

5.2 求出最大值

<script>
    //只有函数才有arguments对象
    function fn(){
      
        var max=arguments[0];
        for(var i =1;i<arguments.length;i++){
      
            if(arguments[i]>max){
      
                max=arguments[i];
            }
        }
        return max;
    }
    var result =fn(11,23,53,59,2);
    console.log(result);
script>

6.函数调用函数

每个函数都会完成特定的功能,功能与功能之间有联系,所以函数与函数之间可以互相调用

7.函数的声明

7.1 使用关键字

function fn(){

}

7.2 函数表达式

函数表达式与声明变量相差无几,只不过变量里面存放的是函数而不是变量值

//函数表达式可以传递参数
var fn = function(aru){

}

8.作用域

作用域就是代码名字在某个范围内起作用和效果,更重要的是减少命名冲突

JS作用域分为局部作用域与全局作用域

  1. 全局作用域:在script标签内的
  2. 局部作用域:在函数内部

8.1 全局变量

全局下都可以使用,注意:如果在函数体内部,没有声明直接赋值的变量也属于全局变量

8.2 局部变量

局部作用域的变量,只能在函数体内部使用,函数的参数也是局部变量

8.3 执行效率区别

  • 全局变量只有在浏览器被关闭以后才会被销毁,比较占用资源
  • 局部变量在我们的程序执行完毕后就会被销毁,解决资源

8.4 块级作用域

在ES6以后新增了块级作用域,被“{ }”包裹的为块级作用域,外部不可以访问里面的变量

8.5 作用域链

在函数内部再声明一个函数,内部函数访问外部函数的变量采取的就是链式查找方法,就近原则,这种结构我们称之为作用域链

<script>
    function f1(){
      
        var num=123;
        function f2(){
      
            console.log(num); //打印的是123
        }
        f2();
    }
    var num =456;
    f1();
script>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7PzJ6RH-1607239291408)(img/image-20201113152207919.png)]

9.JavaScript预解析

9.1 预解析

1》JS代码有浏览器中的JS解析器执行的,解析器在运行JS代码时分为两步:预解析和代码执行

  1. JS引擎会把JS里面的var、function提升到当前作用域的最前面
  2. 代码执行从上而下

2》预解析分为 变量预解析(变量提升)和函数预解析 (函数提升)

变量提升就是把所有的变量声明提升到当前的作用域的最前面,不提升赋值操作

<script>
    //所以应该在打印变量语句之前声明变量
    console.log(num);
    var num=10; //undefind
    //JS解析器执行顺序
    /*
        var num;
        consolo.log(num);
        num=10;
        所以会出现未定义
    */
script>

函数提升就是把所有的函数声明(function关键字)提升到当前作用域的最前面,不调用函数

//应该在函数声明以后再调用函数
<script>
    fn();
    var fn=function(){
      
        console.log("---");
    }
    //报错,JS解析器执行顺序为
    /*
				var fn;
				fn();//此时没有此函数,所以会报错
				fn = function(){
					consoloe.log("---");
				}
			*/

script>

四、JavaScript对象

1.对象

1.1 对象的定义

在JS中,对象是属性与方法的结合

1.2 对象的作用

完整的、有效的保存信息,例如一个人的信息

2.对象的创建

在JS中,创建对象有三种方式

  1. 利用字面量创建对象
  2. 利用 new Objcet创建对象
  3. 利用构造函数创建对象

2.1 字面量创建对象

对象字面量:{ } 里面包含了表达这个具体事物(对象)的属性和方法

<script>
    /*
				多个属性之间用逗号分隔开
				值为键值对的形式存在
				方法为匿名方法
			*/
    var obj={
      
        name:'zhangsan',
        age:'18',
        sayHi:function(){
      
            console.log("hello")
        }
    }
script>

属性的调用两种方法:1>对象名.属性名 2>对象名[‘属性名’]

2.2 new Object创建对象

<script>
    var obj = new Object();//创建了一个空的对象
    //为对象添加属性与方法
    obj.name='zhangsan';
    obj.age='12';
    obj.sayHi=function(){
      
        console.log("hello")
    }
    //调用对象的属性与方法
    console.log(obj.name);
    console.log(obj['age']);
    obj.sayHi();
script>

2.3 构造方法创建对象

构造函数:是一种特殊的函数,主要用来初始化对象

  1. 构造函数首字母要大写
  2. 调用构造函数必须使用 new 关键字
  3. 我们的属性和方法必须先加上 this 关键字
  4. 调用构造方法后会返回一个对象,不需要return关键字
<script>
    function Method(uname,age,sex){
      
        this.uname=uname;
        this.age=age;
        this.sex=sex;
        this.sing=function(sing){
      
					console.log(sing)
				}
    }
    var ldh=new Method('刘德华',18,'男');
    console.log(ldh);
    ldh.sing('冰雨');
script>

3.new关键字

new关键字的执行过程:

  1. new 关键字可以在内存中创建一个空的对象
  2. this 就会指向刚才创建的对象
  3. 执行构造方法里面的代码,给这个空对象添加属性和方法
  4. 返回这个对象

4.遍历对象

for…in 语句用于对数组或者对象的属性进行循环操作(与Java 的foreach功能类似)

var ldh=new Method('刘德华',18,'男');
for(var k in ldh){
	console.log(k); //得到的是 属性名
	console.log(ldh[k]); //得到的是 属性值
}

五、JavaScript内置对象

1.内置对象

内置对象就是JS内部自带的一些对象,这些对象的功能已经实现可以直接拿来使用,优点就是帮助我们最快的开发

2.Math对象

2.1 Math概述

Math数学对象,不是一个构造函数而是静态的,可以直接使用其中的属性与方法

属性与方法名 功能
Math.PI 圆周率
Math.floor() 向下取整
Math.ceil() 向上取整
Math.round() 四舍五入就近取值, 注:-3.5 结果为 -3(.5向大取)
Math.abs() 绝对值
Math.max/Math.min 最大值与最小值

2.2 随机数方法

随机产生一个数字, 数字范围为: 0<=x<1

2.2.1 获得两个随机数并包含边界

<script>
    function getRandom(min,max){
      
        return Math.floor(Math.random()*(max-min+1))+min;
    }
    console.log(getRandom(1,20));
script>

2.2.2 获得两个随机整数

<script>
    function getRandom(min,max){
      
        return Math.floor(Math.random()*(max-min))+min;
    }
    console.log(getRandom(1,20));
script>

3.日期对象

日期对象 一个构造函数,必须创建对象来创建日期对象,构造方法中不传入参数默认为当前时间,参数可以为数字也可以为字符串

3.1 格式化时间

看方法名就知道功能,注:月份是从 0 开始,需要 +1

3.2 获得毫秒数

<script>
    //返回当前总共毫秒数的方法
    var date=new Date();
    console.log(date.valueOf());
    console.log(date.getTime());
    //构造方法之前加上 + 号即可
    var date1 =+new Date();
    console.log(date1);
script>

H5新增的获得毫秒数的方法,无需创建日起对象就可以使用

console.log(Date.now());

3.3 倒计时函数实现

<script>
    function countDown(time){
      
        var nowTime=+new Date(); //返回当前毫秒数
        var inputTime =+new Date(time); //返回用户输入的时间毫秒数
        var times=(inputTime - nowTime)/1000; //times是剩余时间秒数
        var d =parseInt(times/60/60/24); //天
        var h =parseInt(times/60/60%24); //小时
        var m =parseInt(times/60%60); //分钟
        var s =parseInt(times%60); //秒
        return d + '天'+h + '时' + m + '分钟' + s + '秒';
    }
script>

4.数组对象

4.1 创建数组

<script>
    var arr1 = new Array(); //创建了一个空数组
    var arr2 = new Array(2); //表示数组长度为2,内容为空
    var arr3 = new Array(2,3); //表示为[2,3],里面有两个数据
script>

4.2 监测是否为数组

4.2.1 instanceof 运算符

<script>
    var arr ={
      };
    console.log(arr instanceof Array); //false
script>

4.2.2 Array.isArray()方法

可以直接判断出来

4.3 添加、删除数组元素

方法 说明 返回值
push(…) 末尾添加元素,修改原数组 返回新的长度
pop() 删除最后一个元素,数组长度-1,修改原数组 返回它删除的元素的值
unshift(…) 向数组开头添加元素,修改原数组 返回新的长度
shift() 删除数组第一个数组,数组长度-1,修改原数组 返回删除的元素的值

4.4 数组排序

方法名 说明 是否修改原数组
reverse() 颠倒数组中元素的顺序 改变原来的数组,返回新数组
sort() 对数组元素进行排序 改变原来的数组,返回新数组

sort([compareFunction])中的参数是可选的用来指定某种排序顺序,如果省略则默认按照元素的Unicode位点进行排序

<script>
    var arr =[99,58,64,87,11,3];
    arr.sort(function(a,b){
      
        return a - b; //升序排序 , b-a 降序
    });
    console.log(arr);
script>

4.5 数组索引

方法名 说明 返回值
indexOf() 数组中查找给定元素的第一个索引 元素存在返回索引值,否则返回-1
lastIndexOf() 数组中的最后一个索引 元素存在返回索引值,否则返回-1

4.6 数组转换为字符串

方法名 说明 返回值
toString 数组转换为字符串 返回一个字符串
join(‘分隔符’) 字符串用给定分隔符进行分隔 返回一个字符串
<script>
    var str=[1,3,'4'];
    console.log(str.join('-')) //[1-3-4]
script>

4.7 数组操作

方法名 说明 返回值
concat() 连接两个或多个数组不影响原数组 返回一个新数组
slice() 数组截取(begin,end),end取不到 返回被截取产生的新数组

5.字符串对象

5.1 基本包装类型

基本包装类型就是把简单数据类型包装为复杂数据类型,这样基本数据类型就会有了属性与方法

JS中提供了三种特殊的引用类型:String、Number、Boolean

5.2 字符串不可变

5.3 根据字符串返回位置

字符串中的所有方法都不会修改字符串本身,操作完成后会返回一个新的字符串

<script>
    var str ='春天来了,春天走了,春天又来了';
    console.log(str.indexOf('春'),5); //从索引号是5的位置开始查找并返回位置
script>

5.4 查找指定字符出现位置及次数

<script>
    var str='abcodfdfofdaogao';
    var index=str.indexOf('o');
    var num=0;
    while(index!==-1){
      
        console.log(index);
        num++;
        index=str.indexOf('o',index+1);
    }
script>

5.5 根据位置返回字符

方法名 说明 使用
charAt(index) 返回指定位置的字符 str.charAt(0)
charCodeAt(index) 返回指定位置的字符的ASCII码 str.charCodeAt(0)
str[index] 获取指定位置字符 HTML5支持,与charAT相同

5.6 字符串操作

方法名 说明 返回值
split(‘分隔符’) 指定分隔符将数组分割开来
replace(参数1,参数2) 参数1位被替换的字符,参数2位要替换成的字符
substr(参数1,参数2) 参数1位索引号,参数2为取字符个数
<script>
    var str='abc-def-fgd';
    var str1 = str.split('-');
    console.log(str1); //['abc','def','fgd']
script>

6.数据类型

6.1 简单数据类型

简单数据类型保存在栈中

简单数据传参是将栈中的值复制一份传给了形参

<script>
    function fn(a){
      
        a++;
        console.log(a); // 11
    }
    var x = 10;
    fn(x);
    console.log(x); // 10
script>

6.2 复杂数据类型

复杂数据类型保存在堆区中

复杂数据类型传值是将引用的内存地址复制一份传给了形参

<script>
    function Person(name){
      
        this.name = name;
    }
    function fn(x){
      
        console.log(x.name);//tom
        x.name="jack";
        console.log(x.name);//jack
    }
    var p = new Person('tom');
    console.log(p.name); //tom
    fn(p);
    console.log(p.name); //jack
script>

六、WebAPIs

1.Web APIs与JS关联性

1.1 JS的组成

JS=ECMScript+DOM+BOM,而Web APIs就是DOM与BOM

1.2 两种阶段区别

JS基础阶段:

  • 学习JS语言的基础语法
  • 做不了网页交互的效果
  • 为以后的课程打下基础

Web APIs阶段:

  • 是由W3C组织的标准
  • 主要学习DOM、BOM
  • JS语言独有的
  • 学习页面的交互功能

2.API与Web API

2.1 API

API就是已经写好的程序,直接调用即可,不用关心里面的代码以及功能是如何实现的一种接口

2.2 Web API

浏览器提供的一套操作浏览器和页面元素的API(BOM、DOM)

七、DOM对象

1.DOM简介

文档对象模型,是一个标准编程接口

利用DOM接口可以改变页面内容、结构和样式

2.DOM树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tYqTgTwV-1607239291413)(img/DOM树.png)]

  • 文档:一个页面就是一个文档,DOM中使用document表示
  • 元素:页面中的所有标签都是元素,DOM中使用element表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本注释等),DOM中用node表示

DOM把以上内容都看做是对象

3.获取元素

获取元素之前元素必须被网页加载完毕,所以script标签应该写在内容下方

3.1 如何获得页面元素

获取页面元素的四种方式:

  1. 根据ID获取
  2. 根据标签名获取
  3. HTML5新增方法获取
  4. 特殊元素获取

3.2 根据ID获取

参数的id是大小写敏感的字符串

<body>
    <div id='time'>2020-11-16div>
    <script>
        var times = document.getElementById('time');
        console.log(times); //包括标签等将内容完全打印到控制台
        console.log(typeof times); //判断节点是否为对象
        console.dir(times); //新增方法,返回元素对象并且可以查看更多属性和方法
    script>
body>

3.3 根据标签名获取元素

返回的内容以伪数组的形式存储,可以对其进行遍历得到对象。如果数组中没有元素,则为空伪数组

父元素必须是单个对象(必须指明是哪个对象),获取不会获得父元素只有子元素;通常情况下获取父标签可以使用id获取再获取子类

<body>
    <ul>
        <li>1li>
        <li>2li>
        <li>3li>
    ul>
    <script>
        //返回的是伪数组,可以进行遍历获得对象
        var lis = document.getElementsByTagName('li');
        for(var i =0;i<lis.length;i++){
      
            console.log(lis[i]);
        }
        //获得父标签内部的子标签
        var ull =document.getElementsByTagName('ul'); //获得父标签 ull[]数组
        //伪数组中只有一个父标签,指定它
        console.log((ull[0].getElementsByTagName('li')));
    script>
body>

3.4 HTML5新增方法

1.通过类名获取元素,返回的是伪数组

<body>
    <div class="box1">盒子1div>
    <script>
        //返回的是伪数组形式存储
        var box1 = document.getElementsByClassName('box1');
        console.log(box1);
    script>
body>

2.querySelector() 返回指定选择的第一个元素对象,里面的选择器需要加上 表明符号

3.querySelectorAll() 返回指定选择器的所有元素对象**(返回的应该是伪数组)**

<body>
    <div class="box1">盒子1div>
    <div id="box2">盒子2div>
    <div class="box1">盒子3div>
    <script>
        //两个类选择器,只会拿到第一个
        var boxes = document.querySelector('.box1');
        console.log(boxes);
        //指定选择器为ID选择器
        boxes = document.querySelector('#box2');
        console.log(boxes);
        //指定标签,选择所有
        boxes = document.querySelectorAll('div');
        console.log(boxes)
    script>
body>

3.5 特殊标签的获取

1.获取body标签

<script>
    var bodyEle = document.body;
    console.log(bodyEle);
script>

2.获取html标签

<script>
    var htmlEle = document.documentElement;
    console.log(htmlEle);
script>

4.事件基础

4.1 事件概述

JS有能力使我们创建动态页面,而事件是可以被JS侦测到的行为,网页中每个元素都可以产生某些可以被触发JS事件

4.2 事件三要素

事件源:事件被触发的对象,例如 按钮(事件源) 被点击触发

事件类型:如何触发,例如鼠标点击、鼠标移出等

事件处理程序:通过一个函数赋值的方式完成

<body>
    

4.3 事件执行步骤

<body>
    

4.4 鼠标常用事件

鼠标事件 触发条件
onclick 鼠标点击左键触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发

5.操作元素

JS的DOM操作可以改变网页的内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等

5.1 改变元素内容

element.innerText 可以改变页面的内容(或者可以说是指定便签内的内容)

<body>
    <p>手动点击显示时间p>
    <button>时间查询button>
    <div>显示时间的区域div>
    <hr>
    <p>加载页面显示时间p>
    <h3>显示时间的区域h3>
    <script>
        //1.获取事件源
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        //2.绑定事件
        btn.onclick = function(){
      
            div.innerText = getDate();
        }
        function getDate(){
      
            var times = new Date();
            var year = times.getFullYear();
            var month = times.getMonth()+1;
            var day = times.getDay();
            var hour = times.getHours();
            var min = times.getMinutes();
            var second = times.getSeconds();
            return year+'年'+month+'月'+day+'日'+hour+'时'+min+'分'+second+'秒';
        }
        //--------------------------------------------------------------------------
        var h3 = document.querySelector('h3');
        h3.innerText = getDate();
    script>
body>

5.2 innerText、innerHTML

1.element.innerText无法识别html标签,去除html标签、空格与换行(非标准)

<body>
    <div>div>
    <script>
        var div = document.querySelector('div');
        div.innerText = '时间为:'+new Date(); //无法识别HTML代码
    script>
body>

2.element.innerHTML识别html标签(W3C标准),保留空格与换行

<body>
    <div>div>
    <script>
        var div = document.querySelector('div');
        div.innerHTML = '时间为:'+new Date(); //可以识别,字体变为粗体
    script>
body>

3.两个属性可以读写,可以获取元素里面的内容

<body>
    <p>
        我是文字
        <span>第二行为红色的字体span>
    p>
    <div>div>
    <script>
        var p = document.querySelector('p');
        //console.log(p.innerText);//将p标签内容打印出来
        console.log(p.innerHTML); //控制台输出  换行
    script>
body>

5.3 常用元素的属性操作

  1. innerText、innerHTML 改变元素内容
  2. src、href
  3. id、alt、title

修改src属性–>element.src

<body>
    

修改alt属性

imgs.title = '张学友'

用法大致相同,无须赘述

5.4 表单元素的属性操作

利用DOM可以操作:type、value、checked、selected、disable

1.修改value值

<body>
    <input type="text"  value="修改里面的值...." /><br>
    <button>按钮button>
    <script>
        //1.获取对象元素
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        //2.注册事件
        btn.onclick = function(){
      
            //input.innerHTML='修改失败'; 这种方式是普通盒子才能修改
            input.value = '修改成功'; //表单元素必须修改value值才可以
        }
    script>
body>

2.禁用

btn.disabled = true; //按钮被点击一次后被禁用
this.disabled = true; // 这个也可以

总结一下:修改表单元素属性值与修改元素的属性用法相同,不再赘述

5.5 元素样式属性操作

我们可以通过JS修改元素的大小、颜色、位置等样式(例如修改CSS样式)

  1. element.style 行内样式操作
  2. element.className 类名样式修改

5.5.1 通过style修改样式

当样式比较少时,修改比较简练,但是当样式太多时,一个一个修改就会非常麻烦

<body>
    <style type="text/css">
        div{
      
            width: 200px;
            height: 200px;
            background-color: black;
        }
    style>
    <div>div>
    <script>
        //1.获取元素对象
        var div = document.querySelector('div');
        //2.注册事件
        div.onclick = function(){
      
            //div.style.backgroundColor = 'purple';
            //this代表调用样式属性的对象,也就是指div这个元素对象
            this.style.backgroundColor = 'red' ;
            this.style.width = '400px';
            this.style.height = '100 px';
        }
    script>
body>

5.5.2 通过className修改

修改样式过多繁杂且麻烦,直接更改classname就可以直接修改样式,方便快捷

element.className = ‘类名’ 即可:会更改原来的类名并覆盖掉(如果不想被覆盖,则可以写多个类名并加上空格即可)

<body>
    <style type="text/css">
        .message{
      
            color:grey;
        }
        .wrong{
      
            color: red;
        }
        .right{
      
            color: green;
        }
    style>
    <input type="text"/>
    <div class="message">请输入1~16位密码div>
    <script>
        var input = document.querySelector('input');
        var div = document.querySelector('div');
        input.onblur = function(){
      
            if(input.value.length <6 || input.value.length >16){
      
                div.innerHTML = '密码长度不对'
                div.className = 'message wrong'; //这样写保存两个类名,防止被覆盖和页面出错误
            }else{
      
                div.innerHTML = '密码格式正确'
                div.className = 'message right';
            }
        }
    script>
body>

注意:

  1. JS里面采用驼峰命名
  2. JS修改的style样式操作,产生的是行内样式(就是在修改的地方单独加上一个行内标签修改样式不会修改原来CSS样式文件内容)

5.6 小实训

5.6.1 实现密码明文

个人认为已经完善(除前端外,大致代码逻辑)

<body>
    <input type="password"/><button>显示密码button>
    <script>
        //1.获取对象元素
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var flag = 1;
        //2.注册事件
        btn.onclick = function(){
      
            if(!input.value==''){
      
                if(flag ==1){
      
                    input.type = 'text';
                    btn.innerHTML = '隐藏密码'
                    flag =0;
                }else {
      
                    input.type = 'password';
                    btn.innerHTML = '显示密码'
                    flag =1;
                }
            }
        }
    script>
body>

5.6.2 仿隐藏内容

display.none:隐藏元素 display.block:显示元素

<body>
    <style type="text/css">
        div{
      
            width: 200px;
            height: 200px;
            background-color: black;
        }
    style>
    <div>div>
    <br>
    <input type="button" value="隐藏"/>
    <script>
        //1.获取元素对象
        var btn = document.querySelector('input');
        var div = document.querySelector('div');
        //2.注册事件
        btn.onclick = function(){
      
            div.style.display='none';
        }
    script>
body>

5.6.3 显示隐藏文本框内容

当鼠标点击文本框内容时,默认文字隐藏;鼠标离开文本框,默认文字显示

<body>
    <style type="text/css">
        input{
      
            color:#999;
        }
    style>
    <input type="text" value="手机" />
    <script>
        //1.获取元素对象
        var text = document.querySelector('input');
        //2.注册事件
        //获得焦点
        text.onfocus = function(){
      
            if(text.value ==='手机'){
      
                text.value = '';
            }
            this.style.color = '#333';
        }
        //失去焦点
        text.onblur = function(){
      
            if(text.value ===''){
      
                text.value='手机';
            }
            this.style.color ='#999';
        }
    script>
body>

5.6.4 开关灯的实现

<head>
    <meta charset="utf-8">
    <title>title>
    <style type="text/css">
        .background-black{
      
            background-color: black;
        }
        .background-white{
      
            background-color: white;
        }
    style>
head>
<body class="background-white">
    <input type="button" value="开关灯"/>
    <script>
        var body = document.body;
        var input = document.querySelector('input');
        var flag = 1 ;
        input.onclick = function(){
      
			//flag为1说明是开灯效果
            if(flag ===1){
      
                body.className = 'background-black';
                flag = 0;
            }else{
      
                body.className = 'background-white';
                flag = 1;
            }
        }		
    script>
body>

5.7 操作元素小总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfZNHzVZ-1607239291423)(img/image-20201122140509370.png)]

5.8.排他思想

5.8.1 基础用法

如果 有一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:

  1. 所有元素全部清除样式
  2. 给当前元素设置样式
  3. 顺序不能颠倒,首先干掉其他人,在设置自己
<body>
    <input type="button" value="按钮1"/>
    <input type="button" value="按钮2"/>
    <input type="button" value="按钮3"/>
    <input type="button" value="按钮4"/>
    <input type="button" value="按钮5"/>
    <script>
        //返回的是一个伪数组存储数据
        var inputs = document.getElementsByTagName('input');
        //为每一个按钮绑定事件
        for(var i=0;i<inputs.length;i++){
      
            //绑定事件
            inputs[i].onclick = function(){
      
                //先进行for循环,清除所有原先样式
                for(var j =0;j<inputs.length;j++){
      
                    inputs[j].style.color = '';
                }
                //修改全部原先样式后单独修改这个样式
                this.style.color ='pink';
            }	
        }
    script>
body>

5.8.2 小实训

5.8.2.1实现换肤效果

<html>
    <head>
        <meta charset="utf-8">
        <title>title>
        <style type="text/css">
            *{
      
                margin: 0;
                padding: 0;
            }
            body{
      
                background-image: url(imgs/20201115.jpg);
            }
            li{
      
                list-style: none;
            }
            .baidu{
      
                overflow: hidden;
                margin: 100px auto;
                background-color: #fff;
                width: 650px;
                padding-top: 3px;
            }
            .baidu li{
      
                float: left;
                margin: 0 1px;
                cursor: pointer;
            }
            .baidu img {
      
                width: 100px;
            }
        style>
    head>
    <body>
        <ul class="baidu">
            <li><img src="imgs/20201115.jpg">li>
            <li><img src="imgs/20201116.jpg">li>
            <li><img src="imgs/20201117.jpg">li>
            <li><img src="imgs/20201118.jpg">li>
            <li><img src="imgs/20201119.jpg">li>
            <li><img src="imgs/20201120.jpg">li>
        ul>
        <script>
            //获得指定元素对象img
            var imgs = document.querySelector('.baidu').querySelectorAll('img');
            for(var i =0;i<imgs.length;i++){
      
                imgs[i].onclick = function(){
      
                    //修改body的样式属性
                    document.body.style.backgroundImage='url('+this.src+')';
                }
            }
        script>
    body>
html>
5.8.2.2 隔行变色效果

需要新的鼠标事件:鼠标经过和鼠标离开


<html>
    <head>
        <meta charset="utf-8">
        <title>title>
        <style type="text/css">	
            .bg {
      
                background-color: springgreen;
            }
        style>

    head>
    <body>
        <table border="1px" width="600px" align="center">
            <thead>
                <tr>
                    <td>代码td>
                    <td>名称td>
                    <td>人数td>
                tr>
            thead>
            <tbody>
                <tr>
                    <td>101td>
                    <td>javatd>
                    <td>1000td>
                tr>
                <tr>
                    <td>102td>
                    <td>pythontd>
                    <td>1200td>
                tr>
                <tr>
                    <td>103td>
                    <td>C++td>
                    <td>800td>
                tr>
            tbody>
        table>
        <script>
            //获取需要改变样式的指定的所有的行
            var trs = document.querySelector('tbody').querySelectorAll('tr');
            //利用循环将每一行都绑定上时间
            for(var i =0;i<trs.length;i++){
      
                //绑定鼠标经过事件
                trs[i].onmouseover = function(){
      
                    //鼠标经过,为次行单独增加一个CSS背景颜色样式
                    this.className='bg';
                }
                trs[i].onmouseout =function(){
      
                    //鼠标移出,把此行的样式取消掉
                    this.className='';
                }
            }
        script>
    body>
html>
5.8.2.3 表单全选与取消
<body>
    <table border="1px" width="600px" align="center">
        <thead>
            <tr>
                <th><input type="checkbox" id='checkedAll'/>th>
                <th>课程th>
                <th>价格th>
            tr>
        thead>
        
            <tr>
                <td><input type="checkbox"/>td>
                <td>javatd>
                <td>10000td>
            tr>
            <tr>
                <td><input type="checkbox"/>td>
                <td>pythontd>
                <td>12000td>
            tr>
            <tr>
                <td><input type="checkbox"/>td>
                <td>C++td>
                <td>8000td>
            tr>
        tbody>
    table>
    <script>
        //获得总复选框对象
        var checkedAll = document.getElementById('checkedAll');
        //获得所有的复选框对象
        var tb = document.querySelector('#tb').querySelectorAll('input');
        //一、全选按钮点击,所有按钮全部选中,否则全部为选中
        //第二种方法
        checkedAll.onclick=function(){
      
            for(var i =0;i<tb.length;i++){
      
                //this.checked代表的是全选框的状态
                tb[i].checked = this.checked;		   
            }
        }
        /* 
				var flag =1;
				第一种方法,使用if判断
				checkedAll.onclick = function(){
				if(flag===1){
					for(var i =0;i
        //二、按钮全被选中全选按钮也被选中
        //外层for循环作用为为每一个复选框绑定一个事件
        for(var i = 0;i<tb.length;i++){
      
            tb[i].onclick = function(){
      
                var flag = true;
                //内存复选框作用为判断所有的复选框的状态,如果全都被点击,则flag值默认不变
                //如果有一个复选框没有被选中,则将flag的值改变
                for(var i = 0;i<tb.length;i++){
      
                    if(!tb[i].checked){
      
                        flag =false;
                        break; //只要有一个按钮没有被选中,下来的判断没有意义
                    }
                }
                checkedAll.checked = flag;
            }
        }
    script>
body>

5.9 自定义属性操作

自定义属性的目的是为了保存使用数据。有些数据可以保存到页面中而不用保存到数据库中

为了防止开发人员自定义属性与自带属性产生歧义,开发规定:自定义属性按照 data- 开头做属性名并赋值

5.9.1 获取属性值

  • element.属性 :获取内置属性值(元素本身自带的属性)
  • element.getAttribute(‘属性’) :主要获得自定义属性值(开发人员自定义的属性)
<body>
    

p> <script> var p = document.querySelector('p'); console.log(p.id); console.log(p.getAttribute('index')); script> body>

5.9.2 设置属性值

  • element.属性=‘值’
  • element.setAttribute(‘属性名’,‘属性值’)
<body>
    

5.9.3 移除属性值

removeAttribute(‘属性’)移除属性

5.9.4 h5新增获取属性值

<body>
    
div> <script> var div = document.querySelector('div'); div.setAttribute('name','divName'); //常规方法,兼容性强 console.log(div.getAttribute('name')); //h5新增的方法 dataset 相当于一个集合 ,只能获取以 data 开头的属性 console.log(div.dataset.name); script> body>

总结:自带的属性值与开发人员设置的属性值使用分开的方法操作

6 Tab拦切换操作(重点)

点击Tab拦会切换不同的内容


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Documenttitle>
        <style>
            * {
      
                margin: 0;
                padding: 0;
            }

            li {
      
                list-style-type: none;
            }

            .tab {
      
                width: 978px;
                margin: 100px auto;
            }

            .tab_list {
      
                height: 39px;
                border: 1px solid #ccc;
                background-color: #f1f1f1;
            }

            .tab_list li {
      
                float: left;
                height: 39px;
                line-height: 39px;
                padding: 0 20px;
                text-align: center;
                cursor: pointer;
            }

            .tab_list .current {
      
                background-color: #c81623;
                color: #fff;
            }

            .item_info {
      
                padding: 20px 0 0 20px;
            }

            .item {
      
                display: none;
            }
        style>
    head>

    <body>
        <div class="tab">
            <div class="tab_list">
                <ul>
                    <li class="current">商品介绍li>
                    <li>规格与包装li>
                    <li>售后保障li>
                    <li>商品评价(50000)li>
                    <li>手机社区li>
                ul>
            div>
            <div class="tab_con">
                <div class="item" style="display: block;">
                    商品介绍模块内容
                div>
                <div class="item">
                    规格与包装模块内容
                div>
                <div class="item">
                    售后保障模块内容
                div>
                <div class="item">
                    商品评价(50000)模块内容
                div>
                <div class="item">
                    手机社区模块内容
                div>

            div>
        div>
        <script>
            // 获取元素
            var tab_list = document.querySelector('.tab_list');
            var lis = tab_list.querySelectorAll('li');
            var items = document.querySelectorAll('.item');
            // for循环绑定点击事件
            for (var i = 0; i < lis.length; i++) {
      
                // 开始给5个小li 设置索引号 
                lis[i].setAttribute('index', i);
                lis[i].onclick = function() {
      
                    // 1. 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式
                    // 干掉所有人 其余的li清除 class 这个类
                    for (var i = 0; i < lis.length; i++) {
      
                        lis[i].className = '';
                    }
                    // 留下我自己 
                    this.className = 'current';
                    // 2. 下面的显示内容模块
                    var index = this.getAttribute('index');
                    console.log(index);
                    // 干掉所有人 让其余的item 这些div 隐藏
                    for (var i = 0; i < items.length; i++) {
      
                        items[i].style.display = 'none';
                    }
                    // 留下我自己 让对应的item 显示出来
                    items[index].style.display = 'block';
                }
            }
        script>
    body>

html>

7.节点操作

7.1 获取元素的两种方式

通常获取元素使用两种放肆:

  1. 利用DOM提供的方法获取元素
    1. document.getElementById()等
    2. 逻辑性不强、繁琐
  2. 利用节点层级关系获取元素
    1. 利用父子兄弟节点获取元素
    2. 逻辑性强,但是兼容性差

这两种方法都可以获取元素,但是节点获取元素稍微简单

7.2 节点概述

​ 网页中所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。HTML DOM树中的所有节点均可以通过JS进行访问,所有的HTML元素(节点)均可以修改,也可以创建或者删除

一般的,节点至少拥有节点类型、节点名称、节点值三个基本属性

  • 元素节点 node Type 为1
  • 属性节点 node Type 为2
  • 文本节点 node Type 为3(文本节点包含文字、空格、换行等)

在实际开发中,实际操作的是元素节点

7.3 节点层级

利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系

7.3.1 父级节点

node.parentNode:只会获得距离最近的父级节点

<body>
    <div>
        <p>p>
    div>
    <script>
        //1.获取父级节点
        var son = document.querySelector('p');
        console.log(son.parentNode)
    script>
body>

7.3.2 子节点

7.3.2.1node.childrenNodes

会返回所有的子级节点,返回值为一个数组(因为子级节点较多)

<body>
    <ul>
        <li>li>
        <li>li>
        <li>li>
    ul>
    <script>
        //1.获取父级节点
        var father = document.querySelector('ul');
        console.log(father.childNodes);//长度为7,因为换行为文本节点
    script>
body>

注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等;如果需要其中的元素节点,需要专门处理(根据节点type值判断是否为元素节点),所以一般不使用子级节点

7.3.2.2 node.children

只是一个只读属性,返回所有的自元素节点。它只返回所有的元素节点,其余节点不会返回(虽然不是标准但是得到各个浏览器支持)

<body>
    <ul>
        <li>li>
        <li>li>
        <li>li>
    ul>
    <script>
        //1.获取父级节点
        var father = document.querySelector('ul');
        console.log(father.children);//长度为7,因为换行为文本节点
    script>
body>
7.3.2.3 获取首尾子元素

firstChild/lastChild:一般会获取文本节点,但这并不满意

<body>
    <ul>
        <li>li>
        <li>li>
        <li>li>
    ul>
    <script>
        //1.获取父级节点
        var father = document.querySelector('ul');
        console.log(father.firstChild); //text
        console.log(father.lastChild);  //text
    script>
body>
7.3.2.4 获取首尾子元素

node.firstElementChild()/node.lastElementChild():这个可以解决指定获取首位 子元素 而不是其他文本元素,然而可能会需要高版本浏览器支持

<body>
    <ul>
        <li>li>
        <li>li>
        <li>li>
    ul>
    <script>
        //1.获取父级节点
        var father = document.querySelector('ul');
        console.log(father.firstElementChild);
        console.log(father.lastElementChild);
    script>
body>

总结:在实际开发中会使用数组的方式来获取最后一个或者第一个元素

7.3.2.5下拉菜单的实现

核心思路就是鼠标经过时显示鼠标移出后隐藏

    <script>
            // 1. 获取元素
            var nav = document.querySelector('.nav');
            var lis = nav.children; // 得到4个小li
            // 2.循环注册事件
            for (var i = 0; i < lis.length; i++) {
      
                //鼠标移入显示
                lis[i].onmouseover = function() {
      
                    this.children[1].style.display = 'block';
                }
                //鼠标移出隐藏
                lis[i].onmouseout = function() {
      
                    this.children[1].style.display = 'none';
                }
            }
        script>

7.3.3 兄弟节点

node.nextSibling:返回当前元素的下一个兄弟节点/node.previousSiling:返回当前元素的上一个兄弟节点(缺点就是获得的可能是文本节点)

<body>
    <span>span>
    <span id="mid">span>
    <span>span>
    <script type="text/javascript">
        var mid = document.getElementById('mid');
        console.log(mid.nextSibling);     // text
        console.log(mid.previousSibling)    //text
    script>
body>

所以,会有特殊的获取(指定获取元素,但是有兼容性问题):

<body>
    <span>span>
    <span id="mid">span>
    <span>span>
    <script type="text/javascript">
        var mid = document.getElementById('mid');
        console.log(mid.nextElementSibling);
        console.log(mid.previousElementSibling);
    script>
body>

7.4 创建节点

document.createElement(‘tagName’):创建指定的HTML元素,因为这些元素原先不存在,根据需求动态生成,所以也称为动态创建元素节点

7.5 添加节点

7.5.1node.appendChild()

将一个节点添加到指定父节点的子节点列表末尾,可以理解为数组的push方法

<body>
    <ul>ul>
    <script type="text/javascript">
        //创建一个节点
        var li = document.createElement('li');
        //获取父节点并添加新节点
        var ul = document.querySelector('ul');
        ul.appendChild(li);
    script>
body>

7.5.2node.insertBefore()

参数为两个,一个是插入的子元素,另一个是指定元素前面

<body>
    <ul>
        <li>213li>
    ul>
    <script type="text/javascript">
        //创建一个节点
        var li = document.createElement('li');
        //获取父节点
        var ul = document.querySelector('ul');
        //指定位置添加新元素
        ul.insertBefore(li,ul.children[0]);
    script>
body>

7.5.3 简单的留言板案例

<body>
    <style type="text/css">
        li{
      
            background-color:pink;
        }
    style>
    <textarea>textarea><br/>
    <button>留言button><br/>
    <ul>ul>
    <script type="text/javascript">
        //获取动态添加子元素的父节点
        var ul = document.querySelector('ul');
        //获取按钮操作
        var btn = document.querySelector('button');
        //获取文本域对象
        var textarea = document.querySelector('textarea');
        //注册事件
        btn.onclick = function(){
      
            //判断文本框的值是否为空,如果为空就不用创建新标签
            if(textarea.value == ''){
      
                return false;
            }else{
      
                //获取文本框中的值
                var value = textarea.value;
                //(1)创建节点
                var li = document.createElement('li');
                //获取文本框的值并赋予li标签
                li.innerHTML = textarea.value;
                //(2)添加节点(注意不要加上引号)
               	// ul.appendChild(li);
                //最新的留言应该在上面,所以使用这个添加元素的方法
                ul.insertBefore(li,ul.children[0]);
                textarea.value = '';
            }
        }
    script>
body>

7.6 删除节点

node.removeChile(child[id]):删除父节点中的指定子节点

<body>
    <ul>
        <li>熊大li>
        <li>熊二li>
        <li>吉吉li>
    ul>
    <button>删除button>
    <script type="text/javascript">
        //获取删除按钮
        var btn = document.querySelector('button');
        //删除节点
        var ul = document.querySelector('ul');
        //绑定事件
        btn.onclick = function(){
      
           //判断:如果子标签已经删除干净,则此按钮失效
            if(ul.children.length == 0){
      
                	//this代表的当前对象也就是 btn
					this.disabled = true;
				}
            else{
      
					ul.removeChild(ul.children[0]);
				}
        }
    script>
body>

7.6.1 删除留言案例

<body>
    <style type="text/css">
        li{
      
            background-color:pink;
        }
    style>
    <textarea>textarea><br/>
    <button>留言button><br/>
    <ul>ul>
    <script type="text/javascript">
        //获取动态添加子元素的父节点
        var ul = document.querySelector('ul');
        //获取按钮操作
        var btn = document.querySelector('button');
        //获取文本域对象
        var textarea = document.querySelector('textarea');
        //注册事件
        btn.onclick = function(){
      
            //判断文本框的值是否为空,如果为空就不用创建新标签
            if(textarea.value == ''){
      
                return false;
            }else{
      
                //获取文本框中的值
                var value = textarea.value;
                //(1)创建节点
                var li = document.createElement('li');
                //获取文本框的值并赋予li(还添加了一个链接标签)
                li.innerHTML = textarea.value + "删除留言";
                //(2)添加节点
                ul.insertBefore(li,ul.children[0]);
                textarea.value = '';
                //(3)删除元素,获取所有的删除链接
                var as = document.querySelectorAll('a');
                //为每一个链接添加点击事件
                for(var i = 0;i<as.length;i++){
      
                    as[i].onclick = function(){
      
                        //删除的语法是父亲里面的孩子
                        //删除的节点是li,语法格式就是删除ul的子元素,参数为当前对象a的父元素,有点绕呵
                        ul.removeChild(this.parentNode);
                    }
                }
            }
        }
    script>
body>

7.7 复制节点

node.cloneNode():复制节点,也叫克隆节点;该方法会返回调用该方法的节点的一个副本

注意:如果括号内参数为空或为false,则是浅拷贝,即只拷贝节点本身而不会克隆内部子节点

<body>
    <ul>
        <li>1li>
        <li>2li>
        <li>3li>
    ul>
    <script type="text/javascript">
        //获取父节点
        var ul = document.querySelector('ul');
        //浅拷贝,只拷贝节点内部子节点不会拷贝
        var li = ul.children[0].cloneNode();
        //拷贝内容
        var lii = ul.children[0].cloneNode(true);
        ul.appendChild(li);
        ul.appendChild(lii);
    script>
body>

7.7.1 动态生成表格

<body>
    <table border="1" align="center" width="600px">
        <thead>
            <tr>
                <td>姓名td>
                <td>科目td>
                <td>成绩td>
                <td>操作td>
            tr>
        thead>
        <tbody>tbody>
    table>
    <script type="text/javascript">
        var datas = [{
      
            name:'张三',
            subject:'java',
            score:100
        },{
      
            name:'张四',
            subject:'java',
            score:10
        },{
      
            name:'张五',
            subject:'java',
            score:90
        }];
        //1.数组中有多少个对象,创建多少行
        var tbody = document.querySelector('tbody');
        for(var i =0;i<datas.length;i++){
      
            var tr = document.createElement('tr');
            tbody.appendChild(tr);
            //2.在行内创建列,外层for循环控制行数,内层for循环控制列数
            //多少了取决于对象里面的属性个数
            for(var k in datas[i]){
      
                var td = document.createElement('td');
                //将属性值赋予td标签
                //datas[i]相当于obj ,再加上[k]就是属性值
                /*
						for(var k in obj){
							console.log(obj[k]);
						}
					*/
                td.innerHTML = datas[i][k];
                tr.appendChild(td);
            }
            //3.创建删除单元格列
            var td = document.createElement('td');
            td.innerHTML = "删除";
            tr.appendChild(td);
        }
        //4.绑定删除时间
        var as = document.querySelectorAll('a');
        for(var i =0;i<as.length;i++){
      
            as[i].onclick = function(){
      
                tbody.removeChild(this.parentNode.parentNode);
            }
        }
    script>
body>

7.8 三种动态创建元素区别

  1. document.write()
  2. element.innerHTML
  3. document.creatElement()

7.8.1 document.write

<body>
    <button>点击button>
    <p>123p>
    <script type="text/javascript">
        document.write('
'
);
script> body>

区别:直接将内容写入页面的内容流,但是文档流执行完毕,则它将会导致页面全部重绘(重新创建新的HTML页面)

7.8.2 innerHTML与creatElement效率

  1. innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
  2. innerHTML创建多个元素效率更高(不适用拼接字符串,采用数组形式拼接),结构稍微复杂
  3. creatElement创建多个元素效率稍微低一点点,但是结构更清晰

总结:不同的浏览器,innerHTML效率要比creatElement高

8.DOM重点核心

关于DOM操作,我们主要是对元素的操作。操作有创建、增、删、改、查、属性操作、事件操作

主要用作复习即可

8.1 创建

  • document.write
  • innerHTML
  • createElement

8.2 增

  • appendChile
  • insertBefore

8.3 删除

  • removeChild

8.4 改

主要修稿DOM的元素属性,DOM元素的内容、属性、表单的值等

  1. 修改元素属性:src、href、title等
  2. 修改普通元素内容:innerHTML、innerText
  3. 修改表单元素:value、type、disable等
  4. 修改元素样式:style、className

8.5 查

主要查询DOM元素

  1. DOM提供的远古方法:getId等
  2. H5提供新方法:querySelector等
  3. 利用节点操作获取元素:父、子、兄

8.6 属性操作

主要针对于自定义属性:setAttribute/getAttribute/removeAttribute

8.7 事件操作

给元素注册事件等操作

八、事件高级

1.注册事件

给元素添加事件,成为注册事件或者绑定事件

事件注册有两种方式:传统方式和方法监听注册方式

1.1 传统注册事件

  • 利用on开头的事件
  • 特点:注册事件的唯一性
  • 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数

1.2 方法监听注册方式

  • W3C标准推荐方式
  • 特点:同一个元素同一个事件可以注册多个监听器
  • 按照注册顺序依次执行

1.3 addEventListener事件监听

eventTarget.addEventListener(type,listener,useCapture):会有兼容性问题

  1. type:事件类型字符串,例如click等不用加上on
  2. listener:事件处理函数,事件发生时会调用该监听函数
  3. useCapture:可选参数,是一个布尔值,默认值为false
<body>
    <button>点击button>
    <script type="text/javascript">
        var btn = document.querySelector('button');
        //1.里面的事件类型必须是字符串,必定加上引号且不能以on开头
        //2.同一个元素、同一个事件可以添加多个监听器
        btn.addEventListener('click',function(){
      
            alert('11');
        })
        btn.addEventListener('click',function(){
      
            alert('22');
        })
    script>
body>

2.删除事件

也称为解绑事件

2.1 传统删除事件方式

<body>
    <style>
        div{
      
            background-color: red;
            width: 600px;
            margin-bottom: 10px;
        }
    style>
    <div>1div>
    <div>2div>
    <div>3div>
    <script type="text/javascript">
        var divs = document.querySelectorAll('div');
        divs[0].onclick =function(){
      
            alert("11");
            //传统方式就是将此对象的事件赋值为空
            this.onclick = null;
        }
    script>
body>

2.2 方法监听注册方式删除事件

此方式在注册事件的时候不能使用匿名函数的方式

<script type="text/javascript">
    var divs = document.querySelectorAll('div');
    //注意:方法名后面并没有小括号
    divs[0].addEventListener('click',fn);
    function fn(){
      
        alert('11');
        //参数:1 表示要移除的事件名称 2 表示要移除的处理程序名称
        divs[0].removeEventListener('click',fn);
    }
script>

3 DOM事件流

事件流描述的是从页面中接受事件的顺序

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

DOM事件流分为3个阶段:

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程

事件捕获:由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收过程

捕获阶段:addEventListener第三个参数为true,点击son事件会从father事件触发然后触发son事件(由上至下)

冒泡阶段:addEventListener第三个阶段是false或者省略,点击son事件会从son事件触发然后触发father事件(由下至上)

注意:

  • JS代码中只能执行捕获或者冒泡其中的一个阶段
  • onclick和attachEvent只能得到冒泡阶段
  • 在实际开发中,捕获事件很少,更关注事件冒泡
  • 有些事件是没有冒泡的:比如失去、获得焦点、onmouseenter、onmouseleave

4 事件对象

事件对象就是写到我们侦听函数的小括号里面,可以当做形参来对待且由系统自动创建不用传递参数

事件对象是事件一系列相关数据的集合,与事件相关,例如鼠标点击事件对象里面包含了鼠标相关信息(坐标、绑定事件的对象等)

事件没有被触发或者没有事件则不会有事件对象,先有事件再有事件对象

具有兼容性问题: e=e||window.event 解决

<body>
    <div>1div>
    <script type="text/javascript">
        var div = document.querySelector('div');
        //事件对象的名字可以缩写、可以随意写
        div.addEventListener('click',function(event){
      
            console.log(event);
        })
    script>
body>

4.1 常用属性与方法

属性与方法 说明
e.target 返回触发事件的对象,标准
e.srcElement 返回触发事件的对象,非标准
e.type 返回事件的类型,比如click等
e.canceBubble 该属性阻止冒泡,非标准
e.stopPropagation() 阻止冒泡,标准
e.returnValue 该属性阻止默认事件,非标准,例如不让链接跳转
e.preventDefault() 该方法组织默认事件,标准,例如不让连接 跳转

4.2 e.target

e.target与this的区别:点击了哪个元素触发了事件,target返回那个元素;哪个元素绑定了点击事件this返回那个元素

<body>
    <ul>
        <li>1li>
        <li>1li>
        <li>1li>
    ul>
    <script type="text/javascript">
        //为ul绑定了点击事件
        var ul = document.querySelector('ul');
        ul.addEventListener('click',function(e){
      
            //返回的是触发事件的元素,li
            console.log(e.target);
            //返回的是绑定事件的元素,ul
            console.log(this)
        })
    script>
body>

兼容性问题解决:e.target || e.srcElement

4.3 e.type

<body>
    <ul>
        <li>1li>
    ul>
    <script type="text/javascript">
        //为ul绑定了点击事件
        var ul = document.querySelector('ul');
        ul.addEventListener('click',function(e){
      
            //返回的是事件类型,可以使鼠标点击、经过等各种事件,返回的事件类型不带on
            console.log(e.type);
        })
    script>
body>

4.4 阻止默认行为

<body>
    <a href="www.baidu.com">百度a>
    <script type="text/javascript">
        //组织默认事件(页面跳转),DOM标准语法
        //有兼容性问题
        var a = document.querySelector('a');
        a.addEventListener('click',function(e){
      
            e.preventDefault();
        }) 
        //这种方式没有兼容性问题
        a.addEventListener('click',function(e){
      
            //用传统的方式可以,绑定注册事件方式失败
            return false;
        })
    script>
body>

4.5 阻止冒泡

标准写法:利用事件对象里面的 stopPropagation()方法

<body>
    <div id="father">
        <div id="son">
            123
        div>
    div>
    <script type="text/javascript">
        var fahter = document.querySelector('#father');
        var son = document.querySelector('#son');
        //父类元素对象添加方法
        //虽然子类禁止冒泡,但是如果点击父类元素,父类元素还会向上冒泡(如果document有事件则会触发)
        fahter.addEventListener('click',function(){
      
            alert('father');
        })
        //子类元素对象添加方法
        son.addEventListener('click',function(e){
      
            alert('son');
            //事件对象组织冒泡
            e.stopPropagation();
        },false)
    script>
body>

5.事件委托(代理、委派)

事件委托:也称为事件代理,在jQuery里面称为事件委派

事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点

事件委托的作用:只操作一个DOM,提高程序的性能

<body>
    <ul>
        <li>知否知否li>
        <li>知否知否li>
        <li>知否知否li>
    ul>
    <script type="text/javascript">
        var ul = document.querySelector('ul');
        ul.addEventListener('click',function(e){
      
            //利用冒泡点击子类父类弹出框
            //alert('应是绿肥红瘦');
            //点击某个框修改其颜色,需要添加事件对象
            var lis = ul.children;
            //增加排他思想
            for(var i = 0;i<lis.length;i++){
      
                lis[i].style.backgroundColor = '';
            }
            e.target.style.backgroundColor = 'pink';
        })
    script>
body>

6.常用鼠标事件

上面有,此处略过 , 以下两个鼠标事件了解即可

6.1 禁止鼠标右键菜单

contextmenu控制何时显示上下文菜单,主要用于开发人员取消默认的上下文菜单

<body>
    这是一段特殊的文字
    <script type="text/javascript">
        document.addEventListener('contextmenu',function(e){
      
            e.preventDefault();
        })
    script>
body>

6.2 禁止鼠标选中

<body>
    这是一段特殊的文字
    <script type="text/javascript">
        document.addEventListener('selectstart',function(e){
      
            e.preventDefault();
        })
    script>
body>

6.3 鼠标事件对象

现阶段主要是用鼠标事件对象(MouseEvent)和键盘事件对象(KeyboardEvent)

鼠标事件对象 说明
e.clientX 返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY 返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX 返回鼠标相对于文档页面的X坐标
e.pageY 返回鼠标相对于文档页面的Y坐标
e.screenX 返回鼠标相对于电脑屏幕的X坐标
e.screenY 返回鼠标相对于电脑屏幕的Y坐标
<body>
    <script type="text/javascript">
        document.addEventListener('click',function(e){
      
            //1.获取可视区域的鼠标坐标
            console.log(e.clientX);
            console.log(e.clientY);
            //2.获取距离页面区域的鼠标坐标
            console.log(e.pageX);
            console.log(e.pageY);
            //3.获取相对于屏幕的鼠标坐标
            console.log(e.screenX);
            console.log(e.screenY);
        })
    script>
body>

6.4 图片跟随鼠标移动

核心思路:获得鼠标移动的坐标并将其作为图片的坐标

<body>
    <style>
        img {
      
            position: absolute;
            width: 50px;
            height: 50px;
        }
    style>
    <img src="imgs/20201119.jpg"/>
    <script>
        var img = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {
      
            //图片大小为 50X50,鼠标位于图片中央则坐标应该各减去图片大小的一半即可
            var x =e.pageX -25;
            var y =e.pageY -25;
            img.style.left = x+'px';
            img.style.top = y+'px';
        });
    script>
body>

7.常用键盘事件

7.1 键盘事件

键盘事件 触发条件
onkeyup 某个按键被松开时触发
onkeydown 某个按键被按下时触发
onkeypress 某个按键按下时被触发,但是不识别功能键 ctrl、shift、箭头等

执行顺序:down -> press -> up

<script>
    document.addEventListener('keydown',function(){
      
        console.log('down 按下');
    })
    document.addEventListener('keypress',function(){
      
        console.log('press 按下');
    })
    document.addEventListener('keyup',function(){
      
        console.log('up 按下');
    })
script>

7.2 键盘事件对象

e.keyCode:返回ASCII码值,可以用来判断用户到底输入的是哪个键

<script>
    //keydown不会识别英文字母大小写,keypress识别英文字母大小写
    document.addEventListener('keydown',function(e){
      
        console.log(e.keyCode);
    })
    document.addEventListener('keypress',function(e){
      
        console.log(e.keyCode);
    })
script>

7.3 案例-模拟京东按键输入

用户在页面任何地方按下 S 键, 搜索框获得焦点

<body>
    <input type="text"/>
    <script>
        var input = document.querySelector('input');
        //这里使用up是做到只会获取焦点而不会在文本框显示用户输入的字母 S
        document.addEventListener('keyup',function(e){
      
            if(e.keyCode == 83){
      
                input.focus();
            }
        })
    script>
body>

7.4 案例-模拟京东查询快递单号

<body>
    
    <style type="text/css">
        div{
      
            font-size: 60px;
            color: red;
            background-color: aqua;
            width: 200px;
            height: 100px;
            display: none;
        }
    style>
    <div>div>
    <input type="text" placeholder="请输入你的快递单号"/>
    <script>
        var input = document.querySelector('input');
        var div = document.querySelector('div');
        input.addEventListener('keyup',function(e){
      
            //先判断用户输入是否为空
            //输入为空则不显示 div
            if(this.value == ''){
      
                div.style.display = 'none';
            }else{
      
                //输入不为空则显示盒子
                div.innerHTML = this.value;
                div.style.display = 'block';
            }
        })
        //失去焦点 隐藏 div
        input.addEventListener('blur',function(){
      
            div.style.display = 'none';
        })
        //获得焦点先判断文本框内容
        input.addEventListener('focus',function(){
      
            //获得焦点而文本框为空则不显示盒子
            //获得焦点而文本框不为空则显示盒子
            if(this.value != ''){
      
                div.style.display = 'block';
            }
        })
    script>
body>

九、BOM

1.BOM概述

BOM就是浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window

1.1 BOM的特点

BOM由一系列的对象构成,并且每个对象提供了很多属性与方法

  • 浏览器对象模型
  • 把浏览器当做对象来看待
  • BOM的顶级对象时window
  • BOM学习的是浏览器窗口交互的一些对象
  • BOM兼容性较差,没有统一标准

1.2 BOM的组成

BOM比DOM更大,包含了DOM

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vnEUvkFd-1607239291427)(img/image-20201129170700117.png)]

window对象时浏览器的顶级对象,它具有双重角色

  1. 它是JS访问浏览器窗口的一个接口
  2. 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性、方法
<body>
    <script>
        //a 是一个全局变量
        var a = 10;
        //完整的写法
        console.log(window.a);
        //定义函数
        function fn (){
      
            console.log('测试方法');
        }
        //调用函数完整写法:函数变成了window对象的方法
        window.fn();
        fn(); //这种也可以调用
    script>
body>

注意:window对象中有个特殊的属性名为 name(声明式最好不使用name属性)

2.window对象常见事件

2.1 窗口加载事件

window.onload是窗口(页面)加载事件,当文档内容加载完成后才会触发该事件(包括图像、脚本文件、CSS文件等),调用该函数

注意:

  1. 有了window.onload就可以吧JS代码写在页面的任何地方
  2. 该方式使用传统注册事件的方式,如果写了多个则以最后一个为准
  3. 使用注册监听事件的方法可以写多个(屁话一句)
  4. 但是如果图片过多,页面加载时间过长,交互效果就不会被实现,必然影响用户体验

document.addEventListener(‘DOMContentLoaded’,function(){}):具有兼容性问题,如果页面图片过多可以使用这个方法,此方法会在所有元素(标签)加载完毕以后被触发

<body>
    <script>
        window.onload=function(){
      
            alert('页面全部加载完毕后执行');
            var btn = document.querySelector('button');
            btn.addEventListener('click',function(){
      
                alert('按钮被点击');
            })
        }
        document.addEventListener('DOMContentLoaded',function(){
      
            alert('标签元素加载完毕后执行');
        })
    script>
    <button>点击button>
body>

2.2 调整窗口大小事件

window.onresize:窗口的像素值发生改变就会调用该方法

window.innerWidth/innerHeight:获取窗口的宽度与高度

<body>
    <style type="text/css">
        div{
      
            background-color: black;
            width:200px;
            height: 200px;
        }
    style>
    <div>div>
    <script>
        var div = document.querySelector('div');
        window.addEventListener('resize',function(){
      
            //这个属性是获得窗口的宽度像素值
            var width = window.innerWidth;
            console.log(width);
            if(width > 800){
      
                div.style.display = 'block';
            }else{
      
                div.style.display = 'none';
            }
        })
    script>
body>

3.定时器

window对象提供了两个方法:

  1. setTimeout()
  2. setInterval()

3.1 setTimeout()

setTimeout(调用函数,[延迟毫秒数]):设置一个定时器,该定时器到期后执行调用函数

<body>
    <script>
        //window可以省略掉,使用匿名函数的方式
        //可以将定时器函数赋予标识符用来区别
        var times1 = setTimeout(function(){
      
            console.log('两秒后执行')
        },2000);
        //可以不用匿名函数
        function fn(){
      
            console.log('非匿名函数')
        }
        var times2 = setTimeout(fn,5000);
    script>
body>

3.2 回调函数

window.setTimeout(调用函数,[毫秒数]):其中的调用函数就是回调函数(等待时间结束之后在回头调用这个函数称为回调函数)

传统注册事件也是回调函数

<body>
    <style type="text/css">
        img{
      
            width: 200px;
            height: 200px;
        }
    style>
    <img src="imgs/20201119.jpg"/>
    <script>
        var img = document.querySelector('img');
        //五秒钟后隐藏图片功能
        setTimeout(function(){
      
            img.style.display = 'none'
        },5000)
    script>
body>

3.3 清除定时器

window.clearTimeout(timeID):参数为定时器的标识符

<body>
    <button>点击停止button>
    <script>
        var btn = document.querySelector('button');
        //五秒钟后爆炸
        var time = setTimeout(function(){
      
            console.log('爆炸了')
        },5000)
        //添加按钮点击事件,按钮被点击定时器被清除
        btn.addEventListener('click',function(){
      
            //注册监听事件也是一个回调函数
            //window可以省略不写的
            window.clearTimeout(time);
            console.log('爆炸被终结')
        })
    script>
body>

3.4 setInterval()

与上方定时器用法规范基本相同,但是功能不同:此方法会按照时间间隔一直调用

<body>
    <script>
        //它会一直执行,每隔一秒执行一次
        setInterval(function(){
      
            console.log('执行成功')
        },2000)
    script>
body>

3.5 倒计时的时间

<body>
    <style type="text/css">
        div{
      
            width: 50px;
            height: 50px;
            background-color: pink;
            margin: 5px;
            display: block;
            float: left;
        }
    style>
    <div id='min'>1div>
    <div id="hour">2div>
    <div id="second">3div>
    <script>
        var min = document.querySelector('#min');
        var hour = document.querySelector('#hour');
        var second = document.querySelector('#second');
        var inpuTime =+new Date('1997-5-8 18:00:00'); //返回用户输入的时间毫秒数
		//在定时器启动之前先调用一次函数防止刷新页面时间数字不对劲
        countDown(inputTime);
        setInterval(countDown,1000);
        function countDown(){
      
            var nowTime=+new Date(); //返回当前毫秒数
            var times=(nowTime - inpuTime)/1000; //times是剩余时间秒数
            var h =parseInt(times/60/60%24); //小时
            hour.innerHTML = h;
            var m =parseInt(times/60%60); //分钟
            min.innerHTML = m;
            var s =parseInt(times%60); //秒
            second.innerHTML = s;
        }
    script>
body>

3.6 停止Interval定时器

window.clearInterval(intervalID)

<body>
    <button>开启定时器button>
    <button>关闭定时器button>
    <script>
        var btns = document.querySelectorAll('button');
        var time = null;
        btns[0].addEventListener('click',function(){
      
            //为定时器赋予一个标识符
            time = setInterval(function(){
      
                console.log('start.....')
            },1000)
        })
        btns[1].addEventListener('click',function(){
      
            clearInterval(time);
            console.log('over.....')
        })
    script>
body>

3.7 发送短信案例

<body>
    发送短信:<input  type="text"/>
    <button>发送验证码button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
      
            var time = 3;
            btn.disabled =true;
            var se = setInterval(function(){
      
                if(time ==0){
      
                    clearInterval(se);
                    btn.disabled = false;
                    time = 3;
                    btn.innerHTML = '发送验证码';
                }else{
      
                    btn.innerHTML = '剩余时间还有'+time+'秒';
                    time --;
                }
            },1000);	
        })
    script>
body>

4.JS执行队列

4.1 JS单线程

JS语言的一大特点就是单线程,也就是说同一时间只能做一件事

4.2 同步与异步

为解决JS单线程问题,H5提出了新标准Web Worker标准允许JS脚本创建多个线程。于是出现了同步与异步

同步:按照代码的顺序依次执行

异步:在做一件事的同时可以处理其他事情

<body>
    <script>
        //执行顺序为 1-3-2 说明JS实现了异步
        console.log('1')
        setInterval(function(){
      
            console.log('2');
        },2000)
        console.log('3');
    script>
body>

本质:代码流程执行顺序不同

4.2.1 小问题

回调函数的间隔时间为0秒,但是执行顺序还是 1 - 3 - 2,这就需要了解JS语言的执行机制

<body>
    <script>
        //执行顺序为 1-3-2
        console.log('1')
        setInterval(function(){
      
            console.log('2');
        },0)
        console.log('3');
    script>
body>

4.3 执行机制

JS执行时会将内存分为两个部分:执行栈(执行同步任务)任务队列(执行异步任务)

JS执行过程中会先执行同步任务(执行栈中的内容),同步任务执行结束后在执行异步任务(任务队列中的内容放到执行栈中执行)

一般而言,异步任务有三种:

  1. 普通事件
  2. 资源加载
  3. 定时器,包括 setTimeout、setInterval
  4. 回调函(也是异步任务)

执行顺序:

先运行执行栈中的任务,打印 1 ,2(如果点击事件没有触发),1秒钟后定时器任务放在了任务队列中,然后又转移到执行栈中运行打印 3

点击事件与定时器谁先打印根据时间来决定谁先放入任务队列中(即使执行栈已经空了系统还是会去任务队列中查看–>事件循环)

<body>
    <script>
        console.log('1');
        document.onclick = function(){
      
            console.log('click');
        }
        console.log('2');
        setTimeout(function(){
      
            console.log('3')
        },1000)
    script>
body>

由于主线程不断重复的获得新任务、执行任务、在获得新任务、在执行,这种机制被称为事件循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJxGMt2J-1607239291431)(img/image-20201130171034632.png)]

5.location对象

5.1 概述

window对象为我们提供了一个location属性用于获取设置窗体的URL,并可以用于解析URL,因为属性返回的是一个对象,所以我们也将这个属性成为location对象

5.2 location对象的属性

对象属性 返回值
location.href 获取或设置整个URL
location.host 返回主机域名
location.port 返回端口号,如果未写返回空字符串
location.pathname 返回路径
location.search 返回参数
location.hash 返回片段
<body>
    <button>点击button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
      
            //window可以省略,按钮点击返回当前页面URL值
            console.log(window.location.href);
            //点击跳转百度页面
            location.href = 'http://www.baidu.com';
        })
    script>
body>

5.3 自动跳转页面

<body>
    <div>div>
    <script>
        var div = document.querySelector('div');
        var time = 5;
        var times = setInterval(function(){
      
            if(time == 0){
      
                clearInterval(times);
                location.href = 'http://www.baidu.com';
            }else{
      
                div.innerHTML = '还有'+time+'秒跳转页面'
                time--;
            }
        },1000)
    script>
body>

5.4 获取URL参数

<body>
    <script>
        console.log(window.location.search);
        console.log(location.search)
    script>
body>

5.5 location对象的方法

方法 返回值
location.assign() 与href相同,可以跳转页面(也称为重定向)可以后退页面
location.replace() 替换当前页面,因为不记录历史,所以无法后退页面
location.reload() 重新加载页面
<body>
    <button>点击跳转button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
      
            //记录历史可以后退网页
            location.assign('http://www.baidu.com');
            //无记录不可以后退页面
            location.replace('http://www.baidu.com')
            //加上参数为强制刷新
            location.reload(true);
        })
    script>
body>

6.navigator对象

其中包含了有关浏览器的信息,它有很多属性。最常用的是userAgent,该属性可以返回客户机发送给服务器的user-agent头部值

可以判断用户使用手机还是用PC访问网页从而显示不同的页面布局

7.history对象

window对象提供的此对象可以与浏览器历史记录进行交互,该对象包含用户访问过的URL

对象方法 作用
back() 可以后退功能
forward() 前进功能
go(参数) 前进后退功能,参数为1前进1个页面,-1后退一个页面
<body>
    <button>点击button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
      
            history.back();
            history.forward();
            history.go(1);
        })
    script>
body>

注:此对象开发中不常用,OA办公系统会用到

十、PC端网页特效

1.元素偏移量offset系列

offset就是偏移量,使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等

  • 获得与带有定位的父元素位置之间的距离
  • 获得元素自身的大小
  • 注意:返回的值没有带单位

1.1 常用系列属性

属性 作用
element.offsetParent 返回该元素的父元素(带有定位),没有则返回body
element.offsetTop 返回该元素与父元素(带有定位)上方的偏移
element.offsetLeft 返回该元素与父元素(带有定位)左边框的偏移
element.offsetWidth 返回自身的宽度包括:padding、边框、内容区宽度
element.offsetHeight 返回自身的宽度包括:padding、边框、内容区高度
<body>
    <style type="text/css">
        .father{
      
            background-color: pink;
            position: absolute;/* 这里有定位设置 */
            width: 200px;
            height: 200px;
            margin: 100px;
        }
        .son{
      
            background-color: purple;
            position: absolute;
            width: 100px;
            height: 100px;
            margin: 100px;
        }
    style>
    <div class="father">
        <div class="son">div>
    div>
    <script>
        var son = document.querySelector('.son');
        console.log(son.offsetLeft);// 打印100,因为 son的div的margin为100
        console.log(son.offsetTop);
        console.log(son.offsetWidth); // 100
        console.log(son.offsetParent); //father
    script>
body>

1.2 offset与style却别

offset style
可以得到任意样式表中的样式值 只能获得行内样式表中的值
offset系列获得数值没有单位 style.width数组带有单位
offsetWidth包含padding+border+width style.width获得值不包括padding和border值
offsetWidth等属性只读不能赋值 style.width可读写属性
获取元素大小,offset合适 为元素更改值,需要用style改变

1.3 获取鼠标在盒子内坐标

鼠标在盒子内的坐标 = 鼠标距离页面的值 - 盒子距离页面的偏移量(值)

<body>
    <style type="text/css">
        div{
      
            background-color: pink;
            position: absolute;
            width: 300px;
            height: 300px;
            margin: 100px;
        }
    style>
    <div>div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('mousemove',function(e){
      
            //获取盒子具体body(页面)的偏移量
            var leftFather = div.offsetLeft;
            var topFather = div.offsetTop;
            //获取鼠标距离页面的距离,使用鼠标事件对象
            var x = e.pageX;
            var y = e.pageY;
            //计算鼠标距离盒子的距离
            var mouseX = x - leftFather;
            var mouseY = y - topFather;
            div.innerHTML = '鼠标距离盒子距离为:X:'+mouseX+'  Y:'+mouseY;
        })
    script>
body>

1.4 模拟框拖动

盒子移动过程中,鼠标在盒子里面的坐标是不会改变的。

盒子在页面中的位置 = 鼠标在页面中的位置(不断变化的) - 鼠标在盒子内的坐标(固定不变的)

<body>
    <style type="text/css">
        table{
      
            display: none;
        }
        td{
      
            background-color: pink;
            height: 50px;
            width: 100px;
        }
    style>
    <table border="1px" width="400px" height="200px">
        <thead>
            <tr>
                <td>td>
            tr>
        thead>
        <tbody>tbody>
    table>
    <button>显示button>
    <button>Xbutton>
    <script>
        //1.完成表格显示隐藏功能
        var table =document.querySelector('table');
        var btn = document.querySelector('button');
        var n = btn.nextElementSibling;
        btn.addEventListener('click',function(){
      
            table.style.display = 'block';
        })
        n.addEventListener('click',function(){
      
            table.style.display = 'none';
        })
        //2.完成拖拽功能
        //2.1只有鼠标在盒子头才能拖拽,其他位置不能拖拽
        var thead = document.querySelector('thead');
        //2.2鼠标按下瞬间获得鼠标在盒子内的坐标
        thead.addEventListener('mousedown',function(e){
      
            //获取了鼠标在盒子内的距离坐标
            var mX = e.pageX - table.offsetLeft;
            var mY = e.pageY - table.offsetTop;
            //2.3鼠标在按下的同时在页面中移动
            var mousemove = document.addEventListener('mousemove',fn);
            //单独拿出来是为了移除鼠标移动事件
            function fn(e){
      
                //获取页面与盒子之间的距离
                table.style.marginLeft = e.pageX - mX+'px';
                table.style.marginTop = e.pageY - mY+'px';
            }
            //2.4鼠标弹起移除鼠标移动事件
            document.addEventListener('mouseup',function(){
      
                document.removeEventListener('mousemove',fn);
            })
        })
    script>
body>

2.元素可视区client系列

通过client系列的相关属性来获取可视区的相关信息。通过client系列相关属性可以动态的得到该元素的边框大小、元素大小等

2.1 常用属性

系列属性 作用
element.clientTop 返回元素上边框的大小
element.clientLeft 返回元素做边框的大小
element.clientWidth 返回自身包括padding、内容区宽度,不含边框, 返回数值不带单位
element.clientHeight 返回自身包括padding、内容区高度,不含边框, 返回数值不带单位

clientWidth与offsetWidth最大的区别就是:clientWidth不包含边框

2.2 立即执行函数

普通的函数必须调用了才能执行,立即执行函数则不用调用就可以执行

立即执行函数最大的作用是独立创建了一个作用域,里面的变量都是局部变量

<body>
    <script>
        //第一种方式 ()() 第二个小括号相当于调用了并且可以传入参数
        (function fn1(a,b){
      
            console.log(a+b);
        })(1,2);
        //第二种方式 (function fn(){} ())
		//这两种都可以使匿名函数
        (function (a,b){
      
            console.log(a+b);
        } (3,4))
    script>
body>

3.元素滚动scroll系列

使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离

3.1 常用属性

属性 说明
element.scrollTop 返回被卷去的上侧距离,返回数值没有单位
element.scrollLeft 返回被卷去的左侧距离,返回数值没有单位
element.scrollWidth 返回自身实际宽度,不含边框,返回数值不带单位
element.scrollHeight 返回自身实际高度,不含边框,返回数值不带单位

scrollHeight与clientHeight区别:前者高度根据文本内容,后者高度固定(即使内容超过了盒子)

3.2 页面被卷曲的头部

若浏览器的高度宽度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上方被隐藏掉的高度就是称为被卷曲的头部。滚动条在滚动时会触发onscroll事件

<body>
    <style type="text/css">
        div{
      
            width: 100px;
            height: 100px;
            background-color: pink;
            border: 1px solid black;
            padding: 10px;
            
            overflow: scroll;
        }
    style>
    <div>
        我是内容
    div>
    <script>
        var div = document.querySelector('div');
        console.log(div.scrollHeight);
        //添加滚动事件
        div.addEventListener('scroll',function(){
      
            console.log(div.scrollTop);
        })
    script>
body>

3.3 仿淘宝回顶部栏

待续

4.三大系列总结

大小对比 作用
element.offsetWidth 返回自身的宽度包括:padding、边框、内容区宽度
element.clientWidth 返回自身包括padding、内容区宽度,不含边框, 返回数值不带单位
element.scrollWidth 返回自身实际宽度,不含边框,返回数值不带单位

这三个都可以返回自身的大小,主要作用:

  1. offset系列经常用于获取元素的位置 offsetLeft/offsetTop
  2. client系列经常用于获取元素大小 clientWidth/clientHeigth
  3. scroll经常用于获取滚动距离 scrollTOop/scrollLeft

5.mouseenter与mouseover区别

当鼠标移动到元素上时就会触发mouseenter事件,类似over事件,区别在于:

  • over经过自身盒子时触发,经过子盒子还会触发,enter则只会经过自身盒子触发
  • enter不会冒泡,而over会冒泡
  • 与enter相互配合的是mouseleave同样不会冒泡

6.动画函数封装

6.1 动画原理

核心原理:通过定时器setInterval()不断移动盒子

<body>
    <style type="text/css">
        div{
      
            
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    style>
    <div>	div>
    <script>
        //获取值使用offset,设置值用style
        var div = document.querySelector('div');
        var time = setInterval(function(){
      
            div.style.left = div.offsetLeft + 1 + 'px';
            if(div.offsetLeft >= 100 ){
      
                clearInterval(time);
            }
        },100);
    script>
body>

6.2 对象添加动画函数

使用变量来存放动画函数不太合适,将动画函数存放在对象的属性中,确保了动画的独立性不会冲突(大概意思)

<body>
    <style type="text/css">
        div{
      
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    style>
    <button>点击动画开始button>
    <div>div>
    <script>
        function animate(obj,target){
      
            //首行代码解决点击都次动画速度加快的BUG
            clearInterval(obj.time);
            //将定时器封装给obj对象的属性中
            obj.time = setInterval(function(){
      
                if(obj.offsetLeft >= target ){
      
                    clearInterval(obj.time);
                }
                obj.style.left = obj.offsetLeft + 1 + 'px';
            },100);
        }
        var div = document.querySelector('div');
        var btn = document.querySelector('button');
        //添加点击事件,点击之后动画开始
        btn.addEventListener('click',function(){
      
            animate(div,200);
        })
    script>
body>

6.3 缓存动画原理

缓动动画就是让元素运动速度有所变化,最常见的就是让速度慢慢停下来

缓存动画公式 = (目标值-现在的位置) / 10

<body>
    <style type="text/css">
        div{
      
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    style>
    <button>点击动画开始button>
    <div>div>
    <script>
        function animate(obj,target){
      
            //首行代码解决点击都次动画速度加快的BUG
            clearInterval(obj.time);
            //将定时器封装给obj对象的属性中
            obj.time = setInterval(function(){
      
                //步长值放在计时器里,小数字向上取整
                var step = Math.ceil((target-div.offsetLeft) / 10);
                if(obj.offsetLeft == target ){
      
                    clearInterval(obj.time);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            },15);
        }
        var div = document.querySelector('div');
        var btn = document.querySelector('button');
        //添加点击事件,点击之后动画开始
        btn.addEventListener('click',function(){
      
            animate(div,1000);
        })
    script>
body>

6.4 动画多个目标值移动

<body>
    <style type="text/css">
        div{
      
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    style>
    <button class="btn500">点击到500pxbutton>
    <button class="btn800">点击到800pxbutton>
    <div>div>
    <script>
        function animate(obj,target){
      
            obj.time = setInterval(function(){
      
                //因为这个算法所以可以做出前进、后退动作
                //精度问题进行取证,step小于0往小取整,大于0往大取整
                var step =(target-div.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if(obj.offsetLeft == target ){
      
                    clearInterval(obj.time);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            },15);
        }
        var div = document.querySelector('div');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        //添加点击事件,点击之后动画开始
        btn500.addEventListener('click',function(){
      
            animate(div,500);
        })
        btn800.addEventListener('click',function(){
      
            animate(div,800);
        })
    script>
body>

6.5 缓存动画添加回调函数

回调函数原理:函数作为一个参数传递到另一个函数内,另一个函数执行结束后在执行作为参数的函数

回调函数应该写在定时器结尾

<body>
    <style type="text/css">
        div{
      
            position: absolute;
            left: 0px;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    style>
    <button class="btn500">点击到500pxbutton>
    <button class="btn800">点击到800pxbutton>
    <div>div>
    <script>
        //第三个参数为回调函数
        //callBack = function(){}
        function animate(obj,target,callBack){
      
            clearInterval(obj.time);
            obj.time = setInterval(function(){
      
                var step =(target-div.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if(obj.offsetLeft == target ){
      
                    clearInterval(obj.time);
                    //动画结束后才调用函数
                    //判断函数是否存在,存在即调用
                    if(callBack){
      
                        callBack();
                    }
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            },15);
        }
        var div = document.querySelector('div');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        //添加点击事件,点击之后动画开始
        btn500.addEventListener('click',function(){
      
            //两种传递函数的方式,测试都可以
            animate(div,500,fn)
        });
        function fn(){
      
            div.style.backgroundColor = 'red';
        }
        btn800.addEventListener('click',function(){
      
            animate(div,800,function(){
      
                div.style.backgroundColor = 'pink';
            });
        })
    script>
body>

十一、本地存储

数据存储在用户浏览器中,设置、读取方便、刷新页面不会丢失数据且存储量大

1.window.sessionStorage

生命周期为关闭浏览器,在同一个页面下数据共享,存储数据按照键值对的形式

存储数据:sessionStorage.setItem(key,value)

存取数据:sessionStorage.getItem(key)

删除数据:sessionStorage.removeItem(key)

删除所有数据:sessionStorage.clear()

<body>
    <input  type="text"/>
    <button>添加数据button>
    <button class="del">删除数据button>
    <button class="get">获取数据button>
    <button class="delAll">删除所有button>
    <script type="text/javascript">
        //获取元素对象
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var del = document.querySelector('.del');
        var get = document.querySelector('.get');
        var delAll =document.querySelector('.delAll');
        //添加数据
        btn.addEventListener('click',function(){
      
            var val = input.value;
            sessionStorage.setItem('uname',val);
        })
        //删除指定单条数据
        del.addEventListener('click',function(){
      
            sessionStorage.removeItem('uname');
        })
        //获取数据
        get.addEventListener('click',function(){
      
            console.log(sessionStorage.getItem('uname'));
        })
        //清除所有数据
        delAll.addEventListener('click',function(){
      
            sessionStorage.clear();
        })
    script>
body>

2.window.localStorage

存储的数据永久生效,关闭页面后也会生效,只有使用了clear、remove才会删除数据

存放在浏览器中,同一个浏览器的其他页面也可以获得数据

与sessionStorage语法相同

<body>
    <input type="text">
    <button class="set">存储数据button>
    <button class="get">获取数据button>
    <button class="remove">删除数据button>
    <button class="del">清空所有数据button>
    <script>
        var ipt = document.querySelector('input');
        var set = document.querySelector('.set');
        var get = document.querySelector('.get');
        var remove = document.querySelector('.remove');
        var del = document.querySelector('.del');
        set.addEventListener('click', function() {
      
            var val = ipt.value;
            localStorage.setItem('username', val);
        })
        get.addEventListener('click', function() {
      
            console.log(localStorage.getItem('username'));

        })
        remove.addEventListener('click', function() {
      
            localStorage.removeItem('username');

        })
        del.addEventListener('click', function() {
      
            localStorage.clear();

        })
    script>
body>

3.实训记住用户名

<body>
    <input type="text" id="username"> <input type="checkbox" name="" id="remember"> 记住用户名
    <script>
        var username = document.querySelector('#username');
        var remember = document.querySelector('#remember');
        //首先判断本地存储中是否存储用户名,如果有则直接显示否则则不显示
        if (localStorage.getItem('username')) {
      
            username.value = localStorage.getItem('username');
            remember.checked = true;
        }
        //复选框为true,则获取用户名并存储在本地,若为false则移除用户名
        remember.addEventListener('change', function() {
      
            if (this.checked) {
      
                localStorage.setItem('username', username.value)
            } else {
      
                localStorage.removeItem('username');
            }
        })
    script>
body>

你可能感兴趣的:(javascript)