Ajax 入门例子总结

本节内容来自沈泽刚等Java web 编程技术一书的十五章。

一、XMLHttpRequest对象

1.创建对象。

function createXMLHttpRequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}

2.常用的XMLHttpRequest对象的属性和方法

onreadystatechange :为异步请求设置事件处理程序来响应。当请求的状态改变时都会触发这个事件处理器,通常会调用一个javaScript函数,称为回调函数。

readyState:该属性表述请求的状态。0表示未初始化,1表示正在加载,2表示已加载,3表示交互中,4表示完成。

responseText:检索服务器响应,表示为文本。

responseXML:检索服务器响应,表示为XML

status:服务器的HTTP状态。

open(string method, string url, boolean asych):指定使用的HTTP方法和请求的资源(服务器的URL,可以是动态资源或者是静态资源),确定这个调用时异步还是同步。将 readyState属性设置1,正在加载。这样就打开了HTTP请求。

send(data):向服务器发送请求,并检索响应。此 方法的返回值根据open()方法的asych参数是同步或异步有所不同。同步的话,只有在接收到全部响应之后才返回,异步的话立即返回。调用此方法后 readyState属性设置为2,已加载,当请求完成时,该属性设置为4.

3.一般的Ajax具体过程

3.1.客户触发事件。

3.2创建XMLHttpRequest对象

3.3向服务器发出请求

3.4服务器处理请求并返回响应

3.5通过回调函数处理结果

3.6更新HTML DOM对象

4.几个例子

4.1 使用XMLHttpRequest对象的responseText属性,显示静态文本的内容。

a)写xml文件。(simpleResponse.xml)

<?xml version = "1.0" encoding = "utf-8" standalone ="no"?>
<greetings>
<haha>aha!</haha>
<hello>world !</hello> 
</greetings>

b)写表单


<form action="#">
<input type = "button" value = "started asynchronuos " onclick = "startRequest();">
</form>

c)处理单击事件

createXMLHttpRequest();//生成XMLHttpRequest对象
//alert("start sure?  " );
xmlHttp.onreadystatechange = handleStateChange;//写回调函数处理请求的状态改变时的响应事件。
//alert("end start sure?  " );
xmlHttp.open("GET", "simpleResponse.xml", true);
xmlHttp.send(null);
}

function handleStateChange(){
//alert("hand start sure?  " );
if(xmlHttp.readyState == 4){
//alert(xmlHttp.status);
if(xmlHttp.status == 200){
alert("server returned with:  " + xmlHttp.responseText);
}
}
}

4.2使用XMLHttpRequest对象的responseText属性和HTML元素的innerHTML属性,创建动态内容。

a)写xml文件。(innerHTML.xml)


<?xml version="1.0" encoding="UTF-8"?>
<xml-body>
<table border= "1">
<tr> 
<td>学号</td>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
</tr>

<tr> 
<td>20080101</td>
<td>li ming</td>
<td>male</td>
<td>21</td>
</tr>

<tr> 
<td>20080102</td>
<td>zhang ming</td>
<td>male</td>
<td>21</td>
</tr>

<tr> 
<td>20080111</td>
<td>wang ming</td>
<td>female</td>
<td>23</td>
</tr>
</table>
</xml-body>


b)写表单及动态显示内容的位置


<form >
<input type = "button" value ="search student" onclick = "startRequest();">
</form>

<div id="results"></div>

c)处理单击事件


function startRequest(){    
    createXMLHttpRequest();
    xmlHttp.onreadystatechange = handleStateChange;
    xmlHttp.open("get","innerHTML.xml",true);
    xmlHttp.send(null); 
    }
    
function handleStateChange(){
    if (xmlHttp.readyState == 4)
       if(xmlHttp.status == 200) {
      document.getElementById("results").innerHTML = xmlHttp.responseText;
    }   
}


二、DOM  文档对象类型。

用于处理XML文档的DOM元素属性和方法

childNodes:返回当前元素所有子元素的数组

firstChild:返回当前元素的第一个下级子元素

nodeValue:返回结点值

getElementById(id):返回文档中由id指定的元素

getElementsByTagName(name):返回当前元素中由指定标记名的子元素的数组 

hasChildNodes():返回一个布尔值,指示元素是否有子元素

getAttribute(name):返回指定名称的元素的属性值

用于动态常见内容的DOM属性和方法 

document.createElement(tagName):创建由tagName指定的元素

document.creatTextNode(text):创建一个包含静态文本的节点 

<element>.appendChild(childNode):将指定的节点添加到当前元素的子节点列表,作为一个新的子节点

<element>.hasChildNodes():返回一个布尔值,判断该元素是否有子元素

<element>.getAttribute(name):获得元素中name属性的值

<element>.setAttribute(name,value):设置元素中name属性的值

<element>..removeAttribute(name) 从元素中删除属性

<element>.removeChild(chileNode):从元素中删除子元素  

1.几个例子  
1.1使用XMLHttpRequest对象的responseXML属性,将结果获取为xml文档,然后使用DOM方法遍历XML文档中的元素,实现静态读取xml节点元素值。
a)写xml文件.(library.xml)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<library>
<books>

<book id ="100" >
<name>Database System Concept</name>
<author>Abraham Silberschatz</author>
<year>2006.10</year>
<price>69.50</price>
</book>

<book id ="103" >
<name>A Instruction Of Database System </name>
<author>Wang Shan</author>
<year>2006.5</year>
<price>33.80</price>
</book>

</books>

<magazines>
<magazine>
<name>Application Research Of Computers</name>
<author>chengcheng</author>
<year no ="1">2004.10</year>
<volume>21</volume>
<price>147</price>
</magazine>

</magazines>
</library>

b)写表单。


<body>
<h4>Processing XML Document of Publishing</h4>

<form action="#">
<input type ="button"  value ="search book"   onclick = "startRequest('books');"/>
<input type ="button"  value ="search magazine"   onclick = "startRequest('magazines');"/>
</form>
  </body>

c)处理单击事件


<script type="text/javascript">   
   var xmlHttp;
   var requestType ="";
   
   function createXMLHttpRequest(){
   if(window.ActiveXObject){
   xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");   
   }
   else if(window.XMLHttpRequest){
   xmlHttp = new XMLHttpRequest();
   }    
   }
   
   function startRequest(requestedList){
   requestType = requestedList;
   createXMLHttpRequest();
   xmlHttp.onreadystatechange = handlerRequest;
   xmlHttp.open("get","library.xml",true);
   xmlHttp.send(null);
   }
   
   function handlerRequest(){
   if(xmlHttp.readyState == 4){
   if(xmlHttp.status == 200){
   if(requestType == "books"){
   listBooks();//显示book标签的信息
   }
   else if(requestType == "magazines"){
   listMagazines();//显示magazines标签的信息
   }
   }   
   }     
   }
   
   function listBooks(){
   var xmlDoc = xmlHttp.responseXML;
  //alert("xml  "+xmlDoc);
   var bookNode = xmlDoc.getElementsByTagName("books")[0];
   var allBook = bookNode.getElementsByTagName("book");
   
   outputList("All Books",allBook);//输出当前books标签第一个子元素book的第一个子元素的值
   }
   
   function listMagazines(){
   var xmlDoc = xmlHttp.responseXML;
   var magazineNode = xmlDoc.getElementsByTagName("magazines")[0];
   var allMagazine = magazineNode.getElementsByTagName("magazine");
   outputList("AllMagazine",allMagazine); 
   
   }
   
   function outputList(title,items){
   var out = title;//out存放的是初始定值。
   var currentItem = null;
   for(var i = 0; i < items.length; i++){
   currentItem = items[i];
   //alert(currentItem.childNodes[0].firstChild.nodeValue)
   out = out +"\n-"+currentItem.childNodes[0].firstChild.nodeValue;
   }
   alert(out);
   }
   
   </script>


1.2使用DOM和Javascript动态的创建内容

a)写xml文件.(library.xml)


b)写表单和动态显示的表格


<body>
<h4>Search Books And Magazines</h4>
<form action="#">
<input type ="button"  value="search books"  οnclick="startSearch('books')">
<input type ="button"  value="search magazines"  οnclick="startSearch('magazines')">
</form>
<span id = "header"></span>
<table id = "resultsTable" border = "0">
<tbody id = "resultsBody">
</tbody>
</table>
 </body>


c)处理单击事件


<script type="text/javascript">
var xmlHttp ;
var requestType ="";

function createXMLHttpRequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}

function startSearch(requestedList){
requestType = requestedList;
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("get","library.xml",true);
xmlHttp.send(null);

}

function handleStateChange(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
clearResults();//清空上次生成的表格
parseResults();//生成表格
}
}

function clearResults(){
var header = document.getElementById("header");
if(header.hasChildNodes()){
header.removeChild(header.childNodes[0]);
}
var tableBody = document.getElementById("resultsBody");
while(tableBody.childNodes.length > 0){
tableBody.removeChild(tableBody.childNodes[0]);
}
}

function parseResults(){
var results = xmlHttp.responseXML;//results变量获得xml文档内容
var items = null;
var item = null;
var name ="";
var author = "";
var year= "";
var price ="";
var books = null;
var magazines = null;

if (requestType == "books"){
books = results.getElementsByTagName("books");
items = books[0].getElementsByTagName("book");
}
else if(requestType =="magazines"){
magazines = results.getElementsByTagName("magazines");
items = magazines[0].getElementsByTagName("magazine");
}

for(var i =0; i <items.length; i++){
item = items[i];
name = item.getElementsByTagName("name")[0].firstChild.nodeValue;
author = item.getElementsByTagName("author")[0].firstChild.nodeValue;
year = item.getElementsByTagName("year")[0].firstChild.nodeValue;
price = item.getElementsByTagName("price")[0].firstChild.nodeValue;
addTableRow(name,author,year,price);//创建表格中一行
}

var header = document.createElement("h4");
var headerText = document.createTextNode("Results:");
header.appendChild(headerText);
document.getElementById("header").appendChild(header);
document.getElementById("resultsTable").setAttribute("border","1");
}

function addTableRow(name,author,year,price){
var row = document.createElement("tr");
var cell = createCellWithText(name);//创建表格中一列
row.appendChild(cell);
var cell = createCellWithText(author);
row.appendChild(cell);
var cell = createCellWithText(year);
row.appendChild(cell);
var cell = createCellWithText(price);
row.appendChild(cell);
document.getElementById("resultsBody").appendChild(row);
}

function createCellWithText(text){
var cell = document.createElement("td");
var textNode = document.createTextNode(text);
cell.appendChild(textNode);
return cell;
}

</script>


三、几个应用例子

1.实现表单数据验证

1.1写表单


<body>
<h4>Ajax 数据验证示例</h4>
用户名:<input type= "text" size = "10" id= "username">
<input type = "button" value ="检测" onclick ="validate();">
<div id = "results"></div>
</body>


1.2编写服务器端的代码。(ValidationServlet.java,自动生成web,xml相关的配置)


public class ValidationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
resp.setContentType("text/xml");//由于XMLHttpRequest对象只能处理text/html类型的结果,请求的是动态资源,必须将Content-type响应头设置为text/html。
resp.setHeader("Cache-Control", "no-cache");//避免浏览器再本地缓存结果

String username= req.getParameter("username");
//System.out.println(username);
String  message = "The name has not been used";
PrintWriter out = resp.getWriter();
if(username.equals("hacker")){
    message ="The name has been used";
}
out.println("<response>");//生成response标签
out.println("<message>"+message+"</message>");//生成message元素
out.println("</response>");
}
}


1.3处理单击事件


function validate(){
createXMLHttpRequest();
var username = document.getElementById("username");
//alert(username.value);
var url ="ValidationServlet?username="+ escape(username.value);//请求的是动态资源(servlet)
//alert(url);
xmlHttp.open("get",url,true);
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.send(null);

}

function handleStateChange(){
if(xmlHttp.readyState == 4 && xmlHttp.status ==200){
var message = xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;
var messageArea = document.getElementById("results");
messageArea.innerHTML ="<h4>" + message +"</h4>";
}
}

2.动态加载列表框

2.1.写表单


<body>
<h4>请选择着入学年份和班级</h4>
<form action="#">
入学年份:
<select id = "syear" onchange ="refreshNameList();">
<option value= "">请选择</option>
<option value ="2008">2008</option>
<option value = "2009">2009</option>
</select>

班级:
<select id = "sclass" onchange ="refreshNameList();">
<option value = "">请选择</option>
<option value ="class1">一班</option>
<option value ="class2">二班</option>
</select>

<br/><br/>
姓名:
<br/>
<select id ="snames" size ="6" style ="width:270px;"></select>

</form>
</body>



2.2编写服务器端的代码。(refreshNameServlet .java)


public class refreshNameServlet extends HttpServlet {
    
    private static class Student{
        private int syear;
        private String sclass;
        private String sname;
        
        public Student(int syear, String sclass,String sname){
            this.syear=syear;
            this.sclass=sclass;
            this.sname=sname;       
        }
        }
     
private static  List<Student> student = new ArrayList<Student>();

@Override
public void init() throws ServletException {//此处姓名如果写成中文就乱码。没有解决,tbc
student.add(new Student(2008,"class1","jerry"));
student.add(new Student(2008,"class1","peter"));
student.add(new Student(2008,"class1","tomcat"));
student.add(new Student(2008,"class1","ketty"));
student.add(new Student(2008,"class1","too"));
student.add(new Student(2008,"class2","wuet"));
student.add(new Student(2008,"class2","wute"));
student.add(new Student(2008,"class2","atat"));
student.add(new Student(2008,"class2","luews"));
student.add(new Student(2008,"class2","Htnry Jordon"));
student.add(new Student(2008,"class2","karta"));
student.add(new Student(2008,"class1","LuSmitn"));
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
processRequest(req,resp);
}

protected void processRequest(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException,IOException {
    int syear =Integer.parseInt(req.getParameter("syear"));
    String sclass = req.getParameter("sclass");
    
    StringBuffer results = new StringBuffer("<snames>");//生成snames标签
    Student stud = null;

for(Iterator it = student.iterator();it.hasNext();){
    stud =(Student)it.next();
    if(syear == stud.syear){
        if(stud.sclass.equals(sclass)){//生成sname标签,不断追加sname值
            results.append("<sname>");
            results.append(stud.sname);
            results.append("</sname>");
        }       
    }   
}
results.append("</snames>");

resp.setContentType ("text/xml");
resp.getWriter().println(results.toString());

}
}
}


web.xml配置servlet如下:


<servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>refreshNameServlet</servlet-name>
    <servlet-class>com.smg.domain.refreshNameServlet</servlet-class>
  </servlet>
<servlet-mapping>
    <servlet-name>refreshNameServlet</servlet-name>
    <url-pattern>/go</url-pattern>
  </servlet-mapping>



2.3.处理单击事件

<script type="text/javascript">
   var xmlHttp;
   function createXMLHttpRequest(){
   if(window.ActiveXObject){
   xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
   }
   else if(window.XMLHttpRequest){
   xmlHttp = new XMLHttpRequest();   
   }   
   }
   
   function  refreshNameList(){
   var syear = document.getElementById("syear").value;
   var sclass = document.getElementById("sclass").value;
   
   if(sclass =="" || syear == ""){//如果没有选班级或者入学年份,下拉列表清空
   clearNameList();//清空下拉列表
   return;   
   } 
   
   var url = "go?"+createQueryString(sclass,syear) + "&ts=" + new Date().getTime();
  // alert(url);
   createXMLHttpRequest();
   xmlHttp.open("get",url,true);
   xmlHttp.onreadystatechange = handleStateChange;
   xmlHttp.send(null);
   }
   
   function createQueryString(sclass,syear){//返回请求资源键值对
   var queryString = "sclass="+sclass +"&syear="+syear;
   return queryString;
   }
   
   function handleStateChange(){
  if(xmlHttp.readyState == 4 && xmlHttp.status ==200){
   updateNameList(); //匹配入学年份和班级相同的学生的姓名,并显示出来。 
   }
   }
   
   function updateNameList(){
   clearNameList();
   var snames = document.getElementById("snames");
   var results = xmlHttp.responseXML.getElementsByTagName("sname");
   var option = null;
   for(var i = 0; i < results.length; i++){
   option = document.createElement("option");
   option.appendChild(document.createTextNode(results[i].firstChild.nodeValue));
   snames.appendChild(option);
   }
   }
   
   function clearNameList(){
   var snames = document.getElementById("snames");
   while(snames.childNodes.length > 0){
   snames.removeChild(snames.childNodes[0]);
   }
   }
   
   </script>


3.动态更新web页面

3.1 写表单


<body>
<h3>请输入客户信息</h3>
<form action="#">
<table border ="0">
<tr>
<td>客户名:</td>
<td><input type="text" id ="custName"></td>
</tr>
<tr>
<td>Email地址:</td>
<td><input type="text" id ="email"></td>
</tr>
<tr>
<td>电话:</td>
<td><input type="text" id ="phone"></td>
</tr>
<tr><td><input type ="button" value="添加" οnclick="addCustomer();"></td></tr>
</table>
</form>

<span id = "customerListSpan" stytle ="display:none;">
<h3>客户信息如下:</h3>
<table border ="1">
<tbody id ="customerList">
</tbody>
</table>
</span>
  </body>


3.2编写服务器端的代码。(CustomerServlet.java,自动生成web,xml相关的配置



public class CustomerServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

String action = req.getParameter("action");
if(action.equals("add")){
    addCustomer(req,resp);
}
else if(action.equals("delete")){
    deleteCustomer(req,resp);
}
}

protected void addCustomer(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

String uniqueID = storeCustomer();
StringBuffer xml = new StringBuffer("<result><uniqueID>");//生成result和uniqueID标签。创建响应XML
xml.append(uniqueID);
xml.append("</uniqueID>");
xml.append("<status>1</status>");//生成status标签 值设为1,恰好与请求状态为正加载的吻合
xml.append("</result>");
sendResponse(resp,xml.toString());//向浏览器发送响应

}
private String storeCustomer() {
String uniqueID = "";
Random randomizer = new Random(System.currentTimeMillis());//通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
for(int i = 0; i <8;i++){
    uniqueID += randomizer.nextInt(9);//通过Random对象获取获取[0, 9)之间的int整数
}
return uniqueID;//获取8位不重复随机数,作为uniqueID。http://www.cnblogs.com/skywang12345/p/3341423.html
}

private void sendResponse(HttpServletResponse resp, String responseText) throws IOException {
resp.setContentType("text/xml");
resp.getWriter().println(responseText);
}

protected void deleteCustomer(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
String id =req.getParameter("id");
StringBuffer xml = new StringBuffer("<result>");//生成result标签
xml.append("<status>1</status>");//生成status标签 值设为1,恰好与请求状态为正加载的吻合
xml.append("</result>");
sendResponse(resp,xml.toString());

}
}


3.3处理单击事件



<script type="text/javascript">
var xmlHttp;
var custName;
var email;
var phone;
var deleteID;
var PREFIX="cust-";

function createXMLHttpRequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}

function addCustomer(){
custName = document.getElementById("custName").value;
email = document.getElementById("email").value;
phone = document.getElementById("phone").value;
action = "add";
if(custName == "" || email == "" || phone == ""){//如果输入的客户信息为空,不操作
return;
}

var url ="CustomerServlet?" + createAddQueryString(custName,email,phone,action)+"&ts="+new Date().getTime();

createXMLHttpRequest();
xmlHttp.onreadystatechange = handleAddStateChange;//添加按钮的回调函数
xmlHttp.open("get",url,true);
xmlHttp.send(null);
}

function createAddQueryString(custName,email,phone,action){//返回请求资源键值对
var queryString = "custName=" +custName+"&email="+email+"&phone="+phone+"&action="+action;
return queryString;
}


function handleAddStateChange(){
if (xmlHttp.readyState == 4)
    if(xmlHttp.status == 200) {
    updateCustomerList();//添加客户信息到下拉列表
    clearInputBoxes();//添加完客户信息到列表之后,清空之前输入的客户信息
    }   
    else {
    alert("添加客户错误!");
    }
}

function  updateCustomerList(){
var responseXML = xmlHttp.responseXML;
var status = responseXML.getElementsByTagName("status")[0].firstChild.nodeValue;
status = parseInt(status); 
if(status != 1){//表示响应的xml还没有成功生成。
return;
}

var row = document.createElement("tr");//创建列表中的行
var uniqueID = responseXML.getElementsByTagName("uniqueID")[0].firstChild.nodeValue;

row.setAttribute("id", PREFIX+uniqueID);

row.appendChild(createCellWithText(custName));//追加行中的值
row.appendChild(createCellWithText(email));
row.appendChild(createCellWithText(phone));

var deleteButton = document.createElement("input");//创建删除按钮
deleteButton.setAttribute("type", "button");
deleteButton.setAttribute("value","删除");
deleteButton.οnclick=function(){
deleteCustomerID(uniqueID);
}

cell =document.createElement("td");
cell.appendChild(deleteButton);
row.appendChild(cell);//在行尾追加删除按钮这一列

document.getElementById("customerList").appendChild(row);//在HTML中添加新增加的客户信息这一列
updateCustomerListVisibility();
}

function createCellWithText(text){//创建一列元素
var cell = document.createElement("td");
cell.appendChild(document.createTextNode(text));
return cell;
}

function deleteCustomerID(id){
deleteID = id;
var url = "CustomerServlet?action=delete"+"&id="+id+"&ts="+new Date().getTime();
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleDeleteStateChange;//删除按钮的回调函数
xmlHttp.open("get",url,true);
xmlHttp.send(null);
}

function handleDeleteStateChange(){
if (xmlHttp.readyState == 4)
    if(xmlHttp.status == 200) {
    deleteCustomerFromSList();//处理删除一列
    }   
    else {
    alert("删除客户错误!");
    }
}

function deleteCustomerFromSList(){
var status = xmlHttp.responseXML.getElementsByTagName("status")[0].firstChild.nodeValue;
status = parseInt(status); 
if(status != 1){
return;
}

var rowToDelete = document.getElementById(PREFIX +deleteID);
var customerList = document.getElementById("customerList");
customerList.removeChild(rowToDelete);

updateCustomerListVisibility();
}

function updateCustomerListVisibility(){
var customerList = document.getElementById("customerList");
if(customerList.childNodes.length > 0){
document.getElementById("customerListSpan").style.display ="";//当该列有元素时清除display样式
}
else{
document.getElementById("customerListSpan").style.display ="none";//当该列无元素时,不显示表示元素将隐藏
}
}

function clearInputBoxes(){
document.getElementById("custName").value= "";
document.getElementById("email").value="";
document.getElementById("phone").value="";
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值