前端基础--JS(pink老师课程笔记)
初识
-
脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行经行解释并执行
-
也可以基于Node.js技术进行服务器端编程
作用:
-
表单动态校验(密码强度检测)(JS产生最初目的)
-
网页特效
-
服务器开发(Node.js)
-
桌面程序(Electron)
-
APP(Cordova)
-
控制硬件-物联网(Ruff)
-
游戏开发(cocos2d.js)
浏览器执行JS
浏览器分成两部分:渲染引擎和JS引擎
-
渲染引擎:用来解析HTML和CSS,比如Chrome浏览器的blink,老版本的webkit
-
JS引擎:也称为JS解释器,用来读取网页中JavaScript代码,对其处理后运行,比如Chrome浏览器的V8
浏览器本身并不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码。JS引擎执行代码时逐行解释每一句源码(转换成机器语言),然后由计算机去执行,所以JS语言归为脚本语言,会逐行解释执行
JS组成
分为三部分:
-
ECMAScript(JavaScript语法)
-
DOM(页面文档对象模型)
-
BOM(浏览器对象模型)
ECMAScript
ECMAScript是由ECMA国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMAScript语言的实现和扩展。
ECMAScript规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准
DOM--文档对象模型
文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展标记语言的标准编程接口。
通过DOM提供的接口可以对页面上额各种元素进行操作(大小、位置、颜色等)
BOM--浏览器对象模型
BOM(Browser Object Model),是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等等。
JS 三种书写位置
JS有三种书写位置,分别是行内、内嵌和引入。
行内式js
直接卸载元素的内部
<!-- 1、行内式技js 直接写在元素的内部--> <input type="button" value="弹窗" onclick="alert('我是行内式js弹窗')">
注意:
-
可以将单行或少量js代码写在HTML标签的事件属性中(以on开头的属性),比如:onclick;
-
-
可读性差,在HTML中编写大量JS代码时,不方便阅读;
-
引号易错,引号多层嵌套匹配时,非常容易弄混;
-
特殊情况下使用。
内嵌式js
通过script标签内嵌js代码
<script type="text/javascript"> alert('我是内嵌式js弹窗') </script>
注意:
-
可以将多行js代码写到 < script>标签中
-
内嵌js时学习时常用的方式
引入式js
通过script标签引入
<!-- 3、引入式js弹窗 --> <script src="../js/引入式js文件.js"></script>
注意:
-
利于HTML页面代码结构化,把大段JS代码独立到HTML页面之外,既美观,也方便文件级别的复用
-
引用外部js文件的script标签中间不可以写代码
-
适合于js代码量比较大的情况
JS输入输出语句
常用语句:
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
-
console.log长用于调试
变量
变量是用于存放数据的容器,通过变量名获取数据,甚至数据可以修改
本质:变量是程序在内存中申请的一块用来存放数据的空间。
变量声明
变量在使用时分为两步:1、声明变量 2、赋值
var age;
声明一个名称为age的变量
-
var 是一个js关键字,用来声明变量(variable:变量的意思),使用该关键字声明变量后,计算机会自动为变量分配内存空间。
-
age是程序员定义的变量名,我们通过变量名来范文内存中分配的空间
变量初始化
声明一个变量并赋值,称为变量的初始化
var age = 18;
变量的使用:
要求:
1、弹出一个输入框,提示用户输入姓名
2、弹出一个对话框,输出用户刚才输入的姓名
<script type="text/javascript"> // 用户输入姓名,存储到一个变量中 var myname; myname = prompt('请输入你的名字:'); // alert弹窗输出变量 alert(myname); </script>
变量语法扩展
1、更新变量:
一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
2、同时声明多个变量
使用一个var声明多个变量,其他变量用 ‘ , ’ 分隔,最后一个用封号' ;'结尾
变量命
var age=18, address='阿里巴巴', ip='adsfafd';
名规范
规则:
-
由字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成,如:usrAge, num01, _name
-
严格区分大小写。var app; 和 var App; 是两个变量
-
不能 以数字开头。 18age 是错误的
-
不能 是关键字、保留字。例如:var、for、while
-
变量名必须有意义。 MMD BBD nl → age
-
遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。myFirstName(尽量不要直接使用name)
数据类型
数据类型的分类
-
简单数据类型(Number,String,Boolean,Undefined,Null)
-
复杂数据类型(Object)
JavaScript 中的简单数据类型及其说明如下:
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含 整型值和浮点型值,如20,0.2 | 0 |
Boolean | 布尔类型,如 true,false | false |
String | 字符串类型,如 “张三” (注意,js里面字符串都要带引号) | “” |
Undefined | var a;声明了变量a,但是没有赋值,此时a=undefined | underfined |
Null | var a = null; 声明变量a为空值 | null |
字符串长度及拼接
length:检测获取字符串长度(包括空格,也计算在内)
<script type="text/javascript"> var str = 'My name is abc'; console.log(str.length); </script> //结果为 14
字符串拼接:
-
多个字符串之间可以使用加号 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
-
其中任何类型再拼接前,会被转化成字符串,再拼接成一个新的字符串
console.log("dsafa"+121);//dsafa121
获取变量数据类型
typeof 可用来获取检测变量的数据类型
var num = 18; console.log(typeof num) // 结果 number
JS基本语法
流程分支控制
流程控制就是来控制我们的代码按照什么结构顺序来执行
三种结构:顺序结构、分支结构、循环结构
分支结构
-
if的语法结构
-
if(条件表达式){ //执行语句 }else{ } 如果if里面的条件表达式为真,则执行打括号里面的代码,否则向下执行(else语句)
-
-
if-else-if多分支
-
三元表达式 ? :
-
语法结构: 条件表达式 ? 表达式1 : 表达式2
-
如果条件表达式结果为真,则返回表达式1的值,否则返回表达式2的值;
-
var num = 10; var result = num>5?'yes':'no'; console.log(result);//yes
-
-
-
switch 语句
-
switch (表达式){ case value1; 执行语句1: break; case value2: 执行语句2; break; case value3: 执行语句3; break; ... default: (若前面没有执行或没有break)执行最终语句; }
举个栗子
-
var a = prompt('输入一个数字');//此时a是字符串类型,需要转成数值型number a=Number(a); // console.log(typeof(b));//number switch(a){ case 1: console.log('这是1'); break; case 2: console.log('这是2'); break; case 3: console.log('这是3'); break; case 4: console.log('这是4'); break; default: console.log('不在1-4范围内'); }
-
注意事项:
-
表达式中长写成变量
-
num 的值 和 case 里面的值相匹配的时候是 全等,必须是值和数据类型都一致才可以 num & typeof(num)
-
没写break的话,会从符合条件的case向下继续执行,直到遇到break或default执行完毕
-
循环结构
一组被重复执行的语句称为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称为循环语句。
分为三种 for循环 while循环 和do while循环
数组及冒泡排序
-
数组可以把一组相关的数据一起存放,并提供方便的访问(获取)方式。
-
数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
JS 中创建数组有两种方式:
-
利用 new 创建数组
var 数组名 = new Array() ; var arr = new Array(); // 创建一个新的空数组
注意 Array () ,A 要大写
-
利用数组字面量创建数组
//1. 使用数组字面量方式创建空的数组 var 数组名 = []; //2. 使用数组字面量方式创建带初始值的数组 var 数组名 = ['小白','小黑','大黄','瑞奇'];
-
数组的字面量是方括号 [ ]
-
声明数组并赋值称为数组的初始化
-
这种字面量方式也是我们以后最多使用的方式
-
-
数组元素的类型
-
]数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。
-
var arrStus = ['小白',12,true,28.9];
-
-
便利数组(for循环)
-
var arr = ['a','t','r','e','w'] for(var i = 0; i < arr.length;i++){ console.log(arr[i]); } console.log(arr.length);
-
案例:将数组['red','green','blue','pink']转换为字符串,并且用|或其他分割符分割
-
输出:'red|green|blue|pink|'
-
var color = ['red','green','blue','pink']; var result = ''; for(var i = 0;i <color.length;i++){ result+=color[i] + '|'; // result+='|'; } console.log(result);
-
冒泡排序
外层for循环解决便利的次数(趟数),n个数需要 n-1 趟
内层for循环解决交换次数,n个数需要 n-i-1 次
var arr=[2,5,7,6,4,0,1,3,8,9,10,15,22,13,9,8,15,12,1,10]; function bubbleSort(arr){ 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 temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } return arr; } console.log(bubbleSort(arr));
函数
函数就是封装一段可被重复调用执行的代码块。
函数的参数
JS参数分为形参和实参,利用函数的参数实现函数重复不同的代码
先声明,再调用
-
function 函数名 (形参1,形参2...){函数体}
-
调用函数:函数名(实参1,实参2...);
形参与实参的执行过程
//冒泡排序算法封装成函数 var arr=[2,5,7,6,4,0,1,3,8,9,10,15,22,13,9,8,15,12,1,10]; function bubbleSort(arr){ 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 temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } console.log(arr); } bubbleSort(arr);
注意:js中允许实参个数与形参个数不一致,当实参个数小于形参个数时,函数不一定能正常调用,而额外的形参只能是个没有定义的变量,没有实际意义(若实参个数多余形参时,多的实参也没有意义,但能正常调用函数)。
函数的返回值 return
语法格式:
function(){ return 需要返回的结果 }
注意:
-
return 语句终止函数,
-
只能返回一个值,若用逗号隔开多个值,只以最后一个为准(可以通过数组来实现返回多个值)
-
函数若没有返回,则返回的是undefined;
-
return 不仅可以退出循环,还能够返回return语句中的值,同时还可以结束当前的函数体内的代码
arguments
当不确定有多少个参数传递的时候,可以用 arguments 来获取。JavaScript 中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
-
具有 length 属性
-
按索引方式储存数据
-
不具有数组的 push , pop 等方法
注意:在函数内部使用该对象,用此对象获取函数调用时传的实参。
函数的两种声明方式
-
自定义函数方式(命名函数)
利用函数关键字 function 自定义函数方式
// 声明定义方式 function fn() {...} // 调用 fn();
-
因为有名字,所以也被称为命名函数
-
调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
-
-
函数表达式方式(匿名函数)
利用函数表达式方式的写法如下:
// 这是函数表达式写法,匿名函数后面跟分号结束 var fn = function(){...}; // 调用的方式,函数调用必须写到函数体下面 fn();
-
因为函数没有名字,所以也被称为匿名函数
-
这个fn 里面存储的是一个函数
-
函数表达式方式原理跟声明变量方式是一致的
-
函数调用的代码必须写到函数体后面
-
JS 作用域
代码变量再某个范围内起作用和效果,目的是为了提高程序的可靠性,以及减少命名冲突。
作用域分为:全局作用域和局部作用域(es6之前)
-
全局作用域:整个script标签,或者是一个单独的js文件
-
局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字只在函数内部起作用和效果
根据作用域的不同,可分为全局变量和局部变量
-
全局变量:在全局作用域下的变量,在全局都能使用
-
局部变量:在局部作用域下的变量,只能在函数内使用
注意:如果在函数内部没有声明的变量,就直接赋值,那么这个变量也属于全局变量。
从执行效率来看全局变量和局部变量
-
全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
-
局部变量,当我们程序执行完毕就会销毁,比较节约资源
JS在es5之前没有块级作用域,在es6时新增了块级作用域
块级作用域:花括号{}
作用域链:
-
只要写代码,就至少有一个作用域,
-
写在函数内部的局部作用域
-
如果函数内还有其他函数,那么在这个作用域中就可以诞生一个作用域
-
根据内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链。
JS 预解析
js代码时由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:预解析和代码执行。
-
预解析:js引擎会把js里面所有的 var 还有 function 提升到当前作用域的最前面
-
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
-
变量提升:把所有的变量声明提升到当前的作用域最前面,注意:它不提升赋值操作
-
console.log(num); var num = 10; //上面两行代码相当于执行了以下代码: var num;//变量提升 console.log(num);//报错 num = 10;
-
-
函数提升:把所有的通过函数名的方式定义的函数会被提升到当前的作用域最前面(匿名函数不行),注意:它提升了函数定义操作,但不调用函数
-
fun(); //声明定义一个匿名函数 var fun = function(){ console.log(22); } //上面的函数相当于执行了以下代码: var fun; fun();//并没有该函数,因此无法调用 fun = funtion(){ console.log(22); }//报错
-
fn(); function fn(){ console.log(11); } //上面的函数相当于执行了以下代码: function fn(){ console.log(11); }//函数提升,通过函数名的方式定义的函数会被提升到前面 fn();
-
-
-
-
代码执行:按照代码书写的顺序从上往下执行
预解析案例:
-
//预解析案例 var num = 10; fun(); function fun(){ console.log(num); var num = 20; } var num; //相当于执行了以下操作 var num; function fun(){ var num; console.log(num); num = 20; } num = 10; fun();//undefined
对象
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等
对象由属性和方法组成
-
属性:事物的特征,对象中用属性来表示(名词)
-
方法:事物的行为,在对象中用方法来表示(动词)
创建对象的三种方式
在JavaScript中,目前有三种方式创建对象(Object):
-
字面量创建对象
-
new Object创建对象
-
利用构造函数创建对象
字面量创建对象
对象字面量:就是花括号{}里面包含了表达这个具体事务(对象)的属性和方法。
语法:var obj = {};//创建了一个空的对象
var obj = { uname:'a', age:'18', sex'男', sayHi:function(){ console.log('hi~'); } }
注意:
-
{}里面的属性或方法,一般采用键值对形式 键 属性名:值 属性值
-
多个属性或方法之间用逗号隔开
-
方法冒号后面跟一个匿名函数
调用对象
调用对象的属性,一般采取 对象名.属性名 的方式
-
console.log(obj.uname);
调用对象的属性还有另一种方式:对象名['属性名']
-
console.log(obj['age']);
调用对象的方法:对象名.方法名
-
obj.sayHi();//注意别忘了添加小括号
利用new Object创建对象
跟new Array()原理一致
var 对象名 = new Object();
var obj = new Object();//创建了一个空的对象
属性/方法追加
obj.uname = 'a'; obj.age = 18; obj.sex = '男'; obj.sayHi = function(){ console.log('hi~'); }
注意:
-
利用等号 = 赋值的方法,添加对象的属性和方法
-
每个属性和方法之间用 分号 ; 结束
-
对象调用和字面量创建对象的调用方式一致
构造函数创造对象
因为前面两种创建对象的方式 一次只能创建一个对象,因此有时候需要用构造函数来创建(多个)对象。
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用。构造函数就是把对象中一些相同的属性和方法抽象出来,封装到函数里面。
语法格式:
function 构造函数名(){ this.属性 = 值; this.方法 = function(){} } //调用构造函数: new 构造函数名();
举个栗子:
/* 构造函数 */ function Star(uname,age,sex){ this.name = uname; this.age = age; this.sex = sex; } //调用构造函数 var a = new Star('a',18,'男'); console.log(typeof(a));//object console.log(a);
注意:
-
构造函数名字首字母要大写
-
构造函数不需要return 就可以返回结果(一个对象)
-
调用函数必须使用new
new关键字执行过程
-
new 构造函数可以在内存中创建了一个空的对象
-
this 就会只想刚才创建的空对象
-
执行构造函数里面的代码,给这个空对象添加属性和方法
-
返回这个对象(所以构造函数不需要return)
遍历对象
-
通过 for in 遍历对象
-
for(变量 in 对象){}
-
-
举个栗子
for(var key in obj){ console.log(k);//k 变量 输出 得到的是 属性名 console.log(obj[k]);//obj[k] 得到是 属性值 }
内置对象
JavaScript中的对象分为3中,自定义对象,内置对象,浏览器对象
其中 自定义对象和内置对象是JS基础内容,属于ECMAScript;浏览器对象属于JS独有。
内置对象:JS语言自带的一些对象,这些对象工开发者使用,并提供了一些常用的或最基本而必要的功能(属性和方法)
JS提供了多个内置对象:Math、Date、Array、String等
查阅MDN文档
网址:https://developer.mozilla.org/zh-CN/docs/Web
封装自己的方法
//封装方法 myMath={ max:function(){ var max = arguments[0]; for(var i = 0;i<arguments.length;i++){ if(max<arguments[i]){ max = arguments[i]; } } return max; }, min:function(){ var min = arguments[0]; for(var i = 0 ; i <arguments.length;i++){ if(min>arguments[i]){ min = arguments[i]; } } return min; }, PI:3.141592653, } //调用自己的方法 console.log(myMath.max(1,2,5,9)); console.log(myMath.min(1,2,5,9));
格式化日期
获取当前年月日:
var year = date.getFullYear(); var month = date.getMonth()+1; var dates = date.getDate(); var arr = ['周日','周一','周二','周三','周四','周五','周六']; var day = arr[date.getDay()]; console.log('今天是:'+year+'年'+month+'月'+dates+'日 '+day); //今天是:2021年11月14日 周日
封装一个函数 返回当前时间的年月日,时分秒 格式: xxxx年xx月xx日 xx:xx:xx 周x
myDate = { nowDate: function(){ var date = new Date; var year = date.getFullYear(); var month = date.getMonth() + 1; var dates = date.getDate(); var hour = date.getHours(); hour = hour<10?'0'+hour:hour; var minute = date.getMinutes(); minute = minute<10?'0'+minute:minute; var second = date.getSeconds(); second = second<10?'0'+second:second; var arr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; var day = arr[date.getDay()]; console.log('现在是:北京时间' + year + '年' + month + '月' + dates + '日 ' + hour + ':' + minute + ':' + second +' ' + day); }, } myDate.nowDate();
Web APIs
web APIs是JS的应用,大量的使用JS基础语法做交互效果
API 和Web API
API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。
web api 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
DOM
文档对象模型(Document Object Model)是W3C组织推荐的处理可扩展标记语(HTML或XML)的标准编程接口。
通过DOM接口可以改变网页的内容、结构和样式。
DOM树
文档:一个页面就是一个文档,DOM中使用document表示
元素:页面中的所有标签都是元素,DOM中使用element表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示。
DOM把以上内容都看作是对象
根据ID获取元素
语法:document.getElementById(id) 作用:根据ID获取元素对象 参数:id值,区分大小写的字符串 返回值:元素对象 或 null
-
因为我们文档页面从上往下加载,所以先得有标签,所以我们script写在标签的下面
-
getElementById:驼峰命名法
-
get:获得element元素 by :通过
-
element
是一个 Element对象。如果当前文档中拥有特定ID的元素不存在则返回null. -
id
是大小写敏感的字符串,代表了所要查找的元素的唯一ID.
<body> <div id="time">2019-9-9</div> <script> // 因为我们文档页面从上往下加载,所以先得有标签 所以我们script写到标签的下面 var timer = document.getElementById('time'); console.log(timer); console.log(typeof timer); // console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法 console.dir(timer); </script> </body>
根据标签名获取元素
使用 getElementsByTagName()方法可以返回带有指定标签名的对象的集合。
语法:document.getElementsByTagName('标签名') 或者 element.getElementsByTagName('标签名')
作用:根据标签名获取元素对象
参数:标签名
返回值:元素对象集合(伪数组,数组元素是元素对象)
举个栗子
<script> // 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的 var lis = document.getElementsByTagName('li'); console.log(lis); console.log(lis[0]); // 2. 我们想要依次打印里面的元素对象我们可以采取遍历的方式 for (var i = 0; i < lis.length; i++) { console.log(lis[i]); } // 3. element.getElementsByTagName() 可以得到这个元素里面的某些标签 var nav = document.getElementById('nav'); // 这个获得nav 元素 var navLis = nav.getElementsByTagName('li'); console.log(navLis); </script>
根据类名获取元素
-
document.getElementsByClassName('类名');//根据类名返回元素对象集合 var box = document.getElementsByClassName('box'); console.log(box);
根据选择器获取元素
document.querySelector('选择器'); //根据指定选择器返回第一个元素对象(只能返回一个且为第一个) document.querySelectorAll('选择器'); //根据指定选择器返回
注意:
-
querySelector 和 querySelectorAll 里面的选择器需要加符号,比如:document.querySelector('#nav');
-
querySelector 和 querySelectorAll需要写在选择器的下方才有效,写在上方无效
举个栗子:
<body> <script type="text/javascript"> // 1、getElementsByClassName 根据类名获得某些元素集合 var box = document.getElementsByClassName('box'); console.log(box);//有效 var firBox = document.querySelectorAll('#nav'); var allBox = document.querySelectorAll('.box'); console.log(firBox);//无效 console.log(allBox);//无效 </script> <div class="box">盒子1</div> <div class="box">盒子2</div> <div id="nav"> <ul> <li>首页</li> <li>产品</li> </ul> </div> </body>
写在script标签写在div上方,除了getElement有效,querySelector 和 querySelectorAll均无效
获取特殊元素
获取body元素
事件基础
-
事件源(谁):触发事件的元素
-
事件类型(什么事件): 例如 click 点击事件
-
事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数
执行事件的步骤
-
获取事件源
-
注册事件(绑定事件)
-
添加事件处理程序(采取函数赋值形式)
案例
<body> <div>123</div> <script> // 执行事件步骤 // 点击div 控制台输出 我被选中了 // 1. 获取事件源 var div = document.querySelector('div'); // 2.绑定事件 注册事件 // div.onclick // 3.添加事件处理程序 div.onclick = function() { console.log('我被选中了'); } </script> </body>
常见鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
操作元素
改变元素内容
-
element.innerText 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉。
-
element.innerHTML 从起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。
innerText不能识别html标签 而innerHtml能够识别html标签
举个栗子
<body> <div class="box1"></div> <div class="box2"></div> <p>aaaaa <span>123123</span> </p> <script type="text/javascript"> // var div = document.querySelector('div'); // var div = document.getElementsByClassName('box1');//返回一个伪数组 var div1 = document.querySelector('.box1'); var div2 = document.querySelector('.box2'); div1.innerHTML = '<strong>今天是:</Strong> 2021-11-14'; div2.innerText = '<strong>今天是:</Strong> 2021-11-14'; // 通过innerText和innerHTML读取标签内容 var p = document.querySelector('p'); console.log(p.innerText); console.log(p.innerHTML); /* 结果: aaaaa 123123 aaaaa <span>123123</span> */ </script> </body>
结果:
今天是: 2021-11-14 <strong>今天是:</Strong> 2021-11-14 /* 结果: aaaaa 123123 aaaaa <span>123123</span> */
-
innerText 和innerHTML这两个属性是可读写的,可以获取元素里面的内容
操作常见元素的属性
-
innerText、innerHTML 改变元素内容 src、href id、alt、title
案例:
<body> <button>刘德华</button> <button>张学友</button> <img src="../images/ldh.jpg" alt=""> <script type="text/javascript"> // 修改元素属性 src //1、获取元素 var btn = document.querySelectorAll('button'); var img = document.querySelector('img'); // 注册事件 btn[0].onclick = function(){ img.src = '../images/ldh.jpg'; img.title = '刘德华'; } btn[1].onclick = function(){ img.src = '../images/zxy.jpg'; img.title = '张学友'; } </script> </body>
案例二:分时显示不同图片
根据不同时间,页面显示不同图片,同时显示不同的问候语
案例分析:
-
根据系统不同事件来判断,所以需要用到日期内置对象
-
利用多分支语句来设置不同的图片
-
需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性
-
需要一个dic元素。显示不同问候语,修改怨怒内容(innerHTML)
<body> <img src="../images/s.gif" alt=""> <div>上午好</div> <script type="text/javascript"> /* 获取元素 */ var img = document.querySelector('img'); var div = document.querySelector('div'); /* 得到当前的小时数 */ var date = new Date(); var h = date.getHours(); /* h = Number(h); */ /* h = 2; */ if(0<=h&&h<8){ div.innerText = '早上好'; img.src = '../images/z.gif'; }else if(h<12){ div.innerText = '上午好'; img.src = '../images/s.gif'; }else if(h<18){ div.innerText = '下午好'; img.src = '../images/x.gif'; }else if(h<24){ div.innerText = '晚上好'; img.src = '../images/w.gif'; } </script> </body>
表单元素的属性操作
利用DOM可以操作如下表单元素的属性:
type、value、checked、sekected、disabled
举个栗子
<body> <button>按钮</button> <input type="text" value="输入内容"> <script> // 获取元素 var btn = document.querySelector('button'); var input = document.querySelector('input'); // 注册事件,处理程序 btn.onclick = function(){ input.value = '修改了内容'; //(表单里面的值是通过value修改的) // 如果想禁用某个表单,使他不能再点击,修改disabled属性为true,button按钮就会被禁用 btn.disabled = true; this.disabled = true; //this指向事件函数的调用者(btn) } </script> </body>
仿京东显示隐藏密码案例
点击按钮将密码框切换为文本框,并可以查看密码明文。
案例分析
-
核心思路:点击眼睛按钮,把密码框类型改为文本框就可以看见里面的密码
-
一个按钮有两个状态,点击一次,切换为文本框,继续点击一次切换为密码框
-
算法:利用一个flag变量,来判断flag的值,如果是1点击切换为文本框(显示),然后将flag置为0;
如果flag的值为0,点击就切换为密码框(隐藏),然后将flag置为1;
代码:
<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></title> <style type="text/css"> .box{ width: 400px; border-bottom: 1px solid #ccc; margin: 100px auto; position: relative; } .box input{ width: 370px; height: 30px; border:0; outline: none; } /* .box label{ position: relative; } */ .box img{ width: 24px; position: absolute; top: 5px; right: 5px; } </style> </head> <body> <div class="box"> <label for=""> <img src="../images/close.png" > </label> <input type="password"> </div> <script type="text/javascript"> var eye = document.querySelector('img'); var input = document.querySelector('input'); var temp = 0; eye.onclick = function(){ if(temp == 0){ eye.src = '../images/close.png'; input.type = 'password'; temp = 1; }else if(temp == 1){ eye.src = '../images/open.png'; input.type = 'text'; temp = 0; } } </script> </body>
样式属性操作
通过js修改元素的大小、颜色、位置等样式
element.style 行内样式操作
element.className 类名样式操作
注意:
-
JS里面的样式采取驼峰命名法,比如:fontSize,backgroundColor
-
JS 修改style 样式操作,产生的是行内样式,css权重比较高
举个栗子
<head> <meta charset="utf-8"> <title></title> <style type="text/css"> div { width: 100px; height: 100px; background-color: #00BFFF; } </style> </head> <body> <div></div> <!-- 需求:点击div背景颜色改变 --> <script type="text/javascript"> var div = document.querySelector('div'); div.onclick = function() { // 驼峰命名法 this.style.backgroundColor = 'pink'; this.style.width = '200px'; } </script> </body>
仿淘宝二维码显示隐藏案例
-
核心思路:利用样式的显示和隐藏完成,display.none 隐藏元素,display.block 显示元素
-
点击按钮,让二维码盒子隐藏
代码:
<head> <meta charset="utf-8"> <title></title> <style type="text/css"> .box{ position: relative; left: 500px; top: 200px; } .box .closeBtn{ width: 15px; height: 15px; background: url(../images/wrong.png); position: absolute; top: -15px; left: -15px; } </style> </head> <body> <div class="box"> <img src="../images/tao.png" > <div class="closeBtn"></div> </div> <script type="text/javascript"> // var img = document.querySelector('img'); var closeBtn = document.querySelector('.closeBtn'); var box = document.getElementsByClassName('box'); closeBtn.onclick = function(){ box[0].style.display = 'none'; } </script> </body>
循环精灵图背景
案例分析:
-
首先,精灵图图片排列是有规律的
-
核心思路:利用for循环 修改精灵图片的背景位置 background-position
-
找规律,由于这组精灵图是竖着排列的,所以x轴坐标为0;让循环里面的i索引号 * 44就是每个精灵图的y轴坐标。
<head> <meta charset="utf-8"> <title></title> <style type="text/css"> div ul li{ width: 24px; height: 24px; margin: 10px; /* background-color: #00BFFF; */ list-style: none; background: url(../images/sprite.png); } </style> </head> <body> <div> <ul> <li></li><li></li><li></li><li></li><li></li> <li></li><li></li><li></li><li></li><li></li> <li></li><li></li><li></li><li></li> </ul> </div> <script type="text/javascript"> var img = document.getElementsByTagName('li'); for(var i = 0;i<img.length;i++){ var index = i * 44; img[i].style.backgroundPosition = '0 -' + index + 'px'; } </script> </body>
显示隐藏文本框内容
案例分析:
-
首先需要两个事件,获得焦点 onfocus 失去焦点 onblur
-
如果获得焦点,判断表单里面的内容是否为默认文字,如果是默认文字,就清空表单内容
-
如果失去焦点,判断表单内容是否为空,如果为空,则表单内容改为默认文字
<body> <input type="text" value="手机"> <script type="text/javascript"> var onfocus = document.querySelector('input'); var onblur = document.querySelector('input'); var index = 0; onfocus.onfocus = function(){ if(this.value === '手机'){ this.value = ''; } // 获得焦点,文字颜色变深 this.style.color = '#333'; } onblur.onblur = function(){ if(this.value===''){ onblur.value = '手机'; } // 失去焦点,文字颜色变浅 this.style.color = '#999'; } </script> </body>
使用className修改样式属性
element.style 行内样式操作
element.className 类名样式操作
-
使用element.style 获得修改元素样式,如果样式比较少 或者 功能简单的情况下使用
-
通过修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
注意:
-
className 会直接更改元素的类名,会覆盖原先的类名
-
如果想要保留原先的类名,可以在各个类名之间空格隔开(多类名选择器):
this.className = 'first change last a b c'
举个栗子
<html> <head> <meta charset="utf-8"> <title></title> <style> div{ width: 100px; height: 100px; background-color: #00BFFF; } .change{ width: 200px; height: 200px; background-color:pink; color: aqua; font-size: 18px; } </style> </head> <body> <div>改变前</div> <script type="text/javascript"> var test = document.querySelector('div'); test.onclick = function(){ this.innerHTML = '改变后'; this.className = 'change'; } </script> </body> </html>
密码框格式提示错误信息
在用户注册账号时,如果用户离开密码框,里面输入个数不是6-16个字符,则提示错误信息,否则提示输入正确信息
案例分析:
-
首先判断的事件是表单失去焦点 onblur
-
如果输入正确,则提示正确的信息,且颜色为绿色小图标
-
如果输入不是6-16位,则提示输入错误信息,颜色位红色小图标
-
因为里面变化样式较多,所以建议采取className修改样式
<html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> div { width: 600px; margin: 100px auto; } .message { display: inline-block; font-size: 12px; color: #999; background: url(../images/mess.png) no-repeat left center; padding-left: 20px; } .wrong{ color: red; background:url(../images/wrong.png) no-repeat left center; } .true{ background: url(../images/right.png) no-repeat left center; color: green; } </style> </head> <body> <div class="register"> <input type="password" class="ipt"> <p class="message">请输入6-16位密码</p> </div> <!-- 方法一:不用className --> <script type="text/javascript"> var ipt = document.querySelector('.ipt'); var message = document.querySelector('.message'); //注册 失去焦点事件 ipt.onblur = function(){ if(ipt.value.length>=6&&ipt.value.length<=16){ message.style.background ='url(../images/right.png) no-repeat left center'; message.innerHTML = '输入正确'; message.style.color = 'green'; // console.log('正确'); }else{ message.style.background='url(../images/wrong.png) no-repeat left center'; message.innerHTML = '请输入6-16位密码'; message.style.color = 'red'; } } </script> <!-- 方法二:使用className --> <!-- <script type="text/javascript"> var ipt = document.querySelector('.ipt'); var message = document.querySelector('.message'); //注册 失去焦点事件 ipt.onblur = function() { if (ipt.value.length >= 6 && ipt.value.length <= 16) { message.className = 'message true'; message.innerHTML = '输入正确'; // console.log('正确'); } else { message.className = 'message wrong'; message.innerHTML = '请输入6-16位密码'; } } </script> --> </body> </html>
排他思想(算法)
如果有同一组元素,我们想要某个元素实现某种样式,需要用到循环的排他思想算法:
-
所有元素全部清除样式(干掉其他人)
-
给当前元素设置样式(留下我自己)
-
注意顺序不能颠倒,首先干掉其他人,再设置自己(代码从上向下执行)
举个栗子:
给5个按钮同时设置点击事件,当点击某个按钮时背景色改变,而其他按钮背景色不变
<body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script type="text/javascript"> //获取所有按钮元素 var btns = document.getElementsByTagName('button'); //btns 得到的是伪数组, for (var i = 0; i < btns.length; i++) { //console.log(i);//i==0 1 2 3 4 btns[i].onclick = function(){ //为什么不能用 btns[i]? //因为发生点击事件时,此时i==5,btns[5]数组越界了 //先把所有按钮背景色去除,再给当前按钮添加背景色 for(var j = 0 ; j <btns.length;j++){ btns[j].style.backgroundColor = ''; } btns[i].style.backgroundColor = 'pink'; } } </script> </body>
百度换肤效果
案例分析:
-
这个案例练习的是给一组元素注册事件
-
给4个小图片,利用循环注册点击事件
-
当我们点击了这个图片,让我们页面背景改为当前的图片
-
核心算法:把当前图片的src路径取过来,给body作为背景即可
<html> <head> <meta charset="utf-8"> <title></title> <style> * { margin: 0; padding: 0; } body { background: url(../images/1.jpg) no-repeat center top; } li { list-style: none; } .baidu { overflow: hidden; margin: 100px auto; background-color: #fff; width: 410px; 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="../images/1.jpg" alt=""></li> <li><img src="../images/2.jpg" alt=""></li> <li><img src="../images/3.jpg" alt=""></li> <li><img src="../images/4.jpg" alt=""></li> </ul> <script type="text/javascript"> //获取元素 严谨写法 var imgs = document.querySelector('.baidu').querySelectorAll('img'); // var bg = document.querySelector('body'); //通过for循环依次给四个图片注册点击事件 for(var i = 0;i<imgs.length;i++){ imgs[i].onclick = function(){ console.log(this.src); document.body.style.background = 'URL('+this.src+')'; // bg.style.background = 'URL('+this.src+')'; } } </script> </body> </html>
表格隔行变色
案例分析:
-
用到新的鼠标事件,鼠标经过onmouseover 鼠标离开 onmouseout
-
核心思路:鼠标经过tr行,当前的行变背景颜色,鼠标离开去掉当前的背景颜色
-
注意:第一行(thread里面的行) 不需要换掉颜色,因此我们获取的是tbody里面的行
<html> <head> <meta charset="utf-8"> <title></title> <style> table { width: 800px; margin: 100px auto; text-align: center; border-collapse: collapse; font-size: 14px; } thead tr { height: 30px; background-color: skyblue; } tbody tr { height: 30px; } tbody td { border-bottom: 1px solid #d7d7d7; font-size: 12px; color: blue; } .bg { background-color: pink; } </style> </head> <body> <table> <thead> <tr> <th>代码</th> <th>名称</th> <th>最新公布净值</th> <th>累计净值</th> <th>前单位净值</th> <th>净值增长率</th> </tr> </thead> <tbody> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> <tr> <td>003526</td> <td>农银金穗3个月定期开放债券</td> <td>1.075</td> <td>1.079</td> <td>1.074</td> <td>+0.047%</td> </tr> </tbody> </table> <script type="text/javascript"> var trs = document.querySelector('tbody').querySelectorAll('tr'); //利用for循环注册事件 for(var i = 0; i <trs.length;i++){ // 鼠标悬停事件,添加背景色类名 trs[i].onmouseover = function(){ // this.style.backgroundColor = 'pink'; this.className = 'bg'; } // 鼠标离开事件,清空背景色类名 trs[i].onmouseout = function(){ // this.style.backgroundColor = ''; this.className = ''; } } </script> </body> </html>
表单全选取消案例
业务需求:
-
点击上面全选复选框,下面所有的复选框都选中(全选);
-
再次点击全选复选框,下面所有的复选框都不选中(取消全选)
-
如果下面复选框全部选中,上面全选按钮就自动选中
-
如果下面复选框有一个没有选中,上面全选按钮就不选中
-
所有复选框一开始默认都没有选中状态
案例分析:
-
让下面所有复选框的checked属性(选中状态)跟随 全选按钮即可
-
全选和取消全选做法:让下面所有复选框的checked属性(选中状态)跟随 全选按钮即可
-
下面复选框需要全部选中,上面全选才能选中做法:给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否没有选中的,如果有一个没有选中的,上面全选就不选中。
-
可以设置一个变量。控制全选是否选中
代码:
<html> <head> <meta charset="utf-8"> <title></title> <style> * { padding: 0; margin: 0; } .wrap { width: 300px; margin: 100px auto 0; } table { border-collapse: collapse; border-spacing: 0; border: 1px solid #c0c0c0; width: 300px; } th, td { border: 1px solid #d0d0d0; color: #404060; padding: 10px; } th { background-color: #09c; font: bold 16px "微软雅黑"; color: #fff; } td { font: 14px "微软雅黑"; } tbody tr { background-color: #f0f0f0; } tbody tr:hover { cursor: pointer; background-color: #fafafa; } </style> </head> <body> <div class="wrap"> <table> <thead> <tr> <th> <input type="checkbox" id="j_cbAll" /> </th> <th>商品</th> <th>价钱</th> </tr> </thead> <tbody id="j_tb"> <tr> <td> <input type="checkbox" /> </td> <td>iPhone8</td> <td>8000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Pro</td> <td>5000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Air</td> <td>2000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>Apple Watch</td> <td>2000</td> </tr> </tbody> </table> </div> <script type="text/javascript"> // 让下面所有复选框的checked属性(选中状态)跟随 全选按钮即可 //获取元素 var j_cbAll = document.getElementById('j_cbAll'); // console.log(j_cbAll); var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); j_cbAll.onclick = function() { for (var i = 0; i < j_tbs.length; i++) { // j_tbs[i].checked = 'checked'; j_tbs[i].checked = this.checked; } // if(j_cbAll.checked === true){ // // console.log('true'); // for(var i = 0; i <j_tbs.length;i++){ // // j_tbs[i].checked = 'checked'; // j_tbs[i].checked = this.checked; // } // } // else{ // j_cbAll.checked = ''; // for(var i = 0; i <j_tbs.length;i++){ // j_tbs[i].checked = ''; // } // } } for (var i = 0; i < j_tbs.length; i++) { j_tbs[i].onclick = function() { //每次点击下面的复选框 都要循环检查四个是否都全选了 // for(var i = 0;i<j_tbs.length;i++){ // if(j_tbs[i].checked===false){ // j_cbAll.checked = false; // }else{ // j_cbAll.checked =true; // } // } var flag = true; //如果有一个不是选中状态,那么flag就改为false for (var i = 0; i < j_tbs.length; i++) { if (!j_tbs[i].checked) { flag = false; break; } } j_cbAll.checked = flag; } } </script> </body> </html>
自定义属性操作
在某些场合 元素的属性不够用时,需要我们自定义属性(如:date-index = "1")
获取属性值:
-
element.属性
-
element.getAttribute('属性');
举个栗子:
<body> <div id="demo" date-index = "1"></div> <script type="text/javascript"> var div = document.querySelector('div'); // 1 element.属性 console.log(div.id); //element.getAttrabute('属性') attrabute:属性 //date-index = "1" 就是自定义属性,获取方法如下 console.log(div.getAttribute('id')); console.log(div.getAttribute('date-index')); </script> </body>
区别:
-
element.属性 获取内置属性值(元素本身自带的属性)
-
element.getAttribute('属性');主要获得自定义的属性(标准) 由程序员自定义的属性
设置移除自定义属性操作
设置属性:
-
element.属性 = '值';
设置内置属性值 -
element.setAttribute('属性','值');
有get方法那肯定不会少set方法. 主要针对于自定义属性
举个栗子:
<body> <div id="demo" date-index = "1"></div> <script type="text/javascript"> var div = document.querySelector('div'); //给class设置属性:div.className div.id = 'test'; div.className = 'nav'; div.setAttribute('index',2); //注意:class 较特殊,在里面写的就是class,不是className div.setAttribute('class','footer'); </script> </body>
移除属性:remove
//添加类名位footer属性 div.setAttribute('class','footer'); //移除 footer属性 div.removeAttribute('footer');
tab栏切换案例