javascript的事件
javascript是一门基于事件驱动的语言,当html页面中的元素触发一些动作时,可以执行相关的js代码。
1.常见事件
-
浏览器窗体事件
事件名 描述 onload 当窗体内容被加载时触发 onunload 当窗体中内容卸载时触发 onbeforeunload 当窗体内容被卸载之前触发 onresize 当窗体大小被改变时出发 -
鼠标事件
事件名 描述 onclick 当鼠标单击时触发 ondblclick 当鼠标双击时触发 onmouseover 当鼠标悬停到元素上时触发 onmouseout 当输入从元素中移出时触发 onmouseenter 当鼠标进入时触发 onmouseleave 当鼠标离开时触发 onmousedown 当鼠标按下时触发 onmouseup 当鼠标抬起时触发 -
键盘事件
事件名 描述 onkeydown 当键盘按键被按下时触发 onkeyup 当键盘按键抬起触发 onkeypress 当键盘按键被按压时触发 -
表单事件
事件名 描述 onchange 当控件内容改变时触发 onselect 当控件内容被选中时触发 onblur 当控件失去焦点时触发 onfocus 当控件获得焦点时触发 onreset 表单重置时触发 onsubmit 表单提交时触发
2.事件绑定与移除
事件绑定
javascript为元素绑定事件分为两种方式:
- 直接在html中为元素设置相关的事件属性;
- 在javascript中通过dom对象获取目标元素之后为其设置事件属性;
//绑定指定名称的函数
div.onclick=fun;
function fun(){
//执行体
}
//绑定匿名函数
div.onclick=function(){
//执行体
}
- 在js中获取dom之后使用addEventListener函数绑定指定事件。
div.addEventListener('click',fun)
function fun(){
//执行体
}
div.addEventListener('click',function(){
//执行体
})
解除绑定
对于使用addEventListener绑定的事件fun,可以通过removeEventLitener解除:
div.removeEventListener('click',fun);
对于解除绑定,只能解除指定元素中被绑定的回调函数对象(函数指针必须是一致的)
3.事件冒泡与事件捕获以及阻止事件传播
事件冒泡
事件冒泡,即对内层元素触发事件时,逐级向外传播,导致外层事件逐步执行。
事件捕获
事件捕获即由外向内逐层捕获。需要将事件冒泡机制切换为事件捕获,只需要在为元素通过:e.addEventListene(事件名,回调函数,是否捕获)。
阻止事件传播
由于事件流的传播性,实际开发中这些特性会影响程序的事件处理,因此需要对事件传播进行阻止,如果需要阻止事件的传播,只需要在指定元素的触发时调用事件对象提供的stopPropergation()
函数或者设置cancelBubble
为true即可:
//分别获取三个div元素并绑定点击事件
//事件冒泡:从内层->外层 默认
//事件捕获:从外层->内层 加true参数
document.getElementById('box1').addEventListener('click',function (e) {
console.log('外层盒子');
//阻止时间传播
// e.stopPropagation();
e.cancelBubble = true;
});
document.getElementById('box2').addEventListener('click',function (e) {
console.log('中层盒子');
e.cancelBubble = true;
});
document.getElementById('box3').addEventListener('click',function (e) {
console.log('内层盒子');
e.stopPropagation();
});
音乐播放器中的相关事件
html主要布局:
<!-- 底部歌曲播放控制,音量,进度等 -->
<div class="play-bottom">
<!-- 播放控制 -->
<div class="play-control">
<a href="javascript:;" class="btn-pre"></a>
<a href="javascript:;" class="btn-play" id="btnPlay"></a>
<a href="javascript:;" class="btn-next"></a>
</div>
<!--播放进度控制-->
<div class="progress-info">
<div class="play-info">
<a href="" id="playingName">XX</a>
</div>
<div class="play-length">
<div class="play-current">01:10</div>
<!-- 进度条 -->
<div class="play-progress">
<div class="play-panel"></div>
<div class="progress-control">
<div class="dot"></div>
</div>
</div>
<div class="play-duration">05:22</div>
</div>
</div>
<!-- 声音控制 -->
<div class="play-volume">
<div class="volume-icon">
</div>
<div class="volume-wrap">
<div class="volume-panel"></div>
<div class="volume-control">
<a href="" class="dot"></a>
</div>
</div>
</div>
</div>
数据:
var musics = [
{
ablum: "xxx",
artist: "GALA ",
id: 2,
name: "追梦赤子心",
path: "musics/1592373330188.mp3",
size: 8357216,
style: "摇滚",
uptime: 1592373330000
},
{
ablum: "xxx",
artist: "Bruno Mars ",
id: 4,
name: "Just The Way You Are",
path: "musics/1592383891287.mp3",
size: 3602925,
style: "摇滚",
uptime: 1592383891000
}]
添加相关事件
//创建音频播放器对象
var player = document.createElement('audio');
//记录正在播放的歌曲的索引
var currentIndex = 0;
//声明标记,记录歌曲的播放状态(是否播放)
var isplay = false;
//自调用函数绑定列表数据(并动态绘制歌曲列表)
((function() {
//绑定数据到页面中
var html ='';
//循环遍历歌曲列表,根据歌曲数目在页面中生成对应的html代码
for (var i = 0; i < musics.length; i++) {
var m = musics[i];
//根据循环的次数创建对应的歌曲信息
html += `<tr class="music-item" data-index="${i}">
<td class="tb-space" style="text-align: center"></td>
<td><a href="javascript:;">${m.name}</a></td>
<td><a href="javascript:;">${m.artist}</a></td>
<td><a href="javascript:;">${m.ablum}</a></td>
<td>${fmtsize(m.size)}</td>
<td class="tb-space"></td>
</tr>`;
}
//将生成的html代码插入到指定的dom节点
document.getElementById('tbody').innerHTML = html;
//初始化播放源
player.src = musics[currentIndex].path;
})());
//为列表项触发点击事件
var trs = document.querySelectorAll('.music-item');
for (var i = 0; i < trs.length; i++) {
trs[i].addEventListener('click',function() {
clearStatus();
//获取元素上data-index属性的属性值(获取需要播放的歌曲列表项)
var index = this.dataset.index;
//记录正在播放的歌曲
currentIndex = index;
//获取需要播放的歌曲对象
var m = musics[index];
//为播放器设置播放源
player.src = m.path;
//开始播放
startPlay();
});
//使用函数闭包的方式获取点击的列表索引
// trs[i].addEventListener('click',(function (index) {
// return function () {
// alert(index);
// }
// })(i))
}
//清除上一首正在播放的状态
function clearStatus() {
//还原上一首正在播放歌曲的列表项背景
trs[currentIndex].style.backgroundColor = '';
//清除当前行下的第一个单元格内容(清除图标)
trs[currentIndex].getElementsByTagName('td')[0].innerHTML = '';
}
//播放
function startPlay() {
//标记状态为正在播放
isplay = true;
//播放
player.play();
//修改当前正在播放的歌曲所在列表项的背景色
trs[currentIndex].style.backgroundColor = '#f0f0f0';
//清除当前行下的第一个单元格内容(清除图标)
// this.querySelector('td:nth-child(1)');
trs[currentIndex].getElementsByTagName('td')[0].innerHTML = '<img src="imgs/playing-list.gif">';
// 将播放按钮的背景图片设为暂停
document.getElementById('btnPlay').className = 'btn-pause';
//将正在播放的歌曲信息显示在底部控制区域
document.getElementById('playingName').innerText = musics[currentIndex].name;
}
//暂停
function pausePlay(){
//将播放状态标记为false
isplay = false;
//暂停播放
player.pause();
//将当前播放按钮的类名称修改
document.getElementById('btnPlay').className = 'btn-play';
}
//播放控制
document.getElementById('btnPlay').addEventListener('click',function () {
if(isplay){
//暂停
pausePlay();
}else{
//播放
startPlay();
}
});
//记录歌曲的当前播放时间
var now = 0;
//记录歌曲的总播放时间
var total = 0;
//当播放器数据被加载时触发
player.addEventListener('loadeddata',function () {
//获取当前播放器的播放位置和总播放时长
now = player.currentTime;
total = player.duration;
//将歌曲的播放时间显示在控制区域
document.querySelector('.play-current').innerText = fmtTime(now);
document.querySelector('.play-duration').innerText = fmtTime(total);
});
//为播放器绑定播放进度改变事件
player.addEventListener('timeupdate',updateProgress);
function updateProgress() {
//获取最新的播放进度
now = player.currentTime;
//计算进度百分比
var p = now / total * 100 + '%';
document.querySelector('.progress-control').style.width = p;
//更新播放时间
document.querySelector('.play-current').innerText = fmtTime(now);
}
//播放完成事件
player.addEventListener('ended',function () {
//清除上一首播放状态
clearStatus();
currentIndex++;
if(currentIndex >= musics.length){
currentIndex = 0;
}
//为播放器设置播放源
player.src = musics[currentIndex].path;
//开始播放
startPlay();
});
//上一曲事件
document.querySelector('.btn-pre').addEventListener('click',function () {
//清除上一首播放状态
clearStatus();
currentIndex--;
if(currentIndex <= 0){
currentIndex = musics.length - 1;
}
//为播放器设置播放源
player.src = musics[currentIndex].path;
//开始播放
startPlay();
});
//下一曲事件
document.querySelector('.btn-next').addEventListener('click',function () {
//清除上一首播放状态
clearStatus();
currentIndex++;
if(currentIndex >= musics.length){
currentIndex = 0;
}
//为播放器设置播放源
player.src = musics[currentIndex].path;
//开始播放
startPlay();
});
// 滑动进度条改变歌曲播放进度
(function(box,bar) {
//标记鼠标是否按下
var status = false;
//鼠标按下监听事件
document.querySelector(box).addEventListener('mousedown',function (e) {
//解除播放器时间更新事件
player.removeEventListener('timeupdate',updateProgress);
move(e);
});
//鼠标抬起监听事件
document.querySelector(box).addEventListener('mouseup',function () {
//播放进度更新
player.currentTime = now;
//重新绑定播放器时间更新事件
player.addEventListener('timeupdate',updateProgress);
//标记鼠标抬起
status = false;
});
//鼠标移动监听事件
document.querySelector(box).addEventListener('mousemove',function (e) {
if(status){
move(e);
}
});
//滑块移动
function move(e){
//点击事件与左边缘的距离
var eventLeft = e.offsetX;
// 更新进度条位置
document.querySelector(bar).style.width = eventLeft+'px';
// 获取进度条总长度
var w = window.getComputedStyle(document.querySelector(box)).width;
//获取播放器当前所在位置
now = eventLeft / parseInt(w) * total;
//设置鼠标状态为按下
status = true;
}
})('.play-length','.progress-control');//参数为可触发事件的进度条所在盒子类,进度条类
//格式化歌曲的播放时间
function fmtTime(time) {
//秒转化为毫秒
time *= 1000;
//使用毫秒数构建一个日期对象
time = new Date(time);
var min = time.getMinutes();
var sec = time.getSeconds();
min = min < 10? '0'+ min:min;
sec = sec < 10? '0'+ sec:sec;
return min+':'+sec;
}
//格式化歌曲大小
function fmtsize(size) {
size = size / (1024 * 1024);
size = size.toFixed(1);
return size + 'MB';
}
总结
- js语法相对灵活,而结合html+css+js可以完成许多的操作,前两者使得界面更加美观,而后者使得界面具备一些功能。
- 当然,在当前的一些主流框架的使用,使得js语法更加简单,学会后使用也更加方便;其底层一样通过原生js实现理解这些,对jQuery等框架的使用会更加得心应手。