方法 | 说明 | 归属 |
---|---|---|
alert(mesg) | 浏览器弹出警示框 | 浏览器 |
console.log(mesg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
<script>
//输入框
prompt("用户输入");
//弹出警示框
alert("警示框")
//控制台输出打印
console.log("用户看不到");
script>
变量声明用关键字var(variable缩写)
<script>
//获取用户输入值并保存在变量中
var name=prompt("输入你的名字")
//将变量中的值通过警示框显示
alert(name)
script>
变量值可以被覆盖,变量名可以一次声明多个,多个变量名之间使用 ","号分隔开来
声明变量的特殊情况
<script>
//只声明不赋值
var sex;
console.log(sex); //报错为 undefined未定义的,程序也不知道里面有什么
//不声明不赋值
console.log(test); //报错为 test变量没有被定义
//不声明只赋值
tel=110;
console.log(tel) //没有报错正常显示
script>
在计算机中,不同的数据所需占用的存储空间是不同的,为了方便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型
JavaSCript是一种弱类型或者说是动态语言,这个意味着不用提前声明变量的类型,程序运行过程中数据类型会被自动确认
//程序运行到等号的右端才能确定age变量的数据类型
var age =10; //age 是数字类型
age = "18"; //age 是字符串类型,可以动态变化
JS将数据分为两大类:
1>八进制与十六进制
<script>
var number =010; //八进制
console.log(number); //打印出十进制 ---8
number =0x15; //十六进制
console.log(number); //打印出十进制 ---21
script>
2>数字最大值与最小值(了解即可)
//数字型的最大值与最小值
console.log(Number.MAX_VALUE);
console.log(Number.MIN_VALUE);
Number.MAX_VALUE : 1.7976931348623157e+308
Number.MIN_VALUE : 5e-324
3>数字的三个特殊值(了解即可)
//三个特殊值
console.log(Infinity);//单词代表无穷大
console.log(-Infinity); //无穷小
console.log(NaN); //非数值
4>isNaN()方法判断是否为一个数字
//判断数值是否是一个非数字,是数字返回一个false,非数字返回一个true
console.log(isNaN(10));
console.log(isNaN('210abc'));
1>建议使用单引号,因为HTML中属性为双引号;引号嵌套使用要 "外双内单、外单内双"规则
转义字符要放在引号里面
转义符 | 解释说明 |
---|---|
\n | 换行符,相当于newLine的意思 |
\\ | 斜杠 \ |
\’ | ’ 单引号 |
\" | " 双引号 |
\t | tab 缩进 |
\b | 空格,b是blank的意思 |
2>字符串的长度 :—>每个字符串都一个length属性可以获得字符串的长度
3>字符串的拼接:—>与Java相同
4>字符串拼接加强
<script>
var age = prompt("请输入您的年龄:");
var str ='您今年已经'+age+'岁了..';//字符串加强拼接
alert(str)
script>
当布尔类型的数据参与数学运算时,true的值为1,false的值为0
<script>
console.log(true+1); //2
console.log(false+1);//1
script>
undefined与字符串相加会被拼接成一个字符串,与数字相加为 NaN;
null与字符串相加会被拼接为一个字符串,与数字1相加结果为1;
<script>
var age = 18;
console.log(typeof age); //number类型
var name ='张三';
console.log(typeof name);//字符串类型
var flag=true;
console.log(typeof flag);//布尔类型
var define=undefined;
console.log(typeof define);//undefinde类型
var value =null;
console.log(typeof value);//object类型
</object>
script>
使用表单、prompt获取过来的数据默认都是字符串类型,不能直接进行简单的数学运算,需要对数据类型进行转变。通俗来讲就是把一种数据类型的变量转换为另一种数据类型
转换的方法有多重,掌握最重要的一种,其他了解即可
方式 | 说明 | 案例 |
---|---|---|
toString | 转换为字符串 | ;var num =1;alert(num.toString); |
String()强制转换 | 转换为字符串 | var num =1;alert(String(num)); |
“+”拼接字符串 | 转换为字符串 | var num =1;alert(num+""); |
方式 | 说明 | 案例 |
---|---|---|
parseInt(string) | 转换为数字 | parseInt(‘18’); |
parseFloat(String) | 转换为数字 | parseFloat(‘15.01’); |
Number() | 转换为数字 | Number(‘12’); |
<script>
//转换为整数型
var num='18';
console.log(parseInt(num)); //18
num='18.01';
console.log(parseInt(num)); //18
num='18px';
console.log(parseInt(num)); //18
num='max18';
console.log(parseInt(num)); //NaN
-----------------------------------------
//转换为浮点型
var num='18';
console.log(parseFloat(num)); //18
num='18.01';
console.log(parseFloat(num)); //18.01
num='18px';
console.log(parseFloat(num)); //18
num='max18';
console.log(parseFloat(num)); //NaN
script>
隐式转换
<script>
var year=prompt("请输入你的出生年份:");
var age=2020 - year; //隐式转换
alert("今年你已经"+age+"岁了");
script>
方式 | 说明 | 案例 |
---|---|---|
Boolean函数 | 其他类型转换为布尔型 | Boolean(‘true’) |
编译型语言:将全部代码编译之后产生一个中间文件供计算机阅读
解释性语言:遇到一行解释一行运行一行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUVNufvb-1607239291398)(img/image-20201108202203236.png)]
开发人员为变量、属性、参数、函数取的名字
JavaScript本身已经使用了的字,不能再用它充当变量名、方法名
实际为预留的“关键字”,虽然现在不是关键字,未来可能成为关键字
四则运算
注:浮点型运算的精度不及整数型,浮点型之间不要进行相等判断
自增自减运算符只能与变量搭配使用,单独使用时前置自加与后置自加效果相同,与其他代码联用时要注意
<script>
var e = 10 ;
var f = e++ + ++e;
console.log(f);//22
script>
两个数据进行比较时使用的运算符,返回一个布尔类型的值
运算符名称 | 说明 | 案例 | 结果 |
---|---|---|---|
< | 小于号 | ||
> | 大于号 | ||
>= | 大于等于 | ||
<= | 小于等于 | ||
== | 等号(会转型) | 37==‘37’ | true |
!= | 不等号 | 37!=37 | false |
=== ==! | 全等,要求值和数据类型一致 | 37=‘37’ | false |
逻辑 | 符号 | 规律 |
---|---|---|
逻辑与 | && | 两边都为true结果为true |
逻辑或 | || | 两边都为false结果为false |
逻辑非 | ! | 结果取反 |
当有多个表达式时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式值成为短路运算
console.log(表达式1 && 表达式2) :如果表达式1为真,则返回表达式2;如果表达式1为假,返回表达式1
<script>
console.log(''&&123&&456);//返回为空
console.log(0&&123&&456);//0
console.log(123&&456);//456
script>
console.log(表达式1 && 表达式2) :如果表达式1为真,则返回表达式1;如果表达式1为假,返回表达式2
console.log(''||123||456);//123
console.log(0||123||456);//123
console.log(123||456||789);//123
<script>
var num=0;
console.log(123||num++);
console.log(num);//0
script>
+=、-=、*=、/=、%=
括号优先级最高,逻辑运算符优先级较低
流程控制就是控制我们的代码按照什么结构来执行
流程控制主要有三种结构:顺序结构、分支结构、循环结构
代码从上打下按照顺序就行执行
由上到下执行代码的过程中,按照不同的条件执行不同的代码得到不同的结果
JavaScript提供了两种分支结构语句:if、switch语句
<script>
var time=prompt("请输入你的数字:");
var result = time >= 10 ? time : '0'+time; //比较数字大小使用了隐式转换
alert(result);
script>
<script>
var fruit = prompt("请输入水果名");
switch(fruit){
case '苹果':
alert('3.5/斤');
break;
case '香蕉':
alert('4.5/斤');
break;
default:
alert("没有此水果")
}
script>
JavaScript中主要有三种类型的循环语句:for、while、do…while
数组是指一组数据的集合,其中每一个数据被称为元素,在数组中可以存放任意类型的数据,数组是一种将一组数据存储在单个变量名下的优雅方式
<script>
//创建数组的第一种方式
var arr1=new Array();
//创建数组的第二种方式
var arr2=[1,2,'3',true]; //存放数据没有限制
script>
数组可以通过索引来访问、修改对应的数组元素
通过循环将数组中的元素取出来
<script>
//修改数组长度
var arr=['1','2','3'];
arr.length=5;
console.log(arr[3]);//empty
console.log(arr[4]);//empty
script>
//修改数组索引,如果数值不存在则追加,如果存在则覆盖
var arr=['1','2','3'];
arr[3]='4';
arr[4]='5';
console.log(arr[3]);
console.log(arr[4]);
如果将字符串直接赋值给数组变量,则数据类型发生变化由数组变为了字符串
<script>
var arr=['1','2','3'];
var newarray=[];
//i的值存的是数组中的最后一个元素的索引
for(var i =arr.length-1;i>=0;i--){
//将旧数组的最后一个元素赋予新数组的第一个位置
newarray[newarray.length] = arr[i];
}
console.log(newarray);
script>
外层for循环控制趟数,内部for循环控制交换次数
在JS代码中,会有许多相同的代码或者功能相似,代码需要被大量复用,此时函数的作用就体现出来了
函数的使用分为两步,声明函数和调用函数
形式上的参数
实际上的参数
参数个数 | 结果 |
---|---|
实参个数==形参个数 | 结果正常执行 |
实参个数 > 形参个数 | 只取到形参的个数 |
实参个数 < 形参个数 | 多出的参数为underfined,结果为NaN |
个别情况我们希望函数能给调用者一个执行结果或者叫返回值
通过return value;语句可以将结果或者值返回给调用者
return后的语句不会被执行
return只能返回一个值,如果逗号分隔多个值,以最后一个为准,可以将返回的多个值放到数组中,return [value1,value2…];
函数都是有返回值的:
arguments是函数的内置对象,内部可以存储传递的所有实参,当不确定有多少个实参传递的时候,可以通过此对象来获取
<script>
//arguments对象可以接受所有的参数
function fn(){
console.log(arguments);
}
fn(1,2,3,5);
script>
arguments展示形式是一个伪数组,因此可以进行遍历,伪数组的特点:
<script>
//只有函数才有arguments对象
function fn(){
for(var arr=0;arr<arguments.length;arr++){
console.log(arguments[arr]);
}
}
fn(1,2,3,5);
fn('3','2','1','0');
script>
<script>
//只有函数才有arguments对象
function fn(){
var max=arguments[0];
for(var i =1;i<arguments.length;i++){
if(arguments[i]>max){
max=arguments[i];
}
}
return max;
}
var result =fn(11,23,53,59,2);
console.log(result);
script>
每个函数都会完成特定的功能,功能与功能之间有联系,所以函数与函数之间可以互相调用
function fn(){
}
函数表达式与声明变量相差无几,只不过变量里面存放的是函数而不是变量值
//函数表达式可以传递参数
var fn = function(aru){
}
作用域就是代码名字在某个范围内起作用和效果,更重要的是减少命名冲突
JS作用域分为局部作用域与全局作用域
全局下都可以使用,注意:如果在函数体内部,没有声明直接赋值的变量也属于全局变量
局部作用域的变量,只能在函数体内部使用,函数的参数也是局部变量
在ES6以后新增了块级作用域,被“{ }”包裹的为块级作用域,外部不可以访问里面的变量
在函数内部再声明一个函数,内部函数访问外部函数的变量采取的就是链式查找方法,就近原则,这种结构我们称之为作用域链
<script>
function f1(){
var num=123;
function f2(){
console.log(num); //打印的是123
}
f2();
}
var num =456;
f1();
script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I7PzJ6RH-1607239291408)(img/image-20201113152207919.png)]
1》JS代码有浏览器中的JS解析器执行的,解析器在运行JS代码时分为两步:预解析和代码执行
2》预解析分为 变量预解析(变量提升)和函数预解析 (函数提升)
变量提升就是把所有的变量声明提升到当前的作用域的最前面,不提升赋值操作
<script>
//所以应该在打印变量语句之前声明变量
console.log(num);
var num=10; //undefind
//JS解析器执行顺序
/*
var num;
consolo.log(num);
num=10;
所以会出现未定义
*/
script>
函数提升就是把所有的函数声明(function关键字)提升到当前作用域的最前面,不调用函数
//应该在函数声明以后再调用函数
<script>
fn();
var fn=function(){
console.log("---");
}
//报错,JS解析器执行顺序为
/*
var fn;
fn();//此时没有此函数,所以会报错
fn = function(){
consoloe.log("---");
}
*/
script>
在JS中,对象是属性与方法的结合
完整的、有效的保存信息,例如一个人的信息
在JS中,创建对象有三种方式
对象字面量:{ } 里面包含了表达这个具体事物(对象)的属性和方法
<script>
/*
多个属性之间用逗号分隔开
值为键值对的形式存在
方法为匿名方法
*/
var obj={
name:'zhangsan',
age:'18',
sayHi:function(){
console.log("hello")
}
}
script>
属性的调用两种方法:1>对象名.属性名 2>对象名[‘属性名’]
<script>
var obj = new Object();//创建了一个空的对象
//为对象添加属性与方法
obj.name='zhangsan';
obj.age='12';
obj.sayHi=function(){
console.log("hello")
}
//调用对象的属性与方法
console.log(obj.name);
console.log(obj['age']);
obj.sayHi();
script>
构造函数:是一种特殊的函数,主要用来初始化对象
<script>
function Method(uname,age,sex){
this.uname=uname;
this.age=age;
this.sex=sex;
this.sing=function(sing){
console.log(sing)
}
}
var ldh=new Method('刘德华',18,'男');
console.log(ldh);
ldh.sing('冰雨');
script>
new关键字的执行过程:
for…in 语句用于对数组或者对象的属性进行循环操作(与Java 的foreach功能类似)
var ldh=new Method('刘德华',18,'男');
for(var k in ldh){
console.log(k); //得到的是 属性名
console.log(ldh[k]); //得到的是 属性值
}
内置对象就是JS内部自带的一些对象,这些对象的功能已经实现可以直接拿来使用,优点就是帮助我们最快的开发
Math数学对象,不是一个构造函数而是静态的,可以直接使用其中的属性与方法
属性与方法名 | 功能 |
---|---|
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入就近取值, 注:-3.5 结果为 -3(.5向大取) |
Math.abs() | 绝对值 |
Math.max/Math.min | 最大值与最小值 |
随机产生一个数字, 数字范围为: 0<=x<1
<script>
function getRandom(min,max){
return Math.floor(Math.random()*(max-min+1))+min;
}
console.log(getRandom(1,20));
script>
<script>
function getRandom(min,max){
return Math.floor(Math.random()*(max-min))+min;
}
console.log(getRandom(1,20));
script>
日期对象 一个构造函数,必须创建对象来创建日期对象,构造方法中不传入参数默认为当前时间,参数可以为数字也可以为字符串
看方法名就知道功能,注:月份是从 0 开始,需要 +1
<script>
//返回当前总共毫秒数的方法
var date=new Date();
console.log(date.valueOf());
console.log(date.getTime());
//构造方法之前加上 + 号即可
var date1 =+new Date();
console.log(date1);
script>
H5新增的获得毫秒数的方法,无需创建日起对象就可以使用
console.log(Date.now());
<script>
function countDown(time){
var nowTime=+new Date(); //返回当前毫秒数
var inputTime =+new Date(time); //返回用户输入的时间毫秒数
var times=(inputTime - nowTime)/1000; //times是剩余时间秒数
var d =parseInt(times/60/60/24); //天
var h =parseInt(times/60/60%24); //小时
var m =parseInt(times/60%60); //分钟
var s =parseInt(times%60); //秒
return d + '天'+h + '时' + m + '分钟' + s + '秒';
}
script>
<script>
var arr1 = new Array(); //创建了一个空数组
var arr2 = new Array(2); //表示数组长度为2,内容为空
var arr3 = new Array(2,3); //表示为[2,3],里面有两个数据
script>
<script>
var arr ={
};
console.log(arr instanceof Array); //false
script>
可以直接判断出来
方法 | 说明 | 返回值 |
---|---|---|
push(…) | 末尾添加元素,修改原数组 | 返回新的长度 |
pop() | 删除最后一个元素,数组长度-1,修改原数组 | 返回它删除的元素的值 |
unshift(…) | 向数组开头添加元素,修改原数组 | 返回新的长度 |
shift() | 删除数组第一个数组,数组长度-1,修改原数组 | 返回删除的元素的值 |
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 颠倒数组中元素的顺序 | 改变原来的数组,返回新数组 |
sort() | 对数组元素进行排序 | 改变原来的数组,返回新数组 |
sort([compareFunction])中的参数是可选的用来指定某种排序顺序,如果省略则默认按照元素的Unicode位点进行排序
<script>
var arr =[99,58,64,87,11,3];
arr.sort(function(a,b){
return a - b; //升序排序 , b-a 降序
});
console.log(arr);
script>
方法名 | 说明 | 返回值 |
---|---|---|
indexOf() | 数组中查找给定元素的第一个索引 | 元素存在返回索引值,否则返回-1 |
lastIndexOf() | 数组中的最后一个索引 | 元素存在返回索引值,否则返回-1 |
方法名 | 说明 | 返回值 |
---|---|---|
toString | 数组转换为字符串 | 返回一个字符串 |
join(‘分隔符’) | 字符串用给定分隔符进行分隔 | 返回一个字符串 |
<script>
var str=[1,3,'4'];
console.log(str.join('-')) //[1-3-4]
script>
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组不影响原数组 | 返回一个新数组 |
slice() | 数组截取(begin,end),end取不到 | 返回被截取产生的新数组 |
基本包装类型就是把简单数据类型包装为复杂数据类型,这样基本数据类型就会有了属性与方法
JS中提供了三种特殊的引用类型:String、Number、Boolean
字符串中的所有方法都不会修改字符串本身,操作完成后会返回一个新的字符串
<script>
var str ='春天来了,春天走了,春天又来了';
console.log(str.indexOf('春'),5); //从索引号是5的位置开始查找并返回位置
script>
<script>
var str='abcodfdfofdaogao';
var index=str.indexOf('o');
var num=0;
while(index!==-1){
console.log(index);
num++;
index=str.indexOf('o',index+1);
}
script>
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符 | str.charAt(0) |
charCodeAt(index) | 返回指定位置的字符的ASCII码 | str.charCodeAt(0) |
str[index] | 获取指定位置字符 | HTML5支持,与charAT相同 |
方法名 | 说明 | 返回值 |
---|---|---|
split(‘分隔符’) | 指定分隔符将数组分割开来 | |
replace(参数1,参数2) | 参数1位被替换的字符,参数2位要替换成的字符 | |
substr(参数1,参数2) | 参数1位索引号,参数2为取字符个数 |
<script>
var str='abc-def-fgd';
var str1 = str.split('-');
console.log(str1); //['abc','def','fgd']
script>
简单数据类型保存在栈中
简单数据传参是将栈中的值复制一份传给了形参
<script>
function fn(a){
a++;
console.log(a); // 11
}
var x = 10;
fn(x);
console.log(x); // 10
script>
复杂数据类型保存在堆区中
复杂数据类型传值是将引用的内存地址复制一份传给了形参
<script>
function Person(name){
this.name = name;
}
function fn(x){
console.log(x.name);//tom
x.name="jack";
console.log(x.name);//jack
}
var p = new Person('tom');
console.log(p.name); //tom
fn(p);
console.log(p.name); //jack
script>
JS=ECMScript+DOM+BOM,而Web APIs就是DOM与BOM
JS基础阶段:
Web APIs阶段:
API就是已经写好的程序,直接调用即可,不用关心里面的代码以及功能是如何实现的一种接口
浏览器提供的一套操作浏览器和页面元素的API(BOM、DOM)
文档对象模型,是一个标准编程接口
利用DOM接口可以改变页面内容、结构和样式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tYqTgTwV-1607239291413)(img/DOM树.png)]
DOM把以上内容都看做是对象
获取元素之前元素必须被网页加载完毕,所以script标签应该写在内容下方
获取页面元素的四种方式:
参数的id是大小写敏感的字符串
<body>
<div id='time'>2020-11-16div>
<script>
var times = document.getElementById('time');
console.log(times); //包括标签等将内容完全打印到控制台
console.log(typeof times); //判断节点是否为对象
console.dir(times); //新增方法,返回元素对象并且可以查看更多属性和方法
script>
body>
返回的内容以伪数组的形式存储,可以对其进行遍历得到对象。如果数组中没有元素,则为空伪数组
父元素必须是单个对象(必须指明是哪个对象),获取不会获得父元素只有子元素;通常情况下获取父标签可以使用id获取再获取子类
<body>
<ul>
<li>1li>
<li>2li>
<li>3li>
ul>
<script>
//返回的是伪数组,可以进行遍历获得对象
var lis = document.getElementsByTagName('li');
for(var i =0;i<lis.length;i++){
console.log(lis[i]);
}
//获得父标签内部的子标签
var ull =document.getElementsByTagName('ul'); //获得父标签 ull[]数组
//伪数组中只有一个父标签,指定它
console.log((ull[0].getElementsByTagName('li')));
script>
body>
1.通过类名获取元素,返回的是伪数组
<body>
<div class="box1">盒子1div>
<script>
//返回的是伪数组形式存储
var box1 = document.getElementsByClassName('box1');
console.log(box1);
script>
body>
2.querySelector() 返回指定选择的第一个元素对象,里面的选择器需要加上 表明符号
3.querySelectorAll() 返回指定选择器的所有元素对象**(返回的应该是伪数组)**
<body>
<div class="box1">盒子1div>
<div id="box2">盒子2div>
<div class="box1">盒子3div>
<script>
//两个类选择器,只会拿到第一个
var boxes = document.querySelector('.box1');
console.log(boxes);
//指定选择器为ID选择器
boxes = document.querySelector('#box2');
console.log(boxes);
//指定标签,选择所有
boxes = document.querySelectorAll('div');
console.log(boxes)
script>
body>
1.获取body标签
<script>
var bodyEle = document.body;
console.log(bodyEle);
script>
2.获取html标签
<script>
var htmlEle = document.documentElement;
console.log(htmlEle);
script>
JS有能力使我们创建动态页面,而事件是可以被JS侦测到的行为,网页中每个元素都可以产生某些可以被触发JS事件
事件源:事件被触发的对象,例如 按钮(事件源) 被点击触发
事件类型:如何触发,例如鼠标点击、鼠标移出等
事件处理程序:通过一个函数赋值的方式完成
<body>
<body>
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
JS的DOM操作可以改变网页的内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等
element.innerText 可以改变页面的内容(或者可以说是指定便签内的内容)
<body>
<p>手动点击显示时间p>
<button>时间查询button>
<div>显示时间的区域div>
<hr>
<p>加载页面显示时间p>
<h3>显示时间的区域h3>
<script>
//1.获取事件源
var btn = document.querySelector('button');
var div = document.querySelector('div');
//2.绑定事件
btn.onclick = function(){
div.innerText = getDate();
}
function getDate(){
var times = new Date();
var year = times.getFullYear();
var month = times.getMonth()+1;
var day = times.getDay();
var hour = times.getHours();
var min = times.getMinutes();
var second = times.getSeconds();
return year+'年'+month+'月'+day+'日'+hour+'时'+min+'分'+second+'秒';
}
//--------------------------------------------------------------------------
var h3 = document.querySelector('h3');
h3.innerText = getDate();
script>
body>
1.element.innerText无法识别html标签,去除html标签、空格与换行(非标准)
<body>
<div>div>
<script>
var div = document.querySelector('div');
div.innerText = '时间为:'+new Date(); //无法识别HTML代码
script>
body>
2.element.innerHTML识别html标签(W3C标准),保留空格与换行
<body>
<div>div>
<script>
var div = document.querySelector('div');
div.innerHTML = '时间为:'+new Date(); //可以识别,字体变为粗体
script>
body>
3.两个属性可以读写,可以获取元素里面的内容
<body>
<p>
我是文字
<span>第二行为红色的字体span>
p>
<div>div>
<script>
var p = document.querySelector('p');
//console.log(p.innerText);//将p标签内容打印出来
console.log(p.innerHTML); //控制台输出 换行
script>
body>
修改src属性–>element.src
<body>
修改alt属性
imgs.title = '张学友'
用法大致相同,无须赘述
利用DOM可以操作:type、value、checked、selected、disable
1.修改value值
<body>
<input type="text" value="修改里面的值...." /><br>
<button>按钮button>
<script>
//1.获取对象元素
var input = document.querySelector('input');
var btn = document.querySelector('button');
//2.注册事件
btn.onclick = function(){
//input.innerHTML='修改失败'; 这种方式是普通盒子才能修改
input.value = '修改成功'; //表单元素必须修改value值才可以
}
script>
body>
2.禁用
btn.disabled = true; //按钮被点击一次后被禁用
this.disabled = true; // 这个也可以
总结一下:修改表单元素属性值与修改元素的属性用法相同,不再赘述
我们可以通过JS修改元素的大小、颜色、位置等样式(例如修改CSS样式)
当样式比较少时,修改比较简练,但是当样式太多时,一个一个修改就会非常麻烦
<body>
<style type="text/css">
div{
width: 200px;
height: 200px;
background-color: black;
}
style>
<div>div>
<script>
//1.获取元素对象
var div = document.querySelector('div');
//2.注册事件
div.onclick = function(){
//div.style.backgroundColor = 'purple';
//this代表调用样式属性的对象,也就是指div这个元素对象
this.style.backgroundColor = 'red' ;
this.style.width = '400px';
this.style.height = '100 px';
}
script>
body>
修改样式过多繁杂且麻烦,直接更改classname就可以直接修改样式,方便快捷
element.className = ‘类名’ 即可:会更改原来的类名并覆盖掉(如果不想被覆盖,则可以写多个类名并加上空格即可)
<body>
<style type="text/css">
.message{
color:grey;
}
.wrong{
color: red;
}
.right{
color: green;
}
style>
<input type="text"/>
<div class="message">请输入1~16位密码div>
<script>
var input = document.querySelector('input');
var div = document.querySelector('div');
input.onblur = function(){
if(input.value.length <6 || input.value.length >16){
div.innerHTML = '密码长度不对'
div.className = 'message wrong'; //这样写保存两个类名,防止被覆盖和页面出错误
}else{
div.innerHTML = '密码格式正确'
div.className = 'message right';
}
}
script>
body>
注意:
个人认为已经完善(除前端外,大致代码逻辑)
<body>
<input type="password"/><button>显示密码button>
<script>
//1.获取对象元素
var input = document.querySelector('input');
var btn = document.querySelector('button');
var flag = 1;
//2.注册事件
btn.onclick = function(){
if(!input.value==''){
if(flag ==1){
input.type = 'text';
btn.innerHTML = '隐藏密码'
flag =0;
}else {
input.type = 'password';
btn.innerHTML = '显示密码'
flag =1;
}
}
}
script>
body>
display.none:隐藏元素 display.block:显示元素
<body>
<style type="text/css">
div{
width: 200px;
height: 200px;
background-color: black;
}
style>
<div>div>
<br>
<input type="button" value="隐藏"/>
<script>
//1.获取元素对象
var btn = document.querySelector('input');
var div = document.querySelector('div');
//2.注册事件
btn.onclick = function(){
div.style.display='none';
}
script>
body>
当鼠标点击文本框内容时,默认文字隐藏;鼠标离开文本框,默认文字显示
<body>
<style type="text/css">
input{
color:#999;
}
style>
<input type="text" value="手机" />
<script>
//1.获取元素对象
var text = document.querySelector('input');
//2.注册事件
//获得焦点
text.onfocus = function(){
if(text.value ==='手机'){
text.value = '';
}
this.style.color = '#333';
}
//失去焦点
text.onblur = function(){
if(text.value ===''){
text.value='手机';
}
this.style.color ='#999';
}
script>
body>
<head>
<meta charset="utf-8">
<title>title>
<style type="text/css">
.background-black{
background-color: black;
}
.background-white{
background-color: white;
}
style>
head>
<body class="background-white">
<input type="button" value="开关灯"/>
<script>
var body = document.body;
var input = document.querySelector('input');
var flag = 1 ;
input.onclick = function(){
//flag为1说明是开灯效果
if(flag ===1){
body.className = 'background-black';
flag = 0;
}else{
body.className = 'background-white';
flag = 1;
}
}
script>
body>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfZNHzVZ-1607239291423)(img/image-20201122140509370.png)]
如果 有一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
<body>
<input type="button" value="按钮1"/>
<input type="button" value="按钮2"/>
<input type="button" value="按钮3"/>
<input type="button" value="按钮4"/>
<input type="button" value="按钮5"/>
<script>
//返回的是一个伪数组存储数据
var inputs = document.getElementsByTagName('input');
//为每一个按钮绑定事件
for(var i=0;i<inputs.length;i++){
//绑定事件
inputs[i].onclick = function(){
//先进行for循环,清除所有原先样式
for(var j =0;j<inputs.length;j++){
inputs[j].style.color = '';
}
//修改全部原先样式后单独修改这个样式
this.style.color ='pink';
}
}
script>
body>
<html>
<head>
<meta charset="utf-8">
<title>title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
body{
background-image: url(imgs/20201115.jpg);
}
li{
list-style: none;
}
.baidu{
overflow: hidden;
margin: 100px auto;
background-color: #fff;
width: 650px;
padding-top: 3px;
}
.baidu li{
float: left;
margin: 0 1px;
cursor: pointer;
}
.baidu img {
width: 100px;
}
style>
head>
<body>
<ul class="baidu">
<li><img src="imgs/20201115.jpg">li>
<li><img src="imgs/20201116.jpg">li>
<li><img src="imgs/20201117.jpg">li>
<li><img src="imgs/20201118.jpg">li>
<li><img src="imgs/20201119.jpg">li>
<li><img src="imgs/20201120.jpg">li>
ul>
<script>
//获得指定元素对象img
var imgs = document.querySelector('.baidu').querySelectorAll('img');
for(var i =0;i<imgs.length;i++){
imgs[i].onclick = function(){
//修改body的样式属性
document.body.style.backgroundImage='url('+this.src+')';
}
}
script>
body>
html>
需要新的鼠标事件:鼠标经过和鼠标离开
<html>
<head>
<meta charset="utf-8">
<title>title>
<style type="text/css">
.bg {
background-color: springgreen;
}
style>
head>
<body>
<table border="1px" width="600px" align="center">
<thead>
<tr>
<td>代码td>
<td>名称td>
<td>人数td>
tr>
thead>
<tbody>
<tr>
<td>101td>
<td>javatd>
<td>1000td>
tr>
<tr>
<td>102td>
<td>pythontd>
<td>1200td>
tr>
<tr>
<td>103td>
<td>C++td>
<td>800td>
tr>
tbody>
table>
<script>
//获取需要改变样式的指定的所有的行
var trs = document.querySelector('tbody').querySelectorAll('tr');
//利用循环将每一行都绑定上时间
for(var i =0;i<trs.length;i++){
//绑定鼠标经过事件
trs[i].onmouseover = function(){
//鼠标经过,为次行单独增加一个CSS背景颜色样式
this.className='bg';
}
trs[i].onmouseout =function(){
//鼠标移出,把此行的样式取消掉
this.className='';
}
}
script>
body>
html>
<body>
<table border="1px" width="600px" align="center">
<thead>
<tr>
<th><input type="checkbox" id='checkedAll'/>th>
<th>课程th>
<th>价格th>
tr>
thead>
<tr>
<td><input type="checkbox"/>td>
<td>javatd>
<td>10000td>
tr>
<tr>
<td><input type="checkbox"/>td>
<td>pythontd>
<td>12000td>
tr>
<tr>
<td><input type="checkbox"/>td>
<td>C++td>
<td>8000td>
tr>
tbody>
table>
<script>
//获得总复选框对象
var checkedAll = document.getElementById('checkedAll');
//获得所有的复选框对象
var tb = document.querySelector('#tb').querySelectorAll('input');
//一、全选按钮点击,所有按钮全部选中,否则全部为选中
//第二种方法
checkedAll.onclick=function(){
for(var i =0;i<tb.length;i++){
//this.checked代表的是全选框的状态
tb[i].checked = this.checked;
}
}
/*
var flag =1;
第一种方法,使用if判断
checkedAll.onclick = function(){
if(flag===1){
for(var i =0;i
//二、按钮全被选中全选按钮也被选中
//外层for循环作用为为每一个复选框绑定一个事件
for(var i = 0;i<tb.length;i++){
tb[i].onclick = function(){
var flag = true;
//内存复选框作用为判断所有的复选框的状态,如果全都被点击,则flag值默认不变
//如果有一个复选框没有被选中,则将flag的值改变
for(var i = 0;i<tb.length;i++){
if(!tb[i].checked){
flag =false;
break; //只要有一个按钮没有被选中,下来的判断没有意义
}
}
checkedAll.checked = flag;
}
}
script>
body>
5.9 自定义属性操作
自定义属性的目的是为了保存使用数据。有些数据可以保存到页面中而不用保存到数据库中
为了防止开发人员自定义属性与自带属性产生歧义,开发规定:自定义属性按照 data- 开头做属性名并赋值
5.9.1 获取属性值
- element.属性 :获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’) :主要获得自定义属性值(开发人员自定义的属性)
<body>
p>
<script>
var p = document.querySelector('p');
console.log(p.id);
console.log(p.getAttribute('index'));
script>
body>
5.9.2 设置属性值
- element.属性=‘值’
- element.setAttribute(‘属性名’,‘属性值’)
<body>
5.9.3 移除属性值
removeAttribute(‘属性’)移除属性
5.9.4 h5新增获取属性值
<body>
div>
<script>
var div = document.querySelector('div');
div.setAttribute('name','divName');
//常规方法,兼容性强
console.log(div.getAttribute('name'));
//h5新增的方法 dataset 相当于一个集合 ,只能获取以 data 开头的属性
console.log(div.dataset.name);
script>
body>
总结:自带的属性值与开发人员设置的属性值使用分开的方法操作
6 Tab拦切换操作(重点)
点击Tab拦会切换不同的内容
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
.tab {
width: 978px;
margin: 100px auto;
}
.tab_list {
height: 39px;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
}
.tab_list .current {
background-color: #c81623;
color: #fff;
}
.item_info {
padding: 20px 0 0 20px;
}
.item {
display: none;
}
style>
head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍li>
<li>规格与包装li>
<li>售后保障li>
<li>商品评价(50000)li>
<li>手机社区li>
ul>
div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
div>
<div class="item">
规格与包装模块内容
div>
<div class="item">
售后保障模块内容
div>
<div class="item">
商品评价(50000)模块内容
div>
<div class="item">
手机社区模块内容
div>
div>
div>
<script>
// 获取元素
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
// for循环绑定点击事件
for (var i = 0; i < lis.length; i++) {
// 开始给5个小li 设置索引号
lis[i].setAttribute('index', i);
lis[i].onclick = function() {
// 1. 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式
// 干掉所有人 其余的li清除 class 这个类
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
// 留下我自己
this.className = 'current';
// 2. 下面的显示内容模块
var index = this.getAttribute('index');
console.log(index);
// 干掉所有人 让其余的item 这些div 隐藏
for (var i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
// 留下我自己 让对应的item 显示出来
items[index].style.display = 'block';
}
}
script>
body>
html>
7.节点操作
7.1 获取元素的两种方式
通常获取元素使用两种放肆:
- 利用DOM提供的方法获取元素
- document.getElementById()等
- 逻辑性不强、繁琐
- 利用节点层级关系获取元素
- 利用父子兄弟节点获取元素
- 逻辑性强,但是兼容性差
这两种方法都可以获取元素,但是节点获取元素稍微简单
7.2 节点概述
网页中所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。HTML DOM树中的所有节点均可以通过JS进行访问,所有的HTML元素(节点)均可以修改,也可以创建或者删除
一般的,节点至少拥有节点类型、节点名称、节点值三个基本属性
- 元素节点 node Type 为1
- 属性节点 node Type 为2
- 文本节点 node Type 为3(文本节点包含文字、空格、换行等)
在实际开发中,实际操作的是元素节点
7.3 节点层级
利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
7.3.1 父级节点
node.parentNode:只会获得距离最近的父级节点
<body>
<div>
<p>p>
div>
<script>
//1.获取父级节点
var son = document.querySelector('p');
console.log(son.parentNode)
script>
body>
7.3.2 子节点
7.3.2.1node.childrenNodes
会返回所有的子级节点,返回值为一个数组(因为子级节点较多)
<body>
<ul>
<li>li>
<li>li>
<li>li>
ul>
<script>
//1.获取父级节点
var father = document.querySelector('ul');
console.log(father.childNodes);//长度为7,因为换行为文本节点
script>
body>
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等;如果需要其中的元素节点,需要专门处理(根据节点type值判断是否为元素节点),所以一般不使用子级节点
7.3.2.2 node.children
只是一个只读属性,返回所有的自元素节点。它只返回所有的元素节点,其余节点不会返回(虽然不是标准但是得到各个浏览器支持)
<body>
<ul>
<li>li>
<li>li>
<li>li>
ul>
<script>
//1.获取父级节点
var father = document.querySelector('ul');
console.log(father.children);//长度为7,因为换行为文本节点
script>
body>
7.3.2.3 获取首尾子元素
firstChild/lastChild:一般会获取文本节点,但这并不满意
<body>
<ul>
<li>li>
<li>li>
<li>li>
ul>
<script>
//1.获取父级节点
var father = document.querySelector('ul');
console.log(father.firstChild); //text
console.log(father.lastChild); //text
script>
body>
7.3.2.4 获取首尾子元素
node.firstElementChild()/node.lastElementChild():这个可以解决指定获取首位 子元素 而不是其他文本元素,然而可能会需要高版本浏览器支持
<body>
<ul>
<li>li>
<li>li>
<li>li>
ul>
<script>
//1.获取父级节点
var father = document.querySelector('ul');
console.log(father.firstElementChild);
console.log(father.lastElementChild);
script>
body>
总结:在实际开发中会使用数组的方式来获取最后一个或者第一个元素
7.3.2.5下拉菜单的实现
核心思路就是鼠标经过时显示鼠标移出后隐藏
<script>
// 1. 获取元素
var nav = document.querySelector('.nav');
var lis = nav.children; // 得到4个小li
// 2.循环注册事件
for (var i = 0; i < lis.length; i++) {
//鼠标移入显示
lis[i].onmouseover = function() {
this.children[1].style.display = 'block';
}
//鼠标移出隐藏
lis[i].onmouseout = function() {
this.children[1].style.display = 'none';
}
}
script>
7.3.3 兄弟节点
node.nextSibling:返回当前元素的下一个兄弟节点/node.previousSiling:返回当前元素的上一个兄弟节点(缺点就是获得的可能是文本节点)
<body>
<span>上span>
<span id="mid">中span>
<span>下span>
<script type="text/javascript">
var mid = document.getElementById('mid');
console.log(mid.nextSibling); // text
console.log(mid.previousSibling) //text
script>
body>
所以,会有特殊的获取(指定获取元素,但是有兼容性问题):
<body>
<span>上span>
<span id="mid">中span>
<span>下span>
<script type="text/javascript">
var mid = document.getElementById('mid');
console.log(mid.nextElementSibling);
console.log(mid.previousElementSibling);
script>
body>
7.4 创建节点
document.createElement(‘tagName’):创建指定的HTML元素,因为这些元素原先不存在,根据需求动态生成,所以也称为动态创建元素节点
7.5 添加节点
7.5.1node.appendChild()
将一个节点添加到指定父节点的子节点列表末尾,可以理解为数组的push方法
<body>
<ul>ul>
<script type="text/javascript">
//创建一个节点
var li = document.createElement('li');
//获取父节点并添加新节点
var ul = document.querySelector('ul');
ul.appendChild(li);
script>
body>
7.5.2node.insertBefore()
参数为两个,一个是插入的子元素,另一个是指定元素前面
<body>
<ul>
<li>213li>
ul>
<script type="text/javascript">
//创建一个节点
var li = document.createElement('li');
//获取父节点
var ul = document.querySelector('ul');
//指定位置添加新元素
ul.insertBefore(li,ul.children[0]);
script>
body>
7.5.3 简单的留言板案例
<body>
<style type="text/css">
li{
background-color:pink;
}
style>
<textarea>textarea><br/>
<button>留言button><br/>
<ul>ul>
<script type="text/javascript">
//获取动态添加子元素的父节点
var ul = document.querySelector('ul');
//获取按钮操作
var btn = document.querySelector('button');
//获取文本域对象
var textarea = document.querySelector('textarea');
//注册事件
btn.onclick = function(){
//判断文本框的值是否为空,如果为空就不用创建新标签
if(textarea.value == ''){
return false;
}else{
//获取文本框中的值
var value = textarea.value;
//(1)创建节点
var li = document.createElement('li');
//获取文本框的值并赋予li标签
li.innerHTML = textarea.value;
//(2)添加节点(注意不要加上引号)
// ul.appendChild(li);
//最新的留言应该在上面,所以使用这个添加元素的方法
ul.insertBefore(li,ul.children[0]);
textarea.value = '';
}
}
script>
body>
7.6 删除节点
node.removeChile(child[id]):删除父节点中的指定子节点
<body>
<ul>
<li>熊大li>
<li>熊二li>
<li>吉吉li>
ul>
<button>删除button>
<script type="text/javascript">
//获取删除按钮
var btn = document.querySelector('button');
//删除节点
var ul = document.querySelector('ul');
//绑定事件
btn.onclick = function(){
//判断:如果子标签已经删除干净,则此按钮失效
if(ul.children.length == 0){
//this代表的当前对象也就是 btn
this.disabled = true;
}
else{
ul.removeChild(ul.children[0]);
}
}
script>
body>
7.6.1 删除留言案例
<body>
<style type="text/css">
li{
background-color:pink;
}
style>
<textarea>textarea><br/>
<button>留言button><br/>
<ul>ul>
<script type="text/javascript">
//获取动态添加子元素的父节点
var ul = document.querySelector('ul');
//获取按钮操作
var btn = document.querySelector('button');
//获取文本域对象
var textarea = document.querySelector('textarea');
//注册事件
btn.onclick = function(){
//判断文本框的值是否为空,如果为空就不用创建新标签
if(textarea.value == ''){
return false;
}else{
//获取文本框中的值
var value = textarea.value;
//(1)创建节点
var li = document.createElement('li');
//获取文本框的值并赋予li(还添加了一个链接标签)
li.innerHTML = textarea.value + "删除留言";
//(2)添加节点
ul.insertBefore(li,ul.children[0]);
textarea.value = '';
//(3)删除元素,获取所有的删除链接
var as = document.querySelectorAll('a');
//为每一个链接添加点击事件
for(var i = 0;i<as.length;i++){
as[i].onclick = function(){
//删除的语法是父亲里面的孩子
//删除的节点是li,语法格式就是删除ul的子元素,参数为当前对象a的父元素,有点绕呵
ul.removeChild(this.parentNode);
}
}
}
}
script>
body>
7.7 复制节点
node.cloneNode():复制节点,也叫克隆节点;该方法会返回调用该方法的节点的一个副本
注意:如果括号内参数为空或为false,则是浅拷贝,即只拷贝节点本身而不会克隆内部子节点
<body>
<ul>
<li>1li>
<li>2li>
<li>3li>
ul>
<script type="text/javascript">
//获取父节点
var ul = document.querySelector('ul');
//浅拷贝,只拷贝节点内部子节点不会拷贝
var li = ul.children[0].cloneNode();
//拷贝内容
var lii = ul.children[0].cloneNode(true);
ul.appendChild(li);
ul.appendChild(lii);
script>
body>
7.7.1 动态生成表格
<body>
<table border="1" align="center" width="600px">
<thead>
<tr>
<td>姓名td>
<td>科目td>
<td>成绩td>
<td>操作td>
tr>
thead>
<tbody>tbody>
table>
<script type="text/javascript">
var datas = [{
name:'张三',
subject:'java',
score:100
},{
name:'张四',
subject:'java',
score:10
},{
name:'张五',
subject:'java',
score:90
}];
//1.数组中有多少个对象,创建多少行
var tbody = document.querySelector('tbody');
for(var i =0;i<datas.length;i++){
var tr = document.createElement('tr');
tbody.appendChild(tr);
//2.在行内创建列,外层for循环控制行数,内层for循环控制列数
//多少了取决于对象里面的属性个数
for(var k in datas[i]){
var td = document.createElement('td');
//将属性值赋予td标签
//datas[i]相当于obj ,再加上[k]就是属性值
/*
for(var k in obj){
console.log(obj[k]);
}
*/
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
//3.创建删除单元格列
var td = document.createElement('td');
td.innerHTML = "删除";
tr.appendChild(td);
}
//4.绑定删除时间
var as = document.querySelectorAll('a');
for(var i =0;i<as.length;i++){
as[i].onclick = function(){
tbody.removeChild(this.parentNode.parentNode);
}
}
script>
body>
7.8 三种动态创建元素区别
- document.write()
- element.innerHTML
- document.creatElement()
7.8.1 document.write
<body>
<button>点击button>
<p>123p>
<script type="text/javascript">
document.write('');
script>
body>
区别:直接将内容写入页面的内容流,但是文档流执行完毕,则它将会导致页面全部重绘(重新创建新的HTML页面)
7.8.2 innerHTML与creatElement效率
- innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML创建多个元素效率更高(不适用拼接字符串,采用数组形式拼接),结构稍微复杂
- creatElement创建多个元素效率稍微低一点点,但是结构更清晰
总结:不同的浏览器,innerHTML效率要比creatElement高
8.DOM重点核心
关于DOM操作,我们主要是对元素的操作。操作有创建、增、删、改、查、属性操作、事件操作
主要用作复习即可
8.1 创建
- document.write
- innerHTML
- createElement
8.2 增
- appendChile
- insertBefore
8.3 删除
- removeChild
8.4 改
主要修稿DOM的元素属性,DOM元素的内容、属性、表单的值等
- 修改元素属性:src、href、title等
- 修改普通元素内容:innerHTML、innerText
- 修改表单元素:value、type、disable等
- 修改元素样式:style、className
8.5 查
主要查询DOM元素
- DOM提供的远古方法:getId等
- H5提供新方法:querySelector等
- 利用节点操作获取元素:父、子、兄
8.6 属性操作
主要针对于自定义属性:setAttribute/getAttribute/removeAttribute
8.7 事件操作
给元素注册事件等操作
八、事件高级
1.注册事件
给元素添加事件,成为注册事件或者绑定事件
事件注册有两种方式:传统方式和方法监听注册方式
1.1 传统注册事件
- 利用on开头的事件
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
1.2 方法监听注册方式
- W3C标准推荐方式
- 特点:同一个元素同一个事件可以注册多个监听器
- 按照注册顺序依次执行
1.3 addEventListener事件监听
eventTarget.addEventListener(type,listener,useCapture):会有兼容性问题
- type:事件类型字符串,例如click等不用加上on
- listener:事件处理函数,事件发生时会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认值为false
<body>
<button>点击button>
<script type="text/javascript">
var btn = document.querySelector('button');
//1.里面的事件类型必须是字符串,必定加上引号且不能以on开头
//2.同一个元素、同一个事件可以添加多个监听器
btn.addEventListener('click',function(){
alert('11');
})
btn.addEventListener('click',function(){
alert('22');
})
script>
body>
2.删除事件
也称为解绑事件
2.1 传统删除事件方式
<body>
<style>
div{
background-color: red;
width: 600px;
margin-bottom: 10px;
}
style>
<div>1div>
<div>2div>
<div>3div>
<script type="text/javascript">
var divs = document.querySelectorAll('div');
divs[0].onclick =function(){
alert("11");
//传统方式就是将此对象的事件赋值为空
this.onclick = null;
}
script>
body>
2.2 方法监听注册方式删除事件
此方式在注册事件的时候不能使用匿名函数的方式
<script type="text/javascript">
var divs = document.querySelectorAll('div');
//注意:方法名后面并没有小括号
divs[0].addEventListener('click',fn);
function fn(){
alert('11');
//参数:1 表示要移除的事件名称 2 表示要移除的处理程序名称
divs[0].removeEventListener('click',fn);
}
script>
3 DOM事件流
事件流描述的是从页面中接受事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
DOM事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
事件捕获:由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收过程
捕获阶段:addEventListener第三个参数为true,点击son事件会从father事件触发然后触发son事件(由上至下)
冒泡阶段:addEventListener第三个阶段是false或者省略,点击son事件会从son事件触发然后触发father事件(由下至上)
注意:
- JS代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent只能得到冒泡阶段
- 在实际开发中,捕获事件很少,更关注事件冒泡
- 有些事件是没有冒泡的:比如失去、获得焦点、onmouseenter、onmouseleave
4 事件对象
事件对象就是写到我们侦听函数的小括号里面,可以当做形参来对待且由系统自动创建不用传递参数
事件对象是事件一系列相关数据的集合,与事件相关,例如鼠标点击事件对象里面包含了鼠标相关信息(坐标、绑定事件的对象等)
事件没有被触发或者没有事件则不会有事件对象,先有事件再有事件对象
具有兼容性问题: e=e||window.event 解决
<body>
<div>1div>
<script type="text/javascript">
var div = document.querySelector('div');
//事件对象的名字可以缩写、可以随意写
div.addEventListener('click',function(event){
console.log(event);
})
script>
body>
4.1 常用属性与方法
属性与方法
说明
e.target
返回触发事件的对象,标准
e.srcElement
返回触发事件的对象,非标准
e.type
返回事件的类型,比如click等
e.canceBubble
该属性阻止冒泡,非标准
e.stopPropagation()
阻止冒泡,标准
e.returnValue
该属性阻止默认事件,非标准,例如不让链接跳转
e.preventDefault()
该方法组织默认事件,标准,例如不让连接 跳转
4.2 e.target
e.target与this的区别:点击了哪个元素触发了事件,target返回那个元素;哪个元素绑定了点击事件this返回那个元素
<body>
<ul>
<li>1li>
<li>1li>
<li>1li>
ul>
<script type="text/javascript">
//为ul绑定了点击事件
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
//返回的是触发事件的元素,li
console.log(e.target);
//返回的是绑定事件的元素,ul
console.log(this)
})
script>
body>
兼容性问题解决:e.target || e.srcElement
4.3 e.type
<body>
<ul>
<li>1li>
ul>
<script type="text/javascript">
//为ul绑定了点击事件
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
//返回的是事件类型,可以使鼠标点击、经过等各种事件,返回的事件类型不带on
console.log(e.type);
})
script>
body>
4.4 阻止默认行为
<body>
<a href="www.baidu.com">百度a>
<script type="text/javascript">
//组织默认事件(页面跳转),DOM标准语法
//有兼容性问题
var a = document.querySelector('a');
a.addEventListener('click',function(e){
e.preventDefault();
})
//这种方式没有兼容性问题
a.addEventListener('click',function(e){
//用传统的方式可以,绑定注册事件方式失败
return false;
})
script>
body>
4.5 阻止冒泡
标准写法:利用事件对象里面的 stopPropagation()方法
<body>
<div id="father">
<div id="son">
123
div>
div>
<script type="text/javascript">
var fahter = document.querySelector('#father');
var son = document.querySelector('#son');
//父类元素对象添加方法
//虽然子类禁止冒泡,但是如果点击父类元素,父类元素还会向上冒泡(如果document有事件则会触发)
fahter.addEventListener('click',function(){
alert('father');
})
//子类元素对象添加方法
son.addEventListener('click',function(e){
alert('son');
//事件对象组织冒泡
e.stopPropagation();
},false)
script>
body>
5.事件委托(代理、委派)
事件委托:也称为事件代理,在jQuery里面称为事件委派
事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
事件委托的作用:只操作一个DOM,提高程序的性能
<body>
<ul>
<li>知否知否li>
<li>知否知否li>
<li>知否知否li>
ul>
<script type="text/javascript">
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
//利用冒泡点击子类父类弹出框
//alert('应是绿肥红瘦');
//点击某个框修改其颜色,需要添加事件对象
var lis = ul.children;
//增加排他思想
for(var i = 0;i<lis.length;i++){
lis[i].style.backgroundColor = '';
}
e.target.style.backgroundColor = 'pink';
})
script>
body>
6.常用鼠标事件
上面有,此处略过 , 以下两个鼠标事件了解即可
6.1 禁止鼠标右键菜单
contextmenu控制何时显示上下文菜单,主要用于开发人员取消默认的上下文菜单
<body>
这是一段特殊的文字
<script type="text/javascript">
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
script>
body>
6.2 禁止鼠标选中
<body>
这是一段特殊的文字
<script type="text/javascript">
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
script>
body>
6.3 鼠标事件对象
现阶段主要是用鼠标事件对象(MouseEvent)和键盘事件对象(KeyboardEvent)
鼠标事件对象
说明
e.clientX
返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY
返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX
返回鼠标相对于文档页面的X坐标
e.pageY
返回鼠标相对于文档页面的Y坐标
e.screenX
返回鼠标相对于电脑屏幕的X坐标
e.screenY
返回鼠标相对于电脑屏幕的Y坐标
<body>
<script type="text/javascript">
document.addEventListener('click',function(e){
//1.获取可视区域的鼠标坐标
console.log(e.clientX);
console.log(e.clientY);
//2.获取距离页面区域的鼠标坐标
console.log(e.pageX);
console.log(e.pageY);
//3.获取相对于屏幕的鼠标坐标
console.log(e.screenX);
console.log(e.screenY);
})
script>
body>
6.4 图片跟随鼠标移动
核心思路:获得鼠标移动的坐标并将其作为图片的坐标
<body>
<style>
img {
position: absolute;
width: 50px;
height: 50px;
}
style>
<img src="imgs/20201119.jpg"/>
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
//图片大小为 50X50,鼠标位于图片中央则坐标应该各减去图片大小的一半即可
var x =e.pageX -25;
var y =e.pageY -25;
img.style.left = x+'px';
img.style.top = y+'px';
});
script>
body>
7.常用键盘事件
7.1 键盘事件
键盘事件
触发条件
onkeyup
某个按键被松开时触发
onkeydown
某个按键被按下时触发
onkeypress
某个按键按下时被触发,但是不识别功能键 ctrl、shift、箭头等
执行顺序:down -> press -> up
<script>
document.addEventListener('keydown',function(){
console.log('down 按下');
})
document.addEventListener('keypress',function(){
console.log('press 按下');
})
document.addEventListener('keyup',function(){
console.log('up 按下');
})
script>
7.2 键盘事件对象
e.keyCode:返回ASCII码值,可以用来判断用户到底输入的是哪个键
<script>
//keydown不会识别英文字母大小写,keypress识别英文字母大小写
document.addEventListener('keydown',function(e){
console.log(e.keyCode);
})
document.addEventListener('keypress',function(e){
console.log(e.keyCode);
})
script>
7.3 案例-模拟京东按键输入
用户在页面任何地方按下 S 键, 搜索框获得焦点
<body>
<input type="text"/>
<script>
var input = document.querySelector('input');
//这里使用up是做到只会获取焦点而不会在文本框显示用户输入的字母 S
document.addEventListener('keyup',function(e){
if(e.keyCode == 83){
input.focus();
}
})
script>
body>
7.4 案例-模拟京东查询快递单号
<body>
<style type="text/css">
div{
font-size: 60px;
color: red;
background-color: aqua;
width: 200px;
height: 100px;
display: none;
}
style>
<div>div>
<input type="text" placeholder="请输入你的快递单号"/>
<script>
var input = document.querySelector('input');
var div = document.querySelector('div');
input.addEventListener('keyup',function(e){
//先判断用户输入是否为空
//输入为空则不显示 div
if(this.value == ''){
div.style.display = 'none';
}else{
//输入不为空则显示盒子
div.innerHTML = this.value;
div.style.display = 'block';
}
})
//失去焦点 隐藏 div
input.addEventListener('blur',function(){
div.style.display = 'none';
})
//获得焦点先判断文本框内容
input.addEventListener('focus',function(){
//获得焦点而文本框为空则不显示盒子
//获得焦点而文本框不为空则显示盒子
if(this.value != ''){
div.style.display = 'block';
}
})
script>
body>
九、BOM
1.BOM概述
BOM就是浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window
1.1 BOM的特点
BOM由一系列的对象构成,并且每个对象提供了很多属性与方法
- 浏览器对象模型
- 把浏览器当做对象来看待
- BOM的顶级对象时window
- BOM学习的是浏览器窗口交互的一些对象
- BOM兼容性较差,没有统一标准
1.2 BOM的组成
BOM比DOM更大,包含了DOM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vnEUvkFd-1607239291427)(img/image-20201129170700117.png)]
window对象时浏览器的顶级对象,它具有双重角色
- 它是JS访问浏览器窗口的一个接口
- 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性、方法
<body>
<script>
//a 是一个全局变量
var a = 10;
//完整的写法
console.log(window.a);
//定义函数
function fn (){
console.log('测试方法');
}
//调用函数完整写法:函数变成了window对象的方法
window.fn();
fn(); //这种也可以调用
script>
body>
注意:window对象中有个特殊的属性名为 name(声明式最好不使用name属性)
2.window对象常见事件
2.1 窗口加载事件
window.onload是窗口(页面)加载事件,当文档内容加载完成后才会触发该事件(包括图像、脚本文件、CSS文件等),调用该函数
注意:
- 有了window.onload就可以吧JS代码写在页面的任何地方
- 该方式使用传统注册事件的方式,如果写了多个则以最后一个为准
- 使用注册监听事件的方法可以写多个(屁话一句)
- 但是如果图片过多,页面加载时间过长,交互效果就不会被实现,必然影响用户体验
document.addEventListener(‘DOMContentLoaded’,function(){}):具有兼容性问题,如果页面图片过多可以使用这个方法,此方法会在所有元素(标签)加载完毕以后被触发
<body>
<script>
window.onload=function(){
alert('页面全部加载完毕后执行');
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
alert('按钮被点击');
})
}
document.addEventListener('DOMContentLoaded',function(){
alert('标签元素加载完毕后执行');
})
script>
<button>点击button>
body>
2.2 调整窗口大小事件
window.onresize:窗口的像素值发生改变就会调用该方法
window.innerWidth/innerHeight:获取窗口的宽度与高度
<body>
<style type="text/css">
div{
background-color: black;
width:200px;
height: 200px;
}
style>
<div>div>
<script>
var div = document.querySelector('div');
window.addEventListener('resize',function(){
//这个属性是获得窗口的宽度像素值
var width = window.innerWidth;
console.log(width);
if(width > 800){
div.style.display = 'block';
}else{
div.style.display = 'none';
}
})
script>
body>
3.定时器
window对象提供了两个方法:
- setTimeout()
- setInterval()
3.1 setTimeout()
setTimeout(调用函数,[延迟毫秒数]):设置一个定时器,该定时器到期后执行调用函数
<body>
<script>
//window可以省略掉,使用匿名函数的方式
//可以将定时器函数赋予标识符用来区别
var times1 = setTimeout(function(){
console.log('两秒后执行')
},2000);
//可以不用匿名函数
function fn(){
console.log('非匿名函数')
}
var times2 = setTimeout(fn,5000);
script>
body>
3.2 回调函数
window.setTimeout(调用函数,[毫秒数]):其中的调用函数就是回调函数(等待时间结束之后在回头调用这个函数称为回调函数)
传统注册事件也是回调函数
<body>
<style type="text/css">
img{
width: 200px;
height: 200px;
}
style>
<img src="imgs/20201119.jpg"/>
<script>
var img = document.querySelector('img');
//五秒钟后隐藏图片功能
setTimeout(function(){
img.style.display = 'none'
},5000)
script>
body>
3.3 清除定时器
window.clearTimeout(timeID):参数为定时器的标识符
<body>
<button>点击停止button>
<script>
var btn = document.querySelector('button');
//五秒钟后爆炸
var time = setTimeout(function(){
console.log('爆炸了')
},5000)
//添加按钮点击事件,按钮被点击定时器被清除
btn.addEventListener('click',function(){
//注册监听事件也是一个回调函数
//window可以省略不写的
window.clearTimeout(time);
console.log('爆炸被终结')
})
script>
body>
3.4 setInterval()
与上方定时器用法规范基本相同,但是功能不同:此方法会按照时间间隔一直调用
<body>
<script>
//它会一直执行,每隔一秒执行一次
setInterval(function(){
console.log('执行成功')
},2000)
script>
body>
3.5 倒计时的时间
<body>
<style type="text/css">
div{
width: 50px;
height: 50px;
background-color: pink;
margin: 5px;
display: block;
float: left;
}
style>
<div id='min'>1div>
<div id="hour">2div>
<div id="second">3div>
<script>
var min = document.querySelector('#min');
var hour = document.querySelector('#hour');
var second = document.querySelector('#second');
var inpuTime =+new Date('1997-5-8 18:00:00'); //返回用户输入的时间毫秒数
//在定时器启动之前先调用一次函数防止刷新页面时间数字不对劲
countDown(inputTime);
setInterval(countDown,1000);
function countDown(){
var nowTime=+new Date(); //返回当前毫秒数
var times=(nowTime - inpuTime)/1000; //times是剩余时间秒数
var h =parseInt(times/60/60%24); //小时
hour.innerHTML = h;
var m =parseInt(times/60%60); //分钟
min.innerHTML = m;
var s =parseInt(times%60); //秒
second.innerHTML = s;
}
script>
body>
3.6 停止Interval定时器
window.clearInterval(intervalID)
<body>
<button>开启定时器button>
<button>关闭定时器button>
<script>
var btns = document.querySelectorAll('button');
var time = null;
btns[0].addEventListener('click',function(){
//为定时器赋予一个标识符
time = setInterval(function(){
console.log('start.....')
},1000)
})
btns[1].addEventListener('click',function(){
clearInterval(time);
console.log('over.....')
})
script>
body>
3.7 发送短信案例
<body>
发送短信:<input type="text"/>
<button>发送验证码button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
var time = 3;
btn.disabled =true;
var se = setInterval(function(){
if(time ==0){
clearInterval(se);
btn.disabled = false;
time = 3;
btn.innerHTML = '发送验证码';
}else{
btn.innerHTML = '剩余时间还有'+time+'秒';
time --;
}
},1000);
})
script>
body>
4.JS执行队列
4.1 JS单线程
JS语言的一大特点就是单线程,也就是说同一时间只能做一件事
4.2 同步与异步
为解决JS单线程问题,H5提出了新标准Web Worker标准允许JS脚本创建多个线程。于是出现了同步与异步
同步:按照代码的顺序依次执行
异步:在做一件事的同时可以处理其他事情
<body>
<script>
//执行顺序为 1-3-2 说明JS实现了异步
console.log('1')
setInterval(function(){
console.log('2');
},2000)
console.log('3');
script>
body>
本质:代码流程执行顺序不同
4.2.1 小问题
回调函数的间隔时间为0秒,但是执行顺序还是 1 - 3 - 2,这就需要了解JS语言的执行机制
<body>
<script>
//执行顺序为 1-3-2
console.log('1')
setInterval(function(){
console.log('2');
},0)
console.log('3');
script>
body>
4.3 执行机制
JS执行时会将内存分为两个部分:执行栈(执行同步任务) 和 任务队列(执行异步任务)
JS执行过程中会先执行同步任务(执行栈中的内容),同步任务执行结束后在执行异步任务(任务队列中的内容放到执行栈中执行)
一般而言,异步任务有三种:
- 普通事件
- 资源加载
- 定时器,包括 setTimeout、setInterval
- 回调函(也是异步任务)
执行顺序:
先运行执行栈中的任务,打印 1 ,2(如果点击事件没有触发),1秒钟后定时器任务放在了任务队列中,然后又转移到执行栈中运行打印 3
点击事件与定时器谁先打印根据时间来决定谁先放入任务队列中(即使执行栈已经空了系统还是会去任务队列中查看–>事件循环)
<body>
<script>
console.log('1');
document.onclick = function(){
console.log('click');
}
console.log('2');
setTimeout(function(){
console.log('3')
},1000)
script>
body>
由于主线程不断重复的获得新任务、执行任务、在获得新任务、在执行,这种机制被称为事件循环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJxGMt2J-1607239291431)(img/image-20201130171034632.png)]
5.location对象
5.1 概述
window对象为我们提供了一个location属性用于获取设置窗体的URL,并可以用于解析URL,因为属性返回的是一个对象,所以我们也将这个属性成为location对象
5.2 location对象的属性
对象属性
返回值
location.href
获取或设置整个URL
location.host
返回主机域名
location.port
返回端口号,如果未写返回空字符串
location.pathname
返回路径
location.search
返回参数
location.hash
返回片段
<body>
<button>点击button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
//window可以省略,按钮点击返回当前页面URL值
console.log(window.location.href);
//点击跳转百度页面
location.href = 'http://www.baidu.com';
})
script>
body>
5.3 自动跳转页面
<body>
<div>div>
<script>
var div = document.querySelector('div');
var time = 5;
var times = setInterval(function(){
if(time == 0){
clearInterval(times);
location.href = 'http://www.baidu.com';
}else{
div.innerHTML = '还有'+time+'秒跳转页面'
time--;
}
},1000)
script>
body>
5.4 获取URL参数
<body>
<script>
console.log(window.location.search);
console.log(location.search)
script>
body>
5.5 location对象的方法
方法
返回值
location.assign()
与href相同,可以跳转页面(也称为重定向)可以后退页面
location.replace()
替换当前页面,因为不记录历史,所以无法后退页面
location.reload()
重新加载页面
<body>
<button>点击跳转button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
//记录历史可以后退网页
location.assign('http://www.baidu.com');
//无记录不可以后退页面
location.replace('http://www.baidu.com')
//加上参数为强制刷新
location.reload(true);
})
script>
body>
6.navigator对象
其中包含了有关浏览器的信息,它有很多属性。最常用的是userAgent,该属性可以返回客户机发送给服务器的user-agent头部值
可以判断用户使用手机还是用PC访问网页从而显示不同的页面布局
7.history对象
window对象提供的此对象可以与浏览器历史记录进行交互,该对象包含用户访问过的URL
对象方法
作用
back()
可以后退功能
forward()
前进功能
go(参数)
前进后退功能,参数为1前进1个页面,-1后退一个页面
<body>
<button>点击button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
history.back();
history.forward();
history.go(1);
})
script>
body>
注:此对象开发中不常用,OA办公系统会用到
十、PC端网页特效
1.元素偏移量offset系列
offset就是偏移量,使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等
- 获得与带有定位的父元素位置之间的距离
- 获得元素自身的大小
- 注意:返回的值没有带单位
1.1 常用系列属性
属性
作用
element.offsetParent
返回该元素的父元素(带有定位),没有则返回body
element.offsetTop
返回该元素与父元素(带有定位)上方的偏移
element.offsetLeft
返回该元素与父元素(带有定位)左边框的偏移
element.offsetWidth
返回自身的宽度包括:padding、边框、内容区宽度
element.offsetHeight
返回自身的宽度包括:padding、边框、内容区高度
<body>
<style type="text/css">
.father{
background-color: pink;
position: absolute;/* 这里有定位设置 */
width: 200px;
height: 200px;
margin: 100px;
}
.son{
background-color: purple;
position: absolute;
width: 100px;
height: 100px;
margin: 100px;
}
style>
<div class="father">
<div class="son">div>
div>
<script>
var son = document.querySelector('.son');
console.log(son.offsetLeft);// 打印100,因为 son的div的margin为100
console.log(son.offsetTop);
console.log(son.offsetWidth); // 100
console.log(son.offsetParent); //father
script>
body>
1.2 offset与style却别
offset
style
可以得到任意样式表中的样式值
只能获得行内样式表中的值
offset系列获得数值没有单位
style.width数组带有单位
offsetWidth包含padding+border+width
style.width获得值不包括padding和border值
offsetWidth等属性只读不能赋值
style.width可读写属性
获取元素大小,offset合适
为元素更改值,需要用style改变
1.3 获取鼠标在盒子内坐标
鼠标在盒子内的坐标 = 鼠标距离页面的值 - 盒子距离页面的偏移量(值)
<body>
<style type="text/css">
div{
background-color: pink;
position: absolute;
width: 300px;
height: 300px;
margin: 100px;
}
style>
<div>div>
<script>
var div = document.querySelector('div');
div.addEventListener('mousemove',function(e){
//获取盒子具体body(页面)的偏移量
var leftFather = div.offsetLeft;
var topFather = div.offsetTop;
//获取鼠标距离页面的距离,使用鼠标事件对象
var x = e.pageX;
var y = e.pageY;
//计算鼠标距离盒子的距离
var mouseX = x - leftFather;
var mouseY = y - topFather;
div.innerHTML = '鼠标距离盒子距离为:X:'+mouseX+' Y:'+mouseY;
})
script>
body>
1.4 模拟框拖动
盒子移动过程中,鼠标在盒子里面的坐标是不会改变的。
盒子在页面中的位置 = 鼠标在页面中的位置(不断变化的) - 鼠标在盒子内的坐标(固定不变的)
<body>
<style type="text/css">
table{
display: none;
}
td{
background-color: pink;
height: 50px;
width: 100px;
}
style>
<table border="1px" width="400px" height="200px">
<thead>
<tr>
<td>td>
tr>
thead>
<tbody>tbody>
table>
<button>显示button>
<button>Xbutton>
<script>
//1.完成表格显示隐藏功能
var table =document.querySelector('table');
var btn = document.querySelector('button');
var n = btn.nextElementSibling;
btn.addEventListener('click',function(){
table.style.display = 'block';
})
n.addEventListener('click',function(){
table.style.display = 'none';
})
//2.完成拖拽功能
//2.1只有鼠标在盒子头才能拖拽,其他位置不能拖拽
var thead = document.querySelector('thead');
//2.2鼠标按下瞬间获得鼠标在盒子内的坐标
thead.addEventListener('mousedown',function(e){
//获取了鼠标在盒子内的距离坐标
var mX = e.pageX - table.offsetLeft;
var mY = e.pageY - table.offsetTop;
//2.3鼠标在按下的同时在页面中移动
var mousemove = document.addEventListener('mousemove',fn);
//单独拿出来是为了移除鼠标移动事件
function fn(e){
//获取页面与盒子之间的距离
table.style.marginLeft = e.pageX - mX+'px';
table.style.marginTop = e.pageY - mY+'px';
}
//2.4鼠标弹起移除鼠标移动事件
document.addEventListener('mouseup',function(){
document.removeEventListener('mousemove',fn);
})
})
script>
body>
2.元素可视区client系列
通过client系列的相关属性来获取可视区的相关信息。通过client系列相关属性可以动态的得到该元素的边框大小、元素大小等
2.1 常用属性
系列属性
作用
element.clientTop
返回元素上边框的大小
element.clientLeft
返回元素做边框的大小
element.clientWidth
返回自身包括padding、内容区宽度,不含边框, 返回数值不带单位
element.clientHeight
返回自身包括padding、内容区高度,不含边框, 返回数值不带单位
clientWidth与offsetWidth最大的区别就是:clientWidth不包含边框
2.2 立即执行函数
普通的函数必须调用了才能执行,立即执行函数则不用调用就可以执行
立即执行函数最大的作用是独立创建了一个作用域,里面的变量都是局部变量
<body>
<script>
//第一种方式 ()() 第二个小括号相当于调用了并且可以传入参数
(function fn1(a,b){
console.log(a+b);
})(1,2);
//第二种方式 (function fn(){} ())
//这两种都可以使匿名函数
(function (a,b){
console.log(a+b);
} (3,4))
script>
body>
3.元素滚动scroll系列
使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离
3.1 常用属性
属性
说明
element.scrollTop
返回被卷去的上侧距离,返回数值没有单位
element.scrollLeft
返回被卷去的左侧距离,返回数值没有单位
element.scrollWidth
返回自身实际宽度,不含边框,返回数值不带单位
element.scrollHeight
返回自身实际高度,不含边框,返回数值不带单位
scrollHeight与clientHeight区别:前者高度根据文本内容,后者高度固定(即使内容超过了盒子)
3.2 页面被卷曲的头部
若浏览器的高度宽度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上方被隐藏掉的高度就是称为被卷曲的头部。滚动条在滚动时会触发onscroll事件
<body>
<style type="text/css">
div{
width: 100px;
height: 100px;
background-color: pink;
border: 1px solid black;
padding: 10px;
overflow: scroll;
}
style>
<div>
我是内容
div>
<script>
var div = document.querySelector('div');
console.log(div.scrollHeight);
//添加滚动事件
div.addEventListener('scroll',function(){
console.log(div.scrollTop);
})
script>
body>
3.3 仿淘宝回顶部栏
待续
4.三大系列总结
大小对比
作用
element.offsetWidth
返回自身的宽度包括:padding、边框、内容区宽度
element.clientWidth
返回自身包括padding、内容区宽度,不含边框, 返回数值不带单位
element.scrollWidth
返回自身实际宽度,不含边框,返回数值不带单位
这三个都可以返回自身的大小,主要作用:
- offset系列经常用于获取元素的位置 offsetLeft/offsetTop
- client系列经常用于获取元素大小 clientWidth/clientHeigth
- scroll经常用于获取滚动距离 scrollTOop/scrollLeft
5.mouseenter与mouseover区别
当鼠标移动到元素上时就会触发mouseenter事件,类似over事件,区别在于:
- over经过自身盒子时触发,经过子盒子还会触发,enter则只会经过自身盒子触发
- enter不会冒泡,而over会冒泡
- 与enter相互配合的是mouseleave同样不会冒泡
6.动画函数封装
6.1 动画原理
核心原理:通过定时器setInterval()不断移动盒子
<body>
<style type="text/css">
div{
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background-color: pink;
}
style>
<div> div>
<script>
//获取值使用offset,设置值用style
var div = document.querySelector('div');
var time = setInterval(function(){
div.style.left = div.offsetLeft + 1 + 'px';
if(div.offsetLeft >= 100 ){
clearInterval(time);
}
},100);
script>
body>
6.2 对象添加动画函数
使用变量来存放动画函数不太合适,将动画函数存放在对象的属性中,确保了动画的独立性不会冲突(大概意思)
<body>
<style type="text/css">
div{
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background-color: pink;
}
style>
<button>点击动画开始button>
<div>div>
<script>
function animate(obj,target){
//首行代码解决点击都次动画速度加快的BUG
clearInterval(obj.time);
//将定时器封装给obj对象的属性中
obj.time = setInterval(function(){
if(obj.offsetLeft >= target ){
clearInterval(obj.time);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
},100);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
//添加点击事件,点击之后动画开始
btn.addEventListener('click',function(){
animate(div,200);
})
script>
body>
6.3 缓存动画原理
缓动动画就是让元素运动速度有所变化,最常见的就是让速度慢慢停下来
缓存动画公式 = (目标值-现在的位置) / 10
<body>
<style type="text/css">
div{
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background-color: pink;
}
style>
<button>点击动画开始button>
<div>div>
<script>
function animate(obj,target){
//首行代码解决点击都次动画速度加快的BUG
clearInterval(obj.time);
//将定时器封装给obj对象的属性中
obj.time = setInterval(function(){
//步长值放在计时器里,小数字向上取整
var step = Math.ceil((target-div.offsetLeft) / 10);
if(obj.offsetLeft == target ){
clearInterval(obj.time);
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
//添加点击事件,点击之后动画开始
btn.addEventListener('click',function(){
animate(div,1000);
})
script>
body>
6.4 动画多个目标值移动
<body>
<style type="text/css">
div{
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background-color: pink;
}
style>
<button class="btn500">点击到500pxbutton>
<button class="btn800">点击到800pxbutton>
<div>div>
<script>
function animate(obj,target){
obj.time = setInterval(function(){
//因为这个算法所以可以做出前进、后退动作
//精度问题进行取证,step小于0往小取整,大于0往大取整
var step =(target-div.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target ){
clearInterval(obj.time);
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
//添加点击事件,点击之后动画开始
btn500.addEventListener('click',function(){
animate(div,500);
})
btn800.addEventListener('click',function(){
animate(div,800);
})
script>
body>
6.5 缓存动画添加回调函数
回调函数原理:函数作为一个参数传递到另一个函数内,另一个函数执行结束后在执行作为参数的函数
回调函数应该写在定时器结尾
<body>
<style type="text/css">
div{
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background-color: pink;
}
style>
<button class="btn500">点击到500pxbutton>
<button class="btn800">点击到800pxbutton>
<div>div>
<script>
//第三个参数为回调函数
//callBack = function(){}
function animate(obj,target,callBack){
clearInterval(obj.time);
obj.time = setInterval(function(){
var step =(target-div.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target ){
clearInterval(obj.time);
//动画结束后才调用函数
//判断函数是否存在,存在即调用
if(callBack){
callBack();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
//添加点击事件,点击之后动画开始
btn500.addEventListener('click',function(){
//两种传递函数的方式,测试都可以
animate(div,500,fn)
});
function fn(){
div.style.backgroundColor = 'red';
}
btn800.addEventListener('click',function(){
animate(div,800,function(){
div.style.backgroundColor = 'pink';
});
})
script>
body>
十一、本地存储
数据存储在用户浏览器中,设置、读取方便、刷新页面不会丢失数据且存储量大
1.window.sessionStorage
生命周期为关闭浏览器,在同一个页面下数据共享,存储数据按照键值对的形式
存储数据:sessionStorage.setItem(key,value)
存取数据:sessionStorage.getItem(key)
删除数据:sessionStorage.removeItem(key)
删除所有数据:sessionStorage.clear()
<body>
<input type="text"/>
<button>添加数据button>
<button class="del">删除数据button>
<button class="get">获取数据button>
<button class="delAll">删除所有button>
<script type="text/javascript">
//获取元素对象
var input = document.querySelector('input');
var btn = document.querySelector('button');
var del = document.querySelector('.del');
var get = document.querySelector('.get');
var delAll =document.querySelector('.delAll');
//添加数据
btn.addEventListener('click',function(){
var val = input.value;
sessionStorage.setItem('uname',val);
})
//删除指定单条数据
del.addEventListener('click',function(){
sessionStorage.removeItem('uname');
})
//获取数据
get.addEventListener('click',function(){
console.log(sessionStorage.getItem('uname'));
})
//清除所有数据
delAll.addEventListener('click',function(){
sessionStorage.clear();
})
script>
body>
2.window.localStorage
存储的数据永久生效,关闭页面后也会生效,只有使用了clear、remove才会删除数据
存放在浏览器中,同一个浏览器的其他页面也可以获得数据
与sessionStorage语法相同
<body>
<input type="text">
<button class="set">存储数据button>
<button class="get">获取数据button>
<button class="remove">删除数据button>
<button class="del">清空所有数据button>
<script>
var ipt = document.querySelector('input');
var set = document.querySelector('.set');
var get = document.querySelector('.get');
var remove = document.querySelector('.remove');
var del = document.querySelector('.del');
set.addEventListener('click', function() {
var val = ipt.value;
localStorage.setItem('username', val);
})
get.addEventListener('click', function() {
console.log(localStorage.getItem('username'));
})
remove.addEventListener('click', function() {
localStorage.removeItem('username');
})
del.addEventListener('click', function() {
localStorage.clear();
})
script>
body>
3.实训记住用户名
<body>
<input type="text" id="username"> <input type="checkbox" name="" id="remember"> 记住用户名
<script>
var username = document.querySelector('#username');
var remember = document.querySelector('#remember');
//首先判断本地存储中是否存储用户名,如果有则直接显示否则则不显示
if (localStorage.getItem('username')) {
username.value = localStorage.getItem('username');
remember.checked = true;
}
//复选框为true,则获取用户名并存储在本地,若为false则移除用户名
remember.addEventListener('change', function() {
if (this.checked) {
localStorage.setItem('username', username.value)
} else {
localStorage.removeItem('username');
}
})
script>
body>
你可能感兴趣的:(javascript)