上一期我们主要讲解JS逻辑和DOM的结合 - JS设置标签的内容和样式,它是实现页面交互效果的重要基础知识。如果想具体了解JS设置标签的内容和样式,可以回复“标签”到微信公众号。今天我们要来学习简单的页面交互效果 - 点击块,让块运动起来。
1 获取标签
2 绑定事件
3 设置样式
4 代码的封装与优化
5 课程小结
6 课程练习
回顾一下前面学过的知识,如何获取网页中的标签?我们是通过给网页中的标签取一个id名(id名不能重复),再利用getElementById('id名')的方法获取相应的标签,具体看下面的案例。
实例:
<!-- 结构 -->
<div class="wrap">
<h2 id="webName">HTML5学堂</h2>
<p id="founder">刘国利 - 利利 & 陈能堡 - 堡堡</p>
</div>
<!-- 脚本 -->
<script type="text/javascript">
// 获取标签
var webNameEle = document.getElementById('webName'),
founderEle = document.getElementById('founder');
// 输出标签对象
console.log(webNameEle);
console.log(founderEle);
// 输出标签内容
console.log(webNameEle.innerHTML);
console.log(founderEle.innerHTML);
</script>
结果:
今天我们要开始学习简单的页面交互效果,需要使用哪些知识点来实现简单的网页与用户的“交互”,那“交互”方面还需要涉及到哪些知识点呢?接着往下看吧。
从生活中的例子来理解事件,比如我们是通过按电灯的开关来控制开灯或熄灯,“电灯的开关功能”我们可以理解为事件,当我们触发这个事件(电灯的开关功能)的时候去执行开灯或熄灯的操作。在网页中事件又是怎么一回事呢?接下来将为您揭晓答案。
在JS中我们可以把事件分为三大类:一般事件、页面事件、表单事件。
Tips:下面给大家列举比较常用的JS事件类型。
一般事件
1 click - 在用户点击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发;
2 mousedown - 在用户按下了任意鼠标按钮时触发;
3 mouseup - 用户释放鼠标按钮时触发;
4 mousemove - 当鼠标指针在元素内部移动时重复地触发;
5 mouseenter - 在鼠标光标从元素外部首次移动到元素范围之内时触发;
6 mouseleave - 在位于元素上方的鼠标光标移动到元素范围之外时触发;
页面事件
1 load - 当页面完全加载后(包括所有图像、JavaScript文件、CSS文件等外部资源),就会触发window上面的load事件;
2 unload - 在文档被完全卸载后触发。只要用户从一个页面切换到另外一个页面,就会触发unload事件;
3 resize - 当浏览器的窗口大小被改变时触发的事件;
4 scroll - 浏览器的滚动条位置发生变化时触发的事件;
表单事件
1 blur - 当前元素失去焦点时触发的事件;
2 change - 当前元素失去焦点并且元素的内容发生改变而触发的事件;
3 focus - 当某个元素获得焦点时触发的事件;
4 input - 当用户输入时触发;
5 reset - 事件会在表单中的重置按钮被点击时发生;
了解完了JS的事件类型,那我们在网页中该如何使用这些事件类型呢?首先需要获取网页中的标签,再给标签绑定上相应的事件类型,然后通过触发事件去完成相应的页面交互。
语法:
1 标签对象.on事件类型 = function() { }
2 标签对象.on事件类型 = 函数名;
Tips:function类似于我们数学学过的函数,比如sin、cos等函数,当我们触发事件的时候会去执行function里面的代码语句;在JS里面我们是通过function关键字来进行声明函数,具体的下面的内容会讲解到。
实例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>HTML5Course - 梦幻雪冰</title>
<link rel="stylesheet" type="text/css" href="reset.css" />
<style type="text/css">
.btn {
width: 50px;
height: 50px;
border: 2px solid yellow;
background-color: pink;
line-height: 50px;
text-align: center;
cursor: pointer;
}
</style>
</head>
<body>
<!-- 结构 -->
<div class="wrap">
<div class="btn" id="btnEle">点击</div>
</div>
<!-- 脚本 -->
<script type="text/javascript">
// 获取标签
var btnObj = document.getElementById('btnEle');
// 绑定事件
// 标签对象.on事件类型 = function() { }
btnObj.onclick = function() {
alert('你触发了click事件~');
}
</script>
</body>
</html>
结果:点击id名为btnEle标签,弹出弹窗,显示“你触发了click事件~”的内容;
分析:
1 代码28行我们获取了网页中id名为btnEle的标签;
2 代码32~34行通过标签对象.on事件类型 = function() {}的方式给标签绑定上click事件类型;
3 代码33行是事件处理程序代码,也就是触发click事件后需要执行的代码(实现某种功能);
4 因为给标签绑定上了click(点击)事件,当用户触发(点击)事件的时候,会执行function里面的代码,所以才会弹出弹窗;
我们可以通过标签/元素.style.属性 = "属性值" 进行样式的控制或者通过控制类名进行样式的控制,接下来我们要结合JS的事件来设置标签的样式。
实例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>HTML5Course - 梦幻雪冰</title>
<link rel="stylesheet" type="text/css" href="reset.css" />
<style type="text/css">
.btn {
width: 50px;
height: 50px;
border: 2px solid yellow;
background-color: pink;
line-height: 50px;
text-align: center;
cursor: pointer;
}
.model {
width: 130px;
height: 130px;
border: 2px solid gray;
background-color: skyblue;
}
</style>
</head>
<body>
<!-- 结构 -->
<div class="wrap">
<div class="btn" id="btnEle">点击</div>
<div class="model" id="modelEle">我是小块,点击的时候我会动</div>
</div>
<!-- 脚本 -->
<script type="text/javascript">
// 获取标签
var btnObj = document.getElementById('btnEle');
var modelObj = document.getElementById('modelEle');
// 定义变量
var step = 0;
// 绑定事件
btnObj.onclick = function() {
// 每执行一次加1
step++;
// 给小块标签设置样式
modelObj.style.marginLeft = step + 'px';
}
</script>
</body>
</html>
结果:
分析:
1 代码43行每次触发click事件step都会在原来的基础上加1;
2 代码46行step变量的值赋值给标签的margin-left的值,需要注意的是不要忘记属性值的单位;
3 每次点击标签(触发click事件),小块会向左移动1px;
现在点击块,让小块动起来是已经实现了,那么网页中如果又出现了相同的效果,我们该如何处理呢?把代码复制一遍?这样会产生代码冗余,所以我们需要对代码进行封装与优化;
函数:
什么是函数呢?简单的说,函数就是把多条语句封装起来,可以在任意地方放置,也可以在任意地方调用执行。
函数的定义:
语法:
<script>
function functionName(arg0, arg1, ..., argN) {
// 具体函数内容 - HTML5学堂
}
</script>
Tips:functionName代表的是函数名;arg0, arg1, ..., argN代表的是函数的形参(也可以理解为变量);
实例:
<script>
function sayName(name, username) {
alert(name + ':' + username);
}
</script>
函数的执行:
sayName('刘国利', '陈能堡');
函数的参数:
在定义函数的时候括号中的参数叫做形参,调用函数的时候,括号中的参数叫做实参。如果我们规定了形参只有两个(即只有两个用于接收数据的参数),此时在调用的时候我们传递了1个参数或者3个参数进来,解析器也是能够正常解析的,至于原因我们后期的文章会讲解到。
理解函数封装:
实例:
<script type="text/javascript">
/*
* [sum 求两个数之间的和]
* @param {[数字]} startNum [开始的数]
* @param {[数字]} endNum [结束的数]
* @return {[数字]} [求和的结果]
* 示例:sum(10, 20)
* author:陈能堡
*/
function sum(startNum, endNum) {
var result = 0;
for (var i = startNum; i <= endNum; i++) {
result += i;
};
return result;
}
// 第一次调用
console.log(sum(1, 30));
// 第二次调用
console.log(sum(20, 30));
// 第三次调用
console.log(sum(32, 40));
</script>
结果:465 275 324
分析:
1 利用function封装了“求两个数之间的和”的sum功能函数;
2 代码21~25总共三次调用sum功能函数,共用相同的代码实现不同的效果;
3 利用函数封装可以减少代码冗余,提升代码的可读性和复用性;
4 函数封装的另外一个好处在于,你不需要了解函数里面的实现原理,只要懂得调用也能实现相应的效果,便于项目团队的开发;
函数封装前:
<script type="text/javascript">
// 以下的命名只是为了让大家便于理解,请勿模仿!!!
// 获取标签
var btnObj1 = document.getElementById('btnEle1'),
btnObj2 = document.getElementById('btnEle2'),
modelObj1 = document.getElementById('modelEle1'),
modelObj2 = document.getElementById('modelEle2'),
step1 = 0,
step2 = 0;
// 绑定事件
btnObj1.onclick = function() {
// 每执行一次加1
step1++;
// 给小块标签设置样式
modelObj1.style.marginLeft = step1 + 'px';
}
// 绑定事件
btnObj2.onclick = function() {
// 每执行一次加1
step2++;
// 给小块标签设置样式
modelObj2.style.marginLeft = step2 + 'px';
}
</script>
函数封装后:
<script type="text/javascript">
// 以下的命名只是为了让大家便于理解,请勿模仿!!!
// 获取标签
var btnObj1 = document.getElementById('btnEle1'),
btnObj2 = document.getElementById('btnEle2'),
modelObj1 = document.getElementById('modelEle1'),
modelObj2 = document.getElementById('modelEle2'),
step1 = 0,
step2 = 0;
// 函数封装
function move(eleObj, step) {
// 给小块标签设置样式
eleObj.style.marginLeft = step + 'px';
}
// 绑定事件
btnObj1.onclick = function() {
step1 += 2;
move(modelObj1, step1);
}
// 绑定事件
btnObj2.onclick = function() {
step2 += 4;
move(modelObj2, step2);
}
</script>
结果:
分析:
1 提取了重复的JS代码 - 处理标签的样式,封装在move函数里面;
2 代码19和25行,分别调用move函数,并给函数传递两个实参,分别是标签对象和margin-left变化的值;
由于本篇文章的篇幅过长,关于作用域的知识安排到下一期进行讲解,请大家谅解~
this概念:this是JavaScript函数内部的对象(不需要我们声明);
this指向的一句话法则:永远指向其所在函数的所有者如果没有所有者时,指向window;
this的用法:
<!-- 结构 -->
<div class="wrap">
<div class="btn" id="btnEle">点击</div>
</div>
<!-- 脚本 -->
<script type="text/javascript">
// 全局函数中的this
function show() {
// 输出this的值
console.log(this);
}show();
// 对象.方法中的this
var obj = {
name: '陈能堡',
sayName: function() {
// 输出this的值
console.log(this);
}
};
obj.sayName();
// 鼠标点击事件等进行函数的绑定时,this的指向
var btnObj = document.getElementById('btnEle');
btnObj.onclick = function() {
// 输出this的值
console.log(this);
}
</script>
结果:window对象 obj对象 btnObj对象
分析:
1 show这个函数没有所有者,因此此时this指向的是window;
2 obj.sayName表示的是sayName这个函数的所有者是对象obj,因此this应当是指向obj的;
3 onclick事件的拥有者是btnObj。因此,此处this指向btnObj;我们也可以将btnObj.onclick理解为对象.方法;
继续优化上面“函数封装的实例”的JS代码;
实例:
<!-- 脚本 -->
<script type="text/javascript">
// 以下的命名只是为了让大家便于理解,请勿模仿!!!
// 获取标签
var btnObj1 = document.getElementById('btnEle1'),
btnObj2 = document.getElementById('btnEle2'),
modelObj1 = document.getElementById('modelEle1'),
modelObj2 = document.getElementById('modelEle2'),
step1 = 0,
step2 = 0;
// 函数封装
function move(eleObj, step) {
// 给小块标签设置样式
eleObj.style.marginLeft = step + 'px';
}
// 绑定事件
btnObj1.onclick = function() {
step1 += 2;
// this代替btnObj1,扩展性更强
move(this, step1);
}
// 绑定事件
btnObj2.onclick = function() {
step2 += 4;
// this代替btnObj2,扩展性更强
move(this, step2);
}
</script>
分析:
1 代码24和32行利用了this对象做了优化;
2 如果我们修改了btnObj1或btnObj2命名时,click事件里面的代码不用发生改动,因为this指向的还是标签的对象,这样做有利于代码的扩展性;
本文主要按照一个技术角度的思路来讲解简单页面交互效果的实现;
获取标签——>通过id名获取网页中的标签;
绑定事件——>给获取到的标签绑定JS事件;
设置样式——>触发JS事件的时候设置标签的样式来实现简单的页面交互效果;
代码的封装与优化——>利用function来实现函数的封装,利用this对象对代码进行优化;
HTML5学堂小编 - 堡堡 耗时9h
欢迎沟通交流~