基础知识 | BOM 事件

BOM简介

 Browser Object Model 浏览器对象模型,专门操作浏览器窗口或软件的一套对象和方法的集合

BOM没有标准,所以有兼容性问题

BOM比Dom更大,它包含Dom,documnet就是dom

window对象

BOM的核心是window对象,表示浏览器的实例。

window对象保存了所有可以直接使用的原生的对象和函数

原生的对象和函数:浏览器中已经自带的,我们不需要创建或下载,就可以直接使用的一切代码都是原生。包括ES/DOM/BOM

通过var声明的全局变量和函数都会变成window对象的属性和方法。

wndow下的一个特殊属性window.name,就是建议不要声明这个,var name

window下包含六大对象

           location   history   navigator  document (DOM)  screen  event

window窗口

所有现代浏览器都支持4个属性innnerWidth,innerHeight,outerWidth,outerHeight

打开窗口:window.open();

关闭窗口:window.close();

还代表了当前正在打开的浏览器窗口

   

窗口的完整大小:window.outerWidth(窗口完整宽  这里包括窗口的阴影)     

                             window.outerHeight( window.outerHeight<=36来判断窗口是否最小化了,小于36就是最小化了)

           

 文档显示区范围: window.innerwidth(文档显示区 就是代码网页)         

                               window.innerHeight

    

当窗口内容都加载完成后,自动执行:

     window.οnlοad=function(){    }  //事件

当窗口大小重新改变时,自动触发

     window.οnresize=function(){   }//事件

    案列:随着窗口大小,自动调整内部div的宽与窗口等宽

                        

                                                

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			ul{
				list-style:none;
			}
			ul>li{
				float:left;
				border:1px solid #555;
				padding: 5px 10px;
				text-align: center;
			}
			ul>li>div{
				 width:100%; /*如果将来设置wdith:100%不管用,就可以用  window.onresize */
				height:200px;
				border:1px solid #555;
				position:absolute;
				top:50px;
				left:0;
			}
		</style>
	</head>
	<body>
		<ul>
			<li>
				<span>一级菜单</span>
				<div>二级菜单</div>
			</li>
		</ul>
		
	</body>
	<script>
		//当窗口加载完成后,自动执行一项任务
		window.onload=function(){
			//找到div
				var div=document.querySelector("ul>li>div");
				div.style.width=window.innerwidth+"px";
				}
			//当窗口大小重新变化时自动执行一项任务
			window.onresize=function(){
				//找到div 
					var div=document.querySelector("ul>li>didv");
					div.style.width=window.innerWidth+"px";
				</div>
			}
		
	</script>
</html>

打开新链接  

            在当前窗口打开,可后退

                 HTML   <a href="url" target="_self">

                 JS    window.open("url","_self");

            在当前窗口打开,禁止后退

                 JS(只能用js实现):location.replace("新的url")

            在新窗口打开,可打开多个

                 HTML  <a herf="url" target="_blank">

                 JS    window.open("url","_blank");

            在新窗口打开,只能打开一个

                 HTML  <a herf="url" target="自定义窗口名">

                  JS    window.open("url","自定义窗口名");

                         每个窗口在浏览器内存中都有一个唯一的窗口名

                          浏览器规定相同名称的窗口只能打开一个。后打开的同名窗口,会把先打开的同名窗口覆盖掉。

                           我们可以通过a的target属性和window.open()的第二个参数为新窗口指定自定义的名称:

                                     eg:< a href="http://www.baidu.com" target="tmooc">或window.open("http://www.baidu.com","baidu"):

                                   当单击a或按钮时,会打开新窗口,但是窗口名会被改为tmooc.

                                    tmooc就保存在了window.names属性中。window.name是BOM中专门保存窗口名的特殊意义的属性。所以,自己起变量名或属性名时,绝对不能用name.

                                    因为名为tmooc的窗口在内存中已经存在了,所以,将来如果重复点击按钮时,虽然会打开新的窗口,但是新的同名窗口会覆盖掉旧的同名窗口,最后只会有一个窗口被保留下来。

                  预定义窗口名:_self  将当前窗口自己的名字贡献给新窗口。结果,当前窗口自己被新窗口覆盖。

                                          _blank 不指定任何新窗口名。但是浏览器不会让窗口名空着。浏览器绝对不会让窗口名空着。浏览器会自动给新窗口随机起名。因为随机取名一定不会重复,所以_blank打开的窗口可以反复打开多个

                   视频:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="{CHARSET}">
		<title></title>
		<link rel="stylesheet" type="text/css" href="my.css">
		<script>
			function open1(){
				window.open("http://www.baidu.com","_self");
			}
			function open3(){
				location.replace("http://www.baidu.com");
			}
			function open6(){
				window.open("http://www.baidu.com","mylove");
			}
			function open7(){
				window.open("http://www.baidu.com","_blank");
			}
		</script>
	</head>
	<body>
		<h3>在当前窗口打开,可后退</h3>
		<a href="http://www.baidu.com" target="_self">go</a>
		<button onclick="open1()">go to</button>
		
		<h3>在新窗口打开,禁止后退</h3>
		<button onclick="open3()">go to</button>
		
		<h3>在新窗口打开,可打开一个</h3>
		<a href="http://www.baidu.com" target="mylove">go</a>
		<button onclick="open6()">go to</button>
		
		<h3>在新窗口打开,只能打开多个</h3>
		<a href="http://www.baidu.com" target="_blank">go</a>
		<button onclick="open7()">go to</button>
	</body>
</html>

          

history对象   

          浏览器中,专门保存当前窗口打开后,成功访问过的所以url的数组。

          只有在前进、后退、刷新时,才用history

         history.go(i)

                    前进一步 history.go(1)

                    后退一步  history.go(-1)     //当后退一步不管用时,可以后退2步 history.go(-2)

             刷新  history.go(0)

视频:

location对象

       浏览器窗口的地址栏,专门保存当前窗口正在打开的url地址信息。

       location可以获取url信息,执行跳转操作

       location分段获取url各个部分的信息   最后两个补充视频

                location.href  获取完整的url

                location.protocol  获得//前的协议部分

               location.host  获取主机名+端口号

               location.hostname 获得主机名

       location.port 获得端口号

      location.pathname 获得相对路径

      location.search  获得地址栏中显示的表单提交的查询字符串     ?变量1=值1 & 变量2=值2 & .....

      location.hash  获得url中的锚点     #top

    视频:

      执行跳转操作的函数

             在当前窗口打开可后退   location.assign("新url")    ====window.open("新url","_self")

             在当前窗口打开禁止后退  location.replace("新url")

              刷新页面 location.reload();

   

navigator对象

     专门保存浏览器配置信息的对象

     当需要检查浏览器配置时就可以用它。

      navigator.userAgent  : 获取当前浏览器的名称、内核、版本号

      navigator.plugins: 保存当前浏览器安装过的所以插件信息的关联数组

                    检查是否安装了某个插件

                            navigator["插件全名"]!==undefined 说明装了插件

 

      

    

<!DOCTYPE html>
<html>
	<head>
		<meta charset="{CHARSET}">
		<title></title>
		<link rel="stylesheet" type="text/css" href="my.css">
		
	</head>
	<body>
	</body>
	<script>
		//查看浏览器内核 版本号 名称
		console.log(navigator.userAgent);
		//查看浏览器安装的插件信息
		console.log(navigator.plugins);
		//判断浏览器是否安装pdf插件
		if(navigator.plugins["Chrome PDF Viewer "]!==undefined){
			document.write(`已安装pdf插件,可以查看pdf电子书`)
		}else{
			document.write(`未安装pdf插件,请<a href="#">点此安装</a>`)
		}
	</script>
</html>

screen对象

screen内容很多重点,就是那个scrollxy这个东西,我一直都分不清楚

事件

浏览器自动触发的或用户手动触发的页面内容或状态的改变就是事件


绑定事件处理函数的方式

事件处理函数:希望当事件发生时自动执行的函数

事件绑定:提前将事件处理函数,保存在元素的事件属性上.仅保存暂不执行。当事件发生时,浏览器会自动找到元素身上对应事件属性上保存的函数,自动执行 

html中绑定事件

在元素的开始标签中,为元素的事件属性添加一条函数调用语句,在head的script标签里定义事件处理函数

但这种方式事件绑定分散在网页的各个角落,不符合内容与行为分离的原则,不便于维护

<元素  on事件名=“事件处理函数()”>

     

 function   事件处理函数(){

       ........

      }                 

案例:在html中绑定事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				width:100px;
				height: 100px;
				background-color: green;
			}
		</style>
	</head>
	<body>
		<!-- 在html中绑定事件 -->
		<div onclick="bk()">111111</div>
	</body>
	<script>
		function bk(){
			var div=document.getElementsByTagName("div")[0];
			div.style.width=200+"px";
			div.innerHTML=2222;
		}
	</script>
</html>

js中通过赋值方式绑定事件

1.查找元素        

2.元素.on事件名=function(){.......}

所有事件绑定都集中在js中,便于维护

但无法让同一个元素的同一个事件,同时绑定多个事件处理函数

案列:js赋值方式绑定事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- 事件监听和js绑定事件 -->
		<button id="btnShoot">shoot</button><br/>
		<button id="btnAward">获得跟踪导弹</button><br/>
	</body>
	<script>
		// 点击shoot发射子弹
		var btnShoot=document.getElementById("btnShoot");
		btnShoot.onclick=function(){
			console.log("发射子弹.....");
		}
		
		//点击获得跟踪导弹,不发射子弹,给shoot增加一种新子弹,并且之后shoot可以发送两种子弹
		var btnAward=document.getElementById("btnAward");
		btnAward.onclick=function(){
			// js绑定事件
			btnShoot.onclick=function(){
				console.log("发射新子弹=======");
			}
		}
	</script>
</html>

事件监听对象绑定事件

事件监听对象绑定事件

1.查找元素       

2.元素.addEventListener("事件名",事件处理函数)

 案列1:事件监听对象绑定事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button>111</button>
		<script>
		var btn=document.getElementsByTagName("button")[0];
		btn.addEventListener("click",function(){
			console.log("按钮被点击啦");
		})
		</script>
	</body>
</html>

   

案列2:事件监听对象绑定事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- 事件监听和js绑定事件 -->
		<button id="btnShoot">shoot</button><br/>
		<button id="btnAward">获得跟踪导弹</button><br/>
	</body>
	<script>
		// 点击shoot发射子弹
		var btnShoot=document.getElementById("btnShoot");
		btnShoot.onclick=function(){
			console.log("发射子弹.....");
		}
		
		//点击获得跟踪导弹,不发射子弹,给shoot增加一种新子弹,并且之后shoot可以发送两种子弹
		var btnAward=document.getElementById("btnAward");
		btnAward.onclick=function(){		
			//事件监听
			btnShoot.addEventListener("click",function(){
				console.log("发射新子弹=======");
			})
		}
	</script>
</html>

事件监听对象移除事件

移除事件监听对象   

1.查找元素

2.元素.removeEventListener("事件名",原事件处理函数)

条件必须满足这三点,元素对象相同、事件名相同、事件处理函数(必须是原事件处理函数)的事件监听对象,才能将其移除。

 注意:事件处理函数不能用匿名函数绑定。使用匿名函数,移除事件监听对象时,不能获得原事件处理函数的地址值,无法移除原事件处理函数

浏览器规定,完全相同的事件监听对象,只能创建一个,不能重复创建。如果绑定事件时,使用有名称的函数,只能添加一个事件监听对象了,解决方式可以用jquery,自己去找吧!

   

案例:移除事件监听对象    

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- 事件监听和js绑定事件 -->
		<button id="btnShoot">shoot</button><br/>
		<button id="btnAward">获得跟踪导弹</button><br/>
		<button id="btnreload">失去跟踪导弹</button>
	</body>
	<script>
		// 点击shoot发射子弹
		var btnShoot=document.getElementById("btnShoot");
		btnShoot.onclick=function(){
			console.log("发射子弹.....");
		}
		
	//因为这个之后需要移除,所有添加新的子弹用这种方式,之后好移除
		function shoot2(){
			console.log(`发射新子弹=======`);
		}
		
	    //为btnshoot添加新的子弹
		var btnAward=document.getElementById("btnAward");
		btnAward.onclick=function(){		
			btnShoot.addEventListener("click",shoot2)
			
		}
		//当单击btnBreak时,从btnShoot移除所有跟踪导弹,只保留普通子弹
		var btnreload=document.getElementById("btnreload");
		btnreload.onclick=function(){
			btnShoot.removeEventListener("click",shoot2) //以前那种function =new Function  那样就会创建一个新的地址,最后不能移除
		
		}
	</script>
</html>

事件模型

定义: 从触发事件开始,到所有事件处理函数执行完,所执行的整个阶段(三个阶段)。

    阶段:

         事件捕获:由外向内,依次遍历并记录触发事件的元素的各级父元素上绑定的事件处理函数---只记录不执行

         目标触发:浏览器总是有限触发实际点击的目标元素(实际想点击的那个元素)上的事件处理函数      

        事件 冒泡:由内向外,依次触发目标元素上的各级父元素上的事件处理函数。

问题:单击内层子元素,会反复触发父元素上的单击事件处理函数

案例:事件模型 

        

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
				#d1 #d2 #d3 {
					cursor: pointer
				}
		
				#d1 {
					background-color: green;
					position: relative;
					width: 150px;
					height: 150px;
					text-align: center;
					cursor: pointer;
				}
		
				#d2 {
					background-color: blue;
					position: absolute;
					top: 25px;
					left: 155px;
					width: 100px;
					height: 100px;
				}
		
				#d3 {
					background-color: red;
					position: absolute;
					top: 25px;
					left: 205px;
					width: 50px;
					height: 50px;
					line-height: 50px;
				}
			</style>
	</head>
	<body>
		<div id="d1">
				<div id="d2">
					<div id="d3">
					</div>
				</div>
			</div>
			 <script>
		    var d1=document.getElementById("d1")
		    var d2=document.getElementById("d2")
				var d3=document.getElementById("d3")
				//想点哪个div,就只让哪个div喊疼!
                //但是这样做出的效果是点击d3时,d2/d1之后也会喊疼
                //单击d2,d1之后也会喊疼,只有单击d1的效果实现了
				d1.onclick=function(){
					alert("d1 疼!")
				}     
						 
				d2.onclick=function(){
					alert("d2 疼!")
				}
	
				d3.onclick=function(){
					alert("d3 疼!")
				}
			</script> 
	</body>
</html>

       

事件对象  

 定义:事件发生时,自动创建的,封装事件相关信息的对象。

 作用:获取事件相关的信息,改变事件默认的行为

 1.查找元素

 2.先获得事件对象      事件对象总是自动作为事件处理函数的第一个实参值自动传入。

          元素.οnclick=function(变量e){     

                      //当事件发生时,浏览器自动创建事件对象event,自动把event对象传给变量e                        变量e=event

                     ..................

         }

  3.访问事件对象e中的常用属性和方法。

         事件对象常用的操作

                 停止冒泡:e.stopPropagation()  拦截的是外面的事件案例e:

案例:事件对象  

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
				#d1 #d2 #d3 {
					cursor: pointer
				}
		
				#d1 {
					background-color: green;
					position: relative;
					width: 150px;
					height: 150px;
					text-align: center;
					cursor: pointer;
				}
		
				#d2 {
					background-color: blue;
					position: absolute;
					top: 25px;
					left: 155px;
					width: 100px;
					height: 100px;
				}
		
				#d3 {
					background-color: red;
					position: absolute;
					top: 25px;
					left: 205px;
					width: 50px;
					height: 50px;
					line-height: 50px;
				}
			</style>
	</head>
	<body>
		<div id="d1">
				<div id="d2">
					<div id="d3">
					</div>
				</div>
			</div>
			 <script>
		    var d1=document.getElementById("d1")
		    var d2=document.getElementById("d2")
				var d3=document.getElementById("d3")
				//想点哪个div,就只让哪个div喊疼!
				d1.onclick=function(){
					alert("d1 疼!")
				}
				//当事件发生时
				//浏览器自动创建 event 对象
				//                  ↓
				d2.onclick=function(e){
					e.stopPropagation();
					alert("d2 疼!")
				}
				//当事件发生时
				//浏览器自动创建 event 对象
				//                  ↓
				d3.onclick=function(e){
					e.stopPropagation();
					alert("d3 疼!")
				}
			</script> 
	</body>
</html>

冒泡/事件委托     

 定义:所有实际触发的子元素上,不保存任何事件处理函数,都统一委托父元素代为保管一份,所有元素通过冒泡机制共用父元素上的事件处理函数。

1.查找元素

2.元素.οnclick=functoin(){

                //多个平级子元素都要绑定相同的事件处理函数,只需要将事件绑定在父元素上一份  ..........

              }

3.e.target代替this,获得实际触发事件的目标元素/子元素

         this,会随着冒泡而不断改变。事件冒泡到哪一级元素,this就变成指向哪一级,this已经不指当前实际点击的目标元素/子元素,而是指向父元素

        e.target,不断冒泡而改变。永远保存着最初保存触发事件的那个目标元素/子元素。要想使用e.target,必须先获得事件对象e。

   

案例:冒泡/事件委托

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	<div id="keys">
	<button>1</button><span>*</span>
	<button>2</button><span>*</span>
	<button>3</button><span>*</span>
	<button>4</button><span>*</span><br/>
	<button>C</button><span>*</span>
	<button>+</button><span>*</span>
	<button>-</button><span>*</span>
	<button>=</button><span>*</span>
	</div>
	<textarea id="sc" style="resize:none;width:200px;height:50px;" readonly></textarea>
	<script>
		//多个按钮绑定单击事件,用事件委托进行优化,因为事件只绑定在父元素一个就可以了
		var  div=document.getElementById("keys");
		div.onclick=function(e){
			//这里用e.target代替this,因为this会因为父元素变化而变化
			//nodeName所有元素上自带的,保存当前元素的元素名的特殊属性
			if(e.target.nodeName==="BUTTON"){
				var sc=document.getElementById("sc");
				//判断当前按钮的点击内容
				switch(e.target.innerHTML){
					case "C":  //点击了c按钮,清空显示屏内容
					sc.value="";
					break;
					case "=":  //点了=,获得显示屏的表达式,计算结果
					var str=sc.value;
					try{
						//将显示屏内容交给eval做计算,再将结果替换回显示屏中
						sc.value=eval(str);
					}catch(err){
						//执行失败,将错误提示在显示屏上
						sc.value=err;
					}
					break;
					//否则如果点击再普通按钮上
					default:
					sc.value+=e.target.innerHTML;
				}
			}
		}
	</script>
	</body>
</html>

阻止默认行为     

httml中有些元素自身带有一些默认的行为,而多数默认行为是我们不想要的。

a标签  <a href="javascript:;">这样写的a连接不会跳转,不会擅自添加#</a>

javascript: 不让a跳转      ;表示什么也不做的分语句

其他元素:e.preventDefault();        

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<a id="a2" href="#">死链接</a>
		<script>
			var a2=document.getElementById("a2");
			a2.onclick=function(e){
				e.preventDefault();  //防止地址栏添加符号#
			}
		</script>
	</body>
</html>

     

 鼠标坐标位置   3组坐标位置

                   相对于屏幕左上角 e.screenX   e.screenY

                    相对于文档显示区左上角 e.clientX   e.clientY

                    相对于当前触发事件的元素左上角 e.offsetX   e.offsetY

      

                               

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				position:fixed;
				width: 278px;
				height:176px;
				top:100px;
				left:200px;
				background-image:url(images/1111.png);
			}
		</style>
	</head>
	<body>
		<div id="d1"></div>
		<script>
			var d1=document.getElementById("d1");
			d1.onclick=function(e){
				console.log(e.screenX,e.screenY);
				console.log(e.clientX,e.clientY);
				console.log(e.offsetX,e.offsetY);
			}
		</script>
	</body>
</html>

                      

事件 2--其他人的讲法

谁叫我不会提取归纳呢?只能这样再写一遍了

事件就是文档或者浏览器窗口中发生一些特定的交互瞬间

 事件流

事件流,也叫事件传播,描述的是从页面中接受事件的顺序,有三个阶段

事件捕获阶段,处于目标阶段,事件冒泡

事件冒泡的概念

事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		// 事件冒泡
		var box=document.getElementById("box");
		box.onclick = function(){
			box.innerHTML +='div\n'
		}
		document.body.onclick = function(){
			box.innerHTML += 'body\n'
		}
		document.documentElement.onclick = function(){
			box.innerHTML +='html\n'
		}
		document.onclick=function(){
			box.innerHTML +='document\n'
		}
		window.onclick=function(){
			box.innerHTML += 'window\n'
		}
		</script>
	</body>
</html>

事件捕获的概念

事件捕获:由不太具体的节点更早的接受事件,而最具体的节点应该最后接收到事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		// 事件捕获
		var box=document.getElementById("box");
		// 第三个参数为false时,默认也为false,为事件冒泡,值为true时,为事件捕获
		box.addEventListener('click',function(){
			box.innerHTML +='box\n'
		},true)
		document.body.addEventListener('click',function(){
			box.innerHTML +='body\n'
		},true)
		document.documentElement.addEventListener('click',function(){
			box.innerHTML +='html\n'
		},true)
		document.addEventListener('click',function(){
			box.innerHTML +='document\n'
		},true)
		window.addEventListener('click',function(){
			box.innerHTML +='window\n'
		},true)
		</script>
	</body>
</html>

事件处理程序 

事件处理程序有三种,html事件处理程序、dom0级事件处理程序、dom2级事件处理程序、IE事件处理程序

 HTML事件处理程序

缺点:html与js无分离,后期不易维护

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="box" style="width:200px;height:100px;background-color: pink;" onclick="this.innerHTML +='1' "></div>
		
		<div id="box1" style="width:200px;height:100px;background-color: skyblue;" onclick="test()"></div>
		<!-- event事件对象 -->
		<div id="box" style="width:200px;height:100px;background-color: deeppink;" onclick="this.innerHTML +=event"></div>
		<!-- event.type获取当前的事件 -->
		<div id="box" style="width:200px;height:100px;background-color: gold;" onclick="this.innerHTML +=event.type"></div>
		
		<button id="box" value="挣钱学习" style="width:200px;height:100px;background-color: greenyellow;" onclick="this.innerHTML +=value"></button>
		<script>
		function test(){
			document.getElementById("box1").innerHTML += '2';
		}
		</script>
	</body>
</html>

DOM0级事件处理程序

优点:简单  可以跨浏览器

缺点:不能给同一个元素绑定相同的事件处理程序,如果绑定了,会有覆盖现象

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		var box=document.getElementById('box');
		box.onclick=function(){
			this.innerHTML += 1;
		}
		// 只有这样或者关闭网页才能销毁
	   // 删除事件处理程序
	   // box.onclick=null;
 
        //页面值显示2
      
	   box.onclick=function(){
	   	this.innerHTML += 2;
	   }
		</script>
	</body>
</html>

 DOM2级事件处理程序

addEventListner(事件名,事件处理程序,布尔值)布尔值默认为false,false是冒泡阶段,true是处于捕获阶段

addEventListner可以绑定相同事件
removeEventListner 

案例:addeveentListner 

可以绑定相同的事件名

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
	    // Dom定义了两个
		//addEventListner(事件名,事件处理程序,布尔值)布尔值默认为false,false是冒泡阶段,true是处于捕获阶段
		//removeEvebtLister
		
		var box = document.getElementById('box');
		// addEventListen可以绑定相同事件,但是ie9不支持
		box.addEventListener('click',function(){
			this.innerHTML += 1;
		},false);
		box.addEventListener('click',function(){
			this.innerHTML += 2;
		},false);
		</script>
	</body>
</html>

函数的调用有意思

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		var box=document.getElementById('box');
		//注释掉的都可以正常运行,可以自己尝试
		// box.addEventListener('click',test,false);
		// box.addEventListener('click',test(111),false);
        
       //监听函数传参,可以用匿名函数包装一个监听函数
		box.addEventListener('click',function(){
			test(1111)
		},false)
		function test(x){
			alert(x+'我爱学习');
		}
		</script>
	</body>
</html>

案例: removeEvebtLister

反正没有反应,就没做动图

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: skyblue;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		//removeEvebtLister
		var box = document.getElementById('box');
		
		// 这种不能用到移除事件
		// box.addEventListener('click',function(){
		// 	this.innerHTML += 1;
		// },false);
		// 移除事件必须要有处理函数的函数名
		
		function handler(){
			this.innerHTML +=1;
		}
		box.addEventListener('click',handler,false);
		// 移除事件
		box.removeEventListener('click',handler,false);
		</script>
	</body>
</html>

 IE事件处理程序

 ie浏览器   attachEvent detachEvent

我的代码没有运行,不知道是不是因为ie版本的原因,之后看能不能找到这个图上这个东西吧
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: #0000FF;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		// ie浏览器添加和移除,移除方式和dom2级事件一样,就不写了
		// attachEvent detachEvent
		var box=document.getElementById('box');
		box.attachEvent('onclick',function(){
			this.innerHTML += '1';
		})
		</script>
	</body>
</html>

 事件绑定兼容写法

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width:200px;
			height:200px;
			background-color: #0000FF;
		}
		</style>
	</head>
	<body>
		<button id="btn">你过来吗</button>
		<script>
		// 事件处理程序 addEventListener() ie8不支持,attachEvent ie8支持
		var btn=document.getElementById('btn');
		// btn.addEventListener('click',fn,false);
		// btn.attachEvent('onclick',fn)
		addEvent(btn,'click',function(){
			console.log(this.innerHTML);
		})
		
		// 全浏览器事件处理程序的兼容性代码
		function addEvent(target,eventType,handler){
			if(target.addEventListener){
				target.addEventListener(eventType,handler,false)
			}else{
				target.attachEvent('on'+eventType,function(){
					// 这里是为了this的指向问题
					handler.call(target);
				})
			}
		}
				
		</script>
	</body>
</html>

事件的调用顺序 

如果同时出现html事件处理程序和dom0级事件处理程序,Dom0级

这个没有用,所以没有记

获取事件对象event

获取事件对象的兼容性写法,事件对象就是event

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		#box{
			width: 200px;
			height:100px;
			background-color: orange;
		}
		</style>
	</head>
	<body>
		<div id="box"></div>
		<script>
		// 1.如何获取事件对象(event)
		// 2.事件目标
		// 3.事件代理
		// 4.事件冒泡
		// 5.事件流阶段 eventPhase
		// 6.取消默认事件
		
		// 兼容性
		window.onload=function(){
			var box = document.getElementById('box');
			// 1.event对象是事件处理程序的第一个参数,ie8不兼容
			// ie8浏览器结果为undefined,其他浏览器[object  MouseEvent]
			// box.onclick = function(e){
			// 	// console.log(e);
			// 	this.innerHTML = e;
			// }
			
			// 2.直接可以使用event变量,但是火狐不支持
			// box.onclick =function(){
			// 	this.innerHTML = event;
			// }
			
			box.onclick = function (e){
				// 兼容性写法
				e = e || event;
				box.innerHTML = e
			}
		}
		</script>
	</body>
</html>

 事件目标对象 target

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		.item{
			width:100px;
			height:80px;
			background-color: lightblue;
			margin:50px 10px;
		}
		</style>
	</head>
	<body>
		<ul id="box">
		  <li class="item">1</li>
		  <li class="item">2</li>
		</ul>
		<script>
		// 1.如何获取事件对象(event)
		// 2.事件目标target
		// 3.事件代理
		// 4.事件冒泡
		// 5.事件流阶段 eventPhase
		// 6.取消默认事件
		
		// currentTarget target和srcElement(区别是兼容性)
		var box = document.getElementById('box');
		// 1.currentTarget属性返回事件当前所在的节点,正在执行的监听函数所绑定的节点
		// box.onclick = function(e){
		// 	e = e || window.event;
		// 	// console.log(e);
		// 	console.log(e.currentTarget);
		// 	var items=document.getElementsByTagName('li');
		// 	items[0].innerHTML=e.currentTarget;
		// } 
		
		// 2.target属性返回的是事件的实际目标对象,ie8不支持
		// box.onclick = function (e){
		// 	e = e || window.event
		// 	console.log(e.target);
		// 	console.log(e.target===this);
		// 	// this对象跟e.currentTarget属性是一致的
		// 	console.log(e.currentTarget===this);
		// }
		
		
	  // 3.srcElement属性返回的是事件的实际目标对象,ie8支持,以前的低版本火狐不支持
		// box.onclick = function (e){
		// 	e = e || window.event
		// 	console.log(e.srcElement);
			
		// }
		
		// 兼容性代码
		box.onclick = function(e){
			e = e || window.event;
			var target = e.target || e.srcElement;
		}
		</script>
	</body>
</html>

 事件代理 

事件代理也叫事件委托,需要用到事件目标对象 target

就是通过父元素实现子元素想要的效果

后面会出现那种情况不知道为什么

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul{
				list-style: 0;
				overflow: hidden;
				margin-top: 80px;
			}
			ul li{
				float:left;
	            width:100px;
				height:30px;
				text-align: center;
				line-height: 30px;
				color:#fff;
				background-color: #000;
				margin: 0 10px;
			}
		</style>
	</head>
	<body>
		<ul id="box">
			<li>1</li>
			<li>2</li>
			<li>3</li>
			<li>4</li>
			<li>5</li>
		</ul>
		<script>
			// window.onload = function(){
			// 	// 方法1
			// 	var lis = document.getElementsByTagName("li");
			// 	for(var i =0;i<lis.length;i++){
			// 		lis[i].onmouseover = function(){
			// 			this.style.backgroundColor='blue';
			// 		}
			// 		lis[i].onmouseout = function(){
			// 			this.style.backgroundColor='black';
			// 		}
			// 	}
			// }
			
			// 事件委托\代理方式 
			// 它需要事件实际目标对象来实现 target/srcElement event
			// 优点:提高性能以及降低代码的复杂度
			var box=document.getElementById('box');
			box.onmouseover = function(e){
				e = e || window.event;
				var target = e.target || e.srcElement;
				target.style.backgroundColor='blue';
			}
			box.onmouseout = function(e){
				e = e || window.event;
				var target = e.target || e.srcElement;
				target.style.backgroundColor='black';
			}
		</script>
	</body>
</html>

事件代理的应用

事件委托可以让未来的元素也有样式效果

平时用的方式无法给后面添加的元素有一样的样式

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul{
				list-style: 0;
				overflow: hidden;
				margin-top: 80px;
			}
			ul li{
				float:left;
	            width:100px;
				height:30px;
				text-align: center;
				line-height: 30px;
				color:#fff;
				background-color: #000;
				margin: 0 10px;
			}
		</style>
	</head>
	<body>
		<ul id="box">
			<li>1</li>
			<li>2</li>
			<li>3</li>
			<li>4</li>
			<li>5</li>
		</ul>
		<script>
			 window.onload = function(){
				 var box = document.getElementById('box');
				 // 模拟未来的每个事件添加对应的数据 
				 // 添加一个li,但是这样新加的li无法有样式
				 setTimeout(function(){
					  var item =document.createElement('li');
					  item.innerHTML = '6';
					  box.appendChild(item);
				 },100)
			// 	// 方法1
				var lis = document.getElementsByTagName("li");
				for(var i =0;i<lis.length;i++){
					lis[i].onmouseover = function(){
						this.style.backgroundColor='blue';
					}
					lis[i].onmouseout = function(){
						this.style.backgroundColor='black';
					}
				}
			 }
			
		</script>
	</body>
</html>
事件委托/代理 可以让后面添加的元素也有同样的效果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul{
				list-style: 0;
				overflow: hidden;
				margin-top: 80px;
			}
			ul li{
				float:left;
	            width:100px;
				height:30px;
				text-align: center;
				line-height: 30px;
				color:#fff;
				background-color: #000;
				margin: 0 10px;
			}
		</style>
	</head>
	<body>
		<ul id="box">
			<li>1</li>
			<li>2</li>
			<li>3</li>
			<li>4</li>
			<li>5</li>
		</ul>
		<script>
			 window.onload = function(){
				 var box = document.getElementById('box');
				 box.onmouseover = function(e){
				  	e = e || window.event;
				  	var target = e.target || e.srcElement;
				  	target.style.backgroundColor='blue';
				  }
				  box.onmouseout = function(e){
				   	e = e || window.event;
				   	var target = e.target || e.srcElement;
				   	target.style.backgroundColor='black';
				   }
				 // 模拟未来的每个事件添加对应的数据 ,这个像ajax
				 // 添加一个li,这样新加的li有样式
				 setTimeout(function(){
					  var item =document.createElement('li');
					  item.innerHTML = '6';
					  box.appendChild(item);
				 },100)
			 }		
		</script>
	</body>
</html>

事件冒泡 

事件冒泡 bubbles 查看当前事件是否冒泡,根据返回值true/false判读

               cancelBubble 阻止冒泡,全都支持,但不是标准写法

               stopPropagetion() 阻止冒泡,但是无法取消同一事件的其他监听函数被调用

              stopPropagetion()阻止冒泡,也可以取消同一事件的其他监听函数被调用

            stopPropagetion()  stopPropagetion()ie8不支持

案列1: bubbles与 stopPropagetion()

阻止冒泡,然而我不懂为何点击input会有冒泡效果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button id="btn" style="height:30px;width:200px;">按钮</button>
		
		<input type="text" id="test">
		<script>
        // bubbles 返回一个布尔值,表示当前事件是否会冒泡,只读
		// 注意:大部分事件都会冒泡,但是focus/blur scrooll事件不会冒泡
		var btn = document.getElementById('btn');
		btn.onclick = function(e){
			e = e || window.event;
			console.log(e.bubbles); //true会冒泡
		}
		
		// var test=document.getElementById('test');
		// test.onfocus = function(e){
		// 	e = e || window.event;
		// 	console.log(e.bubbles);//false
		// }
		
		// stopPropagation()表示取消事件的进一步冒泡,无返回值,ie8浏览器不支持,但是无法取消同一事件的其他监听函数被调用
		var btn = document.getElementById('btn');
		btn.onclick = function(e){
			e = e || window.event;
			// 阻止冒泡
			e.stopPropagation();
			this.innerHTML = "阻止冒泡";
		}
		//测试是否阻止了冒泡
		document.body.onclick = function (e){
			e = e || window.event;
			console.log('body');
		}
		</script>
	</body>
</html>

案列2: stopImmImmediatePropagation 

没有打印出body,按钮也没有变蓝 stopImmImmediatePropagation

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button id="btn" style="height:30px;width:200px;">按钮</button>
		<script>
		var btn = document.getElementById('btn');
		// stopPropagation()阻止冒泡,无法取消同一事件的其他监听函数被调用
		// dom0级事件同一方法会被覆盖,但是二级事件不会被覆盖,都会执行
		// btn.addEventListener('click',function(e){
		// 	e = e || window.event;
		// 	e.stopPropagation();
		// 	this.innerHTML = "修改了";
		// },false)
		
		// btn.addEventListener('click',function(e){
		// 	e = e || window.event;
		// 	e.stopPropagation();
		// 	this.style.backgroundColor = 'blue';
		// },false)
		// //测试是否阻止了冒泡
		// document.body.onclick = function (e){
		// 	e = e || window.event;
		// 	console.log('body');
		// }
		
		// stopImmediatePropagation()阻止冒泡,阻止同一事件的其他监听函数被调用
		btn.addEventListener('click',function(e){
			e = e || window.event;
			e.stopImmediatePropagation();
			this.innerHTML = "修改了";
		},false)
		
		btn.addEventListener('click',function(e){
			e = e || window.event;
			e.stopImmediatePropagation();
			this.style.backgroundColor = 'blue';
		},false)
		//测试是否阻止了冒泡
		document.body.onclick = function (e){
			e = e || window.event;
			console.log('body');
		}
		</script>
	</body>
</html>

案列3:cancelBubble

不懂为什么阻止了冒泡,打印冒泡状态还是true,不过body没打印出来,证明的确成功阻止了冒泡

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button id="btn" style="height:30px;width:200px;">按钮</button>
		<script>
		var btn = document.getElementById('btn');
		// cancelBubble 阻止冒泡,可以读写,默认值为false,设为true,它可以取消冒泡
		btn.onclick = function(e){
			e = e || window.event;
			e.cancelBubble = true;
			console.log(e.bubbles);
		}
		//测试是否阻止了冒泡
		 document.body.onclick = function (e){
		 	e = e || window.event;
			console.log('body');
		}
		</script>
	</body>
</html>

 事件冒泡兼容性写法

body没有打印

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button id="btn" style="height:30px;width:200px;">按钮</button>
		<script>
		var btn = document.getElementById('btn');
	
	    // 实际应用
		btn.onclick = function(e){
			e = e || window.event;
			if(e.stopPropagation){
				e.stopPropagation();
			}else{
				e.cancelBubble = true
			}
		}
		//测试是否阻止了冒泡
		 document.body.onclick = function (e){
		 	e = e || window.event;
			console.log('body');
		}
		
		// 兼容写法
		// var handler = function (e){
		// 	e = e || window.event;
		// 	if(e.stopPropagation){
		// 		e.stopPropagation();
		// 	}else{
		// 		e.cancelBubble = true
		// 	}
		// }
		</script>
	</body>
</html>

事件流阶段属性 eventPhase

事件流三个阶段捕获 目标 冒泡

只截图了一个
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button id="btn">事件流</button>
		<script>
			var btn=document.getElementById('btn');
			// e.eventPhase 0 表示事件没有发生 1表示捕获阶段 2目标阶段 3冒泡阶段
			// 0阶段无法演示
			
			// 这是2阶段 目标
			// btn.onclick = function(e){
			// 	e = e || window.event;
			// 	this.innerHTML = e.eventPhase +'阶段';
			// }
			
			// 这是1阶段 捕获
			// document.body.addEventListener('click',function(e){
			// 	e = e || window.event;
			// 	this.innerHTML = e.eventPhase +'阶段';
			// },true)
			
			// 这是3阶段 冒泡
			document.body.addEventListener('click',function(e){
				e = e || window.event;
				this.innerHTML = e.eventPhase +'阶段';
				// console.log(e.eventPhase);
			})
		</script>
	</body>
</html>

 取消默认事件

阻止a标签的跳转

  方法一:<a href="javascript:void(0);">11</a>      就是网页地址后面不会加上一个#号

  方法二:<a href="javascript:;">11</a>

阻止默认事件 

preventDefault()    ie8不支持

retuenValue 值为false,禁止跳转  ie8以上不支持

return false 这个好像后面的语句无法执行

两个效果图一样

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<a href="#" id="ad">11</a>
		<script>
			var ad=document.getElementById('ad');
			ad.onclick=function(e){
				e = e  || window.event;
				// e.preventDefault();
				// e.returnValue = false;
				// return false;
				this.innerHTML=22;
			}
			
			//兼容性写法
			// if(e.preventDefault){
			// 	e.preventDefault();
			// }else{
			// 	e.returnValue = false;
			// }
		</script>
	</body>
</html>

 事件对象中的坐标位置

动画效果用的多,如果想要区分他们,建议去学习练习动画

X/Y  相对于浏览器的x轴和Y轴的距离

clientX/clientY 相对于浏览器的x轴和Y轴的距离

offsetX/offsetY  相对于事件源的x轴和y轴距离,没懂事件源是什么

screenX/screenY  想对于显示器屏幕的x轴和y轴的距离

pageX/pageY 想对于页面的x轴和y轴的距离,y轴与滚动条有关系

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div{
				margin: 0;
				padding: 0;
				width:300px;
				height: 100px;
				background-color: pink;
			}
		</style>
	</head>
	<body>
		<div id="box" style="height:1000px"></div>
		<script>
			var box=document.getElementById('box');
			box.onmousemove=function(e){
				e = e || window.event;
				// this.innerHTML=`clientX:${e.clientX},clientY:${e.clientY};X:${e.x},Y:${e.y}`
				
				// this.innerHTML=`screenX:${e.screenX},screenY:${e.screenY};X:${e.x},Y:${e.y}`
				
				// this.innerHTML=`pageX:${e.pageX},pageY:${e.pageY};X:${e.x},Y:${e.y}`
				
				this.innerHTML=`offsetX:${e.offsetX},offsetY:${e.offsetY};X:${e.x},Y:${e.y}`
			}
		</script>
	</body>
</html>

 案例:放大镜

别人是两张图,图片内容一样,但大小不同。

我找不到类似的图,就用一张图代替了。

然后遮罩图别人是透明的,我也找不到,就随便弄了一张。

我感觉放大镜案例对于我来说过于复杂了,我应该找个简单的弄明白offsetWidth与offsetHight的关系还有移动距离算法

可能是因为我图的原因

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			*{
				padding:0;
				margin: 0;
			}
			#box{
				width:430px;
				height:430px;
				border:1px solid #DDDDDD;
				position: relative;
				margin: 50PX;	
			}
			#small_box{
				width:430px;
				height:430px;
				position: relative;
			}
			#small_box #mask{
				position: absolute;
				width:210px;
				height:210px;
				background: url(img/1.jpeg) no-repeat;
				top:0;
				left:0;
				display: none;
			}
			#big_box{
				position: absolute;
				left:440px;
				top:0;
				width:430px;
				height:430px;
				border:1px solid #ddd;
				overflow: hidden;
			}
			#big_box img{
				position:absolute;
				z-index:5;
			}
		</style>
	</head>
	<body>
		<div id="box">
			<div id="small_box">
				<img src="img/11.jpeg" alt="" width='430px' height="430px">
				<span id="mask">
					
				</span>
			</div>
			<div id="big_box">
				<img src="img/11.jpeg">
			</div>
		</div>
		<script>
			window.onload = function(){
				// 1.获取需要的标签
				var box =document.getElementById('box');
				var small_box=box.children[0];
				var big_box=box.children[1];
				var small_img=small_box.children[0];
				var mask=small_box.children[1];
				var big_img = big_box.children[0];
				
				//监听鼠标移入
				small_box.onmouseover=function(){
					// 2.1让遮罩和大盒子显示出来
					mask.style.display="block";
					big_box.style.display='block';
					// 2.2监听鼠标移动
					small_box.onmouseout=function(e){
						e = e || window.event;
						
						// 2.3求出小盒子移动的水平和垂直距离
						var moveX=e.clientX-small_box.offsetLeft-box.offsetLeft-mask.offsetWidth*0.5;
						var moveY=e.clientY-small_box.offsetTop-box.offsetTop-mask.offsetHeight*0.5;
						
						// 2.4边界处理,让小方块在大div内
						if(moveX<0){
							moveX = 0;
						}else if(moveX>=small_box.offsetWidth - mask.offsetWidth){
					   moveX = 	small_box.offsetWidth-mask.offsetWidth;	
						}
						
						if(moveY<0){
							moveY = 0;
					}else if(moveY>=small_box.offsetHeight - mask.offsetHeight){
						moveY =small_box.offsetHeight-mask.offsetHeight;	
				}
						// 2.5让小盒子移动起来
						mask.style.left = moveX+'px';
						mask.style.top = moveY+'px';
						
						// 2.6让大图移动起来
						// 公式 moveX/大图移动的距离??=(small_box宽度-mask宽度)/(big_img宽度-big_box宽度)
						var x=moveX/(small_box.offsetWidth - mask.offsetWidth);
						var y=moveY/(big_img.offsetWidth - big_box.offsetWidth);
						big_img.style.left= - x * (big_img.offsetWidth - big_box.offsetWidth) + 'px';
						big_img.style.top= - y * (big_img.offsetHeight - big_box.offsetHeight) + 'px';
					}
				}
				
				// 监听鼠标移出
				small_box.onmouseout = function(){
					mask.style.display = 'none';
					big_box.style.display='none';
				}
			}
		</script>
	</body>
</html>

推荐看 

JavaScript从入门到放弃 第6章 JS事件_哔哩哔哩_bilibili

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值