目的是为了 JS 后面做铺垫
JavaScript是一种运行在客户端的脚本语言;
脚本语言:不需要编译,运行过程中由js解释器逐行来进行解释并执行;
表单动态校验 (密码强度检测)
网页特效
服务端开发
桌面程序
APP
控制硬件-物联网
游戏开发
HTML决定网页结构和内容,相当于看到什么;
CSS决定网页呈现给用户的模样,相当于给人穿衣服;
JS 实现业务逻辑和页面控制,相当于人的各种动作;
浏览器分成两部分:渲染引擎和 JS 引擎
渲染引擎
:用来解析HTML 与CSS,俗称内核;
JS 引擎
:也称之为JS解释器。用来读取网页中的JavaScript 代码,对其处理后运行;
JS引擎执行代码时逐行解释每一句源码,然后由计算机去执行;
JavaScript由
ECMAScript(JavaScript 语法)
,DOM(页面文档对象类型)
,BOM(浏览器对象类型)
等三部分组成;
ECMAScript:规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
DOM:通过DOM提供的接口可以对页面上的各种元素进行操作(大小,位置,颜色等)
BOM:是指浏览器对象模型,它提供了独立于内容的可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框,控制浏览器跳转,获取分辨率等。
有3中书写位置,分别为行内,内嵌和外内部;
<script>
alert('沙漠骆驼')
script>
<script src="my.js">script>
head>
<body>
<input type="button" value="唐伯虎" onclick="alert('秋香姐')">
body>
为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 |
---|---|
alert(msg) | 浏览器弹出警示框 |
console.log(msg) | 浏览器控制台打印输出信息 |
prompt(into) | 浏览器弹出输入框,用户可以输入 |
prompt('请输入你的年龄')
alert('计算结果是')
console.log('我是程序员')
// 打印我们返回的元素对象,更好的查看里面的属性和方法
console.dir(time);
本质:变量是程序在内存中申请的一块用来存放数据的空间。
变量在使用时分两步:1)声明变量;2)赋值
声明变量
var age; // 声明一个名称为age的变量
var 是一个JS关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管。
age是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间。赋值
age = 18; // 给age 这个变量赋值为10
变量初始化
var age = 18; // 声明变量的同时赋值为18
同时声明多个变量时,只需要写一个var,多个变量名之间使用英文逗号隔开;
var age = 10, name = 'aili', sex = 2;
有字母,数字,下划线,美元符号组成;
严格区分大小写;
不能以数字开头;
不能时关键字,保留字;
变量名必须有意义;
遵守驼峰命名法,首字母小写,后面的单词的首字母需要大写;
JavaScript 是-种弱类型或者说动态语言
。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
var age = 10; // 这是一个数字型
var areYourk = '是的'; // 这是一个字符串
在代码运行时,变量的数据类型是由JS引擎根据=右边变量值的数据类型来判断的,运行完毕之后.变量就确定了数据类型型。
JS把数据类型分为两类:
- 简单数据类型(Number, String, Boolean, Undefined, Null);
- 复杂数据类型(object);
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整型,浮点型值,如21,0.21 | 0 |
Boolean | 布尔值类型,如true,false,等价于1和0 | false |
String | 字符串类型,如“张三”,注意在JS里面,字符串都带引号 | “” |
Undefined | var a; 声明了变量a,但是没有给值,此时 a = undefined | undefined |
Null | var a = null; 声明了变量a, 为空值 | null |
在JS中八进制前面加0, 十六进制前面加0x;
var num1 = 07; // 对应十进制的7
var num2 = 0xA; // 对应十进制的10
用来判断一个变量是否为非数字的类型;是数字返回false;
var ss = isNaN('age');
字符串型可以是引号中的任意文本,其语法为
双引号""
和单引号''
;
通过字符串的
length
属性可以获取整个字符串的长度。
var number = '123456789';
alter(number.length; // 显示 11
多个字符串之间用 + 进行拼接,
字符串 + 任何类型 = 拼接后的新字符串
;数字相加,字符相连;
alert('老师今年' + age + '岁');
typeof
可用来获取检测变量的数据类型;
alert(typeof 12); // number
转换为字符串
方式 | 说明 | 案例 |
---|---|---|
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
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序。
顺序结构
:程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
分支结构
:执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程) , 从而得到不同的结果。
if(条件表达式1) {
语句1;
} else if(条件表达式2) {
语句2;
}else {
// 上述条件都不成立,执行此处代码
}
条件表达式 ? 表达式1 : 表达式2
如果条件表达式结果为真,则返回表达式1的值;如果条件表达式结果为假,则返回表达式2的值;
switch(表达式) {
case value1:
// 表达式 等于 value1 时要执行的代码
break;\
case value2:
// 表达式 等于 value2 时要执行的代码
break;
default:
// 表达式 不等于任何一个 value 时要执行
}
for(初始化变量; 条件表达式; 操作表达式) {
// 循环体
}
初始化变量
就是用var声明的一个普通变量,通常用于 作为计数器使用
条件表达式
就是用来决定每一次循环是 否继续执行就是终止的条件
操作表达式
是每次循环最后执行的代码经常用于我们计数器变量进行更新(递增或者递减)
while(条件表达式) {
// 循环体代码
}
执行思路:
- 先执行条件表达式,如果为true,则执行循环体代码;如果为false,则退出循环,执行后面的代码;
- 执行循环体代码;
- 循环体代码执行完毕后,程序会继续判断执行条件表达式,如果条件仍为true,则会继续执行循环体,直到循环条件为false时,整个循环过程才会结束。
do {
// 循环体代码
} while(条件表达式);
执行思路:
- 先执行一次循环体代码;
- 再执行条件表达式,如果结果为true ,则继续执行循环体代码;如果为false,则退出循环,继续执行后面代码。
注意
:先再执行循环体,再判断,我们会发现d…while循环语句至少会执行一次循环体代码。
continue关键字
用于立即跳出本次循环,继续下一次循环(本次循环体中continue之后的代码就会少执行一次)
break关键字
用于立即跳出整个循环(循环结束)。
利用 new 创建数组
var 数组名 = new Array();
var arr = new Array();
利用数组字面量创建数组
// 1. 使用数组字面方式创建空的数组
var 数组名 = [];
var arr = [];
// 2. 使用数组字面量方式创建带初始值的数组
var 数组名 = ['小白', '小黑', '大黄'];
var arr = [1, 2, 3, 4];
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等;
arr.length
动态检测数组元素的个数;
可以通过修改数组索引追加数组元素。
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示。
var arr = [5, 7, 2, 9, 1, 4];
for(var i = 0; i < arr.length-1; i++) {
for (var j = 0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {
var som = arr[j];
arr[j] = arr[j+1];
arr[j+1] = som;
}
}
}
函数在使用时分为两步:声明函数,调用函数;
// 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 对象中存储了传递的所有实参;
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);
伪数组,并不是真正意义上的数组;
- 具有数组的 length 属性
- 按照索引的方式进行存储的;
- 他没有真正数组的一些方法,pop() push() 等;
JS作用域:就是代码名字(变量) 在某个范围内起作用和效果;
目的是为了提高程序的可靠性,更重要的是减少命名冲突;
全局作用域:整个script
标签或者是一个单独的js文件。
局部作用域:在函数内部就是局部作用域,这个代码的名字只是在函数内部起到效 果和作用。
在全局作用域下声明的变量叫做全局变量 (在函数外部定义的变量);
- 全局变量在代码的任何位置都可以使用;
- 在全局作用域下 var 声明的变量,是全局变量;
- 特殊情况下,在函数内不适用 var 声明的变量也是全局变量 (不建议使用) ;
在局部作用域下声明的变量叫做局部变量 (在函数内部定义的变量);
- 局部变量只能在该函数内部使用;
- 在函数内部 var 声明的变量,是局部变量;
- 函数的形参实际上就是局部变量;
JS引擎运行 js 分两步:预解析 代码运行
- 预解析:JS引擎会把 js 里面所有的 var ,还有 function 提升到当前作用域的最前面;
- 代码执行:按照代码书写顺序从上往下执行
预解析分为:变量解析(变量提升) 和 函数预解析(函数提升);- 变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作;
- 函数提升:就是把所有的函数声明提升到当前作用域最前面,不调用函数;
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/
如何学习对象中的方法
- 查询该方法的功能
- 查看里面参数的意义和类型
- 查看返回值的意义和类型
- 通过demo进行测试
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内的一个随机数
// 随机获取学生姓名
function getRandom(min, max) {
return Math.floor(Math.random() * (max-min+1))+min;
}
var arr = ['张三', '艾莉', '艾琳', '古丽'];
alert(arr[getRandom(0, arr.length-1)]);
Date 对象是一个构造函数,所以需要实例化后才能使用;
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 (中国标准时间)
对象.方法
方法 | 说明 |
---|---|
obj.getFullYear() | 获取当年 |
obj.getMonth() | 获取当月(0~11) 实际应用时,加一 |
obj.getDate() | 获取当天日期 |
obj.getDay() | 获取星期几(周日:0 ~ 周六:6) |
obj.getHours() | 获取当前小时 |
obj.getMinutes() | 获取当前分钟 |
obj.getSeconds() | 获取当前秒钟 |
获取总的毫秒数:Date.now();
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 Array() 创建数组
// var arr1 = new Array(); // 创建了一个空的数组
// var arr1 = new Array(2); // 这个2 表示:里面有2个空的数组元素
var arr1 = new Array(2, 3); // 等价于[2, 3] 这样写表示:里面有两个数组元素,是2和3
方法 | 说明 |
---|---|
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(); // 删除数组的第一个元素,并返回删除的元素值
方法 | 说明 |
---|---|
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; // 降序排序
});
方法 | 说明 |
---|---|
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
方法 | 说明 |
---|---|
arr.toString() | 数组转换成字符串,用逗号分割 |
arr.join(‘/’) | 数组转换成字符串,用户自定义分割字符 |
var arr = new Array(2, 16, 4, 4, 7, 1);
var ss = arr.toString(); // 把数组转换成字符串,逗号分隔每一项
var s = arr.join(' '); // 方法用于把数组中的所有元素转换为一个字符串
方法 | 说明 |
---|---|
indexOf(‘要查找的字符’, 开始的位置) | 从前往后找,找不到返回-1 |
lastIndexOf(‘要查找的字符’, 开始的位置) | 从后往前找,找不到返回-1 |
var arr = 'angla boby';
var i = arr.indexOf('a', 0); // 从前往后找
var j = arr.lastIndexOf('m', 1); // 从后往前找```
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位置的值取不到, 不接受负值
var arr = 'angl abo by';
var s = arr.replace('a', 'q'); // 替换第一个a为q
var ss = arr.split(' '); // 按照分割符,转换为数组
Web APIs 是 JS 所独有的部分;
主要学习页面交互功能;
Web API 主要是针对于浏览器提供的接口,主要针对于浏览器做互动效果;
Web PAI 一般都有输入输出(函数的传参和返回值),Web API 很多都是方法;
文档对象模型
DOM 就是把「文档
」 当作一个「对象
」来看待;
DOM的顶级对象是document
DOM主要学习的是操作页面元素
DOM是W3C标准规范
W3C 已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容,结构和样式;
文档:一个页面就是一个文档,DOM中使用
document
表示;
元素:页面中的所有标签都是元素,DOM中使用element
表示;
节点:网页中的所有内容都是节点(标签,属性,文本,注释等),DOM中使用node
表示;
DOM把以上内容都看做是对象;
因为我们文档页面从上往下加载,所以先得有标签,所以我们script写到标签的下面。
语法:
var element = document.getElementById(id);
参数:
- 如果当前文档中拥有特定ID的元素不存在,返回null;
id
是大小写敏感的字符串,代表了所要查找的元素的唯一ID;返回值:返回一个匹配到ID的
element
对象。若在当前 document 下没有找到,则返回 null;
document——文档
使用 getElementsByTagName() 方法,可以返回带有指定标签名的对象集合。
语法:
document.getElementsByTagName('标签名');
var ul = document.getElementsByTagName('ul');
还可以获取某个元素(父元素) 内部所有指定标签名的子元素;
语法:var ul = document.getElementsByTagName('ul'); console.log(ul[0].getElementsByTagName('li'));
根据类名返回元素对象
集合
:
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'); // 输出结果:
1 根据指定选择器返回元素对象
集合
:
document.querySelectorAll('选择器');
var scrip = document.querySelector('.ss'); // 输出结果:[li.ss, li.ss, li.ss, li.ss, li.ss]
获取body元素:
document.body // 返回body元素对象
获取html元素:
document.documentElement // 返回html元素对象
var body = document.body; // 输出结果:body var html= document.documentElement; // 输出结果:html
事件是可以被JS侦测到的行为;
触发——响应机制
事件是有三部分组成:
- 事件源:事件被触发的对象(按钮)
- 事件类型:如何触发(鼠标点击/鼠标经过/键盘按下)
- 事件处理程序:通过一个函数赋值的方式完成
执行事件步骤:
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
<button id="btn">唐伯虎button> <script> // 获取事件源 var btn = document.getElementById('btn'); // 绑定事件 // btn.onclick // 添加事件处理程序 btn.onclick = function() { alert('点击按钮,弹出对话框!'); } script>
利用DOM操作元素来改变元素里面的内容,属性等。
这两个属性是可读写的,可以获取元素里面的内容,也可以改变元素内容。
修改“内容”的值
内容
var btn1 = document.getElementById('btn'); btn1.innerText = '你好,我是按钮'; // 修改内容 alert(btn1.innerText); // 获取内容
该属性不识别html标签,同时空格和换行也会换掉;
var btn1 = document.getElementById('btn'); btn1.innerHTML= '你好,我是按钮'; alert(btn1.innerHTML); // 获取内容
包括html标签,同时保留空格和换行;
通过修改元素的属性(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>
利用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>
通过JS修改元素的大小,颜色,位置等样式。
element.style 行内样式操作
如果样式比较少或者功能简单的情况下使用element.className 类名样式操作
如果样式修改较多的情况下使用
className
会直接更改元素的类名,会覆盖原先的类名
<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>
<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>
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>
<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>
element.属性
:获取属性值;
img.url // 获取img标签的url属性
element.getAttribute('属性');
区别:
element.属性
获取内置属性值(元素本身自属性element.getAttribute('属性');
主要获取程序员自定义的属性
index = "1"
程序员自己添加的属性。
H5规定自定义属性data开头做为属性名并且赋值。
比如
var li = document.querySelector('.ss'); li.setAttribute('data-index', 12); // 结果:1 3)设置属性值
element.属性 = '值'
:设置内置属性值;
img.url // 获取img标签的url属性
element.setAttribute('属性', '值');
区别:
element.属性
设置内置属性值element.setAttribute('属性');
主要设置自定义的属性4)移除属性
element.removeAttribute('属性')
(五) 节点操作
获取元素通常使用两种方式:
- 利用DOM提供的方法获取元素
逻辑性不强,繁琐。- 利用节点层级关系获取元素
利用父子兄节点关系获取元素
逻辑性强,但是兼容性稍差。
网页中的所有内容都是节点(标签,注释,文本,属性等),在DOM中,节点用nodel来表示。
DOM树中的所有的节点均可通过JS进行访问,所有节点均可被修改,也可以创建或删除。
节点至少拥有
nodeType(节点类型)
,nodeName(节点名称)
和nodeValue(节点值)
这三个基本属性。
- 元素节点
nodeType 为 1
- 属性节点
nodeType 为 2
- 文本节点
nodeType 为 3
(文本节点包含文字,空格,换行)在实际开发中,节点操作主要操作的是元素节点。
1. 节点层级
利用DOM树可以把节点划分为不同的层级关系,常见的是
父子兄层级关系
。1)父级节点
语法:
node.parentNode
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的节点没有父节点,则返回null<div class="demo"> <div class="box"> <div class="erweima">Xdiv> 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>我是lili> <li>我是lili> <li>我是lili> <li>我是lili> 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>我是lili> <li>我是lili> <li>我是lili> <li>我是lili> 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);
注意
:
- 如果括号参数为空或者为false , 则是浅拷贝,即只克隆复制节点本身,不克降里面的子节点。
- 如果括号参数为true。则是深度拷贝,会复制节点本身以及里面所有的子节点。
6. 动态创建元素
1)document.write()(了解)
docoment .write是直接将内容写入页面的内容流。但是文档执行完毕,则它会导教页面全部重绘。
<ul> <li>你好li> <li>我号li> ul> <button>按钮button> <script> // document.write('
大家好 '); var btn = document.querySelector('button'); // 页面加载完毕以后才能点击按钮,这时会发生页面重绘 btn.onclick = function() { document.write('大家好 '); } 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 += '百度'; } // 数组形式拼接创建 var array = []; for (let i = 0; i < 100; i++) { array.push('百度'); } 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>
(六) 事件高级
1. 注册事件(绑定事件)
给元素添加事件,称之为
注册事件
;
注册事件有两种方式:传统方式
和方法监听注册方式
1)传统注册方式
利用on开头的事件onclick
btn.onclick = function() {}
特点:注册事件的唯一性
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。2)方法监听注册方式
w3c 标准 推荐方式
addEventListener
它是一个方法
IE9 之前的IE不支持此方法,可使用attachEvent()
代替
特点:同一个元素同一个事件可以注册多个监听器
按注册顺序依次执行3)addEventListener 事件监听处理
eventTarget.addEventListener() 方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定事件时,就会执行事件处理函数。
语法:
eventTarget.addEventListener(type, listener[, useCapture])
参数:
- type:事件类型字符串,比如click, mouseover, 注意这里不要带on
- listener:事件处理函数,事件发生时,会调用该监听函数
- 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)
参数:
- eventNameWithOn:事件类型字符串,比如onclick, onmouseover, 这里要带on
- 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个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
- JS 中只能执行捕获或者冒泡其中的一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。
- addEventListener(type, listener[, useCapture])第三个参数如果是
true
,表示在事件捕获阶段调用事件处理程序;如果是false
,表示在事件冒泡阶段调用事件处理程序。- 实际开发中,很少用事件捕获,更关注冒泡阶段。
- 有些事件是没有冒泡的,比如onblur, onfocus, onmouseover, onmouseleave.
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。
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 不带one.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. 常用的鼠标事件
使用传统的注册方式:加
on
使用addEventListener:不加on
鼠标事件 触发条件 onclick
鼠标点击左键触发 onmouseover
鼠标经过触发 onmouseout
鼠标离开触发 onfocus
获得鼠标焦点触发 onblur
失去鼠标焦点触发 onmousemove
鼠标移动触发 onmouseup
鼠标弹起触发 onmousedown
鼠标按下触发 禁止鼠标右键菜单
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,他们两者之间的差别是
- mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发,mouseenter 只会经过自身盒子触发
- 之所以这样,就是因为mouseenter不会冒泡
- 跟mouseenter 搭配鼠标离开mouseleave 同样不会冒泡
7. 常用的键盘事件
使用传统的注册方式:加
on
使用addEventListener:不加on
键盘事件 触发条件 onkeyup 某个键盘按键被松开时触发 onkeydown 某个键盘按键按下时触发 onkeypress 某个键盘按键按下时触发
不识别 ctrl shift 箭头 等功能键
1)键盘事件对象
键盘事件对象 属性
说明 keyCode 返回该 键
的ASCLL值注意:
onkeydown
和onkeyup
不区分区分字母大写,onkeypress
区分字母大小写。
在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)。
十四. BOM 浏览器对象类型
浏览器对象模型
把「浏览器
」当做一个「对象
」来看待
BOM的顶级对象是window
BOM学习的是浏览器窗口交互的一些对象
BOM是浏览器厂商在各自浏览器上定义的,兼容性较差(一) BOM的构成
window 对象是浏览器的顶级对象,它具有双重角色。
- 它是JS访问浏览器窗口的一个接口。
- 它是一个全局对象。定义在全局作用域中的变量,函数都会变成window对象的属性和方法。
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert(), prompt()等。
注意:window 下的一个特殊属性 window.name,自带的
(二) window 对象的常见事件
1. 窗口加载事件
1. onload
window.onload
是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像脚本文件、CSS文件等),就调用的处理函数。
语法:window.onload = function(){} window.addEventListener('load', function(){});
注意:
- 有了 window.onload 就可以把JS代码写到页面元素的上方,因为 onload 是等页面内容加载完毕,再去执行处理函数。
- window.onload 传统注册方式只能写一次,如果有多个,会以最后一个为准。
- 如果使用 addEventListener 则没有限制。
2. DOMContentLoaded
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表, 图片. flash等等。
语法:window.addEventListener('DOMContentLoaded', function() {});
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响用户的体验.此时用DOMContentLoaded事件比较合适。
2. 调整窗口大小事件
window. onresize
是调整窗口大小加载事件,当触发时就调用的处理函数。
语法:window.onresize = function(){} window.addEventListener('resize', function(){});
只要窗口大小发生像素变化,就会触发这个事件。
我们经常利用这个事件完成应式布局。
window.innerWidth 当前屏幕的宽度
(三) 定时器
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.comport 端口号
可选,省略时使用方案的默认端口 如http的默认端口为80path 路径
由零或多个’/‘符号隔开的字符串,一般用来表示主机上的一个目录或文件地址query 参数
以键值对的形式,通过&符号分隔开来fragment 片段
#后面内容 常见于链接 锚点2. location 对象的属性
对象属性 返回值 location.href *
获取或者设置
整个URLlocation.host 返回主机(域名)
www.itheima.comlocation.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 返回作为该元素带有定位的父级元素
,如果父级都没有定位则返回bodyelement.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
offset 可以得到
任意样式表中的样式值offset 系列获得的数值是
没有单位的offsetWidth
包含padding+border+width
offsetWidth 等属性是
只读属性,只能获取不能赋值
- 所以我们想要
获取元素大小位置
,用offset 更合适
style
style 只能得到
行内样式表中的样式值style.width 获得的是
带有单位的字符串
style.width 获得
不包含padding 和 border 的值
style.width 是
可读写属性,可以获取也可以赋值
- 所以,我们想要
给元素更改值
,则需要用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() 不断移动盒子位置。
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上一个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
注意此元素需要添加定位,才能使用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. 缓动效果原理
缓动动画
就是让元素运动速度有所变化,最常见的是让速度慢慢停下来。
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
- 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离步长
- 停下来的条件是:让盒子位置等于目标位置就停止定时器
- 注意步长值需要取整
往前: 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. 网页轮播图
防止轮播图按钮连续点击造成播放过快。
节流阀的目的
:当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路
:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
- 开始设置一个变量
var flag = true;
if(flag) { flag = false; do something}
关闭水龙头- 利用回调函数 动画执行完毕,
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. 移动端拖动元素
- touchstart, touchmove, touchend 可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值,我们可以使用targetTouches[0] 里面的 pageX 和 pageY
移动端拖动原理
:手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离- 手指移动的距离: 手指滑动中的位置 - 手指刚开始触摸的位置
拖动元素三部曲:
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)页面。
解决方案:
- 禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300 ms 的点击延迟。
- 利用touch事件自己封装这个事件解决延迟。
- 使用插件。fastclick 插件解决 300 ms 延迟。
(三) 移动端常用开发插件
移动端要求的是快速开发,所以我们经常会借助于些插件来帮我完成操作。
JS插件是
=js文件,它遵循定规范编写,方便程序展示效果,拥有特定功能且方便调用。如轮播图和瀑布流插件。
特点:它般是为了解决某个问题而专门存在,其功能单一, 并且比较小。
我们以前写的animate.js也算一个最简单的插件。1. fastclick插件
fastclick 插件解决 300 ms 延迟。使用延时
GitHub 官网地址:https://github.com/ftlabs/fastclick2. Swiper 插件的使用
中文官网地址:https://www.swiper.com.cn/
- 引入插件相关文件;
- 按照规定语法使用。
3. 移动端常用插件
superslide:http://www.superslide2.com/
iscroll:http://github.com/cubiq/iscroll4. 插件的使用总结
- 确认插件实现的功能
- 去官网查看使用说明
- 下载插件
- 打开demo实例文件,查看需要引入的相关文件,并且引入
- 复制demo实例文件中的结构html,样式css以及js代码
(四) 移动端常用开发框架
框架,就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
前端常用的框架有Bootstrap, Vue, Angular, React
等。既能开发PC端,也能开发移动端。1. Bootstrap
Bootstrap 是一个简洁,直观,强悍的前端开发框架,它让 web 开发更迅速,简单。
它能开发PC端,也能开发移动端
Bootstrap JS 插件使用步骤:
- 引入相关js文件
- 复制HTML结构
- 修改对应样式
- 修改相应JS参数
十七. 本地存储
随着互联网的快速发展,基于网页的应用越来越普遍,同时也便的越来越复杂, 为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5 规范提出了相关解决方案。
本地存储特性:
- 数据存储在用户浏览器中
- 设置,读取方便,甚至页面刷新不丢失数据
- 容量较大,sessionStorage 约 5M,localStorage 约 20M
- 只能存储字符串,可以将对象JSON.stringify() 编码后存储
(一) window.sessionStorage
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
存储数据:
sessionStorage.setItem(key, value);
获取数据:
sessionStorage.getItem(key);
删除数据:
sessionStorage.removeItem(key);
删除所有数据:
sessionStorage.clear();
(二) window.localStorage
- 生命周期永久生效,除非手动删除,否则关闭页面也会存在
- 在多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据:
localStorage.setItem(key, value);
获取数据:
localStorage.getItem(key);
删除数据:
localStorage.removeItem(key);
删除所有数据:
localStorage.clear();
十八. jQuery
(一) JavaScript 库
仓库
:可以把很多东西放到这个仓库里面。找东西只需要到仓库里面查找就可以了。
JavaScript库
:即library,是一个封装好的特定的集合(方法和函数)。从封装一大堆函数的角度理解库,就是在这个库中,封装了很多预先定义好的函数在里面,比如动画animate, hide, show,比如获取元素等。
》就是一个js文件,里面对我们原生js代码进行了封装,存放到里面。这样我们可以快速高效的使用这些封装好的功能了。
》比如jQuery,就是为了快速方便的操作DOM,里面基本都是函数(方法)。
常见的JS库:
- jQuery
- Prototype
- YUI
- Dojo
- Ext JS
- 移动端的zepto
这些库都是对原生JS的封装,内部都是用JS实现的,我们主要学习的是jQuery。
(二) jQuery的概念
jQuery 是一个快速,简洁的JS库,倡导写更少的代码,做更多的事情。
j 就是JS;Query 查询;意思是查询js,把js中的DOM操作进行了封装,我们可以快速的查询使用里面的功能。
jQuery封装了JS常用的功能代码,优化了DOM操作。事件处理。动画设计和Ajax交互。
学习jQuery本质:就是学习调用这些函数(方法)
jQuery出现的目的就是加快前端开发人员的开发速度,我们可以非常方便的调用和使用它,从而提高开发效率。
优点:
- 轻量级,不会影响页面加载速度
- 跨浏览器兼容。基本兼容现主流的浏览器
- 链式编程,隐式迭代
- 对事件,样式,动画支持,大大简化了DOM操作
- 支持插件扩展开发。有着丰富的第三方的插件,例如:树形菜单,日期控件,轮播图等
- 免费,开源
1. jQuery 的下载
官网地址:https://jquery.com/
版本:
1x:兼容IE678等低版本浏览器,官网不再更新
2x:不兼容IE678等低版本浏览器,官网不再更新
3x:不兼容IE678等低版本浏览器,是官网主要更新维护的版本
各个版本的下载:https://code.jquery.com/2. jQuery的使用步骤
- 引入jQuery文件
- 使用即可
3. jQuery 的入口函数
1. $(function() { ... // 此处是页面DOM加载完成的入口 $('div').hide(); // 隐藏 }) 2. $(document).ready(function() { ... // 此处是页面DOM加载完成的入口 })
- 等着DOM结构渲染完毕即可执行内部代码,不必等到所有外部代码资源加载完成,jQuery帮我们完成了封装。
- 相当于原生JS中的DOMContentLoaded。
- 不同于原生JS中的load事件是等页面文档,外部的JS文件,css文件,图片加载完毕才执行内部代码。
- 更推荐使用第一种方式。
4. jQuery 的顶级对象 $
- $ 是jQuery的别称,在代码中可以使用jQuery代替
$
,但一般为了方便,通常都直接使用$
。$
是jQuery的顶级对象,相当于原生JS中的window。把元素利用$
包装成jQuery对象,就可以调用jQuery的方法。5. jQuery 对象和 DOM 对象
- 用原生JS来获取的对象就是DOM对象;
var div = document.querySelector('div');
- jQuery方法获取的元素就是jQuery对象;
$('div');
- jQuery对象的本质:利用$对DOM对象包装后生成的对象(伪数组形式存储);
DOM 对象与jQuery对象之间是可以转换的。
因为原生JS比jQuery更大,原生的一些属性和方法jQuery没有给我们封装,要想使用这些属性和方法需要把jQuery对象转换为DOM对象才能使用。
- DOM对象转换为jQuery对象:
$(DOM对象)
$('div')
- jQuery对象转换为DOM对象:(两种方式)
$('div')[index] index是索引号
$('div').get(index) index是索引号
十九. 数据可视化项目
(一) 什么是数据可视化
1. 数据可视化
数据可视化主要目的
:借助于图形化手段,清晰有效地传达与沟通信息。
数据可视化可以把数据从冰冷的数字转换成图形,揭示蕴含在数据中的规律和道理。2. 数据可视化的场景
目前互联网公司常有这么几大类的可视化需求:
- 通用报表
- 移动端图标
- 大屏可视化
- 图编辑&图分析
- 地理可视化
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对象根据修改好的配置生效