移动端适配方案


像素

设备像素(物理像素)

设备像素(device pixels)也叫物理像素,指的是显示器上的真实像素,每个像素的大小是屏幕固有的属性,屏幕出厂以后就不会再改变。

我们可以这么理解,屏幕是由N多个小方块构成的,每个小方块都只能显示一个颜色,而一个小方块,就是一个设备像素。而在不同的设备上,这个格子的大小是不同的,所以物理像素并不是一个固定大小的单位,它只代表一个显示器上的小格子,格子到底多大,在显示器出厂前已经确定好了。

设备独立像素(逻辑像素)

设备独立像素(device independent pixels)也叫逻辑像素,是操作系统定义的一种像素单位,应用程序将设备独立像素告诉操作系统,操作系统再将设备独立像素转化为设备像素(物理像素),从而控制屏幕上真正的物理像素点。

我们可以这么理解,物理像素是硬件开发相关的单位,是基于一个一个的硬件小方块,其大小由硬件厂家设定。而逻辑像素,则更像是软件开发相关的单位,软件相关的工作人员通过逻辑像素来表达软件相关的尺寸。前端css代码、浏览器显示给开发者的尺寸、UI设计师给出的UI稿,其尺寸单位都是逻辑像素。

举个栗子:比如如下代码,其中标注的14px、26px等值,px就是我们所说的逻辑像素。

image-20230625102051876

那么为什么需要在应用程序和设备像素之间定义这么一种单位呢?为什么应用程序不直接使用设备像素?

例如原先在 1280×720 设备分辨率的显示屏中,显示高度为 12 个设备像素的字体,现在放到设备分辨率为 2560 ×1440 的显示屏中,如果要想得到原先的大小,则需要 24 个设备像素,如果应用程序直接使用设备像素,那么编写应用程序则将变得非常困难,需要编写应用程序逻辑:字体在一些屏幕上高度为 12 个设备像素,在另一些屏幕上却需要 24 个设备像素。

  • 因此操作系统定义了一个单位:设备独立像素
  • 操作系统保证:用设备独立像素定义的尺寸,不管屏幕的参数如何,都能以合适的大小显示。
  • 操作系统是如何做到的呢?对于那些像素密度高的屏幕,将多个设备像素划分为一个设备独立像素。至于将多少设备像素划分为一个逻辑像素,这由操作系统决定。

对于上面的例子:“原本高度为 12 个设备像素的字体,现在高度为 24 个设备像素才能得到相同的大小”,操作系统会将一个逻辑像素定义为 2*2个 真实像素,从而设备独立像素尺寸不需要改变,而且不管在新、旧设备上,显示的尺寸大致相同。

CSS像素

在 CSS 中使用的 px 都是指 css 像素,比如 width: 128px。css 像素的大小是很容易变化的,当我们缩放页面的时候,元素的 css 像素数量不会改变,改变的只是每个 css 像素的大小。也就是说 width: 128px 的元素在缩放200% 以后,宽度依然是 128 个 css 像素,只不过每个 css 像素的宽度高度变为原来的两倍。如果原本元素宽度为 128 个设备独立像素,那么缩放 200% 以后元素宽度为 256 个设备独立像素。

像素之间的关系

  • CSS像素和设备独立像素的关系
  1. 缩放比例:css像素边长/设备独立像素边长
  2. 缩放比例100%:1个css像素大小等于1个设备独立像素
  3. 缩放比例200%:1个css像素大小等于(2*2)个设备独立像素
  • CSS像素和设备像素的关系
  1. 设备像素比(DPR):设备像素的数量/CSS像素的数量。即当前设备将通过几个物理像素点来绘制一个逻辑像素点
  2. 设备像素比 = CSS像素边长/设备像素边长
  3. pc端一个css像素对应一个物理像素

因为屏幕足够大,pc端默认情况下一个css像素就对应着一个物理像素,但是有没有发现你把分辨率调小以后,显示的内容变大了,但是显示器的物理像素肯定不会变啊,这时候其实就是一个css像素对应着若干个物理像素了,这个是与用户设置有关。

  1. m端一个css像素对应多个物理像素

移动设备大小是有限的,而且分辨率不低,甚至比pc端更高,也就是可以显示的物理像素更多,如果和pc端一样,一个css的px和物理像素一一对应,可以想象,显示的内容有多小。这样肯定是不行的,解决这个问题,我们可以很自然的想到,那在移动设备上就别一一对应了,一个css的px对应多个物理像素吧,这样就不至于显示的内容过小了,实际上移动设备也是这么做的,你在开发时写的px和最终渲染显示的物理像素数不是一比一的,可能1个px对应2个物理像素,可能3个物理像素,设备显示的物理像素数和你css的px数的比值就叫做设备像素比,简称dpr。好了,这样显示内容过小的问题就解决了。

  1. dpr越高越好,需要2倍图,3倍图等等来更高清

有了dpr之后,有一个问题就是同样的一张图片,我设了宽高的px数,那么在dpr为1的设备上,和dpr为2的设备上显示的效果是一样的,1个px在dpr为1的设备上会用1个物理像素来显示,在dpr为2的设备上会用2*2个物理像素来显示,这样dpr高的优势就体现不出来了,我设备比他的好,你给我的体验是一样的,可能有些用户不爽,我们可以区分对待,对于高dpr的设备,用物理像素更多的高清图片来替代,也就是2x图,3x图等等。

分辨率

设备分辨率

设备分辨率:描述的就是这个显示器的宽和高分别是多少个设备像素,即设备像素点的总数即为设备分辨率,例如常见的显示器分辨率为1920*1080。

image.png

逻辑分辨率

逻辑分辨率用屏幕的宽高来表示(单位:设备独立像素),即设备独立像素点的总数,我们通过操作系统的分辨率设置来改变设备独立像素的大小。

例如屏幕的设备分辨率是1920 * 1200(单位:设备像素),我们可以在当前的分辨率下设置逻辑分辨率是1280 * 800(单位:设备独立像素)。那么横、纵方向的设备像素数量恰好是设备独立像素的1.5倍。这也意味着,设备独立像素的边长是设备像素边长的1.5倍。

移动端开发分类

  1. 原生App开发
  2. 小程序开发
  3. Web页面

自适应

根据不同的设备屏幕大小来自动调整尺寸、大小

响应式

会随着屏幕的实时变动而自动调整,是一种自适应

视口

  • 在一个浏览器中,我们可以看到的区域就是视口(viewport)

  • fixed就是相对于视口来进行定位的

  • PC端的页面中,我们不需要对视口进行区分,因为我们的布局视口和视觉视口是同一个

  • 但是在移动端中,布局视口是大于视觉视口的。这是因为移动端的网页窗口比较小,我们可能会希望一个大的网页在移动端可以完整的显示。

布局视口(layout viewport)

布局视口的默认宽度是980px

默认情况下,一个PC端的网页在移动端会如何显示

  1. 首先它会按照宽度为980px来布局一个页面的盒子和内容
  2. 为了显示可以完整的显示在页面中,对整个页面进行缩小

image-20230620172741126
在这里插入图片描述

视觉视口(visual layout)

如果默认情况下,我们按照980px显示内容,那么右侧就会有一部分区域就会无法显示,所以手机端浏览器会默认对页面进行缩放以显示到用户的可见区域中,那么显示在可见区域的这个视口,就是视觉视口。

image-20230620173144513

理想视口(ideal layout)

移动设备默认的 viewport 是布局视口,也就是那个比屏幕要宽的 viewport(默认是980px),但在进行移动设备网站的开发时,我们需要的是理想视口。那么怎么才能得到理想视口呢?
例如:如果我们希望设置的是100px,显示的就是100px,就需要通过理想视口。

这时候可以通过设置meta中的viewport

<meta name="viewport" content="width=device-width, initial-scale=1.0">

image-20230620174302816
在这里插入图片描述

将页面设置为视觉视口之后,就可以进行移动端适配工作啦~~~~~~

移动端适配的目的是在屏幕大小不同的终端设备拥有统一的界面,让拥有更大屏幕的终端展示更多的内容。从上面两个角度出发,核心思路是:页面内容充满整个视窗
移动端适配,我们要做的最终效果是什么?
在这里插入图片描述

移动端适配方案

媒体查询

基于 css 的媒体查询属性 @media 分别为不同屏幕尺寸的移动设备编写不同尺寸的 css 属性,示例如下所示。虽然此方法能在一定程度上解决移动设备适配的问题,但我们也可以看出其存在以下问题,所以其已几乎被历史潮流淘汰。

页面上所有的元素都得在不同的 @media 中定义一遍不同的尺寸,这个代价有点高;
如果再多一种屏幕尺寸,就得多写一个 @media 查询块;

@media only screen and (min-width: 375px) {
  .logo {
    width : 62.5px;
  }
}

@media only screen and (min-width: 360px) {
  .logo {
    width : 60px;
  }
}

@media only screen and (min-width: 320px) {
  .logo {
    width : 53.3333px;
  }
}

百分比设置

在 css 中,我们可以使用百分比来实现布局,但是需要特定宽度时,这个百分比的计算对开发者来说并不友好,且元素百分比参考的对象为父元素,元素嵌套较深时会有问题。

举个栗子:设计稿为 750*1136,我们需要一个宽度为 200px 的盒子

.box {
  /* w = 200 / (750/100) = 26.66667 */
  /* 可知,计算复杂,且会存在误差 */
  width: 26.6%;
}

rem单位+动态html的font-size

px = rem * font-size

1 font-size = 视口宽度 / 10

/* 设置html元素的字体大小为 16px,即 1rem = 16px */
html {
    font-size: 16px;
}
/* 设置box元素宽 160px,10rem = 160px */
.box {
    width: 10rem; /* 160px */
}

rem单位是相对于html元素的font-size来设置的,那么如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的font-size尺寸

举个栗子:

  1. 设置一个盒子的宽度是1rem
  2. 设置不同的屏幕上html的font-size不同

image-20230621095854757

这样我们在开发中,我们只需要考虑两个问题:

  1. 针对不同的屏幕,设置html不同的font-size
  • 媒体查询

可以通过媒体查询来设置不同尺寸范围内的屏幕html的font-size尺寸

@media screen and (min-width: 320px) {
    html {
        font-size: 20px
    }
}

缺点:

  1. 我们需要针对不同的屏幕编写大量的媒体查询
  2. 如果动态改变尺寸,不会实时的进行更新
  • JS动态计算

如果我们希望实时改变屏幕尺寸时,font-size也可以实时更改,可以通过js代码。

方法:

  1. 根据html的宽度计算出font-size的大小,并且设置到html上
  2. 监听页面的实时改变,并且重新设置font-size的大小到html上
// 获取html的元素
const htmlEl = document.documentElement

function setRemUnit(){
    // 获取html的宽度(视口的宽度)
    const htmlWidth = htmlEl.clientWidth
    // 根据宽度计算一个html的font-size的大小
    const htmlFontSize = htmlWidth / 10
    // 将font-size设置到html上
    htmlEl.style.fontSize = htmlFontSize + "px"
}

// 保证第一次进来时,可以设置一次font-size
setRemUnit()

// 当屏幕尺寸发生变化时,实时来修改html的font-size 
window.addEventListener("resize",setRemUnit)
  • lib-flexible库

lib-flexible库做的事情是相同的,你也可以直接引入它

  1. 将原来要设置的尺寸,转化成rem单位
  • 手动换算

比如在一个375px屏幕上,100px宽度和高度的盒子

我们需要将100px转成对应的rem值

计算如下:

由375px的屏幕,可得font-size为37.5px
所以1rem = 37.5px
所以100px/37.5px=2.6667rem

  • less/scss函数

  • postcss-pxtorem插件目前在前端的工程化开发中,我们可以借助webpack的工具来完成自动的转化

  1. 使用 vue-cli 创建项目
vue create rem-demo
  1. 设置 viewport
框架已经帮我们设置了,这里可以忽略
<meta name="viewport" content="width=device-width,initial-scale=1">
  1. 动态设置 rem 的值
    创建 rem.js 文件:
// rem-demo/util/rem.js
// 设置基准大小
const baseSize = 32
function setRem () {
// 当前页面宽度相对于 750 宽的缩放比例
const scale = document.documentElement.clientWidth / 750
document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
}
// 初始化
setRem()
window.onresize = function () {
setRem()
}

引入 rem.js 文件:

// rem-demo/src/main.js
import './utils/rem'
  1. 安装并使用 postcss-pxtorem
    安装 postcss-pxtorem
npm i postcss-pxtorem --save-dev
  1. 使用 postcss-pxtorem
// rem-demo/vue.config.js
module.exports = {
 lintOnSave: true,
 css: {
   loaderOptions: {
     postcss: {
       plugins: [
         require('postcss-pxtorem')({
           rootValue : 16, //(数字,函数) 根元素字体大小
           unitPrecision: 5, //(数字)允许REM单位增长的十进制数字
           replace: true, // (布尔值)替换包含rems的规则,而不添加后备
           mediaQuery: false, // (布尔值)允许在媒体查询中转换px
           minPixelValue: 0, // (数字)设置要替换的最小像素值
           selectorBlackList  : [], // 忽略转换正则匹配项
           propList   : ['*'], // 可以从px转换为rem的属性,匹配正则
           exclude: /node_modules/i // (字符串,正则表达式,函数)要忽略并保留为px的文件路径
         }),
       ]
     }
   }
 }
}
  1. 运行结果
    例如:设计稿为 750*1136,我们需要一个盒子宽 375px:
/* 按照设计稿的宽度编写 */
.box {
   width: 375px;
   height: 400px;
   background-color: rgb(202, 246, 232);
}
/* 转换后 */
.box {
   width: 23.4375rem;
   height: 25rem;
   background-color: #caf6e8;
}
/* 使用 Px 和 PX 作为单位,pxtorem 将不进行转换 */
  • VSCode插件

px to rem 的插件,在编写时自动转化

vw/vh单位

vw/vh 方案与 rem 方案类似,都是将页面分成一份一份的,只不过 vw/vh 是将页面分为 100 份,1vw = device-width/100

1vw = 1% * 视口宽度,即 1vw = 视口宽度 / 100
在这里插入图片描述

优势:
image-20230621115057554

  • 手动计算
  • less/scss函数
  • 搭配 postcss-px-to-viewport 搭建项目
  1. 创建项目
vue create vw-demo
  1. 设置viewport
框架已经帮我们设置了,这里可以忽略
<meta name="viewport" content="width=device-width,initial-scale=1">
  1. 安装并使用 postcss-px-to-viewport

安装

npm i postcss-px-to-viewport --save-dev

使用:配置 .postcssrc.js

module.exports = {
  plugins: {
    autoprefixer: {}, // 用来给不同的浏览器自动添加相应前缀,如-webkit-,-moz-等等
    'postcss-px-to-viewport': {
    unitToConvert: 'px', // 要转化的单位
    viewportWidth: 750, // UI设计稿的宽度
    unitPrecision: 6, // 转换后的精度,即小数点位数
    propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
    viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
    fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
    selectorBlackList: ['wrap'], // 指定不转换为视窗单位的类名,
    minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
    mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
    replace: true, // 是否转换后直接更换属性值
    exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
    landscape: false, // 是否处理横屏情况
    },
  },
};
  1. 运行结果
    举例:以 750*1136 的设计稿为例,设计一个宽 375px 的盒子
.test-vw {
 width: 375px;
 height: 100px;
 font-size: 40px;
 background: #13b5b1;
 }
 /* 转换后 */
.test-vw {
 width: 50vw;
 height: 13.333333vw;
 font-size: 5.333333vw;
 background: #13b5b1;
 }
  • VSCode插件

flex的弹性布局

不管移动设备的分辨率怎么变, 关键元素高宽和位置都不变,只有容器元素在做伸缩变换。百分比布局,无需计算百分比,可以很好的适配到所有屏幕

特点:文字流式,控件弹性,图片等比缩放

为什么要使用flex布局

float布局有副作用,如果子元素设置了浮动,会引起父元素的塌陷 /不能动态实现自适应布局/设置padding margin不能正确表达 /之前的元素浮动了,后面的元素可能异位,所以页面越来越复杂,不利于管理

float布局对于移动端布局很不友好,所以出现了弹性布局flex

采用 Flex 布局的元素,称为 Flex 容器。它的所有子元素自动成为容器成员

flex容器属性

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content
  1. flex-direction属性

flex-direction属性决定主轴的方向(即项目的排列方向)。

.box {
  flex-direction: row | row-reverse | column | column-reverse;
}
//依次表示主轴为水平方向,起点在左端。(默认)
//主轴为水平方向,起点在右端。
//主轴为垂直方向,起点在上沿。
//主轴为垂直方向,起点在下沿。

img

  1. flex-wrap属性

默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。

.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
  //依次是不换行
  //换行,第一行在上方。
  //换行,第一行在下方。
}
  1. flex-flow属性

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。

.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}
  1. justify-content属性(这个很重要,经常用)

justify-content属性定义了项目在主轴上的对齐方式。

.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
  //依次是左对齐(默认值)
  //右对齐
  //居中
  //两端对齐,项目之间的间隔都相等。
  //每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
}

img

  1. align-items属性(这个也很重要。也常用)

align-items属性定义项目在交叉轴上如何对齐。

.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
  //依次是交叉轴的起点对齐。
  //交叉轴的终点对齐。
  //交叉轴的中点对齐。
  //项目的第一行文字的基线对齐。
  //如果项目未设置高度或设为auto,将占满整个容器的高度(默认值)
}

img

  1. align-content属性

align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

.box {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
  //依次是与交叉轴的起点对齐。
  //与交叉轴的终点对齐。
  //与交叉轴的中点对齐。
  //与交叉轴两端对齐,轴线之间的间隔平均分布。
  //每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
  //轴线占满整个交叉轴。(默认值)
}

img

项目的属性

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self
  1. order属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

css复制代码.item {
  order: <integer>;
}

img

  1. flex-grow属性(很重要)

flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

css复制代码.item {
  flex-grow: <number>; /* default 0 */
}

img

  1. flex-shrink属性

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

注意:负值对该属性无效。

css复制代码.item {
  flex-shrink: <number>; /* default 1 */
}

img

  1. flex-basis属性(这个是重点,常用)

flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。

  1. flex属性(这个最重要)

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

css复制代码.item {
//该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
//建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
  1. align-self属性

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

arduino复制代码.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
  //这个其实就是在项目里用align-items 注:auto为默认值
}

img

flex实际应用

常用的flex 1

flex 是 flex-grow、flex-shrink、flex-basis的缩写

当 flex 取值为 none,则计算值为 0 0 auto

.div {
    flex-grow: 0;
    flex-shrink: 0;
    flex-basis: auto;
}   

当 flex 取值为 auto,则计算值为 1 1 auto

.div {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: auto;}

当 flex 取值为一个非负数字则 flex-grow 数字,flex-shrink 取 1,flex-basis 取 0%(最常用)

.div {
    flex-grow: 1;//要取的值
    flex-shrink: 1;//默认
    flex-basis: 0%;//默认
}   

当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1

.div {
    flex-grow: 1;//默认
    flex-shrink: 1;//默认
    flex-basis: 0%;//要取得值
}

当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%

.div {
    flex-grow: 1;//要取的第一个值
    flex-shrink: 1;//要取的第二个值
    flex-basis: 0%;//默认
}

当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1

.div {
    flex-grow: 1;//要取的第一个值
    flex-shrink: 1;//默认
    flex-basis: 0%;//要取的第二个值
}   

flex常见布局

flex实现等分布局

.box{
            height: 500px;
            display: flex;
}
.box div{
             height: 300px;
             border: 1px solid #000000;
             flex: 1;//这就是flex:1的妙用
}
    div class="box">
        <div>等分效果</div>
        <div>等分效果</div>
    </div>

左边固定右边自适应

.box {
    height: 500px;
    display: flex;
}
.box div {
    height: 300px;
    text-align: center;
}
.box div.right {
    flex: 1;//右边自适应
    border: 1px solid #000000;
}
.box div.left {
    border: 1px solid #000000;
    flex-basis: 100px;//左边固定,优先级最高
}
//html
<div class="box">
    <div class="left">左边固定效果</div>
    <div class="right">右边自适应效果</div>
</div>

边自适应的内容如果超过范围,自适应的地方添加min-width:0,若 min-width 未设置就默认为 auto,在这里就等于这个自适应的的宽度

垂直水平居中对齐

.box {
    width: 100%;
    height: 300px;
    border: 1px solid purple;
    display: flex;
    justify-content: center;
    align-items: center;
}
//html
<div class="box"><p>居中</p></div>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃炫迈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值