一、JavaScript介绍
1.JavaScript历史
布兰登 艾奇 1995年在网景公司 发明的JavaScript
2. JavaScript与ECMAScript
ECMA是“European Computer Manufacturers Association”的缩写,中文名称为欧洲计算机制造商协会
它组织定制了当时出了JavaScript以外的多门语言标准,这个标准就叫ECMAScript
可以简单地认为ECMAScript就是JavaScript
总结——ECMAScript是一种语言标准,JavaScript是对ECMAScript的一种实现
3. JavaScript组成部分:
- 核心(ECMAScript)
包含:变量、测试语句、数据类型、运算符、数据类型转换、流程控制、常用内置对象(Array,String,Date,Math内置对象,Function函数) - 文档对象模型(DOM)
DOM节点、获取DOM的三种方式、值的操作、样式操作、属性操作、DOM操作 - 浏览器对象模型(BOM)
包含了当前浏览器上的操作,比如关闭按钮,刷新按钮,前进、后退按钮
二、ECMAScript 5.0
1. JS的引入方式
- 内接式
可以写在head标签中,也可以写在body标签中 - 外接式
利用script标签的src属性连接外部js文件
2. 注释
单行注释与多行注释
3. 变量
存储不同数据类型的一个容器
①声明变量
- 在js中使用var关键字 进行变量的声明,注意 分号作为一句代码的结束符
- 变量初始化:声明并且赋值变量
- 变量可以重新赋值,如var x = 30; 然后再x = 50;那么x最后是50
②变量的命名规则
- 必须使用字母、下划线_、或者$作为开始
- 多个英文字母驼峰显示:myName
- 不能使用js中的关键字和保留字来命名
- 严格区分大小写
4. 基本的变量类型
①基本的数据类型
-
number
var a = 100;
var b = 0.1;
var c = -1;
虽然a、b、c分别是整数、浮点数、负数类型,但在JS中都是number类型
可以通过alert(typeof a);在浏览器中显示数据类型 -
string
字符串需要用单引号’'或者双引号"",例如“abc123” -
boolean
布尔类型,0代表False,1代表Truevar x = 1 > 2; #将1>2的结果返回给x alert(x); #打印x为false alert(typeof x); #打印x的类型为boolean
-
undefined
当一个变量只是单纯的声明并没有赋值时,他就是undefinedvar x; 只声明变量 alert(x); 打印x为undefined alert(typeof x); 打印x的类型也为undefined
-
null
类似 python中的none,是一个空值var x = null; #赋值x为null alert(x); #打印x为null alert(typeof x); #打印x的类型为object,是一个空的对象
②引用的数据类型
object、Array、Function
5. 算数运算符
var x = 10;
var y = 5;
var sum = x + y; #加
var en = x - y; #减
var or = x * y; #乘
var op = x / y; #除
x % y #取余数
var c = x + sum / 4 -3; #优先乘除,再做加减
6. 赋值运算符
var x = 10;
x ++; #x加1,等于x += 1
x --; #x减1,等于x -= 1
x += 2;
x -= 3;
x *= 2;
x /= 6;
alert(x);
7. 比较运算符
var x = 1;
var y = "1";
var isEqual_1 = x === y;
console.log(isEqual_1); #三个等于号会比较数值和数据类型,这里返回False
var isEqual_2 = x == y;
console.log(isEqual_2); #两个等于号只会比较数值,这里返回True
取反
var a = true;
! a 等于flase
8. 逻辑运算符
-
if…else语句嵌套
var weather = "sunny"; var temp = 32; if (weather === "sunny") { if (temp > 30) { console.log('天气太热,温度高于30度'); }else if (temp <= 30) { console.log('天气适宜,温度小于30度'); } }
-
逻辑且&&
var weather = "sunny"; var temp = 29; if (weather === "sunny" && temp > 30) { console.log('天气太热,温度高于30度'); }else if (weather ==="sunny" && temp <= 30) { console.log('天气适宜,温度小于30度'); }
-
逻辑或||
if (userName !== "Alex" || passWord !== "abc123") { console.log('登陆失败'); }
-
逻辑非!
var isLogin = false;
if (!isLogin) {
console.log(“登陆失败”);
}
!isLogin代表取反,等于true,符合条件
9. 字符串
-
字符串转译
var x = "Hello I'm \"Kerwin\"" #在需要转义的双引号前面加上斜杠\
-
字符串拼接
var x = “Hello”;
var y = “World”;
var z = x + " " + y;
在字符串中间拼接一个空格,可以在连句中加入空格 -
数值和字符串转换
-
隐式转换
var num = 123;
var myStr = 123 + “”;
将数值后面加空字符串,会自动将数值转换为字符串 -
字符串转数值(Number方法)
var str = “123”;
var myNum = Number(str);
alert(typeof myNum);打印结果为数值类型 -
数值转字符串(对象.toString()方法)
var num = 123;
var myStr = num.toString();
alert(typeof myStr);打印结果为字符串类型 -
报错
var s = "123abc"; var n = Number(s); alert(n); #打印n为NaN,代表Not a number,报错 alert(typeof n); #打印n的类型依旧为number,意味着转换成功,但结果报错
10. 数组Array
- 创建数组
var shopping = [“香蕉”,“牛奶”,“饮料”];
console.log(shopping);——表示通过浏览器控制台查看结果
alert(typeof shopping);——array的数据类型属于object
- 查看数组
var shopping = [“香蕉”,“牛奶”,“饮料”];
var item0 = shopping[0];——查看index=0的数据 - 修改数组
var shopping = [“香蕉”,“牛奶”,“饮料”];
shopping[0] = “面包”; - 查看数组的长度
shopping.length
11. 条件判断
var weather = "cloudy";
if (weather === "sunny"){
console.log("天气晴朗");
}else if (weather === "rainy"){
console.log("下雨天");
}else if(weather === "snowing"){
console.log("下雪了");
}else{
alert("输入的天气有误");
}
- 等于用===表示
12. switch语句(适用多重条件判断)
当需要多条件判断时,用switch可以比if…else简化代码
var weather = "sunny";
switch(weather) {
case "sunny":
console.log('天气晴朗');
break;
case "rainy":
console.log('天气下雨');
break;
case "cloudy":
console.log('天气多云');
break;
}
- switch(判断对象)——判断对象会与后面的case依次匹配,符合条件走下面的代码
- break——记得填写break,否则出现case穿透现象,代码会执行下一个break之前的代码
13. 三元运算符
语法:
条件 ?为真执行代码1 : 为假执行代码2;
例如:
var login = true;
var result = login === true ? ‘登陆成功’ : ‘登陆失败’;
登陆结果返回给result(三元运算会自动return)
- 问号?之前是判断条件
- 冒号:之前是符合条件执行的代码,之后是不符合条件执行的代码
14. for循环
语法:
for(初始化条件;结束条件;递增条件){
执行代码}
-
简单的数值循环
var i; var sum = 0; for (i = 0; i <= 10000; i++) { #初始化i从0开始,到10000结束,每次循环后i加1 sum += i; } console.log(sum);
-
遍历取出数组值的循环
var shoppingList = ["香蕉","苹果","西瓜","牛奶"] for (var i = 0; i < shoppingList.length; i++) { var htmlStr = "<h1>" + shoppingList[i] + "</h1>"; document.write(htmlStr); }
- var i = 0; i < shoppingList.length; i++
表示i从0开始到数组长度-1,遍历所有的索引 - var htmlStr = “<h1>” + shoppingList[i] + “</h1>”;
表示用string格式的h1标签包裹取出来的数组内容 - document.write(htmlStr);
表示将获得的html语句写进浏览器中显示
-
死循环——搭配break和continue使用
var x = 0; for (;;) { #for循环的参数全部不写代表死循环 x++; if (x > 10) { console.log(x); console.log("循环结束"); break; } }
15. while循环和do-while循环
-
while循环语法:
while(条件){执行代码}var n = 1;
var sum = 0;
while (n < 100) {
sum += n;
n ++;
}
console.log(sum); -
do-while循环
区别于while循环,它是先执行,再进行while判断var n = 1; var sum = 0; do { #先do sum += n; n ++; } while (n <= 1); #再判断n console.log(sum);
16. 函数
①函数语法:
function function_name(argument) {
// body...
}
②函数传参
function foo(isLogin) {
if (isLogin === true) {
console.log("登陆成功");}
else if (isLogin === false) {
console.log("登陆失败");
}
}
var isLogin = false;
foo(isLogin);
③函数返回值和函数表达式
- 函数返回值return
function add(x,y) {
return x + y;
}
var sum = add(1,2);
console.log(sum); - 函数表达式
var add = function (a,b) {
return a + b;
}
add(2,3);
#不给函数命名,将匿名函数赋值给add
④函数作用域和全局污染
声明全局变量:windows.a = 1;
全局污染:指引用不同js文件下同一函数名称,调用时会出现后引用js文件覆盖先引用的情况。可以在不同js文件中将函数声明成不同名的全局变量
var x = 1;
function foo() {
window.x = 2; #声明全局变量
}
foo();
console.log(x);
17. 对象object
对象(包含属性和方法)
-
字面量创建
var person = { name : "Kerwin", #属性之间用逗号分隔 age : 18, hobby : function run() { alert("I like running"); } } console.log(person.hobby());
-
工厂模式创建
function createStudent(name, age) { var obj = new Object(); obj.name = name; obj.age = age; return obj; } var student1 = createStudent("easy1", 20); var student2 = createStudent("easy2", 20);
18. 内置对象Array
var colors = new Array();
if (Array.isArray(colors)) {
colors[0] = "red";
colors[1] = "blue";
colors[2] = "yellow";
var x = colors.toString();
console.log(x);
console.log(typeof x);
}
-
var colors = new Array();——new Array()方法
创建一个新的数组,命名为colors -
Array.isArray(colors);——isArray()方法
判断colors是不是一个数组,是就执行代码,否则你操作colors[0]会报错 -
colors.toString();——toString()方法
将数组转换成字符串,中间以逗号隔开 -
toString和toLocaleString区别——定义不同的返回值
var person1 = { toString : function () { return "杨飞"; }, toLocaleString : function () { return "Kerwin"; }, } var person2 = { toString : function () { return "沈瑩娇"; }, toLocaleString : function () { return "Puzzaye"; }, } var people = [person1,person2]; console.log(people.toString()); #调用中文函数,返回杨飞,沈瑩娇 console.log(people.toLocaleString()); #调用英文函数,返回Kerwin,Puzzaye 在不同数值显示上也有些不一样,toLocaleString会结合本地特性,例如: 数字:"1234"和"1,234" 时间:"2017/2/15 上午11:21:31"和"Wed Feb 15 2017 11:21:31 GMT+0800 (CST)"
①数组的join方法
.join()方法,分隔字符串
var colors = ["red","blue","yellow"];
var str = colors.join("|");
console.log(str);
打印结果:red|blue|yellow
②数组的栈方法和队列方法
-
栈方法(lifo:last in first out)后进先出
push()方法——在数组最后一项添加数据var colors = ["red","blue","yellow"]; var newLength = colors.push("orange") #新增一个元素,返回数组的长度 console.log(newLength); #打印结果4 console.log(colors);
pop()方法——从数组末尾删除最后一项
var colors = ["red","blue","yellow"]; var lastItem = colors.pop(); #返回最后一个被删除的值 console.log(lastItem); console.log(colors);
-
队列方法(fifo:first in first out)先进先出
unshift()方法——在数组第一项添加数据var colors = ["red","blue","yellow"]; var newLength = colors.unshift("orange"); #在数组第一个元素新增数据并返回长度 console.log(newLength); console.log(colors);
shift()方法
var colors = ["red","blue","yellow"]; var firstItem = colors.shift(); #返回删除的第一个元素red console.log(firstItem); console.log(colors);
③数组排序
-
反转reverse()方法
var num = [1,3,41,43,12,334,5] num.reverse(); #打印结果:[5, 334, 12, 43, 41, 3, 1] console.log(num);
-
排序sort()方法
var num = [1,3,41,43,12,334,5] num.sort() console.log(num); #打印结果[1, 12, 3, 334, 41, 43, 5] #sort是按照第一个字符的ASCII码顺序排序,当第一个字符相同再比较第二个 如果要按照数值大小升序排列,需要自定义一个比较函数compare: var num = [1,3,41,43,12,334,5] function compare(a,b) { if (a > b) { #代表如果a>b,则索引值为正数,向后退 return 1; #这里的返回值不一定是1,只要是正数就可以 }else if (a < b) { return -1; }else if (a = b) { return 0; } } num.sort(compare); console.log(num); 比较函数可以简写为: function compare(a,b) { return a - b; }
④数组的操作方法
-
数组合并方法concat()
var colors = ["red","yellow","blue"]; 1. 合并单一对象 var newColors = colors.concat({name:"Alex"}); #newColors = ["red", "yellow", "blue", Object] 2. 合并另一个数组(将另一个数组的各个元素添加进来) var newColors = colors.concat(["orange","green"]); #newColors = ["red", "yellow", "blue", "orange", "green"]
-
数组切片方法slice(1,2)
在不影响原有数组的情况下,获得切片后的新数组var names = ["alex","jack","ben","egon","kerwin"]; var newNames = names.slice(1,3); console.log(newNames); #打印结果: ["jack", "ben"] #slice两个参数 第一个参数代表从哪里开始切 第二个参数代表到哪里为止(不填代表切到最后) 遵循顾头不顾尾的原则
-
数组的剪接方法splice()——实现删除、插入、替换功能
names.splice(start: int, deleteCount: int, items…: any)
含有三个参数:第一个起始处索引,第二个删除几个数据,第三个插入的数据var names = ["alex","jack","ben","egon","kerwin"]; 1. 删除功能 names.splice(1,2); #index从1开始删除2个 console.log(names); 打印结果:["alex", "egon", "kerwin"] 2. 插入功能 names.splice(1,0,"puzzaye"); #index从1开始插入puzzaye console.log(names); 打印结果:["alex", "puzzaye", "jack", "ben", "egon", "kerwin"] 3. 替换功能(先删除再插入) names.splice(4,1,"puzzaye"); #删除index为1的kerwin,插入puzzaye在index4上 console.log(names); 打印结果:["alex", "jack", "ben", "egon", "puzzaye"]
⑤数组的位置方法
-
indexof从左往右查到的第一个数值的索引
-
lastIndexof从右往左查到的第一个数值的索引
-
indexof(“alex”,3)和lastIndexof(“alex”,3)
他们都可以加第二个参数,代表从位置3开始向左或者向右查找var names = ["alex","jack","ben","jack","kerwin"]; alert(names.indexOf('jack')); #从左往右第一个jack在1 alert(names.lastIndexOf('jack')); #从右往左第一个jack在3 alert(names.indexOf('jack',2)); #第2个位置开始从左往右第一个jack在3 alert(names.lastIndexOf('jack',2)); #第2个位置开始从右往左第一个jack在1 alert(names.indexOf("XXXX")); #查询不到返回-1
⑥数组的迭代方法
-
filter过滤方法
var num = [1,3,4,12,34,5,9]; var newNum = num.filter(function (item,index,num) { return item > 10; }) console.log(newNum); #打印结果:[12, 34]
filter后面要跟一个过滤函数,指定return的内容
函数传三个参数:item,index,num
-
map方法
var num = [1,3,4,12,34,5,9]; var double = num.map(function (item,index,num) { return item*2; }) console.log(double); #打印结果:[2, 6, 8, 24, 68, 10, 18]
-
forEach遍历方法
var num = [1,3,4,12,34,5,9]; num.forEach(function (item,index) { console.log(item); }) #遍历所有的元素 示例: var peopleInfo = [ {name:"alex",age:18}, {name:"jack",age:8}, {name:"ben",age:20}, ] var names = peopleInfo.map(function (item) { return item.name }) var ages = peopleInfo.map(function (item) { return item.age }) console.log(names); #["alex", "jack", "ben"] console.log(ages); #[18, 8, 20]
19. 字符串
①字符串的字符方法
- length属性
var str = ‘Hello World’;
console.log(str.length); #长度为11(包含空格) - charAt方法——获取指定位置的字符
var str = ‘今天是星期一’;
console.log(str.charAt(2));#打印“是”,index从0开始 - charCodeAt方法——或缺指定字符对应的ASCII码
var str = ‘Hello World’;
console.log(str.charCodeAt(1)); #ASCII码为101 - concat方法——拼接字符串(通常情况下不使用它来拼接,使用+号来拼接)
var str = ‘Hello World’;
console.log(str.concat(’ Alex’,’ Jack’));#打印:Hello World Alex Jack
②字符串的切片方法
slice方法、substring方法、substr方法区别
-
三者第一个参数都是起始的位置
-
slice和substring的第二个参数是结束的位置(顾头不顾尾)
substr的第二个参数是向后取几位var str = 'HelloWorld'; console.log(str.slice(2,4)); #ll console.log(str.substring(2,4)); #ll console.log(str.substr(2,4)); #lloW
③字符串的其他方法
-
split方法
var str = ‘aaaa.bbb’;
var arr = str.split(’.’);
arr = [“aaaa”, “bbb”] -
indexof和lastIndexof
与array的方法一致 -
trim方法——去除空格
var str = ' HelloWorld ' console.log(str.trim()); #HelloWorld console.log(str); # HelloWorld 不会去除原字符串的空格
-
toLowerCase()方法和toUpperCase()——切换大小写
var str1 = 'hello world' console.log(str1.toUpperCase()); #HELLO WORLD var str2 = 'HELLO WORLD' console.log(str2.toLowerCase()); #hello world
-
toLocaleUpperCase和toLocaleLowerCase——针对外国语法切换大小写
④如何查找特定字符在字符串中所有的位置
var str = 'abcdeabcdeabcdeabcde';
var index = str.indexOf('e');
var findResult = [];
while (index > -1) { #判断查询结果大于-1就是找到了,否则找不到index会等于-1
findResult.push(index); #加进查找结果的数组中
index = str.indexOf('e', index + 1); #第二次查找从上一次查找的位置向后+1开始
}
console.log(findResult);
⑤模板字符串
作用类似python中的%s占位符
var name = "Kerwin";
var sayHi = `Hello! ${name}` # tab键上面的反引号包裹起来,变量用${}包裹
console.log(sayHi); # 打印结果是Hello! Kerwin
20. 日期
①创建日期的方式
new Date()方式:
- var now1 = new Date();
不传参数以当前时间创建 - var now2 = new Date(‘March 31,2020 20:27:44’);
依次传入月 日,年 时:分:秒 - var now3 = new Date(2020,2,31,20,27,44);
依次传入年月日时分秒,切记1~12月由数字0-11表示,所以月应该-1,比如三月由2表示
②Date常用方法
var now = new Date();
console.log(now.getFullYear()); #获取年
console.log(now.getMonth()); #获取月(取值0-11)
console.log(now.getDate()); #获取日(取值1-31)
console.log(now.getDay()); #获取星期(取值0-6,0代表星期天)
console.log(now.getHours()); #获取小时(取值0-23)
console.log(now.getMinutes()); #获取分钟(取值0-59)
console.log(now.getSeconds()); #获取秒(取值0-59)
- 需要注意的是:
月份范围0-11,实际月份需要+1,例如:2代表3月
星期范围0-6,3代表星期三,而0代表星期天
③日期格式化方法
var now = new Date();
console.log(now.toDateString());
#Tue Mar 31 2020
console.log(now.toTimeString());
#21:59:19 GMT+0800 (中国标准时间)
// 常用方法
console.log(now.toLocaleDateString());
#2020/3/31
console.log(now.toLocaleTimeString());
#下午9:59:19
console.log(now.toLocaleString());
#2020/3/31 下午9:59:19
// 国际时间
console.log(now.toUTCString());
#Tue, 31 Mar 2020 13:59:19 GMT
-
记住最常用的console.log(now.toLocaleString());
#2020/3/31 下午9:59:19 -
自定义格式的时间显示:如10:59:30 PM
function time_format() { var time = new Date(); var hour = time.getHours(); var minute = time.getMinutes(); var seconds = time.getSeconds(); var amORpm = hour >= 12 ? ' PM' : ' AM'; hour = hour > 12 ? (hour - 12) : hour; minute = minute > 10 ? minute : ('0' + minute); seconds = seconds > 10 ? seconds : ('0' + seconds); time = hour + ':' + minute + ':' + seconds + amORpm; return time; } console.log(time_format());
④日期格式化第三方库:moment
网址:http://momentjs.cn/
下载js,引入项目
21. 字符串和数值类型相互转换
①字符串转数值类型
var str = "123.456";
console.log(parseInt(str));
#转换为整数,只保留整数部分:123
console.log(parseFloat(str));
#转换为浮点数:123.456
console.log(Number(str));
#转换为数值:123.456
var a = "123aaa456"
console.log(isNaN(Number(a)));
#isNaN,检查是否为数值
②数值转换字符串
-
隐式转换
var num = 123.456;
console.log(’’+num);
用空字符串+数值自动转换为字符串 -
强制类型转换
var num = 123.456; # toString方法 console.log(num.toString()); # String方法 console.log(String(num));
-
规定小数点后几位(自动四舍五入)——toFixed方法
var num = 123.567; console.log(num.toFixed(2)); 打印结果:123.57 # 参数2代表小数点后两位
22. global对象的编码和解码方法
global对象(又叫终极对象或兜底对象),类似python中的object类,类似于:isNaN,ParseInt方法都是global对象的方法
-
URI——统一资源标志符(Uniform Resource Identifier)
国际上运用统一的URI,对浏览器的网址进行识别
有效的URI不能包含特殊字符,例如空格
类似于上图中的%20都是对URI中的空格进行编码
URI编码方法就可以对URI进行编码,它们用特殊的UTF-8编码替换所有无效的字 符,从而让浏览器能够接受和理解 -
encodeURI()和encodeURIComponent()的区别
encodeURI()不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;
encodeURIComponent()则会对它发现的任何非标准字符进行编码 -
编码和解码:
var uri = 'http://www.apeland.cn/web index.html?name=zhangsan' console.log(encodeURI(uri)); 打印结果:http://www.apeland.cn/web%20index.html?name=zhangsan # 只针对空格部分进行编码%20 console.log(encodeURIComponent(uri)); 打印结果:http%3A%2F%2Fwww.apeland.cn%2Fweb%20index.html%3Fname%3Dzhangsan # 对所有非标准字符进行编码 # 解码需要匹配编码的方式运用decodeURI(uri)和decodeURIComponent(uri)进行解码
23. window对象
window是JS中最顶层的对象,我们再JS语句中声明的全局变量,全局函数都属于window对象的属性和方法
var x = 3;
console.log(window.x);
# 通过window访问x
function foo() {
alert('Hello World');
}
window.foo();
# 通过window调用foo函数
24. Math数学对象
-
最小值min和最大值max
1. 传入多个参数进行比较 Math.min(11,23,44,2) Math.max(11,23,44,2) 2. 传入数组array进行比较 var num = [2,12,3,43,4,45]; Math.max.apply(null,num) Math.min.apply(null,num) # 对数组内的数据比较时,需要应用apply方法,传2个参数:null和数组
-
Math.ceil向上取整(天花板函数)
Math.floor向下取整(地板函数)
Math.round标准四舍五入var num = 1.5; Math.ceil(num); Math.floor(num); Math.round(num);
-
Math.random随机数(取值范围0-1,可能等于0)
Math.random();1. 获取min到max之间的随机数 Math.random()*(max-min) + min; 2. 生成随机四位验证码 var str = '0123456789abcdefghjklmnpqrstuvwxyz'; var res = ''; for(i=0;i<4;i++){ //随机产生字符串的下标 var n=parseInt(Math.random()*str.length) res+=str[n] } console.log(res)
三、BOM对象
1. BOM对象介绍
浏览器对象模型——操作浏览器部分功能的API。比如让浏览器自动滚动。
- window对象
window对象是JavaScript中的顶级对象。
全局变量、自定义函数也是window对象的属性和方法。
window对象下的属性和方法调用时,可以省略window。 - location对象
location相当于浏览器地址栏,可以将url解析成独立的片段。 - history对象
管理前进后退的网页跳转,保存历史记录
2. window对象的常用方法
-
alert()方法
弹出提示框 -
confirm()方法
var result = confirm('你确定要退出吗?') console.log(result); # 提示用户选择,确定返回true,取消返回false
-
prompt()方法
弹出问题框的方法,可填2个参数:问题和默认答案,并且将答案返回var result = prompt('你叫什么名字?', '杨飞') console.log(result);
3. 定时器方法
-
setTimeout方法
延迟性的操作setTimeout(function foo() { alert('Hello World'); },2000); alert("Hi"); # setTimeout传入2个参数:函数和延迟时间(单位毫秒) 等待过程中会优先执行后面的代码(由于IO等待)
-
setInterval方法
周期性执行的操作var num = 0; var timer = setInterval(function foo() { # 需要给setInterval定义一个变量timer num ++; if (num > 5) { clearInterval(timer); # 清除Interval return; } console.log(num); },1000);
setInterval传入2个参数:函数和周期时间(单位毫秒)
clearInterval终止循环操作,需要传入定时器的名称timer
- 定时器示例:
<body>
<button id="start">开启</button>
<button id="stop">关闭</button>
<p id="now">当前数字:</p>
<span id="num"></span>
<script type="text/javascript">
var start = document.getElementById('start');
var stop = document.getElementById('stop');
var now = document.getElementById('num');
var num = 0;
var timer = null;
start.onclick = function () {
// 注意:使用定时器的时候 先清除定时器 再开启定时器 防止用户频繁性的开启定时器
clearInterval(timer);
timer = setInterval(function(){
num ++;
now.innerHTML = num;
console.log(num);
},1000)
}
stop.onclick = function(){
clearInterval(timer);
}
</script>
</body>
特别注意:使用定时器的时候 先清除定时器 再开启定时器 防止用户频繁性的开启定时器
由于定时器类似于异步调用,当同一个定时器被多次开启,那么它的间隔时间将被缩短
4. location对象的常用属性
location可以获取地址栏中的信息
- location.host——获取服务器和端口
192.168.12.4:8080 - location.hostname——获取服务器地址
192.168.12.4 - location.port——获取端口号
8080 - location.href——获取完整的地址(会对中文和空格等特殊字符进行编码)
“https://www.luffycity.com/study/degree” - location.pathname——获取服务器后的文件目录
“/study/degree” - location.protocol——获取网址协议
“https:”
通常有2种协议:http和https,ssh是加密协议,目前主流是https - location.search——获取地址栏中的查询内容
“?username=Kerwin&password=123” - 如何获取查询字符串的每个参数
- 当前浏览器的位置操作
-
设置2秒后跳转到百度首页,可以后退(记录浏览器历史记录)
setTimeout(function () { location.href = 'https://www.baidu.com/' }, 2000)
-
设置2秒后跳转到百度首页,并且无法后退(不记录浏览器历史记录)
setTimeout(function () { location.replace('https://www.baidu.com/'); }, 2000)
-
设置2秒后刷新本网页
setTimeout(function () { location.reload(); }, 2000)
5. navigator对象
Navigator 对象包含有关浏览器的信息。
-
plugins方法——返回浏览器插件的列表
console.log(navigator.plugins);#结果如下:
-
检测浏览器是否包含所需插件
function hasPlugin (pluginName) { // 插件名切换为小写 pluginName = pluginName.toLowerCase(); // 循环navigator.plugins返回的数组(包含各插件对象) for (var i = 0; i < navigator.plugins.length; i++) { // 判断插件对象的name属性的小写模式中能否查找我们需要检查的插件名称 if (navigator.plugins[i].name.toLowerCase().indexOf(pluginName) > -1) { return true; }else { return false; } } } alert(hasPlugin('Alipay security control'));
6. history对象
-
go方法
setTimeout(function () { history.go(0); },2000)
history.go()中的参数:
0代表当前页面——效果等同于刷新
1代表前进1次,2代表前进2次
-1代表后退一次,-2代表后退2次
7. localStorage
使用localStorage可以存储一些key/value数据在浏览器中
- 存储数据setItem
localStorage.setItem(数据文件名称,数据)
存储的数据最好通过JSON序列化成字符串存储,否则存储进去为一个对象,不方面取出
JSON.stringify(data)将数据转成字符串
JSON.parse(str)将字符串转成数据
存储数据
localStorage.setItem('userinfo',JSON.stringify({name:'Kerwin',age:18}))
取出数据
JSON.parse(localStorage.getItem('userinfo'))
//{name: "Kerwin", age: 18}
删除数据
localStorage.removeItem('userinfo')
四、DOM对象
1. DOM对象介绍
Document Object Model 文档对象模型
JS中对象有三种:
- 用户定义对象
- 内建对象:Array Date Math
- 宿主对象:浏览器提供的对象,如window
DOM节点树
整个HTML文件中包含的各个标签(html下有head、body,head有meta、title,body有div、p、ul)可以看作为DOM对象,各个标签的父子关系可以形成一个树状家谱,DOM就是基于所有标签之间的关系形成一个节点树
解析过程
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性
浏览器会先加载html静态文件,再加载JS中针对DOM的动态设置,渲染到页面中
2. DOM中节点分类
元素节点(element node)
文档中的html、body、div、p等标签都是元素节点,它们构成了文档的结构
文本节点(text node)
如果一个网站只有空的标签,虽然有框架,但是没有内容
然而内容决定一切,没有内容的文档是没有任何价值的,而大多数的内容是由文本提供的
< p>Hello World!< /p>当中包含的hello world就是一个文本节点
属性节点(attribute note)
< p title=“Hello” class=“hi”>Hello!< /p>
当中的title和class都是属性节点,属性节点都包含在元素之上
3. 获取元素节点对象的方式
- document.getElementById(ID)
通过ID获取单个对象
- document.getElementsByTagName(TagName)
通过标签名称获取多个对象
注意:获取的多个元素节点对象组成一个集合,可以通过索引[i]来获取单个li标签;但它不是数组array,不使用array的功能,例如push,splice等 - document.getElementsByClassName(ClassName)
通过类名获取多个对象
- 父节点的children属性
oFather.children[0]
可以获取父节点的所有子节点结合,通过索引值获取第一个子节点
4. 获取和设置元素属性
- object.getAttribute(name)——获取元素属性
获取属性值需要传入一个参数:该属性的属性名称 - object.setAttribute(name,value)——设置元素属性
设置属性值需要传入两个参数:该属性的属性名称,还有属性的值 - object.removeAttribute(name)——删除元素属性
5. 节点对象的三个重要属性
①三个属性
在文档对象模型(DOM)中,每一个节点都是一个对象,DOM节点有三个重要属性:
- nodeName:节点的名称
- nodeValue:节点的值
- nodeType:节点的类型
②nodeName属性:节点的名称,是只读的
- 元素节点的nodeName与标签名相同(大写的)
- 属性节点的nodeName与属性的名称相同
- 文本节点的nodeName永远是#text
- 文档节点的nodeName永远是#document
③nodeValue属性:节点的值
- 元素节点的nodeValue是undefined或null
- 属性节点的nodeValue是属性的值
- 文本节点的nodeValue是文本自身
- 文档节点的nodeValue是null
④nodeType属性:节点的类型,是只读的
以下常用的几种节点类型:
元素节点——1
属性节点——2
文本节点——3
注释节点——8
文档节点——9
⑤验证
<div class="我是属性节点">我是一个文本节点<!-- 我是注释节点 --></div>
<script type="text/javascript">
// 1、元素节点
var oDiv = document.getElementsByTagName('div')[0];
console.log(oDiv.nodeName,oDiv.nodeValue,oDiv.nodeType);
// 2、属性节点
var attrNode = oDiv.attributes[0];
console.log(attrNode.nodeName,attrNode.nodeValue,attrNode.nodeType);
// 3、文本节点
var textNode = oDiv.childNodes[0];
console.log(textNode.nodeName,textNode.nodeValue,textNode.nodeType);
// 4、注释节点
var commentNode = oDiv.childNodes[1];
console.log(commentNode.nodeName,commentNode.nodeValue,commentNode.nodeType);
// 5、文档节点
console.log(document.nodeName,document.nodeValue,document.nodeType);
</script>
- oDiv.attributes[0]——可以获取元素节点的各个属性列表,通过索引获取确定的属性
- oDiv.childNodes[0]——可以获取元素节点包裹着的文本和注释,索引0是文本,索引1是注释
6. 节点对象的其他属性
通过节点树的家谱关系获得其他节点
<body>
<div class="previous-sibling"></div>
<div id="father">
<p>Kerwin1</p>
<p>Kerwin2</p>
</div>
<div class="next-sibling"></div>
<script type="text/javascript">
oFather = document.getElementById('father');
1. 获取该节点下的子节点集合(可以通过索引获取相应节点)
console.log(oFather.childNodes);
打印:[text, p, text, p, text],第一个text节点是紧跟着father div标签后面的换行符
#以下打印结果消除换行符带来的影响
2. 获取该节点下的第一个子节点
console.log(oFather.firstChild);
打印:<p>Kerwin1</p>
3. 获取该节点下的最后一个子节点
console.log(oFather.lastChild);
打印:<p>Kerwin2</p>
4. 获取该节点同级别的上一个兄弟节点
console.log(oFather.previousSibling);
打印:<div class="previous-sibling"></div>
5. 获取该节点同级别的下一个兄弟节点
console.log(oFather.nextSibling);
打印:<div class="next-sibling"></div>
6. 获取该节点的父节点
console.log(oFather.parentNode);
<body>...</body>
</script>
</body>
7. 家族关系获取节点在浏览器中的兼容性
如上一条示例,节点后面的换行导致找到的下一节点总是换行回车的text节点,解决方法如下:
- 去除子节点中的换行
<body>
<div class="previous-sibling"></div>
<div id="father">
<p>Kerwin1</p>
<p>Kerwin2</p>
</div>
<div class="next-sibling"></div>
<script type="text/javascript">
oFather = document.getElementById('father');
function get_childNodes(father) {
// 获取所有子节点(包含换行)
var nodes = father.childNodes;
// 设置空的数组接收符合条件的子节点
var childNodes = [];
for (var i = 0; i < nodes.length; i++) {
// 判断子节点的类型为1元素节点就加进数组中
if (nodes[i].nodeType === 1) {
childNodes.push(nodes[i])
}
}
return childNodes;
}
console.log(get_childNodes(oFather));
</script>
</body>
打印结果father的子节点为:[p, p]
- 去除兄弟节点中的换行
<body>
<div class="previous-sibling"></div>
<div id="father">
<p>Kerwin1</p>
<p>Kerwin2</p>
</div>
<div class="next-sibling"></div>
<script type="text/javascript">
oFather = document.getElementById('father');
function get_nextSibling(object){
// 获取第一个兄弟节点
var sibling = object.nextSibling;
// 判断当前兄弟节点不为空并且不属于元素节点
while (sibling != null && sibling.nodeType != 1) {
// 否则定位到第一个兄弟节点继续寻找下一个兄弟节点
sibling = sibling.nextSibling;
}
return sibling;
}
console.log(get_nextSibling(oFather));
</script>
</body>
打印结果:<div class="next-sibling"></div>
8. 元素节点对象增删改查(动态地操作节点)
- 创建节点
var newNode = document.createElement('p');
- 插入节点
将p标签插入父节点
方法一:最父节点的最后一个子节点append
oFather.appendChild(newNode);
方法二:插入在某个节点之前
oFather.insertBefore(newNode,afterNode);
- 删除节点
方式一:删除子节点
oFather.removeChild(deleteNode);
将节点在内存中释放(设为空值):
deleteNode = null;
方式二:删除自己
object.remove()
- 替换节点
oFather.replaceChild(newNode,oldNode);
- 创建文本节点
var textNode = document.createTextNode('Kerwin');
在p标签下快速插入文本节点
方法一:将插入的文本直接作为html语句插入,可以使a标签的效果生效
oP.innerHTML = '<a href = "#">Kerwin</a>';
方法二:将文本仅仅作为文本插入,不会执行html语句
oP.innerText = '<a href = "#">Kerwin</a>';
- 示例
9. 动态样式设置
- 方式一:直接操作样式属性
这种方法是通过行内式插入样式
var oP = document.getElementById('box');
console.log(oP.style);
通过oP.style获取的是style对象,可以通过style.属性 = '值'来进行设置
注意:oP.style只能获取行内式的样式属性,不能获取内嵌式(写在head标签内)样式属性
- 方式二:通过控制元素的类名来控制样式(常用)
这种方法是通过嵌入式插入样式
10. 事件
①事件三要素
事件的三要素:事件源、事件、事件驱动程序。
比如,我用手去按开关,灯亮了。这件事情里,事件源是:手。事件是:按开关。事件驱动程序是:灯的开和关。
再比如,网页上弹出一个广告,我点击右上角的X,广告就关闭了。这件事情里,事件源是:X。事件是:onclick。事件驱动程序是:广告关闭了。
于是我们可以总结出:谁引发的后续事件,谁就是事件源。
常用事件如下:
- onselect(文本框内容被选中事件)
- onchange(文本框内容改变事件)
- oninput(实时监控表单控件的文本内容)
- onscroll(实时监听页面侧边滚动条的滚动行为)
②绑定事件的两种方式
- 方式一:在元素行内绑定
<style type="text/css">
#box{
height: 200px;
width: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<!-- 在元素的行内插入onclick时间调用的函数并且执行 -->
<div id="box" onclick="start();"></div>
<script type="text/javascript">
function start() {
alert('事件被触发了');
}
</script>
</body>
- 方式二:在JS中用获取到的元素对象来调用onclick(常用)
<body>
<!-- -->
<div id="box"></div>
<script type="text/javascript">
var oDiv = document.getElementById('box');
oDiv.onclick = function changeColor() {
<!-- this相当于self,谁调用它,this就是这个对象 -->
this.style.backgroundColor = 'green';
}
</script>
</body>
用oDiv这个元素节点来调用onclick时间
this是调用onclick这个对象本身
③鼠标悬浮事件
onmouseover和onmouseout
<body>
<div id="box"></div>
<script type="text/javascript">
// 1. 找到事件触发的对象
var oDiv = document.getElementById('box');
// 2. 鼠标滑过事件
oDiv.onmouseover = function () {
// 3. 事件处理程序
this.style.backgroundColor = 'orange';
}
oDiv.onmouseout = function (){
this.style.backgroundColor = 'yellow';
}
</script>
</body>
④光标聚焦和失焦事件
onfocus和onblur
<body>
<form action="">
<p class="name">
<label for="username">用户名:</label>
<input type="text" name="user" id="username">
</p>
<p class="pwd">
<label for="pwd">密码:</label>
<input type="password" name="pwd" id="pwd">
</p>
<input type="submit" name="">
</form>
<script type="text/javascript">
// 1. 获取调用事件的节点对象
var oInput = document.getElementById('username');
// 2. 创建提示的span节点
var newNode = document.createElement('span');
// 3. 光标聚焦时,右边提示
oInput.onfocus = function () {
newNode.innerHTML = '请输入用户名';
newNode.style.color = 'red';
oInput.parentNode.appendChild(newNode);
}
// 4. 光标失焦时,右边提示
oInput.onblur = function (){
newNode.innerHTML = '用户名不正确';
newNode.style.color = 'red';
oInput.parentNode.appendChild(newNode);
}
</script>
</body>
- 聚焦选中文本setSelectionRange
$('input')[0].setSelectionRange(0,5);
代表选中input输入框内文本的index为0~5的文字
⑤文本域内容选中和改变事件
- onselect事件
在文本被选中松开后,字体才会变色 - onchange事件
删除了文本字符后,当文本框失焦时,字体才会变红色 - oninput事件(实时监测文本内容)
onput是只要有输入行为就会执行函数
文本对象都可以通过this.value来获取文本框的内容
⑥窗口加载事件(由window调用)
window.onload——等待文档元素(html静态文档)加载完成才会调用onload事件
- JS语句写在body中产生的问题
oInput元素对象是个空值,它没有oninput属性
原因——文档加载自上而下,还未读取到body中的元素就执行head标签中的script,抓取不到元素节点 - 解决方法——通过window.onload等待页面加载完成后执行事件
<html>
<head>
<title>JavaScript</title>
<meta charset="utf-8">
<script type="text/javascript">
// 等待onload加载完成再执行函数
window.onload = function(){
var oDiv = document.getElementById('box');
oDiv.onclick = function () {
this.innerHTML = 'Kerwin';
}
}
</script>
</head>
<body>
<div id="box">Alex</div>
</body>
</html>
五、JS特效
1. 图片切换
<body>
<img src="images/图片切换1.jpg" id="girl">
<button id="prev">上一张</button>
<button id="next">下一张</button>
<script type="text/javascript">
// 1. 获取事件源需要的标签
var oImg = document.getElementById('girl');
var oNextbtn = document.getElementById('next');
var oPrevbtn = document.getElementById('prev');
// 2. 定义图片序号
var minIndex = 1, maxIndex = 4, currentIndex = 1;
// 3. 点击下一张触发事件
oNextbtn.onclick = function () {
// 4. 判断如果当前图片已是最后一张,重新赋值序号为1,否则+1
if (currentIndex === maxIndex) {
currentIndex = minIndex;
}else {
currentIndex++;
}
// 5. 修改图片链接
oImg.setAttribute('src', `images/图片切换${currentIndex}.jpg`);
}
</script>
</body>
2. 显示和隐藏图片
- 修改图片的display属性在none与block之间切换
- 修改按钮的innerHTML在显示与隐藏之间切换
3. 淘宝商品图片切换
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<meta charset="utf-8">
<style type="text/css">
*{
margin:0;
padding:0;
}
li{
list-style: none;
}
ul li{
float: left;
margin:10px;
width: 60px;
height: 60px;
}
li.active{
border:2px solid red;
}
</style>
</head>
<body>
<img src="images/淘宝商品图片切换1.jpg" id="bigImg">
<ul>
<li class="active">
<img src="images/淘宝商品图片切换1.jpg" width="60px" class="smallImg">
</li>
<li>
<img src="images/淘宝商品图片切换2.jpg" width="60px" class="smallImg">
</li>
<li>
<img src="images/淘宝商品图片切换3.jpg" width="60px" class="smallImg">
</li>
<li>
<img src="images/淘宝商品图片切换4.jpg" width="60px" class="smallImg">
</li>
<li>
<img src="images/淘宝商品图片切换5.jpg" width="60px" class="smallImg">
</li>
</ul>
<script type="text/javascript">
// 1. 获取事件源
var oBigimg = document.getElementById('bigImg');
var oSmallimg = document.getElementsByClassName('smallImg');
// 2. 遍历集合,给每个img标签添加事件
for (var i = 0; i < oSmallimg.length; i++) {
oSmallimg[i].onmouseover = function () {
// 3. 在悬浮到每个img标签之前,先将所有li标签的active类去除(等于去除红色边框)
for (var j = 0; j < oSmallimg.length; j++) {
oSmallimg[j].parentNode.setAttribute('class', '');
}
// 4. 给鼠标悬浮的img标签的父元素li添加active类名(红色边框)
this.parentNode.setAttribute('class', 'active');
// 5. 将大图的src属性修改为被悬浮小图的src
oBigimg.setAttribute('src', this.getAttribute('src'));
}
}
</script>
</body>
</html>
- 用for循环给每个小图添加事件
- 事件逻辑是:
- 去除其他img标签的红色边框
- 给自己添加红色边框
- 给大图修改图片
4. 关闭小广告
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<meta charset="utf-8">
<style type="text/css">
.advertisement{
width: 300px;
height: 90px;
position: relative;
}
#close{
position: absolute;
right: 0;
top: 0;
}
</style>
</head>
<body>
<div class="advertisement">
<img src="images/关闭小广告.jpeg">
<button id="close">关闭</button>
</div>
<script type="text/javascript">
var oButton = document.getElementById('close');
var oAdvertisement = document.getElementsByClassName('advertisement')[0];
oButton.onclick = function () {
// 将窗口display改为none,不显示
oAdvertisement.style.display = 'none';
}
</script>
</body>
</html>
- 将需要关闭的窗口display样式设置为none即可隐藏
5. 百度换肤
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<meta charset="utf-8">
<style type="text/css">
*{
margin:0;
padding: 0;
}
ul li{
list-style: none;
}
#skin{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('images/百度换肤1.jpg') no-repeat center top;
}
#skin-photo{
width: 100%;
height: 100%;
position: relative;
z-index: 10;
}
#skin-photo ul{
overflow: hidden;
width: 1200px;
margin:0 auto;
background-color: rgba(255,255,255,.5);
}
#skin-photo ul li{
float: left;
height: 120px;
cursor: pointer;
margin:10px 0 10px 96px;
}
#skin-photo ul li img{
width: 180px;
height: 120px;
}
</style>
</head>
<body>
<div id="skin"></div>
<div id="skin-photo">
<ul>
<li>
<img src="images/百度换肤1.jpg">
</li>
<li>
<img src="images/百度换肤2.jpg">
</li>
<li>
<img src="images/百度换肤3.jpg">
</li>
<li>
<img src="images/百度换肤4.jpg">
</li>
</ul>
</div>
<script type="text/javascript">
var oSkin = document.getElementById('skin');
var oLis = document.getElementsByTagName('li');
for (var i = 0; i < oLis.length; i++) {
oLis[i].index = i + 1;
oLis[i].onclick = function () {
oSkin.style.backgroundImage = `url('images/百度换肤${this.index}.jpg')`;
}
}
</script>
</body>
</html>
- oLis[i].index = i + 1;
for循环时给每个li标签添加index属性,得到每张图片所属的编号
6. 复选框全选和反选
<!DOCTYPE html>
<html>
<head>
<title>JS</title>
<style type="text/css">
*{
margin:0;
padding:0;
}
#box{
width: 400px;
border:1px solid black;
padding: 20px;
margin: 200px auto;
}
</style>
</head>
<body>
<div id="box">
<div id="title">
<h2>千千音乐盒</h2>
</div>
<hr>
<div id="song-list">
<input type="checkbox">漂洋过海来看你<br>
<input type="checkbox">江南<br>
<input type="checkbox">日不落的想念<br>
<input type="checkbox">没那么简单<br>
<input type="checkbox">温柔<br>
<input type="checkbox">可惜不是你<br>
<input type="checkbox">后来<br>
</div>
<hr>
<div id="btn">
<button id="all-select">全选</button>
<button id="cancel-select">取消选中</button>
<button id="reverse-select">反选</button>
</div>
</div>
<script type="text/javascript">
function getElement(elementName) {
return typeof elementName === 'string' ? document.getElementById(elementName) : null;
}
var oInputs = document.getElementsByTagName('input');
// 全选
getElement('all-select').onclick = function(){
for (var i = 0; i < oInputs.length; i++) {
oInputs[i].checked = true;
}
}
// 取消全选
getElement('cancel-select').onclick = function(){
for (var i = 0; i < oInputs.length; i++) {
oInputs[i].checked = false;
}
}
// 反选
getElement('reverse-select').onclick = function(){
for (var i = 0; i < oInputs.length; i++) {
// 将input的checked属性取反值
oInputs[i].checked = ! oInputs[i].checked;
}
}
</script>
</body>
</html>
- 复选框的checked属性为true打钩,为false未选中
- oInputs[i].checked = ! oInputs[i].checked;
将当前值取反并赋值给自己
7. 表单验证
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<style type="text/css">
input{
outline: none;
border:1px solid darkgrey;
}
#tip{
font-size: 12px;
color: darkgrey;
}
.right{
background: url('images/right.png') no-repeat 5px center;
padding-left: 25px;
background-size: 15px;
color: green !important;
}
.error{
background: url('images/error.png') no-repeat 5px center;
padding-left: 25px;
background-size: 15px;
color: red !important;
}
</style>
</head>
<body>
<label for="score">您的成绩:</label>
<input type="text" id="score" placeholder="请输入分数">
<span id="tip">请输入您的成绩!</span>
<script type="text/javascript">
var oScore = document.getElementById('score');
var oTip = document.getElementById('tip');
// 1. input输入框失去焦点事件
oScore.onblur = function () {
var inputValue = Number(this.value);
// 2. 判断input输入框获得的value
if (isNaN(inputValue)) {
// 2.1 输入为字符串时
oTip.innerHTML = '输入的成绩不正确';
oTip.className = 'error';
oScore.borderColor = 'red';
}else if (inputValue >= 0 && inputValue <= 100) {
// 2.2 输入的为数字时
oTip.innerHTML = '输入的成绩正确';
oTip.className = 'right';
oScore.borderColor = 'green';
}else{
// 2.3 输入数字不在0~100
oTip.innerHTML = '成绩必须在0~100之间';
oTip.className = 'error';
oScore.style.borderColor = 'red';
}
}
// 3. 第二次点击输入框复原
oScore.onfocus = function(){
oTip.className = '';
oScore.borderColor = 'darkgrey';
oScore.value = '';
}
</script>
</body>
</html>
- object.className可以直接修改元素的类名,效果等于object.setAttribute
- 善于运用CSS定义好类的样式,通过JS修改类名调整样式
8. 上传图片格式验证
<body>
<label for="file">上传图片格式验证:</label>
<input type="file" name="" id="file">
<script type="text/javascript">
var oFile = document.getElementById('file');
// 合法文件格式列表
var fileList = ['jpg','png','gif'];
// input中的路径被修改事件
oFile.onchange = function () {
// 获取路径:c:\fakepath\right.png
var path = this.value.toLowerCase();
// 找到文件后缀'.'的位置
var pointIndex = path.lastIndexOf('.');
// 取到后缀名:png
var fileName = path.substring(pointIndex+1);
// 判断后缀名是否在合法格式列表中
if (fileList.indexOf(fileName) == -1) {
alert('上传图片格式错误');
}else{
alert('上传图片格式正确');
}
}
</script>
</body>
- oFile.onchange事件
由于input浏览好文件后value值会改变,随即触发验证程序
9. 随机验证码校验
<!DOCTYPE html>
<html>
<head>
<title>JS</title>
<style type="text/css">
#code{
width: 200px;
height: 200px;
background-color: yellow;
text-align: center;
line-height: 200px;
font-size: 40px;
font-weight: bolder;
letter-spacing: 10px;
color: red;
}
</style>
</head>
<body>
<div id="code">????</div>
<input type="text" name="" id="inputCode">
<input type="button" name="" value="验证" id="check">
<script type="text/javascript">
window.onload = function () {
// 1. 创建验证码函数
function makeCode(){
var str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var code = '';
for (var i = 0; i < 4; i++) {
var index = parseInt(Math.random()*str.length);
code += str[index]
}
return code;
}
// 2. 获取验证码
var code = makeCode()
// 3. 验证码传给div盒子
var oCode = document.getElementById('code');
oCode.innerHTML = code;
// 4. 创建验证按钮事件
var oCheck = document.getElementById('check');
var oInputCode = document.getElementById('inputCode');
oCheck.onclick = function(){
// 5. 验证码正确则跳转网址
if (oInputCode.value === code) {
location.href = 'https://www.luffycity.com/study/degree';
}else{
// 6. 不正确就警告,清空input,更新code
alert('验证码不正确,请重新输入');
oInputCode.value = '';
oCode.innerHTML = makeCode();
}
}
}
</script>
</body>
</html>
10. 发表评论
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<style type="text/css">
*{
margin:0;
padding: 0;
}
#box{
width: 1000px;
border:1px solid grey;
margin:200px auto;
padding:50px;
}
#input{
width: 800px;
height: 200px;
font-size: 20px;
}
#comment li{
width: 800px;
list-style: none;
color: red;
margin-top: 30px;
padding: 10px;
border-bottom: 1px dashed grey;
}
#comment li a{
float: right;
}
</style>
</head>
<body>
<div id="box">
<textarea id="input" placeholder="请输入评论"></textarea>
<button id="submit">发表评论</button>
<div>
<ul id="comment">
</ul>
</div>
</div>
<script type="text/javascript">
window.onload = function () {
var oSubmit = document.getElementById('submit');
// 1.监听按钮的点击
oSubmit.onclick = function(){
var oInput = document.getElementById('input');
// 1.1 获取用户输入的内容
var content = oInput.value;
var oUl = document.getElementById('comment');
// 1.2 判断
if (content === '') {
alert('请输入内容后发表评论');
return;
}
// 1.3 创建li标签插入到ul中
var newLi = document.createElement('li');
newLi.innerHTML = `${content}<a href = 'javascript:void(0)'>删除</a>`;
oUl.insertBefore(newLi, oUl.children[0]);
// 1.4 清空输入框中的内容
oInput.value = '';
// 1.5 删除评论
var oDelete = document.getElementsByTagName('a');
for (var i = 0; i < oDelete.length; i++) {
oDelete[i].onclick = function(){
this.parentNode.remove()
}
}
}
}
</script>
</body>
</html>
- oUl.children[0]
是获得ul标签下所有子节点的集合,通过索引确定li标签的位置,从而实现插入最新一个li的效果
11. 九宫格布局
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.item{
width: 250px;
height: 360px;
font-size: 13px;
text-align: center;
}
.title{
margin: 10px;
}
.price{
font-size: 18px;
font-weight: bolder;
color: #ff6700;
}
</style>
</head>
<body>
<div id="cols">
<button>3列</button>
<button>4列</button>
<button>5列</button>
</div>
<div id="box">
<div class="item">
<div class="imgContainer">
<img src="images/九宫格布局.jpg">
</div>
<p class="title">纯色短袖女春季秋t恤</p>
<p class="price">¥69</p>
</div>
<div class="item">
<div class="imgContainer">
<img src="images/九宫格布局.jpg">
</div>
<p class="title">纯色短袖女春季秋t恤</p>
<p class="price">¥69</p>
</div>
</div>
<script type="text/javascript">
// 1. 获取分列按钮、每个图片盒子、整个盒子
var oButton = document.getElementsByTagName('button');
var oItem = document.getElementsByClassName('item');
var oBox = document.getElementById('box');
// 2. 创建函数,传入分列数,将整个盒子的宽度设置为图片盒子宽度的倍数
function makeCols(colsNum){
for (var i = 0; i < oItem.length; i++) {
oItem[i].style.float = 'left';
oBox.style.width = colsNum*oItem[i].offsetWidth + 'px';
}
}
// 3. 为每个按钮创建点击事件
oButton[0].onclick = function(){
makeCols(3)
}
oButton[1].onclick = function(){
makeCols(4)
}
oButton[2].onclick = function(){
makeCols(5)
}
</script>
</body>
</html>
- object.offsetWidth——获取对象的宽度属性
由于object.style.width只能获取行内的css属性,获取不了内嵌式(写在head标签中)
12. 日期特效
<body>
<div class="box">
<p id="time"></p>
<p id="date"></p>
</div>
<script type="text/javascript">
function timer() {
// 1. 获取时间
var weekArr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth();
var date = now.getDate();
var week = weekArr[now.getDay()];
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
var AMPM = hour < 12 ? 'AM' : 'PM'
// 2020年3月10日 21:48:26 PM 星期五
var time = `${year}年${month}月${date}日 ${hour}:${minute}:${second} ${AMPM} ${week}`;
var oTime = document.getElementById('time');
oTime.innerHTML = time;
var oDate = document.getElementById('date');
oDate.innerHTML = date;
}
// 2. 定时器执行函数
setInterval(timer,10);
</script>
</body>
13. 时钟案例
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<style type="text/css">
#clock{
width: 600px;
height: 600px;
background: url(images/钟.jpg);
position: relative;
}
#hour,#minute,#second{
width: 30px;
height: 600px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -15px;
margin-top: -300px;
}
#hour{
background: url(images/时针.png);
}
#minute{
background: url(images/分针.png);
}
#second{
background: url(images/秒针.png);
}
</style>
</head>
<body>
<div id="clock">
<div id="hour"></div>
<div id="minute"></div>
<div id="second"></div>
</div>
<script type="text/javascript">
// 1.获取标签
var oHour = document.getElementById('hour');
var oMinute = document.getElementById('minute');
var oSecond = document.getElementById('second');
// 2. 开启定时器
setInterval(function () {
// 3. 获取当前时间
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
// 4. 计算时分秒针角度
var secondDeg = (second / 60) * 360;
var minuteDeg = (minute + second / 60) / 60 * 360;
var hourDeg = (hour % 12 + second / 3600) / 12 * 360;
// 5. 对时分秒针进行旋转
oHour.style.transform = `rotate(${hourDeg}deg)`;
oMinute.style.transform = `rotate(${minuteDeg}deg)`;
oSecond.style.transform = `rotate(${secondDeg}deg)`;
},10)
</script>
</body>
</html>
14. 长图滚动案例
<!DOCTYPE html>
<html>
<head>
<title>JS特效</title>
<style type="text/css">
*{
margin:0;
padding:0;
}
body{
background-color: #000;
}
div{
width:658px;
height: 400px;
border:1px solid #ff6700;
position: relative;
margin:100px auto;
overflow: hidden;
}
span{
width: 658px;
height: 50%;
position: absolute;
cursor: pointer;
}
img{
position: absolute;
}
#up{
top: 0;
left: 0;
}
#down{
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<div id="box">
<!-- 658*4066 -->
<img src="images/长图滚动.jpeg" id="picture">
<span id="up"></span>
<span id="down"></span>
</div>
<script type="text/javascript">
// 1. 鼠标悬浮up,创建定时器每0.1秒将图片的top属性减10px,向上拉
var up = document.getElementById('up');
var down = document.getElementById('down');
var picture = document.getElementById('picture');
var imgTop = 0;
// 2. 由于上拉下拉操作的是同一个图片,所以共享一个定时器
var timer = null;
up.onmouseover = function () {
// 3. 开启定时器前先清除定时器
clearInterval(timer);
timer = setInterval(function(){
// 4. 判断图片是否到底,到底了就清除定时器
if (imgTop >= (400 - 4066)) {
imgTop -= 10;
picture.style.top = imgTop + 'px';
}else{
clearInterval(timer);
}
}
,100)
}
up.onmouseout = function(){
clearInterval(timer);
}
down.onmouseover = function () {
clearInterval(timer);
timer = setInterval(function(){
if (imgTop <= 0) {
imgTop += 10;
picture.style.top = imgTop + 'px';
}else{
clearInterval(timer);
}
}
,100)
}
down.onmouseout = function(){
clearInterval(timer);
}
</script>
</body>
</html>
- 切记开启定时器之前先取消定时器,避免用户频繁开启定时器,缩小时间间隔