jQuery

jQuery

jQuery是前端库,一个方法库,分装这一系列操作DOM的方法

基础知识

  1. 前端方法库
    • 插件:实现某一单一类功能
    • 库:封装各种功能和需要的工具
    • 框架:拥有自己完整的生态系统
  2. 优点
    • 选择器
    • 链式编程
    • 隐式迭代
  3. 特点
    • 2.0以前的版本全兼容
    • 2.0以后的不再兼容IE
  4. 自动暴露两个全局变量
    • jQuery
    • $

选择器

基本选择器

  1. 语法:$("选择器")
  2. 返回值:满足条件的所有元素(id选择器除外)
    • 放在数组里面返回
    • 以集合形式,称为jQuery元素集合
  3. css中怎么获取,里面就怎么写

特殊选择器

  1. 语法:$("选择器")

  2. 对已经存在的选择器进行修饰

  3. 取值

    • $("选择器:first"):获取第一个选择器元素

    • $("选择器:last"):获取最后一个个选择器元素

    • $("选择器:eq(数字)"):获取按照索引排列的选择器元素,从0开始

    • $("选择器:odd"):获取按照索引排列的奇数选择器元素

    • $("选择器:even"):获取按照索引排列的偶数选择器元素

      注意:

      //特殊选择器获取索引为偶数选择器,按JS规则获取
      $("选择器:even")
      //普通选择器获取排列为偶数选择器,按CSS规则获取
      $("选择器:nth-child(even)")
      

筛选器

对jQuery的元素集合进行二次筛选,直接进行链式编程就行

注意:只有jQuery的元素集合才可以使用,原生Dom对象不能使用

  1. 元素集合.first():拿到元素集合的第一个

    • $("选择器").first()
    • 为了链式编程,即当用选择器筛选一部分赋予样式后,再次筛选一部分赋予另外的样式
  2. 元素集合.last()

  3. 元素集合.eq(索引)

  4. 元素集合.next():当前元素的下一个

  5. 元素集合.nextAll():

    • 元素集合.nextAll():当前元素后面的所有兄弟元素
    • 元素集合.nextAll("选择器"):当前元素后面所有元素中指定的选择器
  6. 元素集合.nextUntill:

    • nextUntill():当前元素后面的所有兄弟元素

    • nextUntill("选择器"):获取到当前元素后面所有兄弟元素,直到遇到指定选择器

      (不包含选择器元素)

  7. 元素集合.prev():当前元素的上一个元素

  8. 元素集合.prevAll():

    • 元素集合.prevAll():当前元素上面的所有兄弟元素

    • 元素集合.prevAll("选择器"):获取到当前元素上面所有兄弟元素中的指定选择器元素

      ② 倒着往上取

  9. 元素集合.prevUntill()

    • 元素集合.prevUntill():当前元素上面的所有兄弟元素

    • 元素集合.prevUntill("选择器"):获取到当前元素上面所有兄弟元素,直到遇到指定选择器

      ①(不包含选择器元素)

      ② 倒着往上取

  10. 元素集合.parent():获取父元素

  11. 元素集合.parents()

    • 元素集合.parents():获取该元素的所有父元素
    • 元素集合.parents("选择器"):获取所有父元素符合条件的父元素
  12. 元素集合.children()

    • 元素集合.children():获取该元素的所有子元素
    • 元素集合.children("选择器"):获取所有子元素符合条件的元素
  13. 元素集合.sinblings()

    • 元素集合.sinblings():获取该元素的所有兄弟元素,自己除外
  14. 元素集合.find():在该元素的所有后代元素里面找符合选择器条件的元素

  15. 元素集合.index():获取该元素在其父元素里面的索引位置

操作文本

操作元素内的文本与超文本

注意:只有jQuery的元素集合才可以使用,原生Dom对象不能使用

  1. html()

    • 语法:

      元素集合.html()

      ​ 获取元素集合内的超文本内容

      ​ 以字符串形式返回

      元素集合.html("内容")

      ​ 设置元素集合内的超文本内容

       可以编译标签
      

      ​ 完全覆盖式写入

       隐式迭代:元素集合内有多少元素,就写入多少元素,但获取的时候只获取一个,这是为了保证HTML结构
      
  2. text()

    • 语法:

      元素集合.text()

      ​ 获取元素集合内的文本内容

      ​ 以字符串形式返回

      元素集合.text("内容")

      ​ 获取元素集合内的文本内容

      不可以编译标签
      

      ​ 完全覆盖式写入

      ​ 隐式迭代:元素集合内有多少元素,就写入多少元素,

      ​ 获取的时候获取到所有文本内容,因为不涉及html结构

  3. val()

    • 语法

      元素集合.val()

      获取元素集合内第一个的的Val值

      元素集合.vl("内容")

      ​ 设置元素集合内第一个的的Val值

      ​ 完全覆盖式写入

       隐式迭代:元素集合内有多少元素,就写入多少元素
      

操作元素类名

  1. addClass():添加类名
  2. removeClass():删除类名
  3. hasClass():检查类名
  4. toggleClass():有就删除,没有就添加

操作元素样式

  1. 元素集合.css("样式名"):获取元素样式

    是否行内元素都能获取元素样式

  2. 元素集合.css("样式名","样式值):设置行内样式

    隐式迭代:元素集合内有多少元素就设置多少元素

    如果样式值单位是px,可以不写

  3. 元素集合.css({样式名:样式值,样式名:样式值...}):设批量置行内样式

基础事件

on()

  1. 元素集合.on("事件类型",事件处理函数)

    • 隐式迭代:元素集合内有多少元素。就有多少元素绑定事件

    • 选项卡例子:

    $('ul>li').on('click',function(){
    //用this拿到的是DOM元素,用不了jQuery方法
    //DOM元素想用jQuery方法,可以使用$()包起来
    //siblings()选取除自己外所有同级元素,即对同级元素进行反选
    $(this).addClass('active').siblings().removeClass('active')
    //eq(索引)获取匹配元素集上的相应位置索引的元素。
    $('ol>li').removeClass('active').eq($(this).index()).addClass('active')
    })
    
  2. 元素集合.on("事件类型",选择器,事件处理函数)

    • 事件委托的绑定,把选择器元素委托给元素集合内元素
    • 其中,选择器元素是元素集合内元素的后代元素,不然冒泡冒不出来
    • 相当于原生JS的target方法
  3. 元素集合.on("事件类型",复杂数据类型,事件处理函数名(){})

    • 给元素集合内所有元素加加上绑定事件

    • 这个复杂数据类型是事件触发的时候,传递给里面的参数

    • 在事件对象中有一个叫data的成员,就是传递进来的参数

    • 代码理解:

    $('li').on('click',{name:'jack'},function(e){
    console.log('111')
    console.log(e)
    })
    
  4. 元素集合.on("事件类型",选择器,数据,事件处理函数名(){})

    • 事件委托的形式带上传递参数
    • 把选择器所属的事件,委托给了元素集合内的事件
    • 数据位置在事件触发的时候传给事件处理函数的参数
  5. 元素集合.on({事件类型1:事件处理函数,事件类型2:事件处理函数2,...})

    • 为元素集合批量绑定事件
    • 没法传递参数和事件委托

one()

用来绑定事件,和one()方法的参数和使用形式一模一样

但绑定的事件只能执行一次

off()

解除事件绑定

  1. 元素集合.off("事件类型")

    解除元素身上该事件类型所有事件处理函数

  2. 元素集合.off("事件类型",事件处理函数)

    解除元素身上该事件类型某个 事件处理函数

trigger()

用JS代码的方式触发事件

元素集合.trigger("事件类型")

特殊事件

  1. jQuery的事件函数

    • jQuery提供了简洁的绑定事件的方式
    • 这些方法可以直接使用,带有隐士迭代
    • 可以接受传参数,但不能事件委托
    • 快捷绑定事件:常用的都有,像click(),mouseup()
  2. 语法

    • 元素集合.事件类型(事件处理函数)
    • 元素集合.事件类型(传入事件处理函数的参数,事件处理函数)
  3. jQuery唯一的特殊事件

    元素集合.hover(移入事件处理函数,移出事件处理函数)

    一个结合了移入移出的事件,只传一个参数时移入移出都出发这个函数

    用的比较少

节点操作

创建节点

$("html结构字符串")

  • 当$()里传递一个选择器的时候, 就是获取元素

  • 当$()里传递一个html结构字符串的时候,就是创建元素节点

  • 当$()里传递一个DOM元素节点的时候,就是转换成jQuery元素集合

    代码理解

    const box=document.querySelector("div")
    //因为获取的是DOM节点没办法用jQuery方法
    console,log(box.html("111"))
    //转化为jQuery节点
    console,log($(box).html("111"))
    

插入节点

  1. 内部插入(父子关系的插入)

    • 父元素.append(子元素)

      父元素末尾的位置插入子元素

    • 子元素.appendTo(父元素)

      把子元素追加到父元素末尾

    • 父元素.prepend(子元素)

      父元素首位置插入子元素

    • 父元素.append(子元素)

      把子元素追加到父元素首位置

    • 注意:元素节点是jQuery创建的复杂数据类型的变量,存储的是一个地址,只要使用这个变量就是使用堆里面的空间

      代码理解

      $("div").append(p)
      $("div").prepend(p)
      //上面有下面没有
      //以最后一个为准
      
  2. 外部插入(兄弟关系的插入)

    • 存在元素.after(插入元素)

      把插入元素排在存在元素的后面

    • 插入元素.insertAfter(存在元素)

      把插入元素排在存在元素的后面

    • 存在元素.before(插入元素)

      把插入元素排在存在元素的前面

    • 插入元素.insertBefore(存在元素)

      把插入元素排在存在元素的前面

删除节点

  1. 元素集合.remove()

    把自己从父元素中删除

  2. 元素集合.empty()

    把自己变成空标签,把自己所有后代节点删除

替换节点

  1. 换下节点.replaceWith(换上节点)
  2. 换上节点.replaceAll(换下节点)

克隆节点

  1. 元素集合.clone()
    • 必然带着包含的所有节点进来
    • 第一个默认参数是false,表示是否克隆元素本身的事件,选填true
    • 第二个参数默认跟随第一个参数,表示是否克隆元素后代节点的事件
    • 当第一个参数是false时,后面的参数没有意义

操作元素属性

属性分类:

  1. 原生属性

    id,class,src…

  2. 自定义属性

    getAttribute()…

  3. H5自定义属性

    dataset,data-xxx

jQuery操作属性的三种方法

  1. attr()removeAttr()

    • 元素集合.attr("属性名"):

      获取属性,主要用来获取标签属性,包括一些自定义属性

    • 元素集合.attr("属性名","属性值"):

      ①设置和修改标签属性,只是把属性放在标签上,主要当做自定义属性使用,原因看③

      ②设置的不管是什么数据类型,拿出来都会变成字符串类型

      ③对于原生属性有些是没有用的

      <input type="checkbox">
      <input type="button" value="">
      <script>
      //中括号([])里面接的是属性和该属性的值
      这种选择器写法通常用于input,checked,select,radio标签
      $('input[type=button]'.click()=>{
      //Prop()设置或返回被选元素的属性和值
      $(`input`).prop('checked',true)
      //点击单选框会被选中
      $(`input`).attr('checked',true)
      //点击单选框checked值会变,但实际不会被选中,只是在标签上记录这个变化
      })
      
      </script>
      
    • 元素集合.removeAttr("属性名"):

      ①删除元素身上的属性

      ②id,class等属性也可以删除,但不推荐,推荐设置为空

      ③多用于删除attr方法设置的属性

  2. prop()removeProp()

    • 元素集合.prop("属性名"):

      ①可以获取元素的原生属性与自定义属性

      不能获取attr方法设置的自定义属性

    • 元素集合.prop("属性名","属性值"):

      ①主要设置元素的原生属性,也可以设置自定义属性

      ②但设置的自定义属性不会显示在标签上,而是存储在元素身上

      ③设置的时候是什么数据类型,获取的时候还是什么数据类型

      不能获取attr方法设置的自定义属性

    • 元素集合.removeProp("属性名","属性值"):

      ①只能删除prop方法设置的自定义属性

      ②原生属性不能删除

  3. data()removeData()

    • 元素集合.data("属性名"):

      获取使用data方法存储的数据与元素身上data-xx的属性

    • 元素集合.prop("属性名"."属性值"):

      ①设置的时候,只把数据存储在元素身上的某一个对象空间内,不会出现在标签上,即不会有data-xx的属性出现

      ②只能获取,不能设置data-xx的属性(data-xx表示原生JS上的自定义属性)

    • 元素集合.prop("属性名"):

      只能删除由data方法设置的属性,不能删除元素身上data-xx的属性

获取元素尺寸

不管元素在页面中是否占位都可以获取得到

  1. 元素集合.width()/元素集合.heigt()
    • 获取的是元素内容的尺寸
  2. 元素集合.innerWidth()/元素集合.innerHeight()
    • 获取的是内容+padding 的尺寸
  3. 元素集合.outerWidth()/元素集合outerHeight()
    • 获取的是内容+padding +border的尺寸
  4. 元素集合.outerWidth(true)/元素集合outerHeight(true)
    • 获取的是内容+padding +border+margin的尺寸

操作元素位置

操作元素相对于某一个点的位置关系

offSet():

  1. 元素集合.offSet():读取

    • 返回值是一个对象,包含相对于页面左上角的x,y

    • 需要取值时需要元素集合.offSet().top/元素集合.offSet().left,后面不能继续链式编程

  2. 元素集合.offSet({top:xxx,left:xxx}):设置

    • 设置的是相对于页面左上角的位置

    • 设置的时候,如果父子元素都要动,要考虑两者设置的先后顺序

      ①如果先动子元素再动父元素,子元素会率先完成位置改变,然后父元素再在保持子元素与自己相对位置的情况下完成移动

position()

  1. 元素集合.position():只读
    • 获取元素的定位信息,前提是元素有设置定位
    • 如果设置的是right和bottom,会自动计算成left和top

基础动画

就是控制元素的display的none和block

  1. 分类
    • show():显示
    • hide():隐藏
    • toggle():切换(与本身状态相反)
  2. 语法:方法名(运动时间,"运动曲线",回调函数)
    • 运动时间:多长时间运动结束
    • 运动曲线:什么方式运动,运动并不是匀速的,可以设置linner
    • 回调函数:运动结束后触发

折叠动画

  1. 分类

    • slideDown():下拉显示
    • slideUp():上拉隐藏
    • slideToggle():切换下拉显示与上拉隐藏
  2. 语法:方法名(运动 时间,运动曲线,回调函数)

  3. 上拉显示,下拉隐藏的实现

    <style>
    div.outer{
    width:300px;
    height:300px;
    overflow:hidden;
    position:relative;
    }
    div.inner{
    width:300px;
    height:300px;
    background-color:skyblue;
    position:absolute;
    bottom:0;
    left:0;
    }
    </style>
    <button class="show">显示</button>
    <button class="show">隐藏</button>
    <button class="show">切换</button>
    <div class="outer">
    <div classs="inner"></div>
    </div>
    <script>
    $('.show').click(()=>{
    $('.inner').slideDown(1000,'liner',()=>console.log('显示结束'))
    })
    $('.hide').click(()=>{
    $('.inner').slideUp(1000,'liner',()=>console.log('隐藏结束'))
    })
    $('.toggle').click(()=>{
    $('.inner').slideToggle(1000,'liner',()=>console.log('切换结束'))
    })
    </script>
    

渐隐渐显动动画

通过操作opacity达到效果

  1. 分类

    • fadeIn():opacity从0~1
    • fadeOut():opacity从1~0
    • fadeToggle():切换
    • faseTo():运动到指定透明度
  2. 语法:方法名(运动时间,运动曲线,回调函数)

    /方法名(运动时间,指定透明度,运动曲线,回调函数)

综合动画

animate({运动后的属性},时间,运动曲线,回调函数)

其中,关于颜色的属性和CSS3的2d,3d动画实现不了

停止动画

当给一个元素设置动画后,当多次点击后,其必须完整执行完动画,jQuery提供了两种临时停止动画的方法

  1. 元素集合.stop()

    不管运动到什么位置就在那个位置停止

  2. 元素集合.finish()

    不管运动到什么位置,会直接去到运动结束的位置

如果想让动画停止在当前位置后,按照最新的动画进行

元素集合.stop().slideToggle()

animatecss插件

animatecss插件

发送ajax请求

jQuery提供了一个函数$.get()

引入jQuery的同时提供了两个全局变量$与jQuery,两者都是函数数据类型

把这两个数据当做一个对象,想他身上添加一些方法;我们管这两种方法称为jQuery的全局方法,不需要依赖选择器即元素集合,直接调用就行

  1. $.get(地址,传递给后端的数据,回调函数,期望返回的数据类型):专门用于发送get请求

    • 请求地址:可以自主拼接参数,但不推荐可以

    • 数据:给后端的数据,可以写成’key=value&key=value’,还可以写成{…}

    • 回调函数:请求成功的回调,请求成功后会处罚

    • 数据类型:是不是执行解析响应体的操作

      ①’string’:不解析

      ②’json’:执行一步JSON.parse()

    $.get('...','a=100&b=200/{a:100,b:200}',function(res){console.log(res)},'json')
    //res是后端返回的响应体,如果做后写了json,会自动返回JSON.parse()
    
  2. $.post(地址,传递给后端的数据,回调函数,期望返回的数据类型):专门用于发送post请求

    • 四个参数意义和$.get()一模一样
  3. $.ajax(options):综合方法,由自己配置决定发送什么请求

    • options就是本次请求的配置信息,是一个对象数据类型

    • 配置信息里面可以填写的内容

      ①url:请求地址,必填

      ②async:是否异步,默认异步,选填false

      ③type/method:请求方式,默认是GET,大小写无所谓

      ④data:传递给后端的参数,可以是查询字符串的形式,也可以是对象

      ⑤dataType:期望后端返回的数据类型,是否进行JSON.parse()解析

      ⑥success:接受一个函数数据类型,表示成功的回调

      ⑦error:接受一个函数数据类型,表示成功的回调

      ​ 请求失败与解析失败都会走error的失败

      ⑧timeout:设置一个超时时间

      ​ 从发送请求开始到达超时时间还没有接收到响应会直接取消本次请求,到达error函数

      ⑨cache:是否缓存,对于ajax请求默认缓存,选填false

      但对于jsonp请求默认不缓存,选填true

      ​ 缓存原理:当两次发送同一个请求即两次请求地址一模一样,浏览器会缓存下来

                   如果不想进行缓存,就让每次请求地址不一样,那么在每次请求后面携带一个没有用的参数,值设置成时间戳
      

      ⑩context:指定回调函数的this指向,默认指向jQuery封装的axaj对象

    部分格式显示:
    $.ajax({
    url:'...',
    async:true,
    method:'POST',
    dataType:'json',
    success(res){
    //res就是响应体,会根据dataType填写的内容解析
    },
    error(xhr,info,err){
    console.log(xhr)
    //xhr是jQuery分装的ajax对象
    console.log(info)
    //info是本次失败的信息
    console.log(err)
    //err是错误的详细内容,但有时候不详细
    },
    timeout:1000,
    })
    

发送ajax的promise

jQuery对于ajax的封装,除了回调函数的形式接收结果,还封装了promise形式接收

$.ajax({
url:'',
data:{a:100,b:200},
type:'POST',
dataType:'json',
success(res){
console.log('success')
console.log(res)
}
}).then(res=>{
console.log('promise')
console.log(res)
})
//两种都使用的话,两个都会执行,不理解重看24集

ajax发送跨域请求

非同源地址请求

  1. jsonp

    • 前端利用script标签和src属性绕开同源策略

    • 和ajax没有关系,实际上不是在发送ajax请求

    • 实际在请求一个js文件

    • 使用一个叫$.ajax()的方法

      因为jQuery封装Ajax函数时做了一个判断

      if(dataType===‘jsonp’){
      走一套动态创建script标签
      动态添加src属性
      动态插入到body
      动态删除script
      }else{
      按照Ajax的一套流程封装}
      

      只要把dataType书写成’jsonp’就会发送jsonp请求

  2. 代理

    • 有一个同原策略的代理服务端转发请求
    • 对于前端依旧是正常发送请求
    • 只不过把地址书写成代理地址
    • 依旧是直接使用$.ajax()方法来发送
    • 只不过url位置书写代理标识符
  3. cors

    • 服务端允许指定客户端发送请求
    • 和前端没关系
    • 前端正常发送
    • 使用$.ajax()

ajax的全局钩子函数三种解决方法

钩子函数是在ajax某一个阶段自动执行的函数;

ajax的钩子函数是全局的ajax函数;

不是写在ajax内部,是挂在window身上去执行的;

分类:

  • ajaxStart():第一个ajax发送之前触发,执行函数
<script>
        $(window).ajaxStart(function(){
            console.log("第一个ajax发送前执行,有一个请求开始了")
        })
</script>
  • ajaxSend(): 每一个ajax发送之前执行
<script>
        $(window).ajaxSend(function(){
            console.log("每一个ajax发送前执行")
        })
</script>
  • ajaxSuccess():每一个ajax成功会触发一次
<script>
        $(window).ajaxSuccess(function(){
            console.log("每一个ajax成功会触发一次")
        })
</script>
  • ajaxError():每一个ajax失败会触发一次
<script>
        $(window).ajaxError(function(){
            console.log("每一个ajax失败会触发一次")
        })
</script>
  • ajaxComplete():每一个ajax完成会触发一次
<script>
        $(window).ajaxComplete(function(){
            console.log("每一个ajax完成会触发一次")
        })
</script>
  • ajaxStop():最后一个ajax结束会触发
<script>
        $(window).ajaxStop(function(){
            console.log("最后一个ajax结束会触发一次")
        })
</script>

多库并存

当需要引入一个别的插件或者库的时候,别人也向外暴露的是 $ 获取 jQuery

那么,我们的 jQuery 就不能用了,jQuery 为我们提供了一个多库并存的方法

// 这个方法可以交还 jQuery 命名的控制权
jQuery.noConflict()

// 上面代码执行完毕以后 $ 这个变量就不能用了
// 但是 jQuery 可以使用
console.log($) // undefined
console.log(jQuery) // 可以使用
// 这个方法可以交并且传递一个 true 的时候,会完全交出控制权
jQuery.noConflict(true)

// 上面代码执行完毕以后 $ 这个变量就不能用了
// jQuery 这个变量也不能用了
console.log($) // undefined
console.log(jQuery) // undefined
// 可以用一个变量来接受返回值,这个变量就是新的控制权
var aa = jQuery.noConflict(true)

// 接下来就可以把 aa 当作 jQuery 向外暴露的接口使用了
aa('div').click(function () { console.log('我被点击了') })

深浅拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,因此如果修改其中一个对象,另一个也会跟着改变。

深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会影响到原对象。

jQuery的extend()

至少传递两个参数

  1. $.extend(对象1,对象2...):浅拷贝
  2. $.extend(true,对象1,对象2...):深拷贝

插件扩展机制

提供了两个方法

扩展给他自己本身

jQuery.extend方法

扩展完后的内容只能用 $ 或者 jQuery 来调用

// jQuery.extend 接受一个参数,是一个对象,对象里面是我们扩展的方法
jQuery.extend({
    max: function (...n) { return Math.max.apply(null, n) },
    min: function (...n) { return Math.min.apply(null, n) }
})

const max = $.max(4, 5, 3, 2, 6, 1)
console.log(max) // 6
const min = $.min(4, 5, 3, 2, 6, 1)
console.log(min) 

扩展给元素集

jQuery.fn.extend() 方法扩展

扩展完毕以后给元素的集合使用,事用 $(‘li’) 这样的选择器获取到的元素集合来使用

// jQuery.fn.extend() 接受一个参数,是一个对象,对象里面是我们扩展的方法
jQuery.fn.extend({
    checked: function () {
        // return 关键字是为了保证链式编程
        // 后面的代码才是业务逻辑
        return this.each(function() { this.checked = true })
    }
})
// 靠元素集合来调用
$('input[type=checkbox]').checked()
// 执行完毕之后,所有的 复选框 就都是选中状态了

入口函数

等 DOM 结构渲染完毕就可以执行的代码,不用等待图片,css等所有资源都加载完毕,相当于原生 JS 中的 DOMContentLoaded

  1. $( function( ) { XXXX })
  2. $( document ).ready( function( ) { XXXX })

案例总结

回到顶部

选项卡

树状菜单

手风琴

鼠标跟随

全选

表单验证

轮播图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值