JavaScript中的dom编程

◆DOM编程

1.

为什么要学习DOM编程


通过这种交互操作,可以编写各种网页游戏,乌龟抓鸡,贪吃蛇,推箱子,坦克大战。


2.dom编程,也是学习ajax技术的基础,所以要掌握好dom编程


◆dom编程简介

DOM=Document Object Model(文档对象模型)【可以理解为把html文档当作对象来进行编程的模型】



关系图:



DOM编程,把html文件看作一颗DOM树,按照元素依次列下去,如下图:


再把这些元素当作对象,把他们当作对象之后,就可以对这些元素进行动态的控制,增加减少,修改删除都可以了。


◆bom

bom  (browser object model)浏览器对象模型

因为做浏览器的厂家很多,w3c定义了一个做浏览器的规范,规定:



◆dom对象介绍



◆window对象


1.confirm

案例:

window.confirm("确定要删除吗?");

function test(){
var res=window.confirm("确定要删除吗?");
if(res){
window.alert("删除");
}else {
window.alert("放弃删除");
}
}

</script>
</head>
<body>

<input type="button" value="删除记录" οnclick="test()"/>



2.setInterval()

按照指定的周期(以毫秒计)来循环调用函数或计算表达式

案例1:简单的时钟

function showTime(){
//document.writeln(new Date());
//在元素间的文本就是通过    对象.innerText
document.getElementById("mytime").innerText=new Date().toLocaleString();
}
setInterval("showTime()",1000);

</script>
</head>
<body>

<span id="mytime"></span>


案例2:

图片滚动播放,可以通过这个做简单的动画效果

代码:

var n=1;
function  run(){
//得到img对象
var myimg=document.getElementById("myimg");
//这里通过((n++%2)+1)的算法得到1,2,1,2循环的数,得意让图片按照文件名的顺序进行播放
//故而,想要得到从1到m循环的整数,可以用算法((n++%2)+1)来实现,要注意这里的循环是从2开始的。如,若m是4,则为:23412341234.....
myimg.src=((n++%2)+1)+".jpg";
}
setInterval("run()",800);


</script>
</head>
<body>
<!--此案例为轮流播放两张图片,两张图片的命名分别为:1.jpg和2.jpg-->
<img src="1.jpg"  id="myimg"/>
</body>
</html>


3.clearInterval()  

取消setInterval()的周期性执行,需要setInterval()返回的id做参数


案例:让上边的图片播放几次后停下来:

var n=1;
var count=0;


function  run(){


count++;
if(count==11){
//停止定时器
clearInterval(myTimer);
}
//得到img对象
var myimg=document.getElementById("myimg");
//这里通过((n++%2)+1)的算法得到1,2,1,2循环的数,得意让图片按照文件名的顺序进行播放
//故而,想要得到从1到m循环的整数,可以用算法((n++%2)+1)来实现,要注意这里的循环是从2开始的。如,若m是4,则为:23412341234.....
myimg.src=((n++%2)+1)+".jpg";
}
var myTimer=setInterval("run()",800);


</script>
</head>
<body>
<!--此案例为轮流播放两张图片,两张图片的命名分别为:1.jpg和2.jpg-->
<img src="1.jpg"  id="myimg"/>
</body>
</html>


4.setTimeout()

在指定的毫秒数后调用函数或表达式(只调用一次)


案例:在打开页面 5 秒后,弹出hello

//5秒后调用sayHello
function sayHello(){
window.alert("Hello");
}

setTimeout("sayHello()",5000);


5.clearTimeout();

取消setTimeout设置的timeout

案例:3秒后显示abc,加上clearTimeout之后取消

function test(){
window.alert("abc");
}
var mytimer=setTimeout("test()",3000);
clearTimeout(mytimer);//取消timeout



6.moveTo();//以屏幕左上角为原点,把窗口的左上角移动到指定的坐标

   moveBy();//以当前窗口的左上角为原点,把窗口的左上角移动到指定的坐标


案例:

//用IE可以,360不行,兼容模式也不行
function test2(){
window.moveTo(50,50);
}

</script>
</head>
<body>
我是一个窗口
<input type="button" οnclick="test2()" value="移动"/>
</body>
</html>


7.resizeTo();//把窗口调整到 400,300

   resizeBy();   //把窗口在现有的基础上再增大400,300 

//用IE可以,360不行,兼容模式也不行
function test2(){
window.resizeTo(400,300);
//window.resizeBy(400,300);
}

</script>
</head>
<body>
我是一个窗口
<input type="button" οnclick="test2()" value="改变大小"/>
</body>
</html>


8.open()    开一个新的窗口   

注意:这里的open执行完毕之后会返回一个具体的值,返回一直指向子窗口的变量

这里的open有很多的特征值,可以用来设置打开的新窗口的各种属性,在手册里边有

手册的HTML DOM Window 对象参考手册,open用法这里

案例:

function test2(){
window.open("newwindow.html","_blank","width=50,height=50","location=no","menubar=no","status=no","titlebar=no","toolbar=0");
}


</script>
</head>
<body>
我是一个窗口
<input type="button" οnclick="test2()" value="打开新窗口"/>


9.opener()

综合案例:父窗口和子窗口通信(有点难)

父窗口代码:

<html>
<head>
<script language="javascript" type="text/javascript">

var newwindow;
function test2(){
//newwindow 其实就是指向子窗口引用
newwindow=window.open("newwindow.html","_blank");


}
function test3(){
newwindow.document.getElementById("info").value=document.getElementById("info2").value

}
function $(id){
return document.getElementById(id);
}




</script>
</head>
<body>
我是一个窗口
<input type="button" οnclick="test2()" value="打开新窗口"/>
<span id="myspan"></span>
<input type="text" id="info2"/><input type="button" value="发给子窗口"οnclick="test3()"/>
</body>
</html>


子窗口代码:

<script language="javascript" type="text/javascript">
function notify(){
var val=document.getElementById("info").value;
//window.alert(val);
opener.document.getElementById("myspan").innerText=val;
}


</script>
我是新窗口
<input type="text" id="info"/><input type="button" value="发给父窗口"οnclick="notify()"/>


◆综合案例:

简单的登录系统:

1.登陆界面(login.html)代码:

<script language="javascript">

function checkuser(){
if($("uname").value=="creabine"&&$("pwd").value=="123"){
window.alert("ok");
return true;
}else{
window.alert("用户名或密码错误");
$("uname").value="";
$("pwd").value="";//这里是说,若用户名密码错误,自动把输入框清空
return false;
}
}

function $(id){
return document.getElementById(id);
}

</script>

<form action="loginsuccess.html">
user:<input type="text" id="uname"/><br/>
password:<input type="password" id="pwd"/><br/>
<!--下边的onclick后边要加上return。如果不加,表示按键之后执行checkuser()函数,然后提交按钮,这样的话无论你输入什么,都会提交进入下一个页面,就起不到检查用户名密码的目的了。加了之后,表示按键之后查看的是checkuser()函数的返回值,那么当这个函数检查用户名密码错误的时候,就会返回false,此时submit就不会提交,也就不会跳转登录了。-->
<input type="submit" οnclick="return checkuser();" value="登录">


2.登录成功跳转(loginsuccess.html)页面代码:

<script language="javascript">

function tiao(){
clearInterval(mytime);//这里在跳转前把mytime这个定时器关了,以免跳转之后它还在不停的运行,浪费空间。
window.open("afterloginsuccess.html","_self");
//window.alert("tiao le ");测试是否执行这个函数用的
}
setTimeout("tiao()",5000);
function changeSec(){
//得到myspan的值
$("myspan").innerText=parseInt($("myspan").innerText)-1;
}

var mytime=setInterval("changeSec()",1000);

function $(id){
return document.getElementById(id);
}
</script>

登陆成功<p/>

将在<span id="myspan">5</span>秒后自动跳转到管理页面


3.登陆成功之后跳转(afterloginsuccess.html)到的页面代码

管理页面


跳转成功


10.status();

设置窗口状态栏的文本,就是网页最下边的窗口,自己试试


综合练习题:





◆History对象

作用:该对象包含客户端访问过的URL信息,就是返回原来访问过的某个页面

1.back()  加载历史列表中上一个访问过的URL

 2. go()   加载历史列表中的某一个具体的页面

   其实   back()   等价于   go(-1)

3.length()  返回历史列表中URL的数量

4.forward()   加载历史列表中的下一个URL  

调用该方法等价于点击前进按钮,或调用  history.go(1)(这里注意,是曾经访问过,然后跳回来,才能forward,不然浏览器哪里知道你未来会浏览什么页面)


代码:

history1.html:

<a href="history2.html">goto 2</a>

history2.html:

<script language="javascript">

function goback(){
window.alert(history.length);//返回历史浏览列表的数量,即1,因为从1到2,2前边一共就1个
history.back();
}

</script>

<a href="#" οnclick="goback();">返回上级页面</a>


◆location对象

location包含客户端当前的URL信息(相当于就是网址)

案例:

<html>
<head>
<script language="javascript" type="text/javascript">

function test(){
location.reload();//刷新
window.alert(location.href);//显示当前完整的URL
window.alert(location.hostname);//显示当前URL的主机名,因为练习没上网所以显示空
window.alert(location.port);//返回当前URL的端口号,返回空
window.alert(location.protocol);//显示当前URL的协议,因为是本地文件所以返回了file:
}


</script>
</head>
<body>
<input type="button" value="刷新页面" οnclick="test()">
fsdjkgjklsdjgk<br/>

</body>
</html>


◆navigator对象

navigator对象包含有关浏览器的信息


案例:

<html>
<head>
<script language="javascript" type="text/javascript">

document.write("<p>Name:"+navigator.appName+"</p>");//返回当前浏览器的名称
document.write(navigator.platform+"</p>");//返回当前操作系统
document.write(navigator.systemLanguage+"</p>");//返回操作系用的默认语言

</script>
</head>
<body>
</body>
</html>


◆screen对象

该对象包含有关客户机显示屏幕的信息,比如当前显示器的分辨率

用该对象的各种属性,可以返回当前屏幕的信息

案例:

<html>
<head>
<script language="javascript" type="text/javascript">

document.write(screen.width+" "+screen.height+"<br/>");//显示当前屏幕分辨率
document.write(screen.availWidth+" "+screen.availHeight);//显示可用的屏幕高度和宽度(排除windows任务栏)

</script>
</head>
<body>
</body>
</html>


◆event对象

该对象代表事件的状态,比如事件在其中发生的元素,键盘按键的状态,鼠标的位置,鼠标按钮的状态,事件通常与函数结合使用。

在事件驱动变成里讲过了。


如何绑定事件监听:

(1)直接和某个html控件绑定,比如:

<input type="button" value="刷新页面" οnclick="test()"/>

(2)通过getElementById()获取到元素后再绑定监听

案例:

<html>
<head>
<script language="javascript" type="text/javascript">


function test(){
document.write("hello");
}


</script>
</head>
<body>
<input type="button" id="but1" value="刷新界面" />
<script language="javascript" type="text/javascript">


document.getElementById("but1").οnclick=test;//绑定事件监听,注意test后边不要(),如果加了(),那就是调用test函数了。


</script>
</body>
</html>


(3)如果我们有一个投票系统,只能投一次票,按键只能按一次。


下边我们使用IE中独有的监听方法,做了案例,如果其他浏览器可以用上边的W3C标准方法。

使用:attachEvent("onclick",test);  和  detachEvent("onclick",test);

案例:

<html>
<head>
<script language="javascript" type="text/javascript">


function test(){
window.alert("投票成功");
//为了只能投票一次,需要再按钮按一次之后,接触事件绑定
document.getElementById("but1").detachEvent("onclick",test);
}

</script>
</head>
<body>
<input type="button" id="but1" value="投票">
<script language="javascript" type="text/javascript">
document.getElementById("but1").attachEvent("onclick",test);//绑定事件监听,注意,为了上边的解除绑定,这里要用配对的attachEvent("onclick",test);

</script>
</body>
</html>


(4)要求一个文本框,只能输入数字,输入其他的会提示并且无法输入:

案例:

<html>
<head>
<script language="javascript" type="text/javascript">

function test(event){
//用户每按下一个键,就去判断是不是一个数
if(event.keyCode<48||event.keyCode>57){
window.alert("你输入的不是数字");
return false;
}
}
</script>
</head>
<body>
<!--οnkeyup="test(enent)"当按下一个键的时候触发test(),这里的return一定要有,没有return,则虽然会提示输入的不是数字,但还是会输入进去。有了return,表示按下的时候接受test的返回值,不是数字的时候返回false,onkeydown就不会触发,就不会输入值。-->
<input type="text" οnkeydοwn="return test(event)"/>
<input type="button" οnclick="test()" value="提交"/>

</script>
</body>
</html>


◆document对象


定义:document对象代表整个html文档,因此可以去访问到文档中的各个对象(元素)。


1.write()

向文档输出文本或者是js代码

2.writeln

向文档输出文本或者是js代码,与write不一样的地方是,writeln是换行输出。

比如:

document.write("hello");document.writeln("ok");

输出效果:

hello

ok

显示换行,但是对浏览器来说,输出效果没有区别。


3.getElementById()

(1)规定html文档中,要唯一,若不唯一,只取第一个元素。

(2)id不要用数字开头


4.getElementsByName()    注意拼写,是Elements,拼错无法使用

通过元素的名字来获取对象集合

案例:

<html>
<head>
<script language="javascript" type="text/javascript">

function test2(){
//id不可以重复,但是name可以重复
var hobbies=document.getElementByName("hobby");
//window.alert(hobbies.length);
for(var i=0;i<hobbies.length;i++){
//如何判断是否选择
if(hobbies[i].checked){
window.alert("你的爱好是"+hobbies[i].value)
}
}
}

</script>
</head>
<body>

请选择你的爱好
<input type="checkbox" name="hobby" value="足球"/>足球
<input type="checkbox" name="hobby" value="旅游"/>旅游
<input type="checkbox" name="hobby" value="游泳"/>游泳
<input type="checkbox" name="hobby" value="音乐"/>音乐

<input type="button" value="tesing" οnclick="test2()">

</body>
</html>


5.getElementsByTagName()        注意拼写,是Elements,拼错无法使用

通过标签名称来获取对象集合

案例:

<html>
<head>
<script language="javascript" type="text/javascript">


//通过标签名来获取对象(元素)
function test3(){
var myObjs=document.getElementByTagName("input");
for(var i=0;i<myObjs.length;i++){
window.alert(myObjs[i].value);
}
}

</script>
</head>
<body>

<input type="button" value="获取所有input" οnclick="test3()">
</body>
</html>


◆如何动态的创建html元素

举例说明:

动态的添加到document文档中,可以添加各种元素

还可以动态的删除已经添加的新元素,同时还可以通过添加的子元素,得到父元素

案例:

 
<html>
<head>
<script language="javascript" type="text/javascript">

function test1(){
//创建元素
var myElement=document.createElement("a");//(" ")这里边写希望创建的html元素标签名,相当于加了搞个<a></a>进去。
//也可以创建按钮
//var myElement=document.createElement("input");
//myElement.type="button";
//myElement.value="我是按键";
//给新的元素添加必要的信息,即给<a></a>填充东西
myElement.href="http://www.baidu.com";
myElement.innerText="连接到百度";
myElement.id="id1";
//myElement.style.left="200px";//可以修改添加的元素出现的位置
//myElement.style.top="300px";
//myElement.style.position="absolute";
//添加到document.body
//document.body.appendChild(myElement);
//将创建的元素添加到div里边
document.getElementById("div1").appendChild(myElement);
}

function test2(){
//删除一个元素,要删除,首先要获取这个元素的父元素,然后通过id定位该元素来删除
//这是第一种删除方法(比较不灵活)
//document.getElementById("div1").removeChild(document.getElementById("id1"));//这里是通过id找到div1,再从div1里边,删除id为id1的元素
//拓展:也可以使用.parentNode通过子节点得到父节点,下边就用子元素的id找到了父元素div1的id
//window.alert(document.getElementById("id1").parentNode.id);

//由上边的拓展,可以得到第二种删除方法,比较灵活。这样就不需要父元素的id了 
document.getElementById("id1").parentNode.removeChild(document.getElementById("id1"));

}
</script>
</head>
<body>

<input type="button" value="动态的创建一个超链接" οnclick="test1()"/>
<input type="button" value="删除一个元素,di为 id1" οnclick="test2()"/>

<div id="div1" style="width:200px;height:300px;border:1px solid red">div</div>
</body>
</html>


◆对DOM的加强

在dom编程中,一个html文档会被当作一颗dom树,dom会把所有html元素,注释,换行映射成Node节点,于是你就可以使用Node节点(对象)的属性和方法


上边这些,再补上一个属性:   parentNode


通过上边这些属性,可以得到该节点的父节点,子节点,兄弟节点等等。通过上述方法,可以添加删除节点等。


◆document的属性:


案例:

<html>
<head>
<script language="javascript" type="text/javascript">

document.fgColor="white";//前景色白色
document.bgColor="black";//背景色黑色

</script>
</head>
<body>
fdsghsd g
</body>
</html>


◆body对象的说明

1.引用body对象前,要先创建body,在head里边引用body,那时候body还没建立,所以会显示空。

2.注意,这里的appendChild()   和   removeChlid()   是所有节点共有的,body用的比较多所以放在这里了


这里有很多方法,我们用过了,所以这里我们强调innerText() 和innerHtml

案例:

<html>
<head>
<script language="javascript" type="text/javascript">

function test(){
//这里innerText后边,不论加什么,都会当作普通文本
//document.getElementById("myspan").innerText="<a href='http://www.baidu.com'>到百度</a>";
//使用innerHtml,就会当作Html文本,这里就会输出超链接了
document.getElementById("myspan").innerHTML="<a href='http://www.baidu.com'>到百度</a>";
}

</script>
</head>
<body>
<span id="myspan"></span>
<input type="button" οnclick="test()" value="测试"/>
</body>
</html>


body的事件:


用法:

<body οnscrοll="return window_onscroll()" onselectstart="return false">


综合案例:弹来弹去的小太阳

代码:

<html>
<head>
<title>小太阳</title>
</head>
<body style="background-image:url(beijing.jpg)">
<script language="javascript" type="text/javascript">
//定义全局变量
directX=1;//x轴的方向初始化为1
directY=1;//y轴的方向初始化为1
sunX=0;//小太阳的x坐标
sunY=0;//小太阳的y坐标
speed=2;//加入速度变量,改变就可以改变速度
function sunMove(){
sunX+=directX*speed;
sunY+=directY*speed;
//修改div的left   top
sundiv.style.top=sunY+"px";
sundiv.style.left=sunX+"px";
//判断什么时候转变方向
//x方向   offsetWidth可以返回当前对象的实际宽度body.clientWidth显示当前的body宽度
//下边是说,如果  小太阳的右边界遇到body宽度,即遇到最右边  ||   小太阳左边坐标为0,即遇到最左边,那么X轴开始反向移动
if(sunX+sundiv.offsetWidth>=document.body.clientWidth||sunX<=0){
directX=-directX;
}
//同理,纵向
if(sunY+sundiv.offsetHeight>=document.body.clientHeight||sunY<=0){
directY=-directY;
}

}
setInterval("sunMove()",5);
</script>

<div id="sundiv" style="position:absolute">
<img src="sun.png"/>
</div>
</body>
</html>


◆style对象


坦克转向:

讲解背景的样式:

思路一:

做一个坦克的四个方向,然后当转向的时候,换图片,就跟之前的图片轮流显示类似。

这种思路的话,每次转向,都会向服务器发送请求加载新的图片,不划算


思路二:

一次加载一个背景图,通过显示该背景图片的不同部分,实现转向的效果

思路二代码:

<html>
<head>
<script language="javascript" type="text/javascript">


function change(obj){
if(obj.value=="上"){
tank.style.backgroundPositionY="0px";//这种时候,不能background-position-Y写了,禁用了下划线,要如代码中这样写
}else if(obj.value=="左"){
tank.style.backgroundPositionY="196px";
}else if(obj.value=="下"){
tank.style.backgroundPositionY="392px";
}else if(obj.value=="右"){
tank.style.backgroundPositionY="588px";
}
}


</script>
</head>
<body>
<!--注意看下边的解释-->
<div id="tank" style="background-position-Y:0px;background-image:url('tanksucai.png');width:217px; height:196px;"></div><br/>


<input type="button" value="上" οnclick="change(this)"/>
<input type="button" value="右" οnclick="change(this)"/>
<input type="button" value="下" οnclick="change(this)"/>
<input type="button" value="左" οnclick="change(this)"/>
</body>
</html>


解释:div中的图片tanksucai.png,如下图:


是由四个方向的坦克所组成的一个图片,将这个图片,作为div的背景图片,即background-image:url('tanksucai.png'),这时候,其实可以看作div里边不只插入了一个背景图片,而是无数多个排列的背景图,其他的默认暂时没有显示。此时,我们设置div的大小,让其刚好只能显示一个图片的其中一个坦克,再使用background-position-Y:0px,也就是显示这个图片最上边的坦克,即方向向上的。接下来,通过函数,改变background-position-Y的值,就可以显示图片四个坦克其中的一个,这里需要特别注意的是他的坐标:默认div左上角跟背景图片的左上角重合,且为坐标原点,程序中默认设置为0px,即默认显示向上的坦克。Y向下为正,向上为负。此时我们如程序所写的,tank.style.backgroundPositionY="196px";也就是将图片向下移动一个坦克的高度,这时候,会显示这张图片上的另一张4坦克背景图的最下边的坦克。相当于默认显示的图片向下移之后,在它上边的图片,跟着掉下来了。




接下来,再做一个开坦克的案例,即可以转向和移动,以后还可以扩展到打子弹:

代码:

<html>
<head>
<title>开坦克</title>
</head>
<!--这里的οnkeydοwn="dosomething"表示按下键的时候干嘛,以后可以扩展,不一定按键仅仅是移动,还可以发射子弹等-->
<body οnkeydοwn="dosomething(event)">

<div id="filed" style="background-color:black;width:1000px;height:1000px;position:absolute">

<div id="mytank" style="background-position-Y:0px;background-image:url('tanksucai.png');width:217px; height:196px;position:absolute"></div><br/>

</div>

<script language="javascript" type="text/javascript">
//用面向对象的方法开发web版本的坦克大战1.0(可以通过swad键来控制坦克的走向)
function MyTank(x,y,direct){
this.x=x;//坦克横坐标
this.y=y;//坦克纵坐标
this.direct=direct;//方向
this.speed=10;//速度
//初始化,即创建坦克的时候,把坦克图片的坐标放在要求的x,y坐标上,默认坦克头朝上
mytank.style.left=this.x+"px";
mytank.style.top=this.y+"px";
mytank.style.backgroundPositionY="0px";

this.move=function move(event){//这里的event表示按键事件

switch (event.keyCode){//keyCode表示按下键盘的ASCII码是多少
//a表示向左,即x坐标减小   3标记方向
case 65://通过ASCII码表查到a的十进制码是65,即表示键盘按a
mytank.style.backgroundPositionY="196px";
this.x-=this.speed;
this.direct=3;//这里的direct是为了以后如果tank要发射子弹,才知道要在哪个方向创建子弹元素
break;
//s表示向下   2标记方向
case 83://即S码为83
mytank.style.backgroundPositionY="392px";
this.y+=this.speed;
this.direct=2;
break;
//d表示向右   1标记方向
case 68://即d为68
mytank.style.backgroundPositionY="588px";
this.x+=this.speed;
this.direct=1;
break;
//w表示向上   0标记方向
case 87://即w为87
mytank.style.backgroundPositionY="0px";
this.y-=this.speed;
this.direct=0;
break;
}
//上边通过按键改变了坦克对象的坐标xy,改变之后要把这个xy传给坦克图片,并改变图片的方向
mytank.style.left=this.x+"px";
mytank.style.top=this.y+"px";

}
}

//判断用户希望干什么
function dosomething(event){
if(event.keyCode==65||event.keyCode==68||event.keyCode==83||event.keyCode==87){//这里判断,如果按下的键是swad的话
hero.move(event);//调用移动函数
}
//以后扩展的话,可以在这里判断,若按下的是开火键,则调用开火函数。
}

//创建坦克
var hero=new MyTank(200,200,0);

</script>
</body>
</html>












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值