Ajax简介

本文深入探讨Ajax技术,从服务器基本概念到Ajax在jQuery、axios中的使用,涵盖form表单、模板引擎、数据交换格式、跨域与JSONP、HTTP协议等关键知识点,帮助读者全面理解Ajax的工作原理及其在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.1 服务器的基本概念与初识Ajax

2.1.1 服务器的基本概念

1、客户端和服务器

(1)服务器:在上网过程中,负责存放和对外提供资源的电脑,叫做服务器

(2)客户端:在上网过程中,负责获取和消费资源的电脑,叫做客户端

2、URL地址

(1)URL地址的概念

URL中文叫统一资源定位符,用于标识互联网上每个资源的唯一存放位置,浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源

(2)URL地址的组成部分

  • 客户端与服务器之间的通信协议

  • 存有该资源的服务器名称

  • 资源在服务器上具体的存放位置

3 、客户端与服务器的通信过程

(1)客户端与服务器之间的通信过程,分为请求-处理-响应三个步骤

(2)网页中的每一个资源,都是通过请求-处理-响应的方式从服务器获取回来的

4、服务器对外提供了哪些资源

(1)网页中的数据,也使服务器对外提供的一种资源

(2)XMLHttpRequest是浏览器提供的js成员,通过它,可以请求服务器上的数据资源

(3)用法:var xhrObj = new XMLHttpRequest()

(4)资源的请求方式:客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为get和post请求

  • get请求通常用于获取服务端资源(向服务器要资源)

  • post请求通常用于向服务器提交数据(往服务器发送资源)

2.1.2 jQuery中的Ajax

1、最常用的三种方法

(1)$.get()

(2)$.post()

(3)$.ajax()

2、$.get()函数的语法(从服务器拿资源)

$.get(url,[data],[callback])
参数名参数类型是否必选说明
urlstring要请求的资源地址
dataobject请求资源期间要携带的参数
callbackfunction请求成功时的回调函数
  • 使用$.get()函数发起不带参数的请求时,直接提供请求的URL地址和请求成功之后的回调函数即可

  • 使用$.get()函数发起带参数的请求时,三个参数都写

3、$.post()函数的语法(向服务器交资源)

$.post(url,[data],[callback])
参数名参数类型是否必选说明
urlstring提交数据的地址
dataobject要提交的数据
callbackfunction数据提交成功时的回调函数

4、$.ajax()函数的语法(功能综合的函数,允许对Ajax有更详细的配置)

$.ajax({
    type: '',//请求的方式,例如GET或POST
    url: '',//请求的URL地址
    data: {},//这次请求要携带的数据
    success: function(res){}//请求成功之后的回调函数
})

2.1.3 接口

1、接口的概念

使用Ajax请求数据时,被请求的URL地址就叫做数据接口。同时,每个接口必须有请求方式。

2、接口测试工具Postman

3、接口文档(接口的说明文档)

合格的接口文档:

  • 接口名称:用来标识各个接口的简单说明

  • 接口URL:接口的调用地址

  • 调用方式:接口的调用方式(GET、POST)

  • 参数格式:接口需要传递参数,每个参数必须包含参数名称、参数类型、是否必选、参数说明这4项内容

  • 响应格式:接口的返回值的详细描述,一般包含数据名称、数据类型、说明三项内容

  • 返回示例(可选):通过对象的形式,例举服务器返回数据的结构

2.2 form表单与模板引擎

2.2.1 form表单的基本使用

1、表单组成

(1)表单标签

(2)表单域

(3)表单按钮

2、form标签属性

form标签用来采集数据,form标签的属性用来规定如何把采集到的数据发送到服务器

属性描述
actionURL地址规定当提交表单时,向何处发送表单数据
methodget或post(get在url能看见数据,post在url看不见)规定以何种方式把表单数据提交到action URL
enctypeapplication/x-www-form-urlencoded;multipart/form-data;text/plain规定在发送表单数据之前如何对其进行编码
target_blank _self _parent _top framename规定在何处打开action URL

target的值

描述
_blank在新窗口打开
_self默认,在相同框架中打开
_parent在父框架集中打开
_top在整个窗口中打开
framename在指定的框架中打开

enctype

当涉及到文件上传的操作时,必须将enctype的值设置为multipart/form-data

3、表单的同步提交及缺点

(1)表单的同步提交:通过点击submit按钮,触发表单提交的操作,从而使页面跳转到action URL的行为

(2)缺点

  • form表单同步提交后,整个页面会发生跳转,跳转到action URL所指向的地址,用户体验很差

  • form表单同步提交后,页面之前的状态和数据会丢失

(3)解决方案

表单只负责采集数据,Ajax负责将数据提交到服务器

2.2.2 通过Ajax提交表单数据

1、监听表单提交事件

//方法1
$("form").submit(function(e){})
​
//方法2
$("form").on('submit',function(e){})

2、阻止表单默认提交行为

//方法1
$("form").submit(function(e){
    e.preventDefault();
})
​
//方法2
$("form").on('submit',function(e){
    e.preventDefault();
})

3、快速获取表单中的数据:serialize()函数

  • 可以一次性获取到表中所有数据

  • 必须为每个表单元素添加name属性

$("form").serialize()

4、快速清空表单数据:reset()

//$("form")[0]:转化成DOM对象
$("form")[0].reset();

2.2.3 模板引擎的基本概念

1、模板引擎根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面

2、好处

(1)减少字符串的拼接操作

(2)是代码结构更清晰

(3)是代码更易于阅读与维护

2.2.4 art-template模板引擎

1、安装:安装 - art-template

2、步骤:

(1)导入art-template

(2)定义数据

(3)定义模板,模板的html结构必须定义在script中,scrip的type写成 type="text/html"

(4)调用template函数,template('模板的id',需要渲染的数据对象),id不用加#

(5)渲染HTML结构

3、常用语法

(1)标准语法

art-template提供了{{}}这种语法格式,在{{}}内可以进行变量输出或循环数组等操作

(2)标准语法——输出

  • 变量的输出:{{value}}

  • 对象属性的输出:{{obj.key}}

  • 对象属性的输出:{{obj['key']}}

  • 三元表达式的输出:{{a ? b : c}}

  • 逻辑或的输出:{{a || b}}

  • 加减乘除等表达式的输出:{{a + b}}

(3)标准语法——原文输出:{{@ value}}

如果要输出的value值中包含HTML标签结构,则需要使用原文输出,才能保证HTML正常渲染

(4)标准语法——条件输出

如果要实现条件输出,可以在{{}}中使用if..else if.../if的方式,进行按需输出

//第一种
{{if value}} 按需输出的内容 {{/if}}
​
//第二种
{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}

(5)标准语法——循环输出

如果要实现循环输出,则可以在{{}}内通过each语法循环数组,当前循环的索引使用$index进行访问,当前的循环项使用$value进行访问

{{each arr}}
    {{$index}} {{$value}}
{{/each}}

(5)标准语法——过滤器

{{value | filterName}}
​
//定义过滤器语法
template.defaults.imports.filterName = function(value){/*return处理的结果*/}

3、举例

//导入art-template
<script src="template-web.js"></script>
​
<div id="container"></div>
​
<!-- 定义模板 -->
<script type="text/html" id="tpl-user">
    <div>{{title}}</div>
    <div>姓名:<span>{{name}}</span></div>
    <div>年龄:<span>{{age}}</span></div>
    <div>会员:<span>{{isVIP}}</span></div>
    <div>注册时间:<span>{{regTime}}</span></div>
    <div>爱好:
        <ul>
            {{each hobby}}
                <li>{{$value}}</li>  
            {{/each}}
        </ul>
    </div>
</script>
<script>
    //定义数据
    var data = {
        title: '<h3>用户信息</h3>',
        name: 'zs',
        age: 20,
        isVIP: true,
        regTime: new Date(),
        hobby: ['吃饭','睡觉','打豆豆']
    }
​
    // 调用template函数
    var htmlStr = template('tpl-user',data);
​
    // 渲染HTML结构 
    $("#container").html(htmlStr)
</script>

2.2.5 模板引擎的实现原理

1、正则与字符串操作

(1)基本语法

  • exec()函数用于检索字符串中的正则表达式的匹配

  • 如果字符串中有匹配的值,则返回该匹配值,否则返回null

(2)分组

正则表达式中()包起来的内容表示一个分组,可以通过分组来提取自己想要的内容

(3)字符串的replace函数

replace()函数用于在字符串中用一些字符替换另一些字符

str.replace(patternResult[0],patternResult[1])

(4)多次replace

方法1:多次调用replace()函数

方法2:可以进行while循环,条件是patternResult = pattern.exec(str)

(5)replace替换为真值

多了一部取值的操作

str.replace(patternResult[0],data[patternResult[1]])

2、实现简易的模板引擎

步骤

  • 定义模板结构

  • 预调用模板引擎

  • 封装template

  • 导入并使用自定义的模板引擎

2.3 Ajax加强

2.3.1 XMLHttpRequest的基本使用

1、使用xhr发起GET请求

(1)步骤

  • 创建xhr对象

  • 调用xhr.open()函数

  • 调用xhr.send()函数

  • 监听xhr.onreadystatechange事件

(2)代码实现

//创建XHR对象
var xhr = new XMLHttpRequest();
​
//调用open函数,指定请求方式与URL地址
xhr.open('GET','http://www.liulongbin.top:3006/api/getbooks');
​
//调用send函数,发起Ajax请求
xhr.send();
​
//监听onreadystatechange事件
xhr.onreadystatechange = function(){
    //监听xhr对象的请求状态readyState,与服务器响应的状态status(固定写法)
    if(xhr.readyState === 4 && xhr.status === 200){
        //打印服务器响应回来的数据
        console.log(xhr.responseText);
    }
}

2、了解xhr对象的readyState属性

XMLHttpRequest对象的readyState属性,用来表示当前Ajax请求所处的状态,每个Ajax请求必然处于以下状态中的一个:

状态描述
0UNSENTXMLHttpRequest对象已被创建,但尚未调用open()方法
1OPENEDopen()方法已经被调用
2HEADERS_RECEIVEDsend()方法已经被调用,响应头也已经被接收
3LOADING数据接收中,此时response属性中已经包含部分数据
4DONEAjax请求完成,这意味着数据传输已经彻底完成或失败

3、使用xhr发起带参数的GET请求

使用xhr对象发起带参数的GET请求,只需要在调用xhr.open期间,为url地址指定参数即可

xhr.open('GET','http://www.liulongbin.top:3006/api/getbooks?id=1');

4、查询字符串

(1)定义:查询字符串(URL参数)是指在URL的末尾加上用于向服务器发送信息的字符串(变量)

(2)格式:?放在URL的末尾,后面接 参数=值,多个值时用&分隔

(3)get请求携带参数的本质是直接将参数以查询字符串的形式追加到URL后面,发送至服务器

5、URL编码与解码

(1)URL编码定义

  • URL地址中,只允许出现英文相关的字符、标点符号、数字,因此,在URL地址中不允许出现中文字符。如果URL中需要包含中文这样的字符,则必须对中文字符进行编码(转义)

  • 三个%是一个字

(2)如何对URL进行编码与解码

编码:encodeURI()

解码:decodeURI()

6、使用xhr发起POST请求

(1)步骤

  • 创建xhr对象

  • 调用xhr.open()函数

  • 设置Content-Type属性(固定写法):xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")

  • 调用xhr.send()函数,同时指定要发送的数据

  • 监听xhr.onreadystatechange事件

(2)代码实现

// 创建xhr对象
var xhr = new XMLHttpRequest();
​
//调用xhr.open()函数
xhr.open("POST","http://www.liulongbin.top:3006/api/addbook");
​
//设置Content-Type属性(固定写法)
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
​
//调用xhr.send()函数,同时指定要发送的数据
xhr.send('bookname=天天&author=zs&publisher=天津图书出版社');
​
//监听xhr.onreadystatechange事件
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4 && xhr.status === 200){
        console.log(xhr.responseText);
    }
}

2.3.2 数据交换格式

1、定义:数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式(主要是XML和JSON)

2、XML

(1)定义:XML是可扩展的标记语言

(2)缺点:

  • XML格式臃肿,和数据无关的代码多,体积大,传输效率低

  • 在JavaScript中解析XML比较麻烦

3、JSON

(1)定义:JSON就是JavaScript对象和数组的字符串表示法,JSON的本质是字符串

(2)JSON两种结构

  • json就是用字符串来表示JavaScript的对象和数组,所以json中包含对象和数组两种结构,通过这两种结构的相互嵌套,可以表示各种复杂的数据结构

  • 对象结构:对象结构在json中表示为{}括起来的内容,数据结构为{key: value, key:value}的键值对结构,其中key必须使用""包裹的字符串,value的数据类型可以是数字、字符串、布尔值、null、数组、对象

  • 数组结构:数组结构在json中表示为[]括起来的内容,数据结构为{"key","pencil",30,true}的键值对结构,数组的数据类型可以是数字、字符串、布尔值、null、数组、对象

(3)JSON语法注意事项

  • 属性名必须使用双引号包裹

  • 字符串类型的值必须使用双引号包裹

  • JSON中不允许使用单引号表示字符串

  • JSON不能写注释

  • JSON的最外层必须是对象或数组格式

  • 不能使用undefined或函数作为JSON的值

(4)JSON与JS对象的关系:JSON是JS对象的字符串表示法

(5)JSON与JS对象的互转

JSON字符串转化为JS对象:JSON.parse()方法

JS对象转化为JSON字符串:JSON.stringify()方法

(6)序列化和反序列化

把数据对象转换为字符串的过程叫做序列化,将字符串转换为数据对象的过程叫做反序列化

2.3.3 XMLHttpRequest Level2的新特性

1、设置HTTP请求时限

//设置超时时间
xhr.timeout = 3000;
​
//设置超时以后的处理函数
xhr.ontimeout = function(event){
    alert("请求超时");
}

2、FormData对象管理表单数据

//模拟表单操作
//新建FormData对象
var fd = new FormData();
​
//为FormData添加表单项
fd.append('uname','zs');
fd.append('upwd','123456');
​
//创建XHR对象
var xhr = new XMLHttpRequest();
​
//指定请求类型与URL地址
xhr.open("POST","http://www.liulongbin.top:3006/api/formdata");
​
//直接提交FormData对象,这与提交网页表单的效果一致
xhr.send(fd);
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4 && xhr.status === 200){
        console.log(JSON.parse(xhr.responseText));
    }
}
//获取网页表单的值
<form id="form1">
    <input type="text" name="uname" autocomplete="off" />
        <input type="password" name="upwd" />
            <button type="submit">提交</button>
</form>
​
<script>
    //获取表单元素
    var form = document.querySelector("#form1");
​
    //监听表单元素的submit事件
    form.addEventListener("submit",function(e){
        e.preventDefault();
        //根据form表单创建FormData对象,会自动将表单数据填充到FormData对象中
        var fd = new FormData(form);
        var xhr = new XMLHttpRequest();
        xhr.open("POST","http://www.liulongbin.top:3006/api/formdata");
        xhr.send(fd);
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4 && xhr.status === 200){
                console.log(JSON.parse(xhr.responseText));
            }
        }
    })
</script>

3、上传文件

(1)步骤

  • 定义UI结构

  • 验证是否选择了文件

  • 向FormData中追加文件

  • 使用xhr发起上传文件的请求,必须用post

  • 监听onreadystatechange事件

(2)定义UI结构

<!-- 文件选择框 -->
<input type="file" id="file1">
<!-- 上传按钮 -->
<button id="btnUpload">上传文件</button>
<br/>
​
<div class="progress" style="width: 500px; margin: 15px 10px; ">
    <div id="percent" class="progress-bar progress-bar-striped active" style="width: 0%">
        0%
    </div>
</div>
​
<!-- 显示上床到服务器的图片 -->
<img src="" alt="" id="img" width="800"/>

(3)验证是否选择了文件

//获取上传文件的按钮
var btnUpload = document.querySelector("#btnUpload");
//为按钮添加click事件监听
btnUpload.addEventListener("click",function(){
    //获取到选择文件列表
    var files = document.querySelector("#file1").files;
    if(files.length <= 0){
        return alert("请选择要上传的文件");
    }
    console.log("用户选择了待上传的文件");
})

(4)向FormData中追加文件

var fd = new FormData();
fd.append('avatar',files[0]);

(5)显示文件上传进度

//创建xhr对象
var xhr = new XMLHttpRequest();
//监听xhr.upload的onprogress事件
xhr.upload.onprogress = function(e){
    // e.lengthComputable是一个布尔值,表示当前上传的资源是否具有可计算的长度
    if(e.lengthComputable){
        //e.loaded已传输的字节
        //e.total需传输的总字节
        var percentComplete = Math.ceil((e.loaded / e.total)*100);
        $("#percent").attr('style','width:'+percentComplete+'%;').html(percentComplete+'%')
    }
}

(6)监听上传完成的事件

xhr.upload.onload = function(){
    $("#percent").removeClass().addClass('progress-bar progress-bar-success');
}

2.3.4 jQuery高级用法

1、jQuery实现文件上传

(1)定义UI结构

<!-- 文件选择框 -->
<input type="file" id="file1">
<!-- 上传按钮 -->
<button id="btnUpload">上传文件</button>

(2)验证是否选择了文件

$("#btnUpload").on("click",function(){
    var files = $("#file1")[0].files;
    if(files.length <= 0){
        alert("请选择要上传的文件")
    }
})

(3)向FormData中追加文件

var fd = new FormData();
fd.append('avatar',files[0]);

(4)使用jQuery发起上传文件的请求

$.ajax({
    method: "POST",
    url: "http://www.liulongbin.top:3006/api/upload/avatar",
    data: fd,
    contentType: false,
    processData: false,
    success:function(res){
        console.log(res);
    }
})

2、jQuery实现loading效果

(1)ajaxStart(callback)

Ajax请求开始时,执行ajaxStart函数,可以在ajaxStart的callback中显示loading效果

$(document).ajaxStart(function(){
    $("#loading").show()
})

(2)ajaxStop(callback)

Ajax请求结束时,执行ajaxStop函数,可以在ajaxStop的callback中隐藏loading效果

$(document).ajaxStop(function(){
    $("#loading").hide()
})

2.3.5 axios

1、axios专注于网络数据请求的库

2、axios发起GET请求

axios.get('url', {param: {/*参数*/} }).then(callback)

3、axios发起POST请求

axios.post('url',{/*参数*/}).then(callback)

4、直接使用axios发起请求

axios({
    method: '请求类型',
    url: '请求的URL地址',
    data: {/*POST数据*/},
    params: {/*GET参数*/}
}).then(callback)

2.4 跨域与JSONP

1、同源策略和跨域

(1)同源:两个页面的协议、域名、端口都相同则是同源(默认端口是80)

(2)同源策略:是浏览器提供的一个安全策略,不同源JavaScript无法进行资源的交互

(3)跨域:不是同源则是跨域

(4)实现跨域请求:JSONP(只支持GET请求,不支持POST请求)、CORS(是W3C标准,支持GET请求和POST请求)

2、JSONP

jQuery提供的$.ajax()函数,可以发起jsonp数据请求

$.ajax({
    url: '',
    dataType: 'jsonp',
    success: function(){}
})

自定义参数及回调函数的名称

$.ajax({
    url: '',
    dataType: 'jsonp',
    //自定义参数名称
    jsonp: '',
    //自定义回调函数名称
    jsonpCallback: '',
    success: function(){}
})

3、节流

节流策略:减少一段时间内事件的触发频率

2.5 HTTP协议

1、HTTP协议简介

(1)通信:信息的传递和交换

(2)通信三要素:通信的主体、通信的内容、通信的方式

(3)通信协议:通信的双方完成通信所必须遵守的规则和约定

(4)HTTP协议:超文本传输协议,他规定了客户端与服务器之间进行网页内容传输时所必须遵守的传输格式

2、HTTP请求消息

(1)HTTP请求消息的组成部分:请求行、请求头部、空行、请求体

(2)请求行由请求方式、URL、HTTP协议版本组成,他们之间由空格分开

(3)请求头部用来描述客户端的基本信息,从而把客户端相关信息告知服务器,由多行键值对组成,每行键值用冒号分隔

(4)空行:最后一个请求头部字段的后面是一个空行,通知服务器请求头部至此结束

(5)请求体:通过POST方式提交到服务器的数据,GET请求没有请求体

3、HTTP响应消息

(1)HTTP响应消息的组成部分:状态行、响应头部、空行、响应体

(2)状态行由HTTP协议版本、状态码、状态码的描述文本组成,他们之间由空格分开

(3)响应头部用来描述服务器的基本信息,由多行键值对组成,每行键值用冒号分隔

(4)空行:最后一个响应头部字段的后面是一个空行,通知客户端响应头部至此结束

(5)响应体:存放的是服务器响应给客户端的资源内容

4、HTTP请求方法

(1)HTTP请求方法作用:用来表明要对服务器上的资源执行的操作,常用的是GET和POST

(2)HTTP请求方法

序号方法描述
1GET(查询)发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中
2POST(新增)向服务器提交资源,数据被包含在请求体中提交给服务器
3PUT(修改)向服务器提交资源,并使用提交的新资源,替换掉服务器对应的旧资源
4DELETE(删除)请求服务器删除指定的资源
5HEADHEAD方法请求一个与GET请求的响应相同的响应,但是没有响应体
6OPTIONS获取http服务器支持的http请求方法,允许客户端查看服务器的性能
7CONNECT建立一个到由目标资源标识的服务器的隧道
8TRACE沿着到目标资源的路径执行一个消息环回测试,主要用于测试和诊断
9PATCH是对PUT方法的补充,用来对已知资源进行局部更新

5、HTTP响应状态代码

(1)HTTP响应状态码:HTTP协议的一部分,用于标识响应的状态

(2)组成及分类

  • HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后面两个数字用来对状态码进行细分

  • 分类

分类分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误

(3)2**成功相关的响应状态码

状态码状态码英文名称中文描述
200OK请求成功,一般用于GET与POST请求
201Created已创建,成功请求并创建了新的资源,通常用于POST或PUT请求

(3)3**重定向相关的响应状态码

状态码状态码英文名称中文描述
301Moved Permanently永久移动,请求的资源已被永久的移动到新的URL,返回信息会包括新的URL,浏览器会自动定向到新URL,今后任何新的请求都应使用新的URL代替
302Found临时移动,与301相似,但资源只是临时被移动,客户端应继续使用原因URL
304Not Modified无修改,所请求的资源未修改,服务器返回此状态码时,不会返回任何资源(响应消息中不包含响应体),客户端通常会缓存访问过的资源

(4)4**客户端错误相关的响应状态码

状态码状态码英文名称中文描述
400Bad Request1、语义有误,当前请求无法被服务器理解,除非进行修改,否则客户端不应该重复提交这个请求;2、请求参数有误
401Unauthorized当前请求需要用户验证
403Forbidden服务器已经理解请求,但是拒绝执行它
404Not Found服务器无法根据客户端的请求找打资源
408Request Timeout请求超时,服务器等待客户端发送的请求时间过长,超时

(5)5**服务器错误相关的响应状态码

状态码状态码英文名称中文描述
400Internal Server Error服务器内部错误,无法完成请求
401Not Implemented服务器不支持该请求方法,无法完成请求,只有GET和HEAD请求方法是要求每个服务器必须支持的,其他请求方法在不支持的服务器上会返回501
403Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值