bootstrap获取弹框结果_Bootstrap模态弹出框

转自 http://www.cnblogs.com/xiaohuochai/p/7130390.html

前面的话

在 Bootstrap 框架中把模态弹出框统一称为 Modal。这种弹出框效果在大多数 Web 网站的交互中都可见。比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作,也有可能弹出的是一张图片。本文将详细介绍Bootstrap模态弹出框

结构分析

Bootstrap框架中的模态弹出框,分别运用了“modal”、“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在“modal-content”中,其主要又包括三个部分:

弹出框头部,一般使用“modal-header”表示,主要包括标题和关闭按钮

弹出框主体,一般使用“modal-body”表示,弹出框的主要内容

弹出框脚部,一般使用“modal-footer”表示,主要放置操作按钮

×Close

模态弹出窗标题

模态弹出窗主体内容

关闭

保存

对于弹窗而言,modal-content是样式的关键。主要设置了弹窗的边框、边距、背景色和阴影等样式

.modal-content {

position: relative;

background-color: #fff;

-webkit-background-clip: padding-box;

background-clip: padding-box;

border: 1px solid #999;

border: 1px solid rgba(0, 0, 0, .2);

border-radius: 6px;

outline: 0;

-webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);

box-shadow: 0 3px 9px rgba(0, 0, 0, .5);

}

除此之外,modal-content中的modal-header、modal-body和modal-footer三个部分样式设置如下

.modal-header {

min-height: 16.42857143px;

padding: 15px;

border-bottom: 1px solid #e5e5e5;

}.modal-header .close {

margin-top: -2px;

}.modal-title {

margin: 0;

line-height: 1.42857143;

}.modal-body {

position: relative;

padding: 15px;

}.modal-footer {

padding: 15px;

text-align: right;

border-top: 1px solid #e5e5e5;

}

这三个部分主要控制一些间距的样式。而modal-footer都是用来放置按钮,所以底部还对包含的按钮做了一定的样式处理

.modal-footer .btn + .btn {

margin-bottom: 0;

margin-left: 5px;

}.modal-footer .btn-group .btn + .btn {

margin-left: -1px;

}.modal-footer .btn-block + .btn-block {

margin-left: 0;

}

触发方式

众所周知,模态弹出窗在页面加载完成时,是被隐藏在页面中的,只有通过一定的动作(事件)才能触发模态弹出窗的显示。在Bootstrap框架中实现方法有2种

在介绍触发方式之前,首先要说明.show和.fade这两个方法。只有模态弹出窗默认是隐藏的,才能触发其显示

.fade {

opacity: 0;

-webkit-transition: opacity .15s linear;

-o-transition: opacity .15s linear;

transition: opacity .15s linear;

}.show {

display: block!important;

}

【方法一】

模态弹出窗声明,只需要自定义两个必要的属性:data-toggle和data-target(bootstrap中声明式触发方法一般依赖于这些自定义的data-xxx 属性。比如data-toggle="" 或者 data-dismiss="")

data-toggle必须设置为modal(toggle中文翻译过来就是触发器);

data-target可以设置为CSS的选择符,也可以设置为模态弹出窗的ID值,一般情况设置为模态弹出窗的ID值,因为ID值是唯一的值

点击

×Close

模态弹出窗标题

模态弹出窗主体内容

关闭

保存

【方法二】

触发模态弹出窗也可以是一个链接元素,那么可以使用链接元素自带的href属性替代data-target属性

不过建议还是使用统一使用data-target的方式来触发

点击

×Close

模态弹出窗标题

模态弹出窗主体内容

关闭

保存

尺寸

Bootstrap框架为模态弹出窗提供了不同尺寸,一个是大尺寸样式“modal-lg”,另一个是小尺寸样式“modal-sm”。其结构上稍做调整

[注意].bs-example-modal-lg和.bs-example-modal-sm是自定义的名称,而非必须

 ... 
 ... 

大尺寸默认尺寸小尺寸

小火柴的蓝色理想

小火柴的蓝色理想

小火柴的蓝色理想

CSS解析

bootstrap中的“模态弹出框”有以下几个特点:

1、模态弹出窗是固定在浏览器中的。

2、单击右侧全屏按钮,在全屏状态下,模态弹出窗宽度是自适应的,而且modal-dialog水平居中。

3、当浏览器视窗大于768px时,模态弹出窗的宽度为600px

4、模态弹出窗的背景常常有一个透明的蒙层效果

5、触发弹窗时,弹窗是从上到下、逐渐浮现到页面前的

【固定在浏览器实现】

.modal {

position: fixed;

top: 0;

right: 0;

bottom: 0;

left: 0;

z-index: 1050;

display: none;

overflow: hidden;

-webkit-overflow-scrolling: touch;

outline: 0;

}

【水平居中实现】.modal-dialog {

position: relative;

width: auto;

margin: 10px;

}

【当浏览器视窗大于768px时,模态弹出窗的宽度为600px实现】

@media (min-width: 768px) {

.modal-dialog {

width: 600px;

margin: 30px auto;

}

.modal-content {

-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);

box-shadow: 0 5px 15px rgba(0, 0, 0, .5);

}

.modal-sm {

width: 300px;

}}

【蒙版】

弹窗弹出时为 

 元素添加 .modal-open类,从而覆盖页面默认的滚动行为,并且还会自动生成一个 .modal-backdrop 元素用于提供一个可点击的区域,点击此区域就即可关闭模态框.modal-open {

overflow: hidden;

}

.modal-backdrop {

position: fixed;

top: 0;

right: 0;

bottom: 0;

left: 0;

z-index: 1040;

background-color: #000;

}

给其添加了一个过渡动画,从fade到in,把opacity值从0变成了0.5

.modal-backdrop.fade {

filter: alpha(opacity=0);

opacity: 0;

}.modal-backdrop.in {

filter: alpha(opacity=50);

opacity: .5;

}

【动画效果】

弹窗的动画内容是从-25%的top值位置到top:0的位置

.modal.fade .modal-dialog {

-webkit-transition: -webkit-transform .3s ease-out;

-o-transition:      -o-transform .3s ease-out;

transition:         transform .3s ease-out;

-webkit-transform: translate3d(0, -25%, 0);

-o-transform: translate3d(0, -25%, 0);

transform: translate3d(0, -25%, 0);

}.modal.in .modal-dialog {

-webkit-transform: translate3d(0, 0, 0);

-o-transform: translate3d(0, 0, 0);

transform: translate3d(0, 0, 0);

}

如果不需要模态框弹出时的动画效果(淡入淡出效果),删掉 .fade 类即可

点击

×Close

模态弹出窗标题

模态弹出窗主体内容

关闭

保存

参数说明

除了通过data-toggle和data-target来控制模态弹出窗之外,Bootstrap框架针对模态弹出框还提供了其他自定义data-属性,来控制模态弹出窗。有关Modal弹出窗自定义属性相关说明如下所示

该参数设置在按钮上,或者弹窗上都可以。出于方便,一般地,在按钮上设置

[注意]属性值一定要加引号,如data-backdrop="false"

如果想要支持esc键关闭弹窗,需要在弹窗上设置tabindex="-1"

默认样式无蒙版ESC失效弹窗默认不显示

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

JS触发

除了使用自定义属性data-触发模态弹出框之外,还可以通过JavaScript方法来触发模态弹出窗。比如说给按钮设置一个单击事件,然后触发模态弹出窗

只需一行 JavaScript 代码,即可通过元素的 id myModal 调用模态框$('#myModal').modal()

点击

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

使用JavaScript触发模态弹出窗时,Bootstrap框架提供了一些设置,主要包括属性设置、参数设置和事件设置

【属性设置】

模态弹出窗默认支持的自定义属性主要有

不想让用户按ESC键关闭模态弹出窗,可以这样做

$(function(){

$(".btn").click(function(){

$("#mymodal").modal({

keyboard:false

});

});

});

【参数设置】

在Bootstrap框架中还为模态弹出窗提供了三种参数设置,具体说明如下

打开(关闭)

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

$("#btn").click(function(){

$("#mymodal").modal("toggle");

});

});

【事件设置】

模态弹窗还支持五种类型的事件,分别是模态弹出窗的弹出前、弹出后,关闭前、关闭后及远端数据加载后,具体描述如下:

打开

×Close

小火柴的蓝色理想

好的代码像粥一样,都是用时间熬出来的

JS解析

【1】IIFE

使用立即调用函数,防止插件内代码外泄,从而形成一个闭环,并且只能从jQuery的fn里进行扩展+function ($) {    //使用es5严格模式

'use strict';    //}(window.jQuery);

【2】初始设置

var Modal = function (element, options) {    this.options             = options//options是设置选项

this.$body               = $(document.body)//body元素

this.$element            = $(element)element表示modal弹出框容器及内容元素

this.$dialog             = this.$element.find('.modal-dialog')//弹窗对象

this.$backdrop           = null //蒙版对象

this.isShown             = null //弹窗是否显示的标识

this.originalBodyPad     = null //body的padding-right标识    this.scrollbarWidth      = 0 //滚动条宽度为0

this.ignoreBackdropClick = false //默认蒙板可点击

//如果设置了remote,就加载remote指定url的内容到modal-content样式的元素内,并触发loaded.bs.modal事件

if (this.options.remote) {      this.$element

.find('.modal-content')

.load(this.options.remote, $.proxy(function () {          this.$element.trigger('loaded.bs.modal')

}, this))

}

}  //组件版本号3.3.7

Modal.VERSION  = '3.3.7'  //动画持续时间300ms

Modal.TRANSITION_DURATION = 300  //蒙版动画持续时间150ms

Modal.BACKDROP_TRANSITION_DURATION = 150  //默认设置

Modal.DEFAULTS = {

backdrop: true, //显示蒙版

keyboard: true, //按ESC键关闭弹窗

show: true //单击触发元素时打开弹窗

}

【3】插件核心代码

主要是Modal核心类函数的定义、默认参数的定义和9个原型方法的定义,这9个原型方法主要是处理弹窗的反转、打开、关闭和弹窗背景设置、取消等操作

// 反转弹窗(打开或关闭)

Modal.prototype.toggle = function (_relatedTarget) {    //如果弹窗处于显示状态,则调用hide()方法,关闭它;否则,调用show()方法,打开弹窗

return this.isShown ? this.hide() : this.show(_relatedTarget)

}  // 打开弹窗

Modal.prototype.show = function (_relatedTarget) {    //保存this值

var that = this

//定义弹窗前的触发事件

var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })    //打开弹窗前,触发事件

this.$element.trigger(e)    // 如果已经打开了(或者曾经被阻止过),则退出执行,后续代码不做处理

if (this.isShown || e.isDefaultPrevented()) return

//设置弹窗显示标识为true

this.isShown = true

this.checkScrollbar()    this.setScrollbar()    this.$body.addClass('modal-open')    //处理键盘事件,主要是设置按esc键时是否关闭弹窗

this.escape()    this.resize()    // 如果单击了元素内的子元素(带有[data-dismiss="modal"]属性),则关闭弹窗

this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))    //点击弹窗时,如果鼠标的目标是当前弹窗,则将默认蒙板不可点击的标识置为true,并不可再设置

this.$dialog.on('mousedown.dismiss.bs.modal', function () {

that.$element.one('mouseup.dismiss.bs.modal', function (e) {        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true

})

})    //绘制蒙版后,处理以下代码

this.backdrop(function () {      // 判断浏览器是否支持动画,并且弹窗是否设置了动画过渡效果(是否有fade样式)

var transition = $.support.transition && that.$element.hasClass('fade')      // 如果modal弹窗没有父容器,则将它附加到body上

if (!that.$element.parent().length) {

that.$element.appendTo(that.$body)

}      // 显示modal弹窗      that.$element

.show()

.scrollTop(0)

that.adjustDialog()      // 如果支持动画,强制刷新UI现场,重绘弹窗

if (transition) {

that.$element[0].offsetWidth

}      // 给modal弹窗添加in样式,和modal样式一起

that.$element.addClass('in')      // 强制给弹窗设定焦点      that.enforceFocus()      // 打开弹窗显示后的触发事件

var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })

transition ?

that.$dialog //找到弹窗元素

.one('bsTransitionEnd', function () {            // 如果支持动画,则动画结束以后给弹窗内的元素设置焦点,并触发shown事件

that.$element.trigger('focus').trigger(e)

})

.emulateTransitionEnd(Modal.TRANSITION_DURATION) :        // 否则直接设置焦点,并触发shown事件

that.$element.trigger('focus').trigger(e)

})

}  // 关闭弹窗

Modal.prototype.hide = function (e) {    //阻止冒泡

if (e) e.preventDefault()    //定义关闭弹窗前的触发事件

e = $.Event('hide.bs.modal')    //关闭弹窗前触发事件

this.$element.trigger(e)    // 如果已经关闭了(或者曾经被阻止过),则退出执行,后续代码不做处理

if (!this.isShown || e.isDefaultPrevented()) return

//设置显示状态标识为false

this.isShown = false

//处理键盘事件,主要是设置按Esc键的时候是否关闭弹窗

this.escape()    this.resize()    //取消所有的focusin.bs.modal事件

$(document).off('focusin.bs.modal')    this.$element

.removeClass('in') //删除in样式

.off('click.dismiss.bs.modal') //取消dismiss的单击事件

.off('mouseup.dismiss.bs.modal')//取消dismiss的鼠标抬起事件

//取消dismiss的鼠标放下事件

this.$dialog.off('mousedown.dismiss.bs.modal')    //如果支持动画,则动画结束以后再关闭,否则直接关闭

$.support.transition && this.$element.hasClass('fade') ?      this.$element

.one('bsTransitionEnd', $.proxy(this.hideModal, this))

.emulateTransitionEnd(Modal.TRANSITION_DURATION) :      this.hideModal()

}  //强制弹窗处于焦点状态

Modal.prototype.enforceFocus = function () {

$(document)      // 禁用所有的focusin事件,防止无限循环

.off('focusin.bs.modal')

.on('focusin.bs.modal', $.proxy(function (e) {        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {          // 如果处于焦点的元素不是当前元素(或不包含当前元素),则强制给当前元素设置焦点

this.$element.trigger('focus')

}

}, this))

}  //按Esc键是否退出的处理

Modal.prototype.escape = function () {    if (this.isShown && this.options.keyboard) {      //如果弹窗是打开状态,并且keyboard选项为true,则说明允许按ESC键可以关闭弹窗

this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {        //检测键盘事件,如果是ESC(keycode=27),则关闭

e.which == 27 && this.hide()

}, this))

} else if (!this.isShown) {      // 否则,取消键盘事件检测

this.$element.off('keydown.dismiss.bs.modal')

}

}

Modal.prototype.resize = function () {    if (this.isShown) {

$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))

} else {

$(window).off('resize.bs.modal')

}

}  //关闭弹窗

Modal.prototype.hideModal = function () {    var that = this

//关闭弹窗

this.$element.hide()    this.backdrop(function () {      //移除body上的modal-open样式

that.$body.removeClass('modal-open')

that.resetAdjustments()

that.resetScrollbar()      //关闭以后,触发hidden事件

that.$element.trigger('hidden.bs.modal')

})

}

//删除蒙版,关闭弹窗时触发

Modal.prototype.removeBackdrop = function () {    // 删除蒙版

this.$backdrop && this.$backdrop.remove()    // 设置蒙版对象为null

this.$backdrop = null

}

//添加蒙版,打开弹窗时触发

Modal.prototype.backdrop = function (callback) {    var that = this

//是否设置了动画过渡效果,如果是则将animate设置为fade

var animate = this.$element.hasClass('fade') ? 'fade' : ''    //如果是打开状态,并且设置了backdrop参数

if (this.isShown && this.options.backdrop) {      //定义动画标识

var doAnimate = $.support.transition && animate      // 在body上定义蒙版div元素,并附加fade标识以支持动画

this.$backdrop = $(document.createElement('div'))

.addClass('modal-backdrop ' + animate)

.appendTo(this.$body)      //蒙版被单击时进行判断:如果backdrop参数为static,则强制将弹窗设置为售点;否则,关闭弹窗

this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {        if (this.ignoreBackdropClick) {          this.ignoreBackdropClick = false

return

}        if (e.target !== e.currentTarget) return

this.options.backdrop == 'static'

? this.$element[0].focus()

: this.hide()

}, this))      // 如果支持动画,强制刷新UI现场,重绘弹窗

if (doAnimate) this.$backdrop[0].offsetWidth

//添加in样式

this.$backdrop.addClass('in')      //如果没有回调,则直接返回

if (!callback) return

// 如果支持动画,则动画结束执行回调函数;否则,直接执行回调函数

doAnimate ?        this.$backdrop

.one('bsTransitionEnd', callback)

.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :

callback()      //如果是关闭状态,但蒙版对象依然还存在

} else if (!this.isShown && this.$backdrop) {      //去除in样式

this.$backdrop.removeClass('in')      var callbackRemove = function () {

that.removeBackdrop()

callback && callback()

}      // 如果支持动画,则动画结束执行回调函数;否则,直接执行回调函数

$.support.transition && this.$element.hasClass('fade') ?        this.$backdrop

.one('bsTransitionEnd', callbackRemove)

.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :

callbackRemove()

} else if (callback) {

callback()

}

}

【4】滚动条处理

在弹窗插件中,使用了大量的代码对滚动条进行处理

Modal.prototype.handleUpdate = function () {    this.adjustDialog()

}  //处理因为滚动条而使弹窗位置不固定问题

Modal.prototype.adjustDialog = function () {    //如果元素的高度大于页面的高度,即溢出屏幕,则modalIsOverflowing置为true

var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight    //将元素的paddingLeft和paddingRight设置为scrollbarWidth

this.$element.css({

paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',

paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''

})

}  //重置调节器

Modal.prototype.resetAdjustments = function () {    //将元素的paddingLeft和paddingRight置为空

this.$element.css({

paddingLeft: '',

paddingRight: ''

})

}  //检查滚动条

Modal.prototype.checkScrollbar = function () {    //fullWindowWidth储存页面宽度

var fullWindowWidth = window.innerWidth    //IE8-浏览器不支持innerWidth属性

if (!fullWindowWidth) {      //使用getBoundingClientRect方法来获得页面宽度

var documentElementRect = document.documentElement.getBoundingClientRect()

fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)

}    //如果有滚动条,则bodyIsOverflowing置为true

this.bodyIsOverflowing = document.body.clientWidth 

this.scrollbarWidth = this.measureScrollbar()

}  //用来为body元素设置padding-right的值,防止body元素被scrollbar阻挡

Modal.prototype.setScrollbar = function () {    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)    this.originalBodyPad = document.body.style.paddingRight || ''    //如果页面存在滚动条,则body的padding-right设置为默认的padding-right加上滚动条的宽度

if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)

}  //重置滚动条

Modal.prototype.resetScrollbar = function () {    //将body的padding-right值设置为null

this.$body.css('padding-right', this.originalBodyPad)

}

//测量滚动条宽度

Modal.prototype.measureScrollbar = function () {    var scrollDiv = document.createElement('div')

scrollDiv.className = 'modal-scrollbar-measure'    this.$body.append(scrollDiv)    //滚动条宽度等于offetWidth - clientWidth

var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth    this.$body[0].removeChild(scrollDiv)    return scrollbarWidth

}

【5】jQuery插件定义

在jQuery上定义插件,有点特殊的代码是options参数的收集和合并,主要收集了3个部分:插件的默认参数DEFAULTS、modal元素上的data-属性,执行插件时传入的option对象,这三个部分的优先级依次升高

function Plugin(option, _relatedTarget) {    //根据选择器,遍历所有符合规则的元素

return this.each(function () {      var $this   = $(this)      //获取自定义属性bs.modal的值

var data    = $this.data('bs.modal')      //将插件的默认参数DEFAULTS、modal元素上的data-属性,执行插件时传入的option对象,这三种值合并到一起,作为options参数

//后面的参数的优先级高于前面的参数

var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)      //如果值不存在,则将Modal实例设置为bs.modal值

if (!data) $this.data('bs.modal', (data = new Modal(this, options)))      //如果option传递了string,则表示要执行某个方法

if (typeof option == 'string') data[option](_relatedTarget)      else if (options.show) data.show(_relatedTarget)

})

}  var old = $.fn.modal  //保留其他库的$.fn.modal代码(如果定义的话),以便在noConflict之后可以继续使用该老代码

$.fn.modal             = Plugin  //重设插件构造器,可以通过该属性获取插件的真实类函数

$.fn.modal.Constructor = Modal

【6】防冲突处理

$.fn.modal.noConflict = function () {    //恢复以前的旧代码

$.fn.modal = old    //将$.fn.modal.noConflict()设置为Bootstrap的Modal插件

return this

}

【7】绑定触发事件

//监测所有拥有自定义属性data-toggle="modal"的元素上的单击事件

$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {    var $this   = $(this)    //获取href属性值

var href    = $this.attr('href')    //获取data-target属性值,如果没有,则获取href值,该值是所弹出元素的id

var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')))

//如果弹窗元素上已经弹窗实例(即弹出过一次了),则设置option值为字符串toggle,否则将remote值(如果有的话)、弹窗元素上的自定义属性值集合、触发元素上的自定义属性值集合,合并为option对象

var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())    //如果是a链接,则阻止其默认行为

if ($this.is('a')) e.preventDefault()

$target.one('show.bs.modal', function (showEvent) {      if (showEvent.isDefaultPrevented()) return

//定义一次hidden事件,给所单击元素设置focus

$target.one('hidden.bs.modal', function () {

$this.is(':visible') && $this.trigger('focus')

})

})

Plugin.call($target, option, this)

})

}(jQuery);

好的代码像粥一样,都是用时间熬出来的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值