【前端】【JavaScript】基础知识

文章目录

JavaScript 基础

一. 初识 JavaScript

🔰JavaScript是一种运行在客户端的脚本语言;
🔰脚本语言:不需要编译,运行过程中由js解释器逐行来进行解释并执行;

(一) HTML/CSS/JS 的关系

🔰HTML决定网页结构和内容,相当于看到什么
🔰CSS决定网页呈现给用户的模样,相当于给人穿衣服
🔰JS 实现业务逻辑和页面控制,相当于人的各种动作


(二) 浏览器执行 JS 简介

🔰浏览器分成两部分:渲染引擎和 JS 引擎
🔰渲染引擎:用来解析HTML 与CSS,俗称内核;
🔰JS 引擎:也称之为JS解释器。用来读取网页中的JavaScript 代码,对其处理后运行;
🔰JS引擎执行代码时逐行解释每一句源码,然后由计算机去执行;


(四) JS 的组成

🔰JavaScript由ECMAScript(JavaScript 语法),DOM(页面文档对象类型),BOM(浏览器对象类型)等三部分组成;
🔰ECMAScript:规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
🔰DOM:通过DOM提供的接口可以对页面上的各种元素进行操作(大小,位置,颜色等)
🔰BOM:是指浏览器对象模型,它提供了独立于内容的可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框,控制浏览器跳转,获取分辨率等。


(五) JS 书写位置

🔰有3中书写位置,分别为行内,内嵌和外内部;

	<!-- 2.内嵌式的JS -->
    <script>
        alert('沙漠骆驼')
    </script>
    <!-- 3. 外部js ,外部写js,然后引入 -->
    <script src="my.js"></script>
    <!--my.js内代码:alert('我是个学生')-->
</head>
<body>
    <!-- 1.行内式的js  直接写到元素的内部 -->
    <input type="button" value="唐伯虎" onclick="alert('秋香姐')">
</body>


二. JavaScript 常规函数

🔰为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:

方法说明
alert(msg)浏览器弹出警示框
confirm(msg)浏览器弹出确认框
console.log(msg)浏览器控制台打印输出信息
prompt(into)浏览器弹出输入框,用户可以输入
document.write()向 HTML 文档中写入 HTML 或者 JavaScript 代码
prompt('请输入你的年龄')
alert('计算结果是')
console.log('我是程序员')

// 打印我们返回的元素对象,更好的查看里面的属性和方法
console.dir(time); 
函数解析
eval(2 * 11 + 3 / 4)对括号内的表达式进行计算,并返回结果
isNaN(a)对变量进行测试其是否为数字,是数字返回false,不是返回true
parseFloat(“4 number”)将字符串内的数字转换成浮点数字,若遇到非数字字符,将停止转换
parseInt(“A12”, 16)将字符串内的数字转换成整数数字,可设置转换成几进制数字


三. JavaScript的注释

单行注释

<script>
    // 这是注释内容
    console.log("Hello,World!");
</script>

多行注释

<script>
    /**
     * 这是注释内容
     */
    console.log("Hello,World!");
</script>


三. 变量

🔰本质:变量是程序在内存中申请的一块用来存放数据的空间。

(一) 变量的使用

🔰变量在使用时分两步:1)声明变量;2)赋值

  1. 声明变量
    var age; // 声明一个名称为age的变量
    📌var 是一个JS关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管。
    📌age是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间。

  2. 赋值
    age = 18; // 给age 这个变量赋值为10

🔰变量初始化
var age = 18; // 声明变量的同时赋值为18


(二) 变量语法扩展

🔰同时声明多个变量时,只需要写一个var,多个变量名之间使用英文逗号隔开;
var age = 10, name = 'aili', sex = 2;


(三) 变量命名规范

🔰有字母,数字,下划线,美元符号组成;
🔰严格区分大小写;
🔰不能以数字开头;
🔰不能时关键字,保留字;
🔰变量名必须有意义;
🔰遵守驼峰命名法,首字母小写,后面的单词的首字母需要大写;



四. 数据类型

🔰JavaScript 是-种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
var age = 10; // 这是一个数字型
var areYourk = '是的'; // 这是一个字符串
🔰在代码运行时,变量的数据类型是由JS引擎根据=右边变量值的数据类型来判断的,运行完毕之后.变量就确定了数据类型型。


🔰JS把数据类型分为两类:

  1. 简单数据类型(Number, String, Boolean, Undefined, Null);
  2. 复杂数据类型(object);

(一) 简单数据类型

简单数据类型说明默认值
Number数字,包含整型,浮点型值,如21,0.210
Boolean布尔值类,如true,false,等价于1和0false
String字符串,如“张三”,注意在JS里面,字符串都带引号“”
Undefined未定义的值,var a:声明了变量a,但是没有给值,此时 a = undefinedundefined
Null空值,var a = null; 声明了变量a, 为空值null

1. Number

其他进制

🔰在JS中八进制前面加0, 十六进制前面加0x;
var num1 = 07; // 对应十进制的7
var num2 = 0xA; // 对应十进制的10

特殊的数字:

  • Infinity:正无穷
  • -Infinity:负无穷
  • NaN:非法数字(Not A Number)

isNaN()

🔰用来判断一个变量是否为非数字的类型;是数字返回false;
var ss = isNaN('age');

2. String

🔰字符串型可以是引号中的任意文本,其语法为双引号""单引号''


🔰通过字符串的length属性可以获取整个字符串的长度。
var number = '123456789';
alter(number.length); // 显示 11


🔰多个字符串之间用 + 进行拼接,字符串 + 任何类型 = 拼接后的新字符串数字相加,字符相连
alert('老师今年' + age + '岁');

3. 获取检测变量的数据类型

🔰typeof 可用来获取检测变量的数据类型;
alert(typeof 12); // number

转义符含义转义符含义
\n换行\\斜杠
\t制表\’单引号
\b空格\"双引号
\r回车

4. 数据类型转换

转换为字符串

方式说明案例
toString()转成字符串var num = 1;
alert(num.toString());
String()强制转换转成字符串var num = 1;
alert(String(num));
加号拼接字符串和字符串拼接的结果都是字符串var num = 1;
alert(num + "我是字符串");

转换为数字型

方式说明案例
parseInt(string) 函数将 string 类型转换成整数数值型parseInt('78')
parseFloat(string) 函数将 string 类型转换成浮点数数值型parseFloat('78.3')
Number() 强制转换函数将 stirng 类型转换为数值型Number('12')
js 隐式转换(- * /)利用算数运算,隐式转换为数值型'12'-0

转换为布尔型

方式说明案例
Boolean() 函数其他类型转换成布尔值Boolean('true')

🔰代表空、否定的值会被转换为false , 如"、0、 NaN、null. undefined

console. log (Boolean('')); // false
console. log (Boolean(0)); // false
console. log (Boolean(NaN)); // false
console. log (Boolean (null)); // false
console. log (Boolean (unde fined)); // false
conso1e. log (Boolean('小白)); // true
console. log (Boolean(12)); // true

5. 算术运算符

运算符描述运算符描述
+加法-减法
*乘法/除法
%取模(求余数)
++自增- -自减

6. 逻辑运算符

运算符描述
&&and (与)
||or (或)
not (非)

7. 比较运算符

  • 使用 == 来做相等运算
    • 当使用==来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较
  • 使用 != 来做不相等运算
    • 不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false,不相等也会对变量进行自动的类型转换,如果转换后相等它也会返回false
  • 使用 === 来做全等运算
    • 用来判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回false
  • 使用 !== 来做不全等运算
    • 用来判断两个值是否不全等,它和不等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回true

(二) 引用数据类型

Object(对象)、Array(数组)、Function(函数)



五. 流程控制

🔰流程控制主要有三种结构,分别是顺序结构分支结构循环结构,这三种结构代表三种代码执行的顺序。
🔰顺序结构程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
🔰分支结构执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程) , 从而得到不同的结果。

(一) 分支结构

1. if 语句

if(条件表达式1) {
	语句1} else if(条件表达式2) {
	语句2}else {
	// 上述条件都不成立,执行此处代码
} 

2. 三元表达式

🔰条件表达式 ? 表达式1 : 表达式2
🔰如果条件表达式结果为真,则返回表达式1的值;如果条件表达式结果为假,则返回表达式2的值;

3. switch 语句

switch(表达式) {
	case value1:
		// 表达式 等于 value1 时要执行的代码
		break;\
	case value2:
		// 表达式 等于 value2 时要执行的代码
		break;
	default:
		// 表达式 不等于任何一个 value 时要执行
}

(二) 循环结构

1. for 循环

for(初始化变量; 条件表达式; 操作表达式) {
	// 循环体
}

🔰初始化变量就是用var声明的一个普通变量,通常用于 作为计数器使用
🔰条件表达式就是用来决定每一次循环是 否继续执行就是终止的条件
🔰操作表达式是每次循环最后执行的代码经常用于我们计数器变量进行更新(递增或者递减)

2. while 循环

while(条件表达式) {
	// 循环体代码
}

🔰执行思路:

  1. 先执行条件表达式,如果为true,则执行循环体代码;如果为false,则退出循环,执行后面的代码;
  2. 执行循环体代码;
  3. 循环体代码执行完毕后,程序会继续判断执行条件表达式,如果条件仍为true,则会继续执行循环体,直到循环条件为false时,整个循环过程才会结束。

3. do while 循环

do {
	// 循环体代码
} while(条件表达式);

🔰执行思路:

  1. 先执行一次循环体代码;
  2. 再执行条件表达式,如果结果为true ,则继续执行循环体代码;如果为false,则退出循环,继续执行后面代码。
    🔰注意:先再执行循环体,再判断,我们会发现d…while循环语句至少会执行一次循环体代码。

4. continue break

🔰continue关键字用于立即跳出本次循环,继续下一次循环(本次循环体中continue之后的代码就会少执行一次)
🔰break关键字用于立即跳出整个循环(循环结束)。



六. 函数

🔰函数在使用时分为两步:声明函数,调用函数;

(一) 声明函数

// 1. 利用函数关键字自定义函数(命名函数)
function 函数名(形参1, 形参2) {
	// 函数体代码
	return 需要返回的结果;
}

function cook(aru) {
	console.log(aru);
	return 666;
}

// 2. 函数表达式(匿名函数)
// var 变量名 = function() {}
var fun  = function(aru) {
	console.log(aru);
}
fun('pink老师');
// fun 是变量名,不是函数名

🔰function是声明函数的关键字,必须小写;


(二) 调用函数

// 调用函数
函数名(实参1, 实参2); // 通过调用函数名来执行函数体代码

cook('酸辣土豆丝');
var ss = cook('酸辣土豆丝'); // 获取返回值结果

🔰我们的函数如果有return,则返回的是return 后面的值;如果函数没有return ,则返回undef ined。


(三) arguments 的使用

🔰当我们不确定有多少个参数传递的时候,可以使用 arguments 来获取实参的值;
🔰只有函数才有 arguments 对象,而且每个函数都内置好了arguments 对象,arguments 对象中存储了传递的所有实参

function cook() {
	console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1, 2, 3]
	console.log(arguments.length); // 3
	console.log(arguments[1]); // 2

	// 我们可以按照数组的方式遍历 arguments
	for (let i = 0; i < arguments.length; i++) {
		console.log(arguments[i]);
	}
}
cook(1, 2, 3);

🔰伪数组,并不是真正意义上的数组;

  1. 具有数组的 length 属性
  2. 按照索引的方式进行存储的;
  3. 他没有真正数组的一些方法,pop() push() 等;


七. 作用域

🔰JS作用域:就是代码名字(变量) 在某个范围内起作用和效果;
🔰目的是为了提高程序的可靠性,更重要的是减少命名冲突;
🔰全局作用域:整个 script标签或者是一个单独的js文件。
🔰局部作用域:在函数内部就是局部作用域,这个代码的名字只是在函数内部起到效 果和作用。

(一) 全局变量

🔰在全局作用域下声明的变量叫做全局变量 (在函数外部定义的变量);

  1. 全局变量在代码的任何位置都可以使用;
  2. 在全局作用域下 var 声明的变量,是全局变量;
  3. 特殊情况下,在函数内不适用 var 声明的变量也是全局变量 (不建议使用) ;

(二) 局部变量

🔰在局部作用域下声明的变量叫做局部变量 (在函数内部定义的变量);

  1. 局部变量只能在该函数内部使用;
  2. 在函数内部 var 声明的变量,是局部变量;
  3. 函数的形参实际上就是局部变量;


八. JS 预解析

🔰JS引擎运行 js 分两步:预解析 代码运行

  1. 预解析:JS引擎会把 js 里面所有的 var ,还有 function 提升到当前作用域的最前面;
  2. 代码执行:按照代码书写顺序从上往下执行
    🔰预解析分为:变量解析(变量提升) 和 函数预解析(函数提升);
  3. 变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作;
  4. 函数提升:就是把所有的函数声明提升到当前作用域最前面,不调用函数;


九. JS对象

(一) 创建对象

1. 利用对象字面量创建对象

// var obj = {} // 创建了一个空对象
var obj = {
	uname:'张三丰',
	age: 18,
	sex: '男',
	seyHi:function() {
		console.log('hi~');
	}
}

🔰里面的属性或者方法我们采取键值对的形式 键 属性名:值 属性值;
🔰多个属性或者方法中间用逗号隔开的;
🔰方法冒号后面跟的是一个匿名函数;
🔰使用对象:

// 调用对象属性
// 1.  对象.属性名
console.log(obj.uname);
// 2. 对象名['属性名']
console.log(obj['age']);

// 调用对象方法
// 对象名.方法名()
obj.sayHi();

2. 利用 new Object 创建对象

var obj = new Object(); // 创建了一个空对象
obj.uname = '张三丰';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
	console.log('hi~');
}
// 调用对象
console.log(obj.uname);
console.log(obj['age']);
obj.sayHi();

3. 利用构造函数创建对象

// 声明构造函数
function 构造函数名() {
	this.属性 =;
	this.方法 = function() {}
}
function Star(uname, age, sex) {
	this.name = uname;
	this.age = age;
	this.sex = sex;
}

// 使用构造函数
new 构造函数名();
var ldh = new Star('刘德华', 19, '男');
console.log(ldh.name);

(二) 遍历对象

// for in 遍历对象
// for(变量 in 对象) {}
for(var k in obj) {
	console.log(k); // 属性名
	console.log(obj[k]); // 属性值
}


十. 内置对象

(一) 查文档

🔰学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN来查询。
🔰MDN:https://developer.mozilla.org/zh-CN/

如何学习对象中的方法

  1. 查询该方法的功能
  2. 查看里面参数的意义和类型
  3. 查看返回值的意义和类型
  4. 通过demo进行测试

(二) Math 对象

🔰Math 数学对象:不是构造函数,所以不需要new 来调用,直接使用里面的属性和方法即可;

方法/属性说明
Math.PI圆周率值
Math.max(i, j)取最大值
Math.max(12, 23) // 23
Math.min(i, j)取最小值
Math.min(12, 23) // 12
Math.abs(i)绝对值
Math.abs(-12) // 12
Math.round(i)四舍五入, 就近取值
Math.round(1.5) // 2
Math.floor(i)向下取整
Math.floor(3.4) // 3
Math.ceil(i)向上取整
Math.ceil(3.4) // 4
Math.random()随机数
Math.floor(Math.random()*10 // 取0~9内的一个随机数
Math.trunc()将数字的小数部分抹掉
Math.sign()判断一个数到底为正数、负数、还是零
// 随机获取学生姓名
function getRandom(min, max) {
	return Math.floor(Math.random() * (max-min+1))+min;
}
var arr = ['张三', '艾莉', '艾琳', '古丽'];
alert(arr[getRandom(0, arr.length-1)]);
/*固定值*/
console.log("PI = " + Math.PI);
console.log("E  = " + Math.E);
console.log("===============");
/*正数*/
console.log(Math.abs(1));        //可以用来计算一个数的绝对值
console.log(Math.ceil(1.1));     //可以对一个数进行向上取整,小数位只有有值就自动进1
console.log(Math.floor(1.99));   //可以对一个数进行向下取整,小数部分会被舍掉
console.log(Math.round(1.4));    //可以对一个数进行四舍五入取整
console.log("===============");
/*负数*/
console.log(Math.abs(-1));       //可以用来计算一个数的绝对值
console.log(Math.ceil(-1.1));    //可以对一个数进行向上取整,小数部分会被舍掉
console.log(Math.floor(-1.99));  //可以对一个数进行向下取整,小数位只有有值就自动进1
console.log(Math.round(-1.4));   //可以对一个数进行四舍五入取整
console.log("===============");
/*随机数*/
//Math.random():可以用来生成一个0-1之间的随机数
//生成一个0-x之间的随机数:Math.round(Math.random()*x)
//生成一个x-y之间的随机数:Math.round(Math.random()*(y-x)+x)
console.log(Math.round(Math.random() * 10));            //生成一个0-10之间的随机数
console.log(Math.round(Math.random() * (10 - 1) + 1));  //生成一个1-10之间的随机数
console.log("===============");
/*数学运算*/
console.log(Math.pow(12, 3));   //Math.pow(x,y):返回x的y次幂
console.log(Math.sqrt(4));      //Math.sqrt(x) :返回x的平方根

(三) 日期对象

🔰Date 对象是一个构造函数,所以需要实例化后才能使用;
🔰Date 实例用来处理日期和时间;

1. Date() 方法

1)获取当前时间必须实例化

var now = new Date();
alert(now); // Tue Nov 22 2022 16:49:21 GMT+0800 (中国标准时间)

2)Date() 构造函数的参数

🔰如果构造函数括号里面有时间,就返回参数里面的时间。
var now = new Date('2022-11-12 / 2022/11/12');
// Sat Nov 12 2022 08:00:00 GMT+0800 (中国标准时间)

var date = new Date();
console.log(date);

console.log(date.getFullYear());//获取当前日期对象的年份(四位数字年份)
console.log(date.getMonth());//获取当前日期对象的月份(0 ~ 11)
console.log(date.getDate());//获取当前日期对象的日数(1 ~ 31)
console.log(date.getHours());//获取当前日期对象的小时(0 ~ 23)
console.log(date.getMinutes());//获取当前日期对象的分钟(0 ~ 59)
console.log(date.getSeconds());//获取当前日期对象的秒钟(0 ~ 59)
console.log(date.getMilliseconds());//获取当前日期对象的毫秒(0 ~ 999)

2. 日期格式化

🔰对象.方法

方法说明
obj.getFullYear()获取当年
obj.getMonth()获取当月(0~11)
实际应用时,加一
obj.getDate()获取当天日期
obj.getDay()获取星期几(周日:0 ~ 周六:6)
obj.getHours()获取当前小时
obj.getMinutes()获取当前分钟
obj.getSeconds()获取当前秒钟

🔰获取总的毫秒数:Date.now();

3. 倒计时案例实现

在这里插入图片描述

function conutDown(time) {
	var nowTIme = +new Date(); // 返回的时当前时间总的毫秒数
	var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
	var times = (inputTime - nowTIme) / 1000; // time 是剩余时间总的毫秒数
	var d = parseInt(times / 60 / 60 / 24); // 天
	d = d < 10 ? '0' + d : d;
	var h = parseInt(times / 60 / 60 % 24); // 时
	h = h < 10 ? '0' + h : h;
	var m = parseInt(times / 60 % 60); // 分
	m = m < 10 ? '0' + m : m;
	var s = parseInt(times % 60); // 当前的秒
	s = s < 10 ? '0' + s : s;
	return d + '天' + h + '时' + m + '分' + s + '秒';
}
alert(conutDown('2022-11-22 18:47:00'));

(四) 数组对象

利用 new 创建数组

var 数组名 = new Array();
var arr = new Array();

利用数组字面量创建数组

// 1. 使用数组字面方式创建空的数组
var 数组名 = [];
var arr = [];
// 2. 使用数组字面量方式创建带初始值的数组
var 数组名 = ['小白''小黑', '大黄'];
var arr = [1, 2, 3, 4];

🔰数组中可以存放任意类型的数据,例如字符串,数字,布尔值等;
🔰 arr.length动态检测数组元素的个数;
🔰可以通过修改数组索引追加数组元素。

// 利用 new Array() 创建数组
// var arr1 = new Array(); // 创建了一个空的数组
// var arr1 = new Array(2); // 这个2 表示:里面有2个空的数组元素
var arr1 = new Array(2, 3); // 等价于[2, 3] 这样写表示:里面有两个数组元素,是2和3

1. 添加和删除数组元素

方法说明
Array.isArray(arr)判断是否是一个数组
arr.push(i)数组末尾添加元素
arr.unshift(i)数组开头添加元素
arr.pop()删除数组最后一个元素
arr.shift()删除数组第一个元素
var arr = new Array();
Array.isArray(arr); // 判断是否为数组
arr.push(2, 1, 'pink'); // 在数组末尾,添加一个或多个数组元素
arr.unshift(3, 'lov'); // 在数组开头,添加一个或多个数组元素
arr.pop(); // 删除数组的最后一个元素,并返回删除的元素值
arr.shift(); // 删除数组的第一个元素,并返回删除的元素值

2. 数组排序

方法说明
arr.reverse()颠倒数组中元素的顺序
arr.sort()对数组中元素进行排序
var arr = new Array(2, 16, 4, 7, 1);
arr.reverse(); // [1,7,4,6,2] 颠倒数组中元素的顺序
arr.sort(); // [1,2,4,6,7]  对数组中元素进行排序(0~9比较好使)
arr.sort(function(a, b) { // 对所有的数字都好使
   return a - b; // 升序排序
   // return b - a; // 降序排序
});

3. 数组索引方法

方法说明
arr.indexOf(i)查找指定素第一个索引号
arr.lastIndexOf(i)查找指定 元素最后一个索引号
var arr = new Array(2, 16, 4, 4, 7, 1);
var ss = arr.indexOf(4); // 数组中查找给定元素的第一个索引,返回索引号,不存在返回-1
var s = arr.lastIndexOf(4); // 数组中的最后一个索引,返回索引号,不存在返回-1

4. 数组转换为字符串

方法说明
arr.toString()数组转换成字符串,用逗号分割
arr.join(‘/’)数组转换成字符串,用户自定义分割字符
var arr = new Array(2, 16, 4, 4, 7, 1);
var ss = arr.toString(); // 把数组转换成字符串,逗号分隔每一项
       var s = arr.join(' '); // 方法用于把数组中的所有元素转换为一个字符串

(五) 字符串对象

1. 根据字符返回位置

方法说明
indexOf(‘要查找的字符’, 开始的位置)从前往后找,找不到返回-1
lastIndexOf(‘要查找的字符’, 开始的位置)从后往前找,找不到返回-1
var arr = 'angla boby';
var i = arr.indexOf('a', 0); // 从前往后找
var j = arr.lastIndexOf('m', 1); // 从后往前找```

2. 拼接以及截取字符串

var arr = 'angla boby';
var ar = '12';
var arr1 = arr.concat(ar); // 拼接多个字符串
var i = arr.substr(2, 5); // 从索引为2的位置开始,取5个数
var ss = arr.slice(1, 6); // 从1位置开始,截取到6位置,6位置的值取不到
var s = arr.substring(1, 5); // 从1位置开始,截取到5位置,5位置的值取不到, 不接受负值

3. 替换字符串以及转换为数组

var arr = 'angl abo by';
var s = arr.replace('a', 'q'); // 替换第一个a为q
var ss = arr.split(' '); // 按照分割符,转换为数组


Web APIs

🔰Web APIs 是 JS 所独有的部分;
🔰主要学习页面交互功能;


🔰Web API 主要是针对于浏览器提供的接口,主要针对于浏览器做互动效果;
🔰Web PAI 一般都有输入输出(函数的传参和返回值),Web API 很多都是方法;

十一. DOM 文档对象类型

在这里插入图片描述

🔰文档对象模型
🔰DOM 就是把「文档」 当作一个「对象」来看待;
🔰DOM的顶级对象是document
🔰DOM主要学习的是操作页面元素
🔰DOM是W3C标准规范
🔰W3C 已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容,结构和样式;

(一) DOM 树

🔰文档:一个页面就是一个文档,DOM中使用 document 表示;
🔰元素:页面中的所有标签都是元素,DOM中使用 element 表示;
🔰节点:网页中的所有内容都是节点(标签,属性,文本,注释等),DOM中使用 node 表示;
🔰DOM把以上内容都看做是对象;


(二) 获取元素

🔰因为我们文档页面从上往下加载,所以先得有标签,所以我们script写到标签的下面。

1. 根据 ID 获取

🔰语法
var element = document.getElementById(id);
🔰参数

  1. 如果当前文档中拥有特定ID的元素不存在,返回null;
  2. id是大小写敏感的字符串,代表了所要查找的元素的唯一ID;

🔰返回值:返回一个匹配到ID的 element 对象。若在当前 document 下没有找到,则返回 null;
document——文档

2. 根据标签名获取

🔰使用 getElementsByTagName() 方法,可以返回带有指定标签名的对象集合。
🔰语法
document.getElementsByTagName('标签名');

var ul = document.getElementsByTagName('ul');

🔰还可以获取某个元素(父元素) 内部所有指定标签名的子元素;
🔰语法

var ul = document.getElementsByTagName('ul');
console.log(ul[0].getElementsByTagName('li'));

3. 通过 HTML5 新增的方法获取(推荐)

🔰根据类名返回元素对象集合
document.getElementsByClassName('类名');

var scrip = document.getElementsByClassName('ss');
// 输出结果: [li.ss, li.ss, li.ss, li.ss, li.ss]

🔰根据指定选择器(.box/#box)返回第一个元素对象
document.querySelector('选择器');

var scrip = document.querySelector('.ss');
// 输出结果:<li class="ss">1</li>

🔰根据指定选择器返回元素对象集合
document.querySelectorAll('选择器');

var scrip = document.querySelector('.ss');
// 输出结果:[li.ss, li.ss, li.ss, li.ss, li.ss]

4. 特殊元素获取

🔰获取body元素:
document.body // 返回body元素对象
🔰获取html元素:
document.documentElement // 返回html元素对象

var body = document.body;
// 输出结果:body
var html= document.documentElement;
// 输出结果:html

(四) 操作元素

🔰利用DOM操作元素来改变元素里面的内容,属性等。

1. 操作元素内容

🔰这两个属性是可读写的,可以获取元素里面的内容,也可以改变元素内容。
🔰<div>内容</div> 修改“内容”的值

1)element.innerText
var btn1 = document.getElementById('btn');
btn1.innerText = '你好,我是按钮'; // 修改内容
alert(btn1.innerText); // 获取内容

该属性不识别html标签,同时空格和换行也会换掉;

2)element.innerHTML (大量使用)
var btn1 = document.getElementById('btn');
btn1.innerHTML= '你好,我是按钮';
alert(btn1.innerHTML); // 获取内容

包括html标签,同时保留空格和换行;

2. 操作元素属性

🔰通过修改元素的属性(src, href, title),进行操作。

<!-- 点击按钮,换图片 -->
<button id="btn">刘德华</button>
<button id="btn1">张学友</button><br>
<img src="btn.gif" alt="">
<script>
	var btn = document.getElementById('btn');
	var btn1 = document.getElementById('btn1');
	var imgs = document.querySelector('img');
	btn1.onclick = function() {
		imgs.src = 'btn1.gif';
		imgs.title = '张学友';
	}
	btn.onclick = function() {
		imgs.src = 'btn.gif';
		imgs.title = '刘德华';
	} 
</script>

在这里插入图片描述在这里插入图片描述

3. 操作表单元素属性

🔰利用DOM可以操作表单元素的属性。
type value checked selected disabled


🔰element.value.length:表单元素值的长度

<button>按钮</button>
<input type="text" value="请输入内容">
<script>
	var btn = document.querySelector('button');
	var input = document.querySelector('input');
	btn.onclick = function() {
		// 修改value的值
		input.value = '被点击了';
		// btn.disabled = true;
		this.disabled = true;
		// this 指向的是事件函数的调用者  btn
	}
</script>

4. css样式属性操作

🔰通过JS修改元素的大小,颜色,位置等样式。

  1. element.style 行内样式操作
    如果样式比较少或者功能简单的情况下使用
  2. element.className 类名样式操作
    如果样式修改较多的情况下使用
    className会直接更改元素的类名,会覆盖原先的类名
1)element.style(行内样式操作)
<!--element.style 行内样式操作-->
<style>
	.box {
		width: 200px;
		height: 200px;
		background-color: pink;
	}
</style>
<div class="box"></div>
<script>
	var box = document.querySelector('div');
	box.onclick = function() {
		// 改变颜色,宽 css样式
		this.style.backgroundColor = 'yellow';
		this.style.width = '250px';
	}
</script>
2)element.className(类名样式操作)
<style>
	div {
		background: pink;
		width: 150px;
		height: 150px;
	}
	.change {
		background: purple;
		color: #fff;
		font-size: 25px;
		margin-top: 100px;
	}
</style>
<div>文本</div>
<script>
	var div = document.querySelector('div');
	div.onclick = function() {
		this.className = 'change';
	}
</script>

5. 鼠标经过变色案例

1. 普通设计

<!--鼠标经过按钮,按钮颜色发生改变,之后变回原来的颜色-->
<input type="button" value="开关灯" id="1">
<input type="button" value="开关灯" id="2">
<input type="button" value="开关灯" id="3">
<input type="button" value="开关灯" id="4">
<input type="button" value="开关灯" id="5">
<script>
	var button = document.getElementsByTagName('input');
	for(var i = 0; i < button.length; i++) {
		button[i].onmouseover = function() {
			this.style.backgroundColor = 'pink';
		}
		button[i].onmouseout = function() {
			this.style.backgroundColor = '#efefef';
		}
	}
</script>

排他思想(算法)进行设计

<script>
	// 1. 获取所有的按钮元素
	var button = document.getElementsByTagName('input');
	// 2. button 得到的是伪数组
	for(var i = 0; i < button.length; i++) {
		button[i].onmouseover = function() {
			// 1) 先把所有的按钮背景颜色去掉  干掉所有人
			for(var i = 0; i < button.length; i++) {
				button[i].style.backgroundColor = '';
			}
			// 2) 然后让当前的元素颜色为pink  留下我自己
			this.style.backgroundColor = 'pink';
		}
	}
</script>

在这里插入图片描述在这里插入图片描述

6. 排他思想()算法设计换肤效果案例

<style>
	img {
		position: relative;
		width: 100px;
		height: 100px;
		margin: auto;
		left: 20%;
		margin-top: 50px;
	}
</style>
<img src="/Picture/静态合集/大背景.gif" alt="">
<img src="/黑背景.gif" alt="">
<img src="/Picture/动图合集/雨滴.gif" alt="">
<img src="/Picture/动图合集/1.gif" alt="">
<script>
	// 1. 获取元素
	var imgs = document.getElementsByTagName('img');
	var body = document.body;
	// 2. 循环注册事件
	for(var i = 0; i < imgs.length; i++) {
		imgs[i].onclick = function() {
			// 1) 先把所有的背景去掉  干掉所有人
			for(var i = 0; i < imgs.length; i++) {
				body.style.backgroundImage = '';
			}
			// 2) 然后让当前点击元素的url为body的url  留下我自己
			body.style.background = 'url('+this.src+')';
		}
	}
</script>

7. 自定义属性的操作

1)获取属性值

🔰element.属性:获取属性值;
img.url // 获取img标签的url属性
🔰element.getAttribute('属性');
🔰区别:

  1. element.属性获取内置属性值(元素本身自属性
  2. element.getAttribute('属性');主要获取程序员自定义的属性
2)自定义属性

🔰index = "1"
程序员自己添加的属性。
🔰H5规定自定义属性data开头做为属性名并且赋值。
比如<div data-index= "1” > </div>
或者使用JS设置
element.setAttribute( 'data-index', 2)

var li = document.querySelector('.ss');
li.setAttribute('data-index', 12);
// 结果:<li class="ss" data-index="12">1</li>

获取自定义属性值:element.getAttribute('data-index')

3)设置属性值

🔰element.属性 = '值':设置内置属性值;
img.url // 获取img标签的url属性
🔰element.setAttribute('属性', '值');
🔰区别:

  1. element.属性设置内置属性值
  2. element.setAttribute('属性');主要设置自定义的属性
4)移除属性

🔰element.removeAttribute('属性')


(五) 节点操作

🔰获取元素通常使用两种方式:

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

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


🔰节点至少拥有nodeType(节点类型)nodeName(节点名称)nodeValue(节点值)这三个基本属性。

  1. 元素节点nodeType 为 1
  2. 属性节点nodeType 为 2
  3. 文本节点nodeType 为 3(文本节点包含文字,空格,换行)

🔰在实际开发中,节点操作主要操作的是元素节点。

1. 节点层级

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

1)父级节点

🔰语法:node.parentNode
🔰parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
🔰如果指定的节点没有父节点,则返回null

<div class="demo">
	<div class="box">
		<div class="erweima">X</div>
	</div>
</div>
<script>
	// 利用DOM提供的方法获取父节点
	var erweima = document.querySelector('.erweima');
	var box = document.querySelector('.box');

	// 利用父子节点关系获取父节点
	var erweima = document.querySelector('.erweima');
	var box = erweima.parentNode;
	var demo = box.parentNode; // 获取demo节点
</script>
2)子节点

获取子节点

🔰语法:parentNode.childNodes
🔰parentNode. childNodes 返回包含指定节点的子节点的集合.该集合为即时更新的集合。
🔰返回值里面包含所有的子节点,包括元素节点,文本节点等。


🔰语法:parentNode.children
🔰parentNode. children是一个只读属性,返回所有的子元素节点它只返回子元素节点,其余节点不返回

<ul>
	<li>我是li</li>
	<li>我是li</li>
	<li>我是li</li>
	<li>我是li</li>
</ul>
<script>
	// 利用DOM提供的方法获取所有的子节点
	var ul = document.querySelector('ul');
	var li = ul.querySelector('li');

	// 利用父子节点关系获取所有的子节点
	var ul = document.querySelector('ul');
	var li = ul.childNodes; // [text, li, text, li, text, li, text, li, text]
	var li1 = ul.children; //  [li, li, li, li]
</script>

获取第一个和最后一个子节点

🔰语法:parentNode.firstChild
🔰firstChild返回第一个子节点,找不到则返回null.同样,也是包含所有的节点
🔰语法:parentNode.lastChild
🔰lastChild返回最后一个子节点,找不到则返回null.同样,也是包含所有的节点
🔰不足之处:返回值里面包含所有节点


🔰语法:parentNode.firstElementChild
🔰firstElementChild返回第一个子元素节点,找不到则返回null。
🔰语法:parentNode.lastElementChild
🔰lastElementChild返回最后一个子元素节点,找不到则返回null。
🔰不足之处:这两个方法有兼容性问题,IE9以上才支持


🔰如果想要一个子元素节点,可以使用parentNode.children[0]
parentNode.children[0]

<ul>
	<li>我是li</li>
	<li>我是li</li>
	<li>我是li</li>
	<li>我是li</li>
</ul>
<script>
	var ul = document.querySelector('ul');
	// 1. firstChild 第一个子节点不管是文本节点还是元素节点
	var som1 = ul.firstChild; // #text
	var som2 = ul.lastChild; // #text
	// 2. firstElementChild 返回第一个子元素节点
	var som3 = ul.firstElementChild; // li
	var som4 = ul.lastElementChild; // li
</script>
3)兄弟节点

获取兄弟节点

🔰语法:node.nextSibling
🔰nextsibling返回当前元素的下一个兄弟节点。找不到则返回null。同样,也是包含所有的节点。
🔰语法:node.previousSibling
🔰previoussibling返回当前元素上一个兄弟节点。找不到则返回null.同样,也是包含所有的节点。

获取兄弟元素节点

🔰语法:node.nextElementSibling
🔰nextElementsibling返回当前元素下一个兄弟元素节点。找不到则返回null.
🔰语法:node.previousElementSibling
🔰previousElementsibling返回当前元素上一个兄弟节点。找不到则返回null,
🔰注意:这两个方法有兼容性问题,IE9以上才支持。
自己封装一个兼容性的函数

function getNextElementSibling(element) {
	var el = element;
	while(el = el.nextSibling) {
		if(el.nodeType == 1) {
			return el;
		}
	}
	return null;
}

2. 创建节点

🔰语法:document.createElement('tagName')
🔰document. createElement()方法创建由tagName指定的HTMIL 元素。因为这些元素原先不存在是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
🔰实例:var a = document.createElement('a');

3. 添加节点

1)appendChild

🔰语法:node.appendChild(child)
🔰node . appendChild()方法将一个节点添加到指定父节点的子节点列表末尾,类似于css里面的after伪元素。
🔰实例: create.appendChild(a);

2)insertBefore

🔰语法:node.insertBefore(child, 指定元素)
🔰node . insertBefore ()方法将一个节点添加到父节点的指定子节点前面。 类似于css里面的before伪元素。
🔰实例:ul.insertBefore(li, ul.children[0]);

<ul >你好</ul>
<script>
	// 1. 创建节点元素节点
	var li = document.createElement('li');
	// 2. 添加节点,node.appendChild(child) node 父级 child 子级
	var ul = document.querySelector('ul'); // 获取父节点
	ul.appendChild(li); // 添加节点
	// 3. 添加节点node. insertBefore(child,指定元素);
	var lili = docment.createElement('li');
	ul.insertBefore(lili, ul.children[0]);
</script>

4. 删除节点

🔰语法:node.removeChild(child)
🔰node . removeChild()方法从DOM中删除一个子节点 ,返回删除的节点。

// 1,. 获取元素
var ul = document.querySelector('ul');
// 2. 删除元素
ul.removeChild(ul.children[0]);

5. 复制节点

🔰语法:node.cloneNode()
🔰node . cl oneNode()方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点

var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括号为空或者里面是false,只复制标签
// 2. node.cloneNode(true); 括号为true,复制标签,也复制里面的内容
var li = ul.children[0].cloneNode(true);
ul.appendChild(li);

注意:

  1. 如果括号参数为空或者为false , 则是浅拷贝,即只克隆复制节点本身,不克降里面的子节点。
  2. 如果括号参数为true。则是深度拷贝,会复制节点本身以及里面所有的子节点。

6. 动态创建元素

1)document.write()(了解)

🔰docoment .write是直接将内容写入页面的内容流。但是文档执行完毕,则它会导教页面全部重绘

<ul>
	<li>你好</li>
	<li>我号</li>
</ul>
<button>按钮</button>
<script>
	// document.write('<li>大家好</li>');
	var btn = document.querySelector('button');
	// 页面加载完毕以后才能点击按钮,这时会发生页面重绘
	btn.onclick = function() { 
		document.write('<li>大家好</li>');
	}
</script>
2)element.innerHTML

🔰innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
🔰innerHIML创建多个元素效率更高(不要拼接字符串.采取数组形式拼接),结构稍微复杂;

<div class="inner"></div>
<script>
	var inner = document.querySelector('.inner');
	 // 拼接字符串方式创建
	for (let i = 0; i < 100; i++) {
		inner.innerHTML += '<a href="#">百度</a>';
	}
	
	// 数组形式拼接创建
	var array = [];
	for (let i = 0; i < 100; i++) {
		array.push('<a href="#">百度</a>');
	}
	inner.innerHTML = array.join('');
</script>

不同浏览器下,innerHTML效率要比creatElement 高

3)document.createElement()

🔰createElement() 创建多个元索效率稍低一点点 ,但是结构更清晰;

<div class="create"></div>
<script>
	var create = document.querySelector('.create');
	for (let i = 0; i < 100; i++) {
		// 创建元素
		var a = document.createElement('a'); 
		// 添加元素
		create.appendChild(a);
	}
</script>

(六) DOM 事件

🔰事件是可以被JS侦测到的行为;触发——响应机制
🔰事件是有三部分组成:

  1. 事件源:事件被触发的对象(按钮)
  2. 事件类型:如何触发(鼠标点击/鼠标经过/键盘按下)
  3. 事件处理程序:通过一个函数赋值的方式完成

🔰执行事件步骤:

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)
<!-- 点击按钮,弹出对话框 -->
<button id="btn">唐伯虎</button>

<script>
	// 获取事件源
	var btn = document.getElementById('btn');
	// 绑定事件
	// btn.onclick
	// 添加事件处理程序
	btn.onclick = function() {
		alert('点击按钮,弹出对话框!');
	}
</script>

🔰使用传统的注册方式:加on
🔰使用addEventListener:不加on

1. 注册事件(绑定事件)

🔰给元素添加事件,称之为注册事件
🔰注册事件有两种方式:传统方式方法监听注册方式

1)传统注册方式

🔰利用on开头的事件onclick
<button onclick="alert('hi~')"></button>
btn.onclick = function() {}
🔰特点:注册事件的唯一性
🔰同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。

2)方法监听注册方式

🔰w3c 标准 推荐方式
🔰addEventListener它是一个方法
🔰IE9 之前的IE不支持此方法,可使用 attachEvent()代替
🔰特点:同一个元素同一个事件可以注册多个监听器
🔰按注册顺序依次执行

3)addEventListener 事件监听处理

🔰eventTarget.addEventListener() 方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,就会执行事件处理函数。
🔰语法:
eventTarget.addEventListener(type, listener[, useCapture])
🔰参数:

  1. type:事件类型字符串,比如click, mouseover, 注意这里不要带on
  2. listener:事件处理函数,事件发生时,会调用该监听函数
  3. useCapture:可选参数,是一个布尔值,默认是false
var li = document.querySelector('.ss');
li.addEventListener('click', function() {
	alert(22);
})
li.addEventListener('click', function() {
	alert(33);
})
4)attachEvent 事件监听方式(了解)

🔰eventTarget.attachEvent() 方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,指定的回调函数就会被执行。
🔰语法:eventTarget.attachEvent(eventNameWithOn, callback)
🔰参数:

  1. eventNameWithOn:事件类型字符串,比如onclick, onmouseover, 这里要带on
  2. callback:事件处理函数,当目标触发事件时回调函数被调用
var li = document.querySelector('.ss');
li.attachEvent('click', function() {
	alert(22);
})

2. 删除事件(解绑事件)

1)传统注册方式

🔰eventTarget.onclick = null;

2)方法监听注册方式

🔰eventTarget.removeEventListener(type, listener{, useCapture]);
🔰下面的方法与 attachEvent 事件监听方法一起用:
eventTarget.detachEVent(eventNameWithOn, callback);

var li = document.querySelectorAll('.ss');
li[0].onclick = function() {
	alert(11);
	// 1. 传统方式删除事件
	li[0].onclick = null;
}

li[1].addEventListener('click', fn);
function fn() {
	alert(22);
	// 2. removeEventListener 删除事件
	li[1].removeEventListener('click', fn);
}
        
li[2].attachEvent('onclick', fn1);
function fn1() {
	alert(33);
	// 3. detachEVent 删除事件
	li[2].detachEVent('onclick', fn1);
}

3. DOM事件流

🔰事件流描述的是从页面中接受事件的顺序。
🔰事件发生时会发生在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
🔰DOM事件流分为3个阶段:

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

在这里插入图片描述
🔰注意:

  1. JS 中只能执行捕获或者冒泡其中的一个阶段。
  2. onclick 和 attachEvent 只能得到冒泡阶段。
  3. addEventListener(type, listener[, useCapture])第三个参数如果是true表示在事件捕获阶段调用事件处理程序;如果是false表示在事件冒泡阶段调用事件处理程序
  4. 实际开发中,很少用事件捕获,更关注冒泡阶段。
  5. 有些事件是没有冒泡的,比如onblur, onfocus, onmouseover, onmouseleave.
  6. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。
var li = document.querySelector('.ss');
li.addEventListener('click', function() {
	alert(22);
}, ture);

4. 事件对象

var li = document.querySelectorAll('.ss');
li[0].onclick = function(event) {
	// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
}
li[0].addEventListener('click', function(event) {
	// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
})  

🔰这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
🔰当我们注册事件时,event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。

1)事件对象的常见属性和方法
事件对象属性方法说明
e.target返回触发事件的对象 标准
e.srcElement返回触发事件的对象 非标准 ie6-8使用
e.type返回事件的类型
比如:click mouseover 不带on
e.preventDefault()该方法阻止默认事件(默认行为) 标准
比如:不链接跳转
e.returnValue该属性阻止默认事件(默认行为) 非标准
e.stopPropagation()阻止冒泡 标准
e.cancelBubble该属性阻止冒泡 非标准 ie6-8使用

1. e.target返回触发事件的对象

🔰e. target返回的是触发事件的对象(元素)
🔰this返回的是绑定事件的对象(元素)

var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
	// 我们给 ul 绑定了事件  那么 this 就指向 ul
	console.log(this); // 结果:ul
	// e.target 指向我们点击的那个对象 谁触发了这个事件 
	// 我们点击的是 li e.target 指向的就是 li
	console.log(e.target); // 结果:li
});

🔰ie6-8使用e.srcElement返回触发事件的对象,用法同上。

2. e.type返回事件类型

🔰返回 click mouseover 等, 不带on

var div = document.querySelector('div');
div.addEventListener('click', function(e) {
	console.log(e.type); // click
});

3. e.preventDefault()阻止默认行为

🔰让链接不跳转或者让提交按钮不提交等;

var a = document.querySelector('a');
a.addEventListener('click', function(e) {
	// 标准写法
	e.preventDefault();
	// 低版本浏览器
	e.returnValue;
	// 可以利用return false 也能阻止默认行为 没有兼容性问题
	return false;
});

**4. e.stopPropagation() **:阻止事件冒泡

🔰阻止冒泡

var som = document.querySelector('.som');
som.addEventListener('click', function(e) {
	alert('som');
	if(e&&e.stopPropagation) {
		// stop 停止 Propagation 传播
	} else {
		// 非标准 cancel 取消 bubble 泡泡
		window.event.cancelBubble = true;
	}
}, false);

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

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

var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
	alert('知否知否,点我应有弹框在手!');
	e.target.style.backgroundColor = 'pink';
});

6. 表单事件

表单事件在HTML表单中触发 (适用于所有 HTML 元素,但该HTML元素需在form表单内):

表单事件触发条件
onblur当元素失去焦点时触发
onfocus当元素获得焦点时触发
onchange当元素改变时触发
oninput当元素获得用户输入时触发
oninvalid当元素无效时触发
onselect当选取元素时触发
onsubmit当提交表单时触发
<form id="myform">
    <input type="text" id="text" required>
    <input type="submit" value="submit" id="submit">
</form>

<script>
    var textInput = document.getElementById("text");

    textInput.onfocus = function () {
        console.log("获取焦点");
    };

    textInput.onblur = function () {
        console.log("失去焦点");
    };

    textInput.onchange = function () {
        console.log("元素内容改变");
    };

    textInput.oninput = function () {
        console.log(this.value);
    };

    textInput.oninvalid = function () {
        console.log("请您完善表单内容!");
    };

    textInput.onselect = function () {
        console.log("您已经选择了文本框内容!");
    };

    var myform = document.getElementById("myform");
    myform.onsubmit = function () {
        console.log("表单提交");
        return false;/* 用来阻止表单提交的,你不写它会跳转请求 */
    };
</script>

7. 键盘事件

键盘事件触发条件
onkeyup某个键盘按键被松开时触发
onkeydown某个键盘按键按下时触发

键盘事件对象

键盘事件对象 属性说明
keyCode返回该的ASCLL值

🔰注意:onkeydownonkeyup不区分区分字母大写onkeypress区分字母大小写
🔰在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)。

键鼠属性:

属性描述
ctrlKey返回当事件被触发时,“CTRL” 键是否被按下。
altKey返回当事件被触发时,“ALT” 是否被按下。
shiftKey返回当事件被触发时,“SHIFT” 键是否被按下。
clientX返回当事件被触发时,鼠标指针的水平坐标。
clientY返回当事件被触发时,鼠标指针的垂直坐标。
screenX返回当某个事件被触发时,鼠标指针的水平坐标。
screenY返回当某个事件被触发时,鼠标指针的垂直坐标。
window.onkeydown = function (event) {
	/* 解决兼容性问题 */
	event = event || window.event;
	if (event.keyCode == 65) {
		console.log("true");
	} else {
		console.log("false");
	}
};

8. 鼠标事件

通过鼠标触发事件,类似用户的行为:

鼠标事件触发条件
onclick鼠标点击左键触发
ondblclick鼠标双击左键触发
onmousedown鼠标按下触发
onmouseup鼠标弹起触发
onmousemove鼠标移动触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onmousewheel转动鼠标滚轮时触发
onscroll滚动元素的滚动条时触发

禁止鼠标右键菜单

🔰contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

var ul = document.querySelector('ul');
	ul.addEventListener('contextmenu', function(e) {
	e.preventDefault();
});

禁止鼠标选中(selectstart 开始选中)

🔰禁止鼠标选中文字等。

var ul = document.querySelector('ul');
	ul.addEventListener('selectstart', function(e) {
	e.preventDefault();
});
1) event 鼠标事件对象
鼠标事件对象说明
e.clientX返回鼠标相对于浏览器窗口可视区域的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区域的Y坐标
e.pageX返回鼠标相对于文档页面的X坐标 IE9+ 支持
e.pageY返回鼠标相对于文档页面的Y坐标 IE9+ 支持
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的Y坐标
2) mouseenter 和 mouseover 的区别

🔰当鼠标移动到元素上时就会触发mouseenter 事件
🔰类似于mouseover,他们两者之间的差别是

  1. mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发,mouseenter 只会经过自身盒子触发
  2. 之所以这样,就是因为mouseenter不会冒泡
  3. 跟mouseenter 搭配鼠标离开mouseleave 同样不会冒泡

9. 媒体事件

通过视频(videos),图像(images)或音频(audio) 触发该事件。

属性描述
onabort当发生中止事件时运行脚本。
oncanplay当媒介能够开始播放但可能因缓冲而需要停止时触发
oncanplaythrough当媒介能够无需因缓冲而停止即可播放至结尾时触发
ondurationchange当媒介长度改变时触发
onemptied当媒介资源元素突然为空时(网络错误、加载错误等)触发
onended当媒介已抵达结尾时触发
onerror当在元素加载期间发生错误时触发
onloadeddata当加载媒介数据时触发
onloadedmetadata当媒介元素的持续时间以及其它媒介数据已加载时触发
onloadstart当浏览器开始加载媒介数据时触发
onpause当媒介数据暂停时触发
onplay当媒介数据将要开始播放时触发
onplaying当媒介数据已开始播放时触发
onprogress当浏览器正在取媒介数据时触发
onratechange当媒介数据的播放速率改变时触发
onreadystatechange当就绪状态(ready-state)改变时触发
onseeked当媒介元素的定位属性不再为真且定位已结束时触发
onseeking当媒介元素的定位属性为真且定位已开始时触发
onstalled当取回媒介数据过程中(延迟)存在错误时触发
onsuspend当浏览器已在取媒介数据但在取回整个媒介文件之前停止时触发
ontimeupdate当媒介改变其播放位置时运触发
onvolumechange当媒介改变音量亦或当音量被设置为静音时触发
onwaiting当媒介已停止播放但打算继续播放时触发


十二. BOM 浏览器对象类型

🔰浏览器对象模型
🔰把「浏览器」当做一个「对象」来看待
🔰BOM的顶级对象是window
🔰BOM学习的是浏览器窗口交互的一些对象
🔰BOM是浏览器厂商在各自浏览器上定义的,兼容性较差

(一) BOM的构成

在这里插入图片描述

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

  1. 它是JS访问浏览器窗口的一个接口。
  2. 它是一个全局对象。定义在全局作用域中的变量,函数都会变成window对象的属性和方法

🔰在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert(), prompt()等。
🔰注意:window 下的一个特殊属性 window.name,自带的


🔰BOM 比 DOM 更大,它包含 DOM。
在这里插入图片描述

(二) window 对象的常见事件

窗口事件触发条件
onblur当窗口失去焦点时触发
onfocus当窗口获得焦点时触发
onload当文档加载之后触发
onresize当调整窗口大小时触发
window.onblur = function() {
	alert("窗口失去焦点");
}

1. 窗口加载事件

1. onload

🔰window.onload 是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像脚本文件、CSS文件等),就调用的处理函数
🔰语法:

window.onload = function(){}
window.addEventListener('load', function(){});

🔰注意:

  1. 有了 window.onload 就可以把JS代码写到页面元素的上方,因为 onload 是等页面内容加载完毕,再去执行处理函数。
  2. window.onload 传统注册方式只能写一次,如果有多个,会以最后一个为准。
  3. 如果使用 addEventListener 则没有限制。

2. DOMContentLoaded

🔰DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表, 图片. flash等等。
🔰语法:

window.addEventListener('DOMContentLoaded', function() {});

🔰如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响用户的体验.此时用DOMContentLoaded事件比较合适。

2. 调整窗口大小事件

🔰window. onresize调整窗口大小加载事件,当触发时就调用的处理函数。
🔰语法:

window.onresize = function(){}
window.addEventListener('resize', function(){});

🔰只要窗口大小发生像素变化,就会触发这个事件
🔰我们经常利用这个事件完成应式布局。
🔰window.innerWidth 当前屏幕的宽度

3. 常用窗口属性

这两个属性都以像素返回尺寸:

  • window.innerHeight - 浏览器窗口的内高度(以像素计)
  • window.innerWidth - 浏览器窗口的内宽度(以像素计)

4. 其他窗口方法

window.open() :打开新的窗口

window.open(URL,name,specs,replace);

在这里插入图片描述

window.close() :关闭当前窗口

window.close();

window.moveTo() :移动当前窗口

window.moveTo(x,y);

window.resizeTo() :调整当前窗口

window.resizeTo(width,height);

(三) 定时器

1. setTimeout() 定时器设置

🔰setTimeout() 方法用于设置一个定时器,该定时器在定时器到期后执行调用函数
🔰语法:

window.setTimeout(调用函数, [延迟的毫秒数]);
var timer1 = setTimeout(function(){}, 2000);

🔰window 可以省略。
🔰这个调用函数可以直接写函数,或者写函数名。
🔰延迟的毫秒数省略默认是0,如果写,必须是毫秒。
🔰因为定时器可能有很多,所以我们经常给定时器赋值一个标识符

2. 停止 setTimeout() 定时器

🔰clearTimeout ()方法取消了先前通过调用setTimeout ()建立的定时器
🔰window 可以省略

window.clearTimeout(timeout ID);

var div = document.querySelector('div');
// 设置定时器
var timer1 = setTimeout(function(){
	div.style.display = 'none';
}, 2000);
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
	// 停止定时器
	clearTimeout(timer1);
});

3. setInterval() 定时器设置

🔰setTimeout() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
🔰语法:

window.setInterval(回调函数, [间隔的毫秒数]);
var timer1 = setInterval(function(){}, 2000);

🔰window 可以省略。
🔰这个调用函数可以直接写函数,或者写函数名。
🔰延迟的毫秒数省略默认是0,如果写,必须是毫秒。
🔰因为定时器可能有很多,所以我们经常给定时器赋值一个标识符

4. 停止 setInterval() 定时器

🔰clearInterval()方法取消了先前通过调用setInterval()建立的定时器
🔰window 可以省略
🔰里面的参数就是定时器的标识符

window.clearInterval(timeout ID);

var div = document.querySelector('div');
// 设置定时器
var timer1 = setInterval(function(){
	div.style.display = 'none';
}, 2000);
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
	// 停止定时器
	clearInterval(timer1);
});

5. this 指向问题

🔰一般情况下,this 最终指向的是那个调用它的对象。
🔰全局作用域或者普通函数中,this 指向全局对象 window (注意定时器里面的 this 指向 window)。
🔰方法调用中,谁调用,this 指向谁。
🔰构造函数中,this 指向构造函数的实例。

(四) JS执行机制

1. JS 是单线程

🔰JS 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 JS 这门脚本语言诞生的使命所致——JS 是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
🔰单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。 这样所导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

2. 同步和异步

🔰为了解决上面提到的问题。利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JS脚本创建多个线程。于是,IS中出现了同步和异步。
🔰异步和同步的本质区别:这条流水线上各个流程的执行顺序不同。

1)同步

🔰前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后) ,再去切菜,炒菜。

2)异步

🔰你在做一件事情时,因为这件事情会花费很长时间。在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜,

(五) location 对象

在这里插入图片描述

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

1. URL

🔰统一资源定位符(URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它
🔰URL 一般语法格式为:
> protocol://host[:port]/path/[?query]#fragment
> http://www.baidu.itcast.cn/index.html?name=andy&age=18#link

组成说明
protocol通信协议 常用http, ftp, maito等
host主机(域名)www.itheima.com
port端口号 可选,省略时使用方案的默认端口 如http的默认端口为80
path路径 由零或多个’/‘符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
query参数 以键值对的形式,通过&符号分隔开来
fragment片段 #后面内容 常见于链接 锚点

2. location 对象的属性

对象属性返回值
location.href*获取或者设置 整个URL
location.host返回主机(域名)www.itheima.com
location.port返回端口号 如果未返回 空字符串
location.pathname返回路径
location.search*返回参数
location.hash返回片段 #后面内容 常见于链接 锚点

3. location 对象的方法

location 对象方法返回值
location.assign()跟href一样,可以跳转页面(也称之为重定向页面)
location.replace()替换当前页面,因为不记录历史,所以不能后退页面
location.reload()重新加载页面,相当于刷新按钮或者 f5 ,如果参数为true 强制刷新 ctrl+f5

(六) navigator 对象

🔰navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent ,该属性可以返回由客户机发送服务器的user-agent头部的值。
🔰判断用户用哪个终端打开页面,实现跳转:

if(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPed|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
	window.location.href = "";  // 手机
} else {
	window.location.href = "";  // 电脑
}

(七) history 对象

在这里插入图片描述

🔰window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL

history 对象方法作用
back()后退功能
forward()前进功能
go(参数)前进后退功能
参数如果时 1 ,前进一个页面
如果是 -1 ,后退一个页面
var btn = document.querySelector('input');
btn.addEventListener('click', function() {
	history.back();     // 后退
	history.forward();  // 前进
	history.go(1);      // 前进一个页面
	history.go(-1);     // 后退一个页面
});

__


十三. PC端网页特效

(一) 元素偏移量 offset 系列

🔰offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等
🔰获得元素距离带有定位父元素的位置
🔰获得元素自身的大小 (宽度高度)
🔰注意返回的数值都不带单位

offset 系列常用属性作用
element.offsetParent返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body
element.offsetTop返回元素相对带有定位父元素上方的偏移
element.offsetLeft返回元素相对带有定位父元素左边框的偏移
element.offsetWidth返回自身包括padding,边框,内容区的宽度,返回数值不带单位
element.offsetHeight返回自身包括padding,边框,内容区的高度,返回数值不带单位
var btn = document.querySelector('input');
// 返回带有定位的父级元素
var parent = btn.offsetParent; 
// 返回上方偏移量
var top = btn.offsetTop;
// 返回左边框偏移量
var left = btn.offsetLeft;
// 返回padding,边框,内容区的宽度
var width = btn.offsetWidth;
// 返回padding,边框,内容区的高度
var height = btn.offsetHeight;

1. offset 与 style 区别

🔰offset

  1. offset 可以得到任意样式表中的样式值
  2. offset 系列获得的数值是没有单位的
  3. offsetWidth 包含 padding+border+width
  4. offsetWidth 等属性是只读属性,只能获取不能赋值
  5. 所以我们想要获取元素大小位置,用offset 更合适

🔰style

  1. style 只能得到行内样式表中的样式值
  2. style.width 获得的是带有单位的字符串
  3. style.width 获得不包含 padding 和 border 的值
  4. style.width 是可读写属性,可以获取也可以赋值
  5. 所以,我们想要给元素更改值,则需要用style改变

2. 获取盒子中鼠标的坐标

鼠标移动,获取坐标

var som = document.querySelector('div');
som.addEventListener('mousemove', function(e) {
	// 鼠标在盒子中的坐标 = 鼠标在页面中的坐标(e.pageX, e.pageY) - 盒子在页面中的距离(this.offsetLift, this.offsetTop)
	var x = e.pageX - this.offsetLeft;
	var y = e.pageY - this.offsetTop;
	this.innerHTML = 'x坐标是' + x + 'y坐标是' + y;
});

拖动模块框,放大镜效果实例


📌offset 系列经常用于获得元素位置offsetLeft offsetTop


(二) 元素可视区 client 系列

🔰client翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

client 系列属性作用
element.clientTop返回元素上边框的大小
element.clientLeft返回元素左边框的大小
element.clientWidth返回自身包括padding,内容区的宽度,不含边框,返回数值不带单位
element.clientHeight返回自身包括padding,内容区的高度,不含边框,返回数值不带单位
var div = document.querySelector('div');
var top = div.clientTop; // 元素上边框大小
var left = div.clientLeft; // 元素左边框大小
var width = div.clientWidth; // 返回自身宽度
var height = div.clientHeight; // 返回自身高度

1. 立即执行函数

🔰立即执行函数(function() {})()或者(function(){}())
🔰主要作用:创建一个独立的作用域。避兔了命名冲突问题

// 写法 可以传递参数进来
// 1. (function() {})();   或者   2. (function(){}());
(function(a, b) {
	console.log(a + b);
	var num = 10;
})(1, 2); // 第二个括号可以看作是调用函数

(function sum(a, b) {
	console.log(a + b);
	var num = 10; // 局部变量
}(2, 3));

2. 淘宝 js 源码

(function flexible(window, document) {
	// 获取html的根元素
	var docEl = document.documentElement;
	// dpr 物理像素比
	var dpr = window.devicePixelRatio || 1;

	// 设置body 的字体大小
	function setBodyFontSize() {
		// 如果页面中有body 这个元素 就设置body 的字体大小
		if(document.body) {
			document.body.style.fontsize = (12 * dpr) + 'px';
		} else {
			// 如果没有body 这个元素,则等页面主要的DOM元素加载完毕再去设置body的字体大小
			document.addEventListener('DOMContentLoaded', setBodyFontSize);
		}
	}
	setBodyFontSize();

	// 设置html 元素的文字大小
	function setRemUnit() {
		var rem  = docEl.clientWidth;
		docEl.style.fontsize = rem + 'px';
	}
	setRemUnit();

	// 当页面尺寸发生变化的时候,要重新设置以下rem 的大小
	window.addEventListener('resize', setRemUnit);
	// pageshow 是我们重新加载页面触发的事件
	window.addEventListener('pageshow', function(e) {
		// e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也从新计算一下rem 的大小
		if(e.persisted) {
			setRemUnit();
		}
	});

	// 有些移动端浏览器不支持 0.5 像素的写法
	if(dpr >= 2) {
		var fakeBody = document.createElement('body');
		var testElement = document.createElement('div');
		testElement.style.border = '.5px solid transparent';
		fakeBody.appendChild(testElement);
		docEl.appendChild(fakeBody);
		if(testElement.offsetHeight === 1) {
			docEl.classList.add('hairlines');
		}
		docEl.removeChild(fakeBody);
	}
})(window, document);

📌client 系列经常用于获取元素大小clientWidth clientHeight


(三) 元素滚动 scroll 系列

1. 元素scroll系列属性

🔰scroll翻译过来就是滚动的,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等

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

2. 页面被卷去的头部

🔰如果浏览器的高(宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,称之为页面被卷去的头部。滚动条在滚动时会触发onscroll事件。
🔰注意:元素卷去的头部是element.scroltTop,如果是页面被卷去的头部则是window.pageYOffset


📌scroll 系列经常用于获取滚动距离scrollTop scrollLeft


(四) 动画函数封装

1. 动画实现原理

🔰核心原理通过定时器setInterval() 不断移动盒子位置。
🔰实现步骤:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上一个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 注意此元素需要添加定位,才能使用element.style.left

2. 动画函数简单封装

🔰注意函数需要传递两个参数,动画对象移动距离

// 简单动画函数封装
function animate(obj, target) {
	var timer1 = setInterval(function() {
		if(obj.offsetLeft >= target) {
			clearInterval(timer1);
		}
		obj.style.left = obj.offsetLeft+5+'px';
	}, 50);
}

var div = document.querySelector('div');
// 调用函数
animate(div, 350);

3. 给不同元素记录不同定时器

// 简单动画函数封装
// 给不同的元素指定了不同的定时器  obj.timer
function animate(obj, target) {
	// 先清除以前的定时器,只保留当前的一个定时器执行 
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		if(obj.offsetLeft >= target) {
			clearInterval(obj.timer);
		}
		obj.style.left = obj.offsetLeft+5+'px';
	}, 50);
}

var div = document.querySelector('div');
// 调用函数
animate(div, 350);

4. 缓动效果原理

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

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
  2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离步长
  3. 停下来的条件是:让盒子位置等于目标位置就停止定时器
  4. 注意步长值需要取整
    往前: Math.ceil(8.1) -> 9
    往后:Math.floor(-8.1)-> -9
// 简单动画函数封装
// 给不同的元素指定了不同的定时器  obj.timer
function animate(obj, target) {
	// 先清除以前的定时器,只保留当前的一个定时器执行 
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		var step = (target - obj.offsetLeft) / 10;
		// 判断是正着走还是负着走
		step > 0 ? Math.ceil(step) : Math.floor(step);
		if(obj.offsetLeft == target) {
			clearInterval(obj.timer);
		}
		obj.style.left = obj.offsetLeft+step+'px';
	}, 15);
}
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画 就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10

var div = document.querySelector('div');
// 调用函数
animate(div, 350);

5. 动画函数添加回调函数

🔰回调函数原理函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完毕后,再执行传进去的这个函数,这个过程就叫做回调。

// 简单动画函数封装
function animate(obj, target, callback) {
	// 先清除以前的定时器,只保留当前的一个定时器执行 
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		var step = (target - obj.offsetLeft) / 10;
		// 判断是正着走还是负着走
		step > 0 ? Math.ceil(step) : Math.floor(step);
		if(obj.offsetLeft == target) {
			// 定时器结束
			clearInterval(obj.timer);
			if(callback) {
				// 调用函数
				callback();
			}
		}
		obj.style.left = obj.offsetLeft+step+'px';
	}, 15);
}
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画 就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10

var div = document.querySelector('div');
// 调用函数
animate(div, 350, function() {});

(五) 常见网页特效案例

1. 网页轮播图

🔰防止轮播图按钮连续点击造成播放过快。
🔰节流阀的目的当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触发。
🔰核心实现思路利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

  1. 开始设置一个变量var flag = true;
  2. if(flag) { flag = false; do something} 关闭水龙头
  3. 利用回调函数 动画执行完毕,flag = ture 打开水龙头
// flag 节流阀
// 设置变量
var flag = true;
// 判断节流阀是否打开
if(flag) {
	flag = false; // 关闭节流阀
	// 执行动画函数
	// 动画函数执行完毕后,回调函数内打开节流阀,继续执行下一个动画函数
	animate(ul, -num * focusWidth, function() {
		flag = true; // 打开节流阀
	});
}

【轮播图】实例



十四. 移动端网页特效

(一) 触屏事件

🔰移动端浏览器兼容性比较好,不需要考虑兼容性问题,可以放心的使用原生JS书写效果。
🔰触屏事件 touch (也称触摸事件)。
🔰touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触摸事件可响应用户手指对屏幕或者触控板操作。
🔰常见的触屏事件如下:

触屏touch事件说明
touchstart手指触摸到一个DOM元素时触发(手指按下)
touchmove手指在一个DOM元素上滑动时触发(手指按住滑动)
touchend手指从一个DOM元素上移开时触发(手指离开)

1. 触摸事件对象(TouchEvent)

🔰TouchEvent是一类描述手指在触摸屏面(如屏幕,触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少等。
🔰touchstart 等事件都会各自有事件对象。
🔰三个常见触摸事件对象列表:

触摸列表说明
touches正在触摸屏幕的所有手指的一个列表
targetTouches正在触摸当前DOM元素上的手指的一个列表
changedTouches手指状态发生改变的列表,从无到有,从有到无变化

🔰因为平时我们都是给元素注册触摸事件,所以重点记住 targetTouches

var span = document.querySelector('span');
span.addEventListener('touchstart', function(e) {
	// touches  正在触屏的所有手指的列表
	// targetTouches  正在触摸当前DOM元素的手指列表
	// changedTouches  手指状态发生了改变的列表
	
	// 得到正在触摸DOM元素的第一个手指的相关信息  比如 手指的坐标等
	console.log(e.targetTouches[0]);
})

2. 移动端拖动元素

  1. touchstart, touchmove, touchend 可以实现拖动元素
  2. 但是拖动元素需要当前手指的坐标值,我们可以使用targetTouches[0] 里面的 pageX 和 pageY
  3. 移动端拖动原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
  4. 手指移动的距离: 手指滑动中的位置 - 手指刚开始触摸的位置

🔰拖动元素三部曲:
1)触摸元素tuochstart:获取手指初始坐标,同时获得盒子原来的位置
2)移动手指touchmove:计算手指的滑动距离,并且移动盒子
3)离开手指touchend

注意:手指移动也会触发滚动屏幕,所以这里要阻止默认的屏幕滚动 e.preventDefault();

// 获取元素
var div = document.querySelector('div');
// 获取手指初始坐标
var startX = 0;
var startY = 0;
// 获取盒子原来的位置
var x = 0;
var y = 0;
// 1. 触摸元素
div.addEventListener('touchstart', function(e) {
	// 获取手指的初始坐标
	startX = e.targetTouches[0].pageX;
	startY = e.targetTouches[0].pageY;
	// 获取盒子原来的位置
	x = this.offsetLeft;
	y = this.offsetTop;
})
// 2. 移动手指
div.addEventListener('touchmove', function(e) {
	// 计算手指移动的距离 移动后的位置 - 初始位置
	var moveX = e.targetTouches[0].pageX - startX;
	var moveY = e.targetTouches[0].pageY - startY;
	// 移动盒子
	this.style.left = x+moveX+'px';
	this.style.top = y+moveY+'px';
	e.preventDefault(); // 组织屏幕滚动
})

(二) 移动端常见特效

1. 自动播放功能-无缝滚动

🔰注意,我们判断条件是要等到图片滚动完毕再去判断,就是过渡完成后判断
🔰此时需要添加检测过渡完成事件 transitionend

2. classList 属性

🔰classList 属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。
🔰该属性用于在元素中添加,移除及切换CSS类

1)添加类

🔰element.classList.add("类名");
例:div.classList.add('current');
🔰在后面追加类名,不会覆盖以前的类名,前面不需要加.

2)移除类

🔰element.classList.remove("类名");
例:div.classList.remove('current');

1)切换类

🔰element.classList.toggle("类名");
例:div.classList.toggle('current');

3. click 延时解决方案

🔰移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
🔰解决方案:

  1. 禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300 ms 的点击延迟。
    <meta name="viewport" content="user-scalable=no">
  2. 利用touch事件自己封装这个事件解决延迟。
  3. 使用插件。fastclick 插件解决 300 ms 延迟。

(三) 移动端常用开发插件

🔰移动端要求的是快速开发,所以我们经常会借助于些插件来帮我完成操作。
🔰JS插件是=js文件,它遵循定规范编写,方便程序展示效果,拥有特定功能且方便调用。如轮播图和瀑布流插件。
🔰特点:它般是为了解决某个问题而专门存在,其功能单一, 并且比较小。
🔰我们以前写的animate.js也算一个最简单的插件。

1. fastclick插件

🔰fastclick 插件解决 300 ms 延迟。使用延时
GitHub 官网地址:https://github.com/ftlabs/fastclick

2. Swiper 插件的使用

🔰中文官网地址:https://www.swiper.com.cn/

  1. 引入插件相关文件;
  2. 按照规定语法使用。

3. 移动端常用插件

🔰superslide:http://www.superslide2.com/
🔰iscroll:http://github.com/cubiq/iscroll

4. 插件的使用总结

  1. 确认插件实现的功能
  2. 去官网查看使用说明
  3. 下载插件
  4. 打开demo实例文件,查看需要引入的相关文件,并且引入
  5. 复制demo实例文件中的结构html,样式css以及js代码

(四) 移动端常用开发框架

🔰框架,就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
🔰前端常用的框架有Bootstrap, Vue, Angular, React等。既能开发PC端,也能开发移动端。

1. Bootstrap

🔰Bootstrap 是一个简洁,直观,强悍的前端开发框架,它让 web 开发更迅速,简单。
🔰它能开发PC端,也能开发移动端
🔰Bootstrap JS 插件使用步骤:

  1. 引入相关js文件
  2. 复制HTML结构
  3. 修改对应样式
  4. 修改相应JS参数


十五. 本地存储

🔰随着互联网的快速发展,基于网页的应用越来越普遍,同时也便的越来越复杂, 为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5 规范提出了相关解决方案。
🔰本地存储特性:

  1. 数据存储在用户浏览器中
  2. 设置,读取方便,甚至页面刷新不丢失数据
  3. 容量较大,sessionStorage 约 5M,localStorage 约 20M
  4. 只能存储字符串,可以将对象JSON.stringify() 编码后存储

(一) window.sessionStorage

  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用

🔰存储数据:
sessionStorage.setItem(key, value);
🔰获取数据:
sessionStorage.getItem(key);
🔰删除数据:
sessionStorage.removeItem(key);
🔰删除所有数据:
sessionStorage.clear();


(二) window.localStorage

  1. 生命周期永久生效,除非手动删除,否则关闭页面也会存在
  2. 在多窗口(页面)共享(同一浏览器可以共享)
  3. 以键值对的形式存储使用

🔰存储数据:
localStorage.setItem(key, value);
🔰获取数据:
localStorage.getItem(key);
🔰删除数据:
localStorage.removeItem(key);
🔰删除所有数据:
localStorage.clear();



十六. 数据可视化项目

(一) 什么是数据可视化

1. 数据可视化

🔰数据可视化主要目的借助于图形化手段,清晰有效地传达与沟通信息。
🔰数据可视化可以把数据从冰冷的数字转换成图形,揭示蕴含在数据中的规律和道理。

2. 数据可视化的场景

🔰目前互联网公司常有这么几大类的可视化需求:

  1. 通用报表
  2. 移动端图标
  3. 大屏可视化
  4. 图编辑&图分析
  5. 地理可视化

3. 常见的数据可视化库

🔰D3.js:目前Web端评价最高的JS可视化工具库(入手难)
🔰ECharts.js:百度出品的一个开源JS数据可视化库
🔰Highcharts.js:国外的前端数据可视化库,非商用免费,被许多国外大公司所使用
🔰AntV:蚂蚁金服全新一代数据可视化解决方案


(二) ECharts 简介

🔰ECharts 是一个使用JS实现的开源可视化库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器,底层依赖矢量图形库ZRender,提供直观,交互丰富,可高度个性化的数据可视化图表。
🔰官网地址:https://echarts.apache.org/zh/index.html


(三) ECharts 的基本使用

1. ECharts 使用五步骤

🔰步骤1:下载并引入 echarts.js 文件 ----> 图表依赖这个js库
🔰步骤2:准备一个具备大小的DOM容器 ----> 生成的图表会放入这个容器内
🔰步骤3:初始化 echarts 实例对象 ----> 实例化echarts对象
🔰步骤4:指定配置项和数据(option) ----> 根据具体需求修改配置选项
🔰步骤5:将配置项设置给 echarts 实例对象 ----> 让echarts对象根据修改好的配置生效



十七. 异常处理

🔰在编程中,有时代码并不会像我们预期的那样运行,会遇到各式各样的错误,例如代码中使用了错误的符号、调用未定义的方法、网络错误、读取不存在的文件、没有操作权限等。

🔰根据类型的不同,JavaScript 编程中的错误大致可以分为以下三种类型:

  1. 语法错误:也称为解析错误,一般是因为代码存在某些语法错误引起的。当发生语法错误时,代码会停止运行;
  2. 运行时错误:也称为异常,发生在程序运行期间,例如调用未定义的方法、读取不存在的文件等,发生运行时错误也会终止代码运行;
  3. 逻辑错误:是最难发现的一种错误,逻辑错误通常是因为代码存在瑕疵,导致程序输出意外的结果或终止运行。

(一) 错误和异常的区别

  • 错误(Error)是在代码运行之前出现的,在运行 JavaScript 程序之前,JavaScript 解释器会先对代码进行检查,如果代码有误,例如某些语法错误,浏览器就会报出相应的错误,只有将错误修正后,代码才能运行。

  • 异常(Exception)是在代码运行中出现的,例如调用某个未定义的方法、读取不存在的文件等。在出现异常之前,代码的运行并不受影响,当出现异常时,会在浏览器控制台输出错误信息,并终止程序的运行。


(二) JS 异常处理

🔰异常处理的目的是捕捉产生异常的代码,使整个程序不会因为异常而终止运行。在 JavaScript 中,您可以使用 try catch 语句来捕获异常,并做出相应处理,语法格式如下:

try {
    // 可能会发生异常的代码
} catch(error) {
    // 发生异常时要执行的操作
}

我们可以将任何可能发生异常的代码放到 try 语句块中,并在 catch 语句块中定义处理异常的方法。如果 try 语句块中的代码发生错误,代码会立即从 try 语句块跳转到 catch 语句块中,如果 try 语句块中代码没有发生错误,就会忽略 catch 语句块中的代码。


(三) JS 错误类型

错误类型说明
EvalError使用 eval() 函数时发出错误,会抛出该错误
InternalError由 JavaScript 引擎内部错误导致的异常,会抛出该错误
RangeError范围错误,当使用了超出允许范围的数值时,会抛出该错误
SyntaxError语法错误,当代码中存在任何语法错误时,会抛出该错误
TypeError类型错误,当使用的值不是预期类型时,会抛出该错误,例如对数字调用字符串方法,对字符串调用数组方法等
URIError URI错误,当使用 URI 相关函数但传入 URI 参数时,会抛出该错误
ReferenceError参数错误,当尝试使用未定义的变量、函数、对象时,会抛出该错误


JS 表单验证

表单验证通常由两个部分组成:

  • 必填字段验证:确保必填的字段都被填写;
  • 数据格式验证:确保所填内容的类型和格式是正确的、有效的。

1. 必填字段验证

🔰必填字段验证在用户注册时比较常见,通过必填字段验证,能够确保表单中的必填字段都被填写,例如用户名、密码、邮箱等。

🔰实现必填字段验证非常简单,只需要通过程序来检查必填表单元素的值是否为空即可,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
    <style>
        .error{
            color: red;
        }
        label{
            display: inline-block;
            width: 70px;
            text-align: right;
        }
    </style>
</head>
<body>
    <form onsubmit="return validateForm()" action="" method="post">
        <fieldset>
            <legend>注册:</legend>
            <div class="row">
                <label>用户名:</label>
                <input type="text" name="name">
                <span class="error" id="nameErr"></span>
            </div>
            <div class="row">
                <label>密码:</label>
                <input type="password" name="pwd">
                <span class="error" id="pwdErr"></span>
            </div>
            <div class="row">
                <label>Email:</label>
                <input type="text" name="email">
                <span class="error" id="emailErr"></span>
            </div>
            <div class="row">
                <label>手机号:</label>
                <input type="text" name="mobile" maxlength="11">
                <span class="error" id="mobileErr"></span>
            </div>
            <div class="row">
                <label>验证码:</label>
                <input type="text" name="captcha" maxlength="4"><span id="captcha" onclick="getCaptcha()"></span>
                <span class="error" id="captchaErr"></span>
            </div>
            <div class="row">
                <input type="submit" value="注册">
            </div>
        </fieldset>
    </form>
    <script>
        var captcha = getCaptcha(); // 生成验证码
        // 清空 input 标签后的提示信息
        var tags = document.getElementsByTagName('input');
        for (var i = 0; i < tags.length; i++) {
            tags[i].onchange = function(){
                var idname = this.name + "Err";
                document.getElementById(idname).innerHTML = '';
            }
        }
        // 显示错误消息
        function printError(elemId, hintMsg) {
            document.getElementById(elemId).innerHTML = hintMsg;
        }
        // 验证表单数据
        function validateForm() {
            // 获取表单元素的值
            var name = document.querySelector("input[name='name']").value;
            var pwd = document.querySelector("input[name='pwd']").value;
            var email = document.querySelector("input[name='email']").value;
            var mobile = document.querySelector("input[name='mobile']").value;
            var captcha = document.querySelector("input[name='captcha']").value;
                  
            if(name == "" || name == null){
                printError("nameErr", "用户名不能为空");
                return false;
            }
            if(pwd == "" || pwd == null){
                printError("pwdErr", "密码不能为空");
                return false;
            }
            if(email == "" || email == null){
                printError("emailErr", "邮箱不能为空");
                return false;
            }
            if(mobile == "" || mobile == null){
                printError("mobileErr", "手机号不能为空");
                return false;
            }
            if(captcha == "" || captcha == null){
                printError("captchaErr", "验证码不能为空");
                return false;
            }
        }
        // 获取验证码
        function getCaptcha(){
            var cap = Math.floor(Math.random()*10000).toString();
            if(cap.length != 4) cap += "0";
            captcha = cap;
            document.getElementById("captcha").innerHTML = cap;
        }
    </script>
</body>
</html>

2. 数据格式验证

🔰数据格式验证就是通过正则表达式来验证用户所填的数据,是否符合要求,以邮箱地址为例,正确的邮箱地址中要包含一个 @ 和一个 . ,而且 @ 不能是邮箱地址的第一个字符,. 要出现在 @ 之后。

🔰示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
    <style>
        .error{
            color: red;
        }
        label{
            display: inline-block;
            width: 70px;
            text-align: right;
        }
    </style>
</head>
<body>
    <form onsubmit="return validateForm()" action="" method="post">
        <fieldset>
            <legend>注册:</legend>
            <div class="row">
                <label>用户名:</label>
                <input type="text" name="name">
                <span class="error" id="nameErr"></span>
            </div>
            <div class="row">
                <label>密码:</label>
                <input type="password" name="pwd">
                <span class="error" id="pwdErr"></span>
            </div>
            <div class="row">
                <label>Email:</label>
                <input type="text" name="email">
                <span class="error" id="emailErr"></span>
            </div>
            <div class="row">
                <label>手机号:</label>
                <input type="text" name="mobile" maxlength="11">
                <span class="error" id="mobileErr"></span>
            </div>
            <div class="row">
                <label>验证码:</label>
                <input type="text" name="captcha" maxlength="4"><span id="captcha" onclick="getCaptcha()"></span>
                <span class="error" id="captchaErr"></span>
            </div>
            <div class="row">
                <input type="submit" value="注册">
            </div>
        </fieldset>
    </form>
    <script>
        var capCode = getCaptcha(); // 生成验证码
        console.log(capCode);
        // 清空 input 标签后的提示信息
        var tags = document.getElementsByTagName('input');
        for (var i = 0; i < tags.length; i++) {
            tags[i].onchange = function(){
                var idname = this.name + "Err";
                document.getElementById(idname).innerHTML = '';
            }
        }
        // 显示错误消息
        function printError(elemId, hintMsg) {
            document.getElementById(elemId).innerHTML = hintMsg;
        }
        // 验证表单数据
        function validateForm() {
            // 获取表单元素的值
            var name = document.querySelector("input[name='name']").value;
            var pwd = document.querySelector("input[name='pwd']").value;
            var email = document.querySelector("input[name='email']").value;
            var mobile = document.querySelector("input[name='mobile']").value;
            var captcha = document.querySelector("input[name='captcha']").value;
                  
            if(name == "" || name == null){
                printError("nameErr", "用户名不能为空");
                return false;
            }
            if(pwd == "" || pwd == null){
                printError("pwdErr", "密码不能为空");
                return false;
            }
            if(email == "" || email == null){
                printError("emailErr", "邮箱不能为空");
                return false;
            } else {
                var regex = /^\S+@\S+\.\S+$/;
                if(regex.test(email) === false) {
                    printError("emailErr", "请输入正确的邮箱地址");
                    return false;
                }
            }
            if(mobile == "" || mobile == null){
                printError("mobileErr", "手机号不能为空");
                return false;
            } else {
                var regex = /^[1]\d{10}$/;
                if(regex.test(mobile) === false) {
                    printError("mobileErr", "您输入的手机号码有误");
                    return false;
                }
            }
            if(captcha == "" || captcha == null){
                printError("captchaErr", "验证码不能为空");
                return false;
            } else {
                console.log(capCode);
                console.log(captcha);
                if(capCode != captcha){
                    printError("captchaErr", "验证码有误");
                    return false;
                }
            }
        }
        // 获取验证码
        function getCaptcha(){
            var cap = Math.floor(Math.random()*10000).toString();
            if(cap.length != 4) cap += "0";
            document.getElementById("captcha").innerHTML = cap;
            return capCode = cap;
        }
    </script>
</body>
</html>

JS 侧边动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #box {
            width: 200px;
            height: 200px;
            margin-top: 10px;
            background: rgb(43, 221, 255);
            position: relative;
            left: -200px;
            top: 0;
        }
        #box span {
            width: 20px;
            background: rgb(255, 119, 157);
            position: absolute;
            left: 200px;
            top: 75px;
            color: #fff;
            text-align: center;
            cursor: pointer;
            padding: 5px 1px 5px 0;
            border-radius: 0 5px 5px 0;
        }
        #box span:hover {
            background: rgb(255, 84, 137);
        }
    </style>   
</head>
<body>
    <div id="box">
        <span id="share">分享</span>
    </div>
    <script>
        window.onload = function () {
            //动画
            var div = document.getElementById("box");
            var timer = null;
            div.onmouseover = function () {
                startMove(0);
            };
            div.onmouseout = function () {
                startMove(-200);
            };
            function startMove(targetPosition) {
                clearInterval(timer);
                var speed = 0;
                if (targetPosition < 0) {
                    speed = -10;
                } else {
                    speed = 10;
                }
                timer = setInterval(function () {
                    if (div.offsetLeft == targetPosition) {
                        clearInterval(timer);
                    } else {
                        div.style.left = div.offsetLeft + speed + 'px';
                    }
                }, 17);
            }
        };
    </script>
</body>
</html>

在这里插入图片描述

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码字小萌新♡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值