Html是描述页面内容的、CSS是让页面好看的,而JavaScript是让页面能够交互的。我们做网站的时候要实现“点击按钮之后图片切换”、“鼠标放到图片上显示放大图”等效果都要写能够被浏览器端识别运行的代码,这些代码是无法直接使用后端开发的Java、C#、C等语言编写的,目前主流浏览器支持的唯一编程语言就是JavaScript(简称JS)。
当然JavaScript不仅仅能运行在浏览器端,借助于NodeJS,我们也可以用JavaScript写后端程序。
注意JavaScript只是定义了语法规范(循环控制、流程控制、变量等),实现不同功能只要提供对应的API即可,比如只要提供访问数据库和网站处理的API,就可以用JavaScript开发网站,只要提供访问游戏引擎的API,就可以用Javascript开发游戏,只要提供浏览器操作的API,就可以用Javascript写浏览器端的程序。
JavaScript语法和C、Java、C#等语法差不多,下面只讲不同的部分。
这一章我们只讲Javascript语法,对于如何操作浏览器是下一章讲的。
(一)ECMAScript
JavaScript是1995年在Netscape浏览器引入的,微软也在自己的浏览器IE上加入了类似的语言JScript。为了避免各自为政,ECMA这个国际组织出面制定了ECMAScript语法规范。各个浏览器下的JavaScript都要按照这个规范来实现。
所以ECMAScript是标准规范,各个平台下的JavaScript是这个标准规范的实现。
ECMAScript规范也是一直在升级的,目前所有主流浏览器都支持的ECMAScript版本是2009年发布的ECMAScript 5(ES5),又推出ECMAScript 2015规范(简称ES2015,曾经也被叫过ES6)。目前还有一些浏览器不支持或者不完全支持ES2015。有人开发出了Babel这样的翻译工具,用于把ES2015这种新语法翻译成ES5的语法。初学阶段,我们先学习主流浏览器都支持的ES5语法。
JS简介
JavaScript是一种计算机编程语言,可以像等其他编程语言那样定义变量,执行循环等。
JavaScript代码主要执行在浏览器上,为HTML页面提供动态效果,而且JavaScript是一种脚本语言,它的代码是解释执行的,也就是解释一句代码后就会执行这句代码。
JavaScript可简称为 js。
(二)JS的语法特点
- 浏览器中如何写Javascript代码
可以在页面任意位置(一般写到head标签中)加入<script>标签,一定要设置type属性的值为"text/javascript"。JS代码就写到script标签。浏览器加载这个网页之后就按照顺序加载、运行这些内容。
- 变量和数据类型
js是弱类型语言,弱类型并不是说数据本身没有类型,而是变量没有类型。如一个变量a,a的值可以指向字符串类型,也可以指向数值类型。
js使用关键字var 声明变量:var a ; 或者 var a = 1.2; 或者 var a,b,c;
由于js的弱类型特点,我们可以这样编写代码:
var a = 1.2;
a = "hello";
切记:js中没有int a = 1; 这种写法
当然尽量不要让一个变量指向不同类型的对象。
声明变量的时候不写var也是可以的,但是那样不好,所以统一都写上。
- Js数据类型
js定义了6种数据类型,其中有5种原始类型:Boolean、Number、String、Null、Undefined,和一种Object类型
Boolean:true 、 false
Number:-(253 -1) 到 253 -1 之间的实数 、外加 Infinity、NaN 两个特殊值
String:使用一对双引号或者单引号包裹的任意字符序列,如"abc"‘abc’
Null:null
Undefined:undefined
Object:Object类型的值称为对象(后面详细讲)
算数运算符:+ - * / % (++ -- += -= *= /= %=)
比较运算符:>>= <<= == === != !==
逻辑运算符:|| && !
位运算符:| & ~ <<>>>>>(了解)
字符串连接符:+
其他:typeof instanceof new
运算符的优先级和其他编程语言相似
- 输出的方法
写JavaScript程序,可以用console.debug()输出调试信息,注意是使用小写开头的console。在HBuilder内置的浏览器中,输出结果会输出到【控制台】中。而使用Chrome、IE等主流浏览器,都可以在浏览器界面按F12,在【控制台/Console】中看到输出。这个普通用户是不知道怎么看的,不用管这个“404、favicon”的这个错误。
如果是输出给浏览器端的用户的消息,可以用alert函数。
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var age=18;
var name="李大鹏";
var s = "你好,我是"+name+",我的年龄是"+age;
console.log("控制台消息:"+s);
alert("弹窗消息:"+s);
</script>
</head>
<body>
</body>
</html>
- JS中字符串可以用单引号或者双引号包裹
var s1="abc";
var s2='abc';
都是可以的。
但是不能一半单引号一半双引号。
var s3="abc';
这样做的好处是:如果字符串里有很多单引号,那么字符串就用双引号包裹;如果字符串励有很多双引号,那么字符串就用单引号包裹。省的转移的麻烦。
- null和undefined
js中变量如果没有被初始化,那么也可以打印它的值,值是undefined,如果变量被赋值null,才是null。所以null和undefined不同。
<script type="text/javascript">
var a;
var b=null;
alert("a="+a);
alert("b="+b);
alert("c="+c);
</script>
JavaScript中变量没有初始化也可以可以用,只不过初始值是undefined。
注意最后一行会报错“Uncaught ReferenceError: c is not defined”,因为不存在这样一个变量。跟异常一样,从出错的代码之后的代码就不执行了。
写JS程序的时候建议总是看控制台输出,这样如果有语法错误,就会有提示。
- JavaScript的运行
JavaScript在浏览器端是解析执行的,所以即使中间某行代码有语法错误,之前的代码还是可以运行的。
- 布尔判断
JS中的if不仅可以写布尔值,也可以写普通值。当值为0、undefined、null的时候认为是false,否则是true。while、for循环中也是如此。
下面的代码尝试把a的值改为undefined、null、1、-1、true等值试试。
<script type="text/javascript">
var a=null;
if(a)
{
alert("true");
}
else
{
alert("false");
}
</script>
- 数组 (长度可变,添加任意类型)
JavaScript中声明数组方式:
var arr1 = ["abc","123","hello"];
Javascript中的数组是长度可变的,可以通过push向数组中添加元素
var arr1 = ["abc","123","hello"];
arr1.push("yes");
for(var i=0;i<arr1.length;i++)
{
console.log(arr1[i]);
}
也可以通过new Array()创建一个空数组对象,然后push向里面加数据。
<script type="text/javascript">
var arr1 = new Array();
arr1.push("abc");
arr1.push("123");
arr1.push("hello");
arr1.push("yes");
for(var i=0;i<arr1.length;i++)
{
console.log(arr1[i]);
}
</script>
数组还有其他操作:unshift() 在开头添加元素;pop() 删除最后元素;shift() 删除首元素;
(三)相等判断
js有两种比较相等的方式:标准比较(==) 和严格比较(===)
严格比较:两个操作数的值以及数据类型都相同时比较结果才为true
1 === 1 结果 true
1 === "1"结果 false
标准比较:先把两个操作数转换为数据类型相同的值,再进行严格比较
1 == 1 结果 true
1 == "1"结果 true
js关键字:js已经在使用的含有特殊含义的单词
break、case、class、catch、const、continue、debugger、default、delete、do、else、export、extends、finally、for、function、if、import、in、instanceof、let、new、return、super、switch、this、throw、try、typeof、var、void、while、with、yield
js保留字:js将来可能会使用其作为特定用途的单词
enum、await、implements、package、protected、static、interface、private、public、abstract、boolean、byte、char、double、final、float、goto、int、long、native、short、synchronized、transient、volatile
(四)Object 和Json
Object是js最基本的类,用来创建普通对象,通常用这些对象存储数据
创建方式:var obj = new Object();
添加属性(数据):obj.name = "李大鹏";
获取属性值:var name = obj.name;也可以obj["name"]
还有另一种创建对象的方式:
var obj = { } ;
var obj2 = {"name":"李大鹏" , "age":24} ;
这种方式称为:JSON (JavaScript Object Notation) 即js表示对象的方式
JSON格式语法:
- 一个对象由一对 { } 花括号表示
- 对象中可以包含若干键值对数据,key必须是String类型的值,value可以是任意类型的值。
- 在一些不严格写法中,可以省略key两边的双引号,但绝不建议这么做
- 一个键值对内部使用 : 冒号分隔key和value,不同键值对之间使用 , 逗号分隔。
- 特别的,一个数组对象使用一对 [ ] 中括号表示,数组元素可以是任意类型的值。
声明一个家庭信息的对象,并输出信息。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var family = {"name":"幸福一家",
"money":1888.8,"mate":{"name":"美妞","age":28},
"children":[{"name":"老大",age:13},
{"name":"老二",age:6}]};
console.log(family.name);
console.log(family.mate.name);
for(var i=0;i<family.children.length;i++)
{
console.log(family.children[i].name);
}
</script>
</head>
<body>
</body>
</html>
由于Javascript是弱类型语言,因此自动提示之类的仅供参考,能自动提示出来的方法不见得能用,不能自动提示出来的不见得不能用。
数组有一个forEach方法可以用来遍历一个数组里的每个元素,它的参数就是一个function,表示对于这个数组的每个对象都调用这个回调函数,两个参数,第一个是当前遍历的对象,第二个参数是当前遍历的序号。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var family = {"name":"幸福一家",
"money":1888.8,"mate":{"name":"美妞","age":28},
"children":[{"name":"老大",age:13},
{"name":"老二",age:6}]};
family.children.forEach(function(item,index){
console.log("第"+index+"个,"+item.name);
});
</script>
</head>
<body>
</body>
</html>
(五)函数 function
Javascript中最难也是最灵活的就是函数,这一章重点全面的讲解一下。讲的这些奇怪的语法不是在“秀技术”,而是确实有用。
1.命名function
function 函数名(参数列表){
函数体
}
调用语法:函数对象()
function sum( n1 ,n2 ){
var sum = n1+n2;
return sum;
}
var n = sum(5,6);
console.log(n);
函数名:由字母、数字、下划线或者$ 组成,并且不能以数字开头
参数列表:函数希望接收的参数。由于js是弱类型语言,声明语法中参数列表中只要写参数名即可
返回值类型:声明语法中没有返回值类型,但函数可以在函数体中使用return语句返回任意类型的值。如果没有return语句,默认返回undefined
<script type="text/javascript">
function sum(n1, n2) {
var sum = n1 + n2;
return sum;
}
var n = sum(5, 6);
console.log(n);
</script>
浏览器中的js引擎在执行js代码之前会解析并管理使用这种方式声明的函数。所以可以在这种函数声明之前就调用它
2.函数重载
js没有函数重载的概念,多个同名函数中,无论参数个数、名称是否一样,后声明的会覆盖先声明的
<script type="text/javascript">
test();
function test(i)
{
alert("1");
}
function test()
{
alert("2");
}
test();
test(3);
</script>
三个的打印结果都是2。
JavaScript中的参数可以不按照形参的个数传递,没有传递的参数的值就是undefined,可以如下模拟实现重载:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
function calc(name,age)
{
if(age==undefined)
{
age=18;
}
alert("name="+name+",age="+age);
}
calc("tom",10);
calc("jerry");
</script>
</head>
<body>
</body>
</html>
3.匿名函数
var 变量名 = function(参数列表){
函数体
}
var sum = function(n1 ,n2){
var sum = n1+n2;
return sum;
}
sum(1,2);//调用此函数
这种方式也被称为匿名函数,js引擎并不会事先就解析管理匿名函数,所以匿名函数不可提前调用,也不存在覆盖的情况。
如果一个变量被两次赋值为匿名函数,则两次赋值后都是有效的,只不过第二次赋值时变量指向了新的函数。
<script type="text/javascript">
var f = function (i)
{
alert("1");
}
f();
f = function()
{
alert("2");
}
f();
</script>
注意f和f()不一样,f表示指向函数的变量,而f()代表执行f指向的函数。
<script type="text/javascript">
var f = function (i)
{
return 5;
}
alert(f);
alert(f());
</script>
4.函数还能这么玩?
JavaScript中函数就是对象,也可以当成函数参数使用,也可以作为返回值返回。
做参数:
<script type="text/javascript">
function add(i,j)
{
return i+j;
}
var multi=function(i,j)
{
return i*j;
}
function f(f1,f2)
{
alert(f1(1,2));
alert(f2(1,2));
}
f(add,multi);
</script>
(六)对象
JavaScript中的语法结构比较简单,不像Java、C#等有类、继承、多态等语法,JavaScript中实现类似效果都是靠其他语法模拟的。关于继承、多态等作为后端开发者不用研究很深,大家只要看这样一个例子就行。
如下就是一种声明一个对象,带name、age,还有一个hello方法:
<script type="text/javascript">
var p={
name:'rupeng',
age:8,
hello:function(msg){
alert("我叫"+this.name+",我的年龄是"
+this.age+",我想说:"+msg);
}
};
p.hello("早上好");
p.name="yzk";
p.age=18;
p.hello("晚安");
</script>
(七)变量作用域
在<script>标签内直接定义的变量是全局变量,对整个页面的所有js代码都有效js预先定义了一些全局变量,比如说name,测试额时候要注意js引擎在执行代码之前,会把所有的全局变量声明放在顶部,赋值语句位置不变在if、循环等语句中声明的变量,只要声明语句执行过,变量就会被提升为全局变量变量可重复声明并会发生覆盖,使用变量时值为前面最后一次声明的值在函数内定义的变量是局部变量,局部变量不会提升为全局变量,所以外面不可访问在两个嵌套的函数中,外层函数定义的变量对内层函数有效,反之无效在两个不是嵌套关系的函数中定义的变量对彼此都无效特别注意嵌套函数内变量的使用(见备注)
(八)常用类
1.字符串操作
获取长度的length 属性、indexOf、replace、trim等都和Java等语言中一样,自动提示就有了。
length 属性: 此字符串的字符个数
indexOf(string) 返回指定字符串在此字符串中首次出现的索引位置
replace(string1,string2) 使用string2替换string1 一次
trim() 剪去两端的空白字符
js中的字符串没有contains函数(判断一个字符串是否包含另外一个字符串)
<script type="text/javascript">
var email="[email protected]";
if(email.indexOf('@')<0)
{
alert("不含有@");
}
else
{
alert("含有@");
}
</script>
2.Math类
Math类中的方法都是静态方法。常用方法:
Math.abs(x) 返回x的绝对值
Math.ceil(x) 返回x向上取整后的值
Math.floor(x) 返回小于x的最大整数
Math.round(x) 返回四舍五入后的整数
Math.max(n1,n2 ...) 返回0个到多个数值中最大值
Math.min(n1,n2...) 返回0个到多个数值中最小值
Math.pow(x,y) 返回x的y次幂
Math.random() 返回0到1之间的伪随机数
(九)使用JS的方式
1.写到标签里
写到标签的事件里,后面会详细讲什么是事件,先看<body>的onload事件,窗口加载。
这种写法不适合写太复杂的代码,也不推荐使用。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body οnlοad="var a=3;alert(a);">
</body>
</html>
2.写到<script>标签中
可以写多个<script>标签
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var s = "ab";
alert(s);
function test() {
alert("test");
}
</script>
</head>
<body>
</body>
<script type="text/javascript">
var b = "yes";
alert(b);
test();
</script>
</html>
3.写到单独的js文件中
可以js代码写到js文件中,不能写html代码;
单独的放到js文件夹下(规矩,不是强制)common.js
function add(i,j)
{
return i,j;
}
alert("in common.js");
页面中通过<script src="js/common.js"></script>来引入
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/common.js"></script>
<script type="text/javascript">
alert(add(1,2));
</script>
</head>
<body>
</body>
</html>
注意如果html中要用到js中定义的函数,则要先引入js文件,如果颠倒顺序就会报错。
引入外部js文件的<script>标签内不能再写js代码,会被忽略,也不能写成单标签形式:<script src="js/common.js"/>
写到js文件中的好处是可以被多个页面共用,当然需要用的的页面也引用这个js文件。而写到html中则只能在这个页面中使用。
(十)JavaScript调试
js代码的执行有个特点:从上往下,解释一句执行一句,遇到错误就停止执行
js代码调试步骤:按F12打开调试界面 >选中Sources >点击要调试的页面 >刷新页面 >(添加断点刷新页面)。如果引用单独的js,则打开js即可。
<script type="text/javascript">
var a;
var a1 = 0;
var a2 = 'hello';
var sum = 0;
for(var i=0; i<10; i++){
sum += i;
}
var date = new Date();
//alert(xxxx);
var obj = {"name":"李大鹏" , "age":16 ,"show":function(){alert('你好')} };
for(var key in obj){
var value = obj[key];
if(value instanceof Function){
value();
}else{
alert(key+" --- "+value);
}
}
</script>
写JS的时候建议大家一直打开F12开发人员工具,看看Console有没有报错。
五、window
window对象表示整个浏览器窗口,不仅仅js内容,整个HTML页面(包括所有元素和CSS内容)也都在window对象的管理之下
浏览器每打开一个标签页面就会创建一个window对象,浏览器窗口有时候会打开多个页面,也就对应多个window对象。
在浏览器环境下,所有的对象都在window对象下,只不过一般都省略window,比如在浏览器环境下,alert("hello")和window.alert("hello")一样,Math.abc(-1)和window.Math.abs(-1)一样、navigator.userAgent和window.navigator.userAgent一样。
(一)导航
location.href可以获取当前的网址;如果给location.href赋值则可以起到页面重定向的效果,比如:
location.href="http://www.baidu.com";
location.reload()可以刷新当前页面
(二)对话框函数
alert() 弹出消息框;参数是提示消息;
confirm() 弹出询问对话框;参数是提示消息;返回值是boolean值,true是点了【确定】,false是点了【取消】
prompt() 第一个参数是提示消息,第二个参数(可选)是默认值;返回值是用户输入的值。
例子:
<script type="text/javascript">
var name = prompt("请输入你的姓名");
var country = prompt("请输入你的国籍","中国");
var ok = confirm("你确认提交吗?");
if(ok)
{
alert("来自"+country+"的"+name);
}
</script>
(三)定时器
1.setInterval
setInterval(code, millisec) 是设定每隔millisec毫秒执行一次code,反复执行。网页中的动画效果很多可以使用setInterval实现。code中既可以写一段字符串类型的js代码,也可以写一个function。
比如下面的代码就会设定每隔2秒钟弹出一个对话框:
setInterval("alert('1')",2000);
想停止弹窗只能关窗口。所以间隔时间段不要太短,否则没机会关闭窗口。
注意第一次执行是setInterval执行后的第millisec毫秒;如果定时执行的代码中有alert等阻塞函数,则只有关闭对话框才会继续计时;这个计时也不是非常精准的,有误差。
一般建议不要第一个参数传代码字符串,而是写function,也就是:
<script type="text/javascript">
setInterval(function(){
alert("33");
},2000);
</script>
或者
<script type="text/javascript">
function test()
{
alert("hello");
}
setInterval(test,2000);
</script>
注意不要写成setInterval(test(),2000);因为这样就表示执行test函数,然后把函数返回值传递给setInterval,而test没有返回值。所以就没任何效果。
思考下面的代码执行效果是什么?
<script type="text/javascript">
function test()
{
alert("a");
return function(){
alert("b");
};
}
setInterval(test,2000);
</script>
思考下面代码的执行效果是什么?
<script type="text/javascript">
function test()
{
alert("a");
return function(){
alert("b");
};
}
setInterval(test(),2000);
</script>
可以同时设定多个定时器;setInterval有返回值,返回值是定时器的Id,可以调用clearInterval()来停止这个定时器。
下面的代码当i==3的时候就停止了:
<script type="text/javascript">
var i=0;
var intId = setInterval(function(){
i++;
alert(i);
if(i==3)
{
clearInterval(intId);
}
},2000);
</script>
2.setTimeout
setTimeout(code, millisec)、clearTimeout(timeoutId)的用法和setInterval、clearTimeout几乎一样。只不过setTimeout是过了millisec毫秒执行一次code,但是只执行一次,不会反复执行。
代码:
<script type="text/javascript">
setTimeout(function(){alert('hello');},1000)
</script>
(四)获取浏览器信息
navigator对象不是公开标准,但是主流浏览器都支持,但是支持的属性不同。
navigator.userAgent获取浏览器版本信息
navigator.platform 获取操作系统平台信息
代码:
<script type="text/javascript">
alert(navigator.userAgent);
alert(navigator.platform);
</script>
(五)history对象
history.back()是后退,和点击浏览器【后退】效果一样,也可以写成history.go(-1)
history.forward()是前进,和点击浏览器【前进】效果一样,也可以写成history.go(1)
这个要等后面讲完了DOM的事件之后自己测试。
六、DOM
DOM (Document Object Model) 文档对象模型。DOM思想使用节点树(node tree)的概念来描述一个HTML页面,页面中的每一个元素、属性、文本都被认为是节点。此外,DOM还定义了一系列编程接口(DOM API),用来操作页面的任意一部分内容。
在 js + DOM编程中,一般的编程思路是这样的:由js基本语法控制程序的执行逻辑,由DOM API进行元素的查找获取,进而再对元素进行增删改等操作。
Dom操作是最底层的网页操作API,无论是jQuery等老框架,还是Vue、Angular、React等这些,底层都是对Dom的封装。大家可以不精通Dom,但是一定要知道Dom的基本操作,这样才不会在“你方唱罢我登场,各领风骚五六月”的前端框架变化中迷失。所以这一章我们不求全面讲解Dom,但求讲解Dom底层的精髓。因此掌握课程中讲的Dom即可,不用再深入。
(一)节点树
对于下面的html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="text"value="5"/>
<input type="text"value="6"/>
<input type="text"value="7"/>
<span><span>11</span><span>22</span><input type="text"value="8"/></span>
</p>
</body>
</html>
节点树结构
节点类型
HTML页面中的主要节点有四种:文档节点、元素节点、属性节点、文本节点。
DOM API提供了一个Node父接口表示任意类型的节点,同时提供了两个子接口:Document、Element分别表示整个文档和元素节点。当然,还提供了其他类型的子接口,如DocumentType、Attr、Text等。
(二)document对象
document对象表示整个HTML页面,是DOM的核心对象。document对象是连接JavaScript和DOM的桥梁,使得我们可以在JavaScript环境中操作页面内容
document对象提供了查找获取元素节点的方法,所以document是DOM的编程入口,此外还提供了创建新节点的方法。
1.document获取元素
Element getElementById(string) 根据元素的id属性值获取元素,因为页面中id不能重复,所以返回的是一个对象。
对于下面的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p id="p1">
<input id="ip1"name="age"type="text"value="5"/>
<input id="ip2"name="age"type="text"value="6"/>
<input id="ip3"name="age"type="text"value="7"/>
<input id="ip4"name="height"type="text"value="8"/>
</p>
</body>
</html>
注意,获取节点的js代码必须在dom节点加载完成后执行才可以。下面的写法是不行的。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var t3 = document.getElementById("txt3");
alert(t3.value);//获取元素的value属性
</script>
</head>
<body>
<p id="p1">
<input id="txt1" name="age" type="text" value="5" />
<input id="txt2" name="age" type="text" value="6" />
<input id="txt3" name="age" type="text" value="7" />
<input id="txt4" name="height" type="text" value="8" />
</p>
</body>
</html>
运行的时候“控制台”(Console)会直接报错“"Uncaught TypeError: Cannot read property 'value' of null" /b/3.html (8)”
Cannot read property 'value' of null这种错误一般都是在指向null的变量上调用成员造成的,而且也说了是第8行的错误。因为script写到了head中,执行的时候Dom节点还没加载。有两种写法:
把script写到Dom节点后面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p id="p1">
<input id="txt1"name="age"type="text"value="5"/>
<input id="txt2"name="age"type="text"value="6"/>
<input id="txt3"name="age"type="text"value="7"/>
<input id="txt4"name="height"type="text"value="8"/>
</p>
</body>
<script type="text/javascript">
var t3 = document.getElementById("txt3");
alert(t3.value);
</script>
</html>
或者写到window.onload事件中,也就是页面加载之后才会自动触发window.onload指向的function。后面详细讲什么是事件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.οnlοad=function(){
var t3 = document.getElementById("txt3");
alert(t3.value);
};
</script>
</head>
<body>
<p id="p1">
<input id="txt1" name="age" type="text" value="5" />
<input id="txt2" name="age" type="text" value="6" />
<input id="txt3" name="age" type="text" value="7" />
<input id="txt4" name="height" type="text" value="8" />
</p>
</body>
</html>
注意对于上面的代码,直接写控件的id也是可以直接获得对象的,但是建议统一通过getElementById获取,因为直接写控件的id有时候是获取不到的(不用研究)。
<script type="text/javascript">
window.οnlοad=function(){
alert(txt3.value);
};
</script>
2.其他获取节点的方法
NodeList getElementsByTagName(string) 根据元素的标签名获取元素,因为有可能有多个相同标签名的标签,所以返回的是集合
NodeList getElementsByName(string) 根据元素的name值获取元素,因为有可能有多个同名的标签,所以返回的是集合
NodeList querySelectorAll(string) 根据选择器(和CSS选择器语法一致值)获取元素,因为有可能有多个同名的标签,所以返回的是集合。这是Html5新增的特性,有了它其实就用不到其他获取节点的方法了。后续我们主要用querySelectorAll
遍历NodeList的方法:
nodeList.length 包含的元素个数
nodeList.item(index)或者nodeList[index] 获取指定索引位置的元素
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p id="p1">
<input id="txt1" name="age" type="text" value="5" />
<input id="txt2" name="age" type="text" value="6" />
<input id="txt3" name="age" type="text" value="7" />
<input id="txt4" name="height" type="text" value="8" />
</p>
</body>
<script type="text/javascript">
console.log("----------getElementsByName");
var txts = document.getElementsByName("age");
for(var i=0;i<txts.length;i++)
{
var txt = txts[i];
console.log(txt.value);
}
console.log("----------getElementsByTagName");
txts = document.getElementsByTagName("input");
for(var i=0;i<txts.length;i++)
{
var txt = txts[i];
console.log(txt.value);
}
console.log("----------querySelectorAll");
txts = document.querySelectorAll("input[name=age]");
for(var i=0;i<txts.length;i++)
{
var txt = txts[i];
console.log(txt.value);
}
</script>
</html>
(三)Element
document.createElement(tagName) 根据元素标签名称创建元素节点
document创建出的新节点需要添加到一个Element中才属于页面的内容,才能显示出来,也就是给它“找个爹”:appendChild(node) 给元素添加node作为子节点
可以直接使用element.attrName的方式读写属性值。在js中,操作checkbox、radio的checked属性,select的selected属性值时,使用true或false , 表单元素的disabled属性也是如此。获得元素的内部Html使用innerHTML属性,获取元素内部HTML的纯文本表示用innerText(注意和表单元素的value不一样)。
因为class是关键字,所以操作class属性时使用className代替。
也可以直接用p1.style.cursor="pointer";这样的方法来直接操作元素节点的样式,需要注意background-color、border-color、background-image属性中的“-”在Javascript中是减号的意思,所以不能直接p1.style.background-color="red";一般把-去掉,然后-之后的单词首字母大写p1.style.backgroundColor="red";
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.warn
{
color:red;
}
.notify
{
font-style: italic;
}
</style>
</head>
<body>
<p id="p1">
<input id="txt1" name="age" type="text" value="5" />
<input id="txt2" name="age" type="text" value="6" />
<input id="txt3" name="age" type="text" value="7" />
<input id="txt4" name="height" type="text" value="8" />
</p>
<p id="p6">
hello
<input type="password" value="123" />
</p>
</body>
<script type="text/javascript">
var btnNew = document.createElement("input");
btnNew.type="button";
btnNew.value="新按钮";
btnNew.className="warn notify";
btnNew.style.backgroundColor="yellow";
btnNew.style.cursor="pointer";
var p1 = document.getElementById("p1");
p1.appendChild(btnNew);
</script>
</html>
注意一个一个节点对象只能放到一个父节点之后,如果它又被加为其他节点的儿子了,那么自动和之前的父节点脱离父子关系。
看下面的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.warn
{
color:red;
}
.notify
{
font-style: italic;
}
</style>
</head>
<body>
<p id="p1">
<input id="txt1" name="age" type="text" value="5" />
<input id="txt2" name="age" type="text" value="6" />
<input id="txt3" name="age" type="text" value="7" />
<input id="txt4" name="height" type="text" value="8" />
</p>
<p id="p6">
hello
<input type="password" value="123" />
</p>
</body>
<script type="text/javascript">
var btnNew = document.createElement("input");
btnNew.type="button";
btnNew.value="新按钮";
btnNew.className="warn notify";
btnNew.style.backgroundColor="yellow";
btnNew.style.cursor="pointer";
var p1 = document.getElementById("p1");
p1.appendChild(btnNew);
var p6 = document.getElementById("p6");
p6.appendChild(btnNew);//认贼作父,那么就和p1就脱离父子关系了
p6.appendChild(btnNew);
p6.appendChild(btnNew);//因为是同一个对象,所以加多次也是一个
</script>
</html>
还可以通过insertBefore(newNode, node)等方法来把节点添加到某个节点之前、removeChild(node)删除子节点、parentNode 获取元素的父元素。
(四)DOM事件机制
通常的,当浏览器状态改变、用户操作时都会触发一些事件。如用户点击了一个按钮,就触发了按钮的点击事件,按钮称为事件源。
当一个事件被触发时,浏览器就会创建一个event事件对象,这个对象一般以事件处理函数的第一个参数传递,参数名一般命名为e或者event,这个事件对象包含和此事件相关的各种信息,如点击事件的事件对象包含点击位置的信息,可供编程人员使用。
如果希望当一个事件发生时针对这个事件做一些处理,就需要给该事件注册一个事件处理函数,当该事件真的发生时,该处理函数就会被浏览器自动调用。这种机制叫做“回调”。
之前我们写的window.οnlοad=function(){
alert("hello");
};
就是在注册onload事件,当发生onload事件的时候执行注册的function。
通俗的解释就是:你把孩子托付给邻居了,说“当他哭闹的时候就抽他”。
常见的事件有以下几类:窗体事件、鼠标事件、键盘事件、焦点事件等
1.页面加载完成事件
load 页面加载完成时触发(window对象为事件源)
<script type="text/javascript">
window.οnlοad=function(){
var element = document.getElementById("div01");
alert(element);
}
</script>
注意:load是事件的名称,onload是元素的属性,用来给元素注册事件处理函数。
2.鼠标事件
click、dblclick 鼠标单击、双击时触发
mousemove 鼠标移动时触发(进入元素后)
mousedown、mouseup 鼠标按键按下、弹起时触发(进入元素后)
鼠标事件的event对象包含如下信息:
clientX、clientY 鼠标指针的窗口坐标
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
#div2
{
background-color: green;
width:150px;
height:150px;
}
</style>
</head>
<body>
<input type="button"id="btn1"value="点我"/>
<div id="div1">1
<div id="div2">2</div>
</div>
</body>
<script type="text/javascript">
var btn1 = document.getElementById("btn1");
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
btn1.οnclick=function(){
alert("点我干啥");
};
div1.οnclick=function(e){
console.log("div1被click"+e.clientX+","+e.clientY);
};
div2.οnclick=function(e){
console.log("div2被click"+e.clientX+","+e.clientY);
};
div1.οnmοusedοwn=function(e){
console.log("div1 上鼠标按下"+e.clientX+","+e.clientY);
}
div2.οnmοusedοwn=function(e){
console.log("div2上鼠标按下"+e.clientX+","+e.clientY);
}
div1.οnmοuseup=function(e){
console.log("div1 上鼠标抬起"+e.clientX+","+e.clientY);
}
div2.οnmοuseup=function(e){
console.log("div2上鼠标抬起"+e.clientX+","+e.clientY);
}
div1.οnmοusemοve=function(e){
console.log("div1 上鼠标移动"+e.clientX+","+e.clientY);
}
div2.οnmοusemοve=function(e){
console.log("div2上鼠标移动"+e.clientX+","+e.clientY);
}
</script>
</html>
我们看到这些事件都是div1、div2的事件都触发,而且是内层先触发、外层再触发,这叫做“事件冒泡”,内层就像水池的底部,事件就像气泡一样从底部向上冒泡。还可以有更多的嵌套层次。
e.stopPropagation()可以终止冒泡,也就是拦截冒泡,“戳破泡”。用上面的onclick做测试,改成alert会更明显。
mouseover、mouseout 鼠标指针进入、离开元素时触发。如果有内嵌的子元素,则移动、离开子元素的时候会触发。
mouseenter、mouseleave鼠标指针进入、离开元素时触发。如果有内嵌的子元素,则移动、离开子元素的时候不会触发。
知道这么一回事即可,不用去记
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
#div2
{
background-color: green;
width:150px;
height:150px;
}
</style>
</head>
<body>
<div id="div1">1
<div id="div2">2</div>
</div>
</body>
<script type="text/javascript">
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
div1.οnmοuseοver=function(e){
console.log("div1 上mouseover"+e.clientX+","+e.clientY);
}
div2.οnmοuseοver=function(e){
console.log("div2上mouseover"+e.clientX+","+e.clientY);
}
div1.οnmοuseοut=function(e){
console.log("div1 上mouseout"+e.clientX+","+e.clientY);
}
div2.οnmοuseοut=function(e){
console.log("div2上mouseout"+e.clientX+","+e.clientY);
}
div1.οnmοuseenter=function(e){
console.log("div1 上mouseenter"+e.clientX+","+e.clientY);
}
div2.οnmοuseenter=function(e){
console.log("div2上mouseenter"+e.clientX+","+e.clientY);
}
div1.οnmοuseleave=function(e){
console.log("div1 上mouseleave"+e.clientX+","+e.clientY);
}
div2.οnmοuseleave=function(e){
console.log("div2上mouseleave"+e.clientX+","+e.clientY);
}
</script>
</html>
3.注册事件的两种方式
第一种方式,通过DOM方式把事件处理函数赋值给事件属性(称为注册事件处理函数)。这是最推荐的写法。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.οnlοad=function(){
var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
alert("点我了1");
}
btn1.onclick = function(){
alert("点我了2");
}
}
</script>
</head>
<body>
<input type="button" id="btn1" value="点我" />
</body>
</html>
注意对于同一个元素的同一个事件不能重复注册。如果要想重复注册,可以用addEventListener,不过直接用Dom的机会不多,因此不再详细讲。
当然也可以用命名函数或者匿名函数:
<script type="text/javascript">
var f= function(){
var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
alert("点我了1");
}
btn1.onclick = function(){
alert("点我了2");
}
};
window.οnlοad=f;//不要写成window.οnlοad=f();
</script>
第二种方式直接在HTML元素标签的事件属性上写要执行的代码,需要注意单引号、双引号的问题。这种写法不推荐,因为常规的写法是把html和JavaScript分开,不要混到一起写。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button"οnclick="alert('点我了')"id="btn1"value="点我"/>
</body>
</html>
还有一种更不推荐的写法是直接把代码写到超链接的href属性上,只要前面加上javascript:即可。
<a href="javascript:alert('点我了')">来呀帅哥</a>
因为普通用户会认为超链接点击后会显示一个网页,你这样的行为会让用户很困惑,所以不如把它搞成按钮。
当然非要用超链接,也把html和js分离开:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.οnlοad=function(){
var link1 = document.getElementById("link1");
link1.οnclick=function(){
alert('点我了');
};
};
</script>
</head>
<body>
<a href="javascript:void(0)"id="link1">来呀帅哥</a>
</body>
</html>
4.this的使用
在事件响应回调函数中,this代表当前事件监听的对象
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
#div2
{
background-color: green;
width:150px;
height:150px;
}
</style>
</head>
<body>
<div id="div1">1
<div id="div2">2</div>
</div>
</body>
<script type="text/javascript">
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
div1.οnclick=function()
{
alert("div1.click.this="+this.id);
}
div2.οnclick=function()
{
alert("div2.click.this="+this.id);
}
</script>
</html>
我们发现,当点击div2的时候,div1、div2的onclick都会执行(因为事件冒泡),各自的this也是div1、div2。
对于事件冒泡来讲,this永远是当前事件监听的对象,而e.target则是冒泡的初始对象:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
#div2
{
background-color: green;
width:200px;
height:200px;
}
#div3
{
background-color: yellow;
width:100px;
height:100px;
}
</style>
</head>
<body>
<div id="div1">1
<div id="div2">2
<div id="div3">3</div>
</div>
</div>
</body>
<script type="text/javascript">
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
div1.οnclick=function(e)
{
alert("div1.click this="+this.id+
",target="+e.target.id);
}
div2.οnclick=function(e)
{
alert("div2.click this="+this.id+
",target="+e.target.id);
}
div3.οnclick=function(e)
{
alert("div3.click this="+this.id+
",target="+e.target.id);
}
</script>
</html>
注意下面写不行:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
</style>
</head>
<body>
<div id="div1">
</div>
</body>
<script type="text/javascript">
var div1 = document.getElementById("div1");
function f1(e)
{
alert("1 this="+this.id);
alert("1 target="+e.target.id);
}
div1.οnclick=function(){
f1();
};
</script>
</html>
因为只有在事件回调函数中e、this才代表我们讲的意思,执行到f1的时候this已经不是当前绑定的对象了。这个涉及到“function的四种调用方法”这个前端的深入问题,初学者只要知道不能这么写就行了。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1
{
background-color: red;
width:300px;
height:300px;
}
</style>
</head>
<body>
<div id="div1" οnclick="f1()">
</div>
</body>
<script type="text/javascript">
function f1(e)
{
alert("this="+this.id);
alert("target="+e.target.id);
}
</script>
</html>
通俗的来讲就是“在回调的函数里this、e才是我们讲的意思,只要又调用一次函数就不是了”。
下面实现点击按钮一秒钟之后再显示被点击按钮的value属性,是不行的:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button"id="btn1"value="11"/>
<input type="button"id="btn2"value="22"/>
</body>
<script type="text/javascript">
var btnOnClick = function(){
setTimeout(function(){
alert(this.value);
},1000);
};
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
btn1.onclick = btnOnClick;
btn2.onclick = btnOnClick;
</script>
</html>
看起来setTimeout的function参数是写到onclick的回调函数中的,但是它是独立的function,因此这里的this已经和onclick中的this不一样了,如下改造。也就是this还能用的时候,把它存到一个变量中,这个深入涉及到js中的闭包的问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button" id="btn1" value="11" />
<input type="button" id="btn2" value="22" />
</body>
<script type="text/javascript">
var btnOnClick = function(){
var src=this;
setTimeout(function(){
alert(src.value);
},1000);
};
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
btn1.onclick = btnOnClick;
btn2.onclick = btnOnClick;
</script>
</html>
(五)练习案例
1.文本时钟
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="divClock"></div>
<input type="text"id="txtClock"/>
</body>
<script type="text/javascript">
var divClock = document.getElementById("divClock");
var txtClock = document.getElementById("txtClock");
var timer = function(){
var now = new Date().toLocaleTimeString();
divClock.innerText = now;
txtClock.value = now;
};
setInterval(timer,1000);
timer();//立即执行一次,防止1秒中后才执行
</script>
</html>
这样又复习了innerText和value的区别。
2.检查登陆
实际做项目的时候不会在浏览器做判断,这样太不安全了,这只是在演示而已
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<label for="username">用户名:</label><input type="text"id="txtUsername"/><br/>
<label for="password">密码:</label><input type="password"id="txtPassword"/><br/>
<input type="button"value="登录"id="btnLogin"/>
</body>
<script type="text/javascript">
var txtUsername = document.getElementById("txtUsername");
var txtPassword = document.getElementById("txtPassword");
var btnLogin = document.getElementById("btnLogin");
btnLogin.οnclick=function(){
var username = txtUsername.value;
var password = txtPassword.value;
if(username=="admin"&&password=="123")
{
alert("登录成功");
}
else
{
alert("登录失败");
}
};
</script>
</html>
最经常写错的是把用户名密码提前获取了,比如如下写法:
<script type="text/javascript">
var txtUsername = document.getElementById("txtUsername");
var txtPassword = document.getElementById("txtPassword");
var username = txtUsername.value;
var password = txtPassword.value;
var btnLogin = document.getElementById("btnLogin");
btnLogin.οnclick=function(){
if(username=="admin"&&password=="123")
{
alert("登录成功");
}
else
{
alert("登录失败");
}
};
</script>
发现即使输错了还是提示登录失败,调试发现username、password一直为空,因为var username = txtUsername.value;是在页面打开的时候执行的,所以username一直是初始值""。
3.注册按钮倒计时
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button"id="agree"value="同意以上协议(5)"disabled/>
</body>
<script type="text/javascript">
var agree = document.getElementById("agree");
var i=5;
var intId = setInterval(function(){
i--;
if(i==0)
{
agree.disabled=false;//启用按钮
agree.value="同意以上协议";
clearInterval(intId);//停止计时器
}
else
{
agree.value="同意以上协议("+i+")";
}
},1000);
</script>
</html>
4.动态加载表格
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<table border="1">
<thead>
<tr><th>id</th><th>姓名</th><th>年龄</th></tr>
</thead>
<tbody id="tb">
</tbody>
</table>
</body>
<script type="text/javascript">
var tb= document.getElementById("tb");
var persons =[{id:1,name:'Baidu',age:8},{id:2,name:'QQ',age:18},{id:3,name:'淘宝',age:12}];
for(var i=0;i<persons.length;i++)
{
var p = persons[i];
//创建id的td
var tdId = document.createElement("td");
tdId.innerText = p.id;
var tdName = document.createElement("td");
tdName.innerText = p.name;
var tdAge = document.createElement("td");
tdAge.innerText = p.age;
//创建tr节点
var tr = document.createElement("tr");
tr.appendChild(tdId);//把tdId加入tr中
tr.appendChild(tdName);
tr.appendChild(tdAge);
tb.appendChild(tr);//tr加入到tbody中
}
</script>
</html>
5.全选、全不选、反选效果
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul>
<li><input type="checkbox" id="p1" name="site" /><label for="p1">百度</label></li>
<li><input type="checkbox" id="p2" name="site" /><label for="p2">百度</label></li>
<li><input type="checkbox" id="p3" name="site" /><label for="p3">腾讯</label></li>
<li><input type="checkbox" id="p4" name="site" /><label for="p4">阿里</label></li>
<li><input type="checkbox" id="p5" name="site" /><label for="p5">头条</label></li>
</ul>
<input type="button" id="selectAll" value="全选" />
<input type="button" id="deSelectAll" value="全不选" />
<input type="button" id="revSelectAll" value="反选" />
</body>
<script type="text/javascript">
var selectAll= document.getElementById("selectAll");
var deSelectAll= document.getElementById("deSelectAll");
var revSelectAll= document.getElementById("revSelectAll");
selectAll.onclick = function(){
var sites = document.querySelectorAll("input[name=site]");
for(var i=0;i<sites.length;i++)
{
var site = sites[i];
site.checked = true;
}
};
deSelectAll.onclick = function(){
var sites = document.querySelectorAll("input[name=site]");
for(var i=0;i<sites.length;i++)
{
var site = sites[i];
site.checked = false;
}
};
revSelectAll.onclick = function(){
var sites = document.querySelectorAll("input[name=site]");
for(var i=0;i<sites.length;i++)
{
var site = sites[i];
site.checked = !site.checked;
}
};
</script>
</html>
6.切换区域的显示
如果勾选了vip,则显示输入卡号、密码的区域:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#vipArea
{
display:none;
}
</style>
<script type="text/javascript">
window.οnlοad=function(){
var isVip=document.getElementById("isVip");
var vipArea = document.getElementById("vipArea");
isVip.οnchange=function(){
if(this.checked)
{
vipArea.style.display="block";
}
else
{
vipArea.style.display="none";
}
};
}
</script>
</head>
<body>
<p><input type="checkbox"id="isVip"/><label for="isVip">VIP会员</label></p>
<span id="vipArea">
<p><label for="cardNum">卡号:</label><input type="text"id="cardNum"/></p>
<p><label for="password">密码:</label><input type="password"id="password"/></p>
</span>
</body>
</html>
(六)其他常用事件
1.键盘事件
keydown 键盘按键被按下
keyup 键盘按键被弹起
keypress 按键,按住不放会连续触发
event事件对象的属性:
event.keyCode 被按下的按键的整数编码,和大小写无关
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input id="txt1"/>
</body>
<script type="text/javascript">
var txt1 = document.getElementById("txt1");
txt1.onkeydown = function(e)
{
console.log("onkeydown keyCode="+e.keyCode);
}
txt1.onkeyup = function(e)
{
console.log("onkeyup keyCode="+e.keyCode);
}
txt1.onkeypress = function(e)
{
console.log("onkeypress keyCode="+e.keyCode);
}
</script>
</html>
2.取消某些事件的浏览器默认动作
对于某些元素的特点事件,浏览器会有一个默认的动作,如超链接触发点击事件时页面会跳转、表单提交事件被触发时表单数据会被提交到服务器、键盘按下在输入框中输入字符等。
DOM提供了两种方式来取消浏览器的默认动作:在处理函数中执行事件对象的preventDefault()方法 或者return false;。取消事件的浏览器默认动作和取消事件冒泡是不同的概念。
例子1:另一种阻止超链接跳转的方式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="http://www.rupeng.com"id="link1">如鹏网</a>
</body>
<script type="text/javascript">
var link1 = document.getElementById("link1");
/*
//第一种方法
link1.οnclick=function(){
alert("就是不让你点");
return false;
};*/
//第二种方法
link1.οnclick=function(e){
alert("就是不让你点");
e.preventDefault();
};
</script>
</html>
例子2,输入框不能输入非数字字符
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text"id="txt1"/>
</body>
<script type="text/javascript">
var txt1 =document.getElementById("txt1");
txt1.οnkeypress=function(e)
{
//之后后退键(删除)和0-9输入能输入
if(e.keyCode==8||(e.keyCode>=48&&e.keyCode<=57))
{
return true;
}
else
{
return false;
}
}
txt1.οnpaste=function()
{
//组织粘贴的默认动作,禁止粘贴
return false;
}
</script>
</html>
3.焦点事件
focus 元素获得焦点
blur 元素失去焦点
练习案例:输入校验
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.errorMsg
{
color:red;
background-color: yellow;
}
</style>
</head>
<body>
<input type="text" id="txt1" />
<div id="txtMsg"></div>
</body>
<script type="text/javascript">
var txt1 =document.getElementById("txt1");
var txtMsg =document.getElementById("txtMsg");
txt1.onblur = function()
{
var value = txt1.value;
if(value.length==0)
{
return;
}
if(value.length>=3&&value.length<=8)
{
txtMsg.innerText="输入合法";
txtMsg.className="";//清理样式
}
else
{
txtMsg.innerText="长度不能<3,也不能大于8";
txtMsg.className="errorMsg";// 设置错误样式
}
}
</script>
</html>
(七)其他常用Html5新特性
只介绍后端工程师常用的新特性。这些不是重点,代码也不用记,知道这么一回事即可。
1.读取文件
为JavaScript提供新的API,使其能够处理要上传的文件。可以通过type=file的input拿到File对象,不能自己决定读哪个文件,只能用户选的文件你才能读。
-
File 表示被选中的一个文件,包含和此文件相关的信息
- size属性文件大小
- type属性文件类型
- name属性文件名
-
FileReader 对文件数据进行处理
- readAsText( file, encoding) 以文本的形式读取文件数据
- readAsDataURL( file) 以base64编码的形式读取文件数据
- result属性读取到的被处理过的文件数据
- onload事件属性,文件读取成功时触发
演示代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="file"id="file1"/>
<p>
<input type="button"value="读取图像"οnclick="readAsDataURL()"/>
<input type="button"value="读取二进制数据"οnclick="readAsBinaryString()"/>
<input type="button"value="读取文本文件"οnclick="readAsText()"/>
</p>
<div id="result"name="result"></div>
</body>
<script type="text/javascript">
var file1=document.getElementById("file1");
var result=document.getElementById("result");
function readAsDataURL(){
//检验是否为图像文件
var file = file1.files[0];//因为Html5中一个选择控件可以选择多个文件,所以files是一个数组
if(file.type.indexOf("image/")!=0){
alert("请选择图片!");
return;
}
var reader = new FileReader();
//将文件以Data URL形式读入页面
reader.οnlοad=function(e){
var result=document.getElementById("result");
result.innerHTML='<img src="'+ this.result +'" alt="" />';
}
reader.readAsDataURL(file);
}
function readAsBinaryString(){
var file = file1.files[0];
var reader = new FileReader();
//将文件以二进制形式读入页面
reader.readAsBinaryString(file);
reader.οnlοad=function(f){
var result=document.getElementById("result");
//显示文件
result.innerHTML=this.result;
}
}
function readAsText(){
var file = file1.files[0];
var reader = new FileReader();
//将文件以文本形式读入页面
reader.readAsText(file);
reader.οnlοad=function(f){
var result=document.getElementById("result");
//显示文件
result.innerHTML=this.result;
}
}
</script>
</html>
2.绘图功能
HTML5 新增了<canvas>标签(画布的意思),同时提供了一组新的JavaScript API,相配合完成绘图功能
绘制过程是由js代码控制,一般步骤为:
1 获得canvas画布元素对象
2 设置画笔颜色或者填充颜色
3 绘制基本图形或者图片
4 重复2和3步,最终绘制成复杂的图形
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<canvas id="c1"></canvas>
</body>
<script type="text/javascript">
var x=10,y=10,width=80,height=80;
var context = document.getElementById("c1").getContext("2d"); //获得绘图上下文(绘图功能的核心对象)
context.strokeStyle = "颜色值"; //设置画笔颜色
context.fillStyle = "颜色值"; //设置填充颜色
context.fillRect(x, y , width , height); //绘制并填充矩形
context.strokeRect(x, y , width , height); //绘制矩形
context.clearRect(x, y , width , height); // 清除矩形区域内的图形
//绘制图片
var img = new Image(); //创建图片对象
img.src="../img/1.png"; //设置图片的src,设置后即开始加载图片数据
img.οnlοad=function(){ //图片数据加载完成后才可以绘制此图片
context.drawImage(img,230,10);
}
</script>
</html>
对咱们后端开发人员来说,只需要了解一下绘图功能即可。可以网上去搜一下canvas的炫酷效果,这些都是需要有图形学、数学的强大基础的。
3.本地存储
在HTML5之前,服务器可以通过cookie把少量数据存储到用户本地电脑上,存储上限每个网站大约是4KB。这个后面讲后端开发的时候会讲
HTML5为window对象新增了localStorage属性对象,存储字符串类型的键值对数据,如:
localStorage.setItem("username","管理员");//或者l
localStorage.getItem("username");
这些键值对数据会存储到用户本地电脑上,并且这些数据是网站独享的,各个网站之间的数据并不会相互影响,而且浏览器之间也是不共享的
HTML5的本地存储大约可以存储5MB的数据。
案例:实现一个保存textarea中上次编写内容的效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible"content="IE=edge">
<meta name="viewport"content="width=device-width,minimum-scale=1.0">
<title>FileReader</title>
</head>
<body>
<div id="file-div">
<textarea id="txt1"rows="10"cols="50"></textarea>
</div>
<script>
var txt1 =document.getElementById("txt1");
var msg = window.localStorage.getItem('msg');
txt1.value = msg;
var saveMsg = function()
{
window.localStorage.setItem('msg',txt1.value);
}
txt1.οnkeypress=saveMsg;
txt1.οnchange=saveMsg;
</script>
</body>
</html>
可以F12看到LocalStorage保存的数据,根据浏览器的不同,本地存储不一定是保存到磁盘上,所以不用琢磨到底保存到哪里了。