手把手教你用Vue3动态挂载DOM节点:实现Element Plus图片预览自由布局

Element Plus中el-image预览层被遮挡?三种方案实现body节点挂载 本文针对Element Plus中el-image组件预览层被遮挡的常见问题,深入剖析了其根源在于DOM层级嵌套与CSS层叠上下文。文章重点推荐了使用内置的preview-teleported属性这一官方方案,它能通过Vue Teleport将预览层挂载至body节点,从根本上解决层级问题。同时,也探讨了手动操作DOM和完全自定义组件两种备选方案,为不同场景提供解决思路。 阅读详情

Vue3动态挂载DOM节点实战:Element Plus图片预览自由布局全解析

在现代化前端开发中,图片预览功能几乎是每个Web应用的标配需求。Element Plus作为Vue3生态中最受欢迎的UI组件库之一,其el-image组件提供了开箱即用的图片预览功能。但当我们面对复杂布局或需要深度定制时,默认的预览行为可能无法满足需求——特别是当预览层被其他高层级元素遮挡时。本文将深入探讨如何通过动态DOM操作,实现Element Plus图片预览的自由控制。

1. 理解Element Plus图片预览的底层机制

Element Plus的图片预览功能本质上由两个独立组件协同工作:

  • el-image:负责图片的展示和基础交互
  • el-image-viewer:实际处理预览功能的独立组件

默认情况下,预览层会挂载在el-image所在的组件上下文中。这种设计在简单场景下工作良好,但当遇到以下情况时就会出现问题:

// 典型的问题场景示例
<template>
  <div class="complex-layout">
    <el-dialog v-model="dialogVisible">
      <el-table :data="tableData">
        <el-table-column prop="image">
          <template #default="{ row }">
            <el-image :src="row.image" :preview-src-list="[row.image]" />
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

在这个例子中,当点击表格中的图片时,预览层可能会被对话框或表格的其他部分遮挡。这是因为:

  1. 层级关系限制:对话框的z-index通常较高(如2000+),而预览层可能被限制在表格的上下文中
  2. 溢出隐藏问题:父容器设置了overflow: hidden属性
  3. 定位上下文:祖先元素设置了非static的定位属性

2. 官方解决方案:preview-teleported属性

Element Plus其实已经预见到了这类问题,提供了内置的解决方案:

<el-image 
  :src="imageUrl"
  :preview-src-list="[imageUrl]"
  preview-teleported
/>

preview-teleported属性的核心作用是将预览层直接挂载到body元素下,而非组件内部。这种方式能有效解决大部分层级问题,因为它:

  • 脱离了原有组件的DOM上下文
  • 避免了祖先元素样式的影响
  • 可以自由控制z-index

属性对比表:

属性默认值作用适用场景
preview-teleportedfalse控制预览层是否挂载到body需要突破父容器限制时
append-to-bodyfalse控制弹层类组件挂载位置对话框、下拉菜单等
z-index2000控制预览层层级需要调整显示优先级时

3. 深度定制:手动控制DOM挂载

当官方属性无法满足特殊需求时,我们需要手动控制DOM挂载流程。以下是完整的实现方案:

3.1 基础DOM操作实现

<template>
  <el-image :src="imageUrl" @click="handleImageClick" />
</template>

<script setup>
import { ref, nextTick } from 'vue'

const imageUrl = ref('https://example.com/image.jpg')
const viewerRef = ref(null)

const handleImageClick = async () => {
  await nextTick() // 等待Element Plus默认预览层渲染
  
  const viewer = document.querySelector('.el-image-viewer__wrapper')
  if (viewer && viewer.parentNode !== document.body) {
    // 移动DOM节点到body
    document.body.appendChild(viewer)
    
    // 添加自定义样式
    const style = document.createElement('style')
    style.textContent = `
      .el-image-viewer__wrapper {
        z-index: 9999 !important;
      }
    `
    document.head.appendChild(style)
  }
}
</script>

3.2 进阶实现:封装可复用的高阶组件

对于需要多处使用的场景,我们可以封装一个高阶组件:

// ImagePreviewTeleport.vue
<template>
  <el-image v-bind="$attrs" @click="handleClick" />
</template>

<script setup>
import { ref, onUnmounted } from 'vue'

const customStyle = ref(null)

const handleClick = () => {
  nextTick(() => {
    const viewer = document.querySelector('.el-image-viewer__wrapper')
    if (viewer) {
      document.body.appendChild(viewer)
      
      customStyle.value = document.createElement('style')
      customStyle.value.textContent = `
        .el-image-viewer__wrapper {
          z-index: ${props.zIndex};
        }
        ${props.customCSS}
      `
      document.head.appendChild(customStyle.value)
    }
  })
}

onUnmounted(() => {
  if (customStyle.value) {
    document.head.removeChild(customStyle.value)
  }
})

const props = defineProps({
  zIndex: {
    type: Number,
    default: 9999
  },
  customCSS: {
    type: String,
    default: ''
  }
})
</script>

使用方式:

<ImagePreviewTeleport 
  :src="imageUrl" 
  :preview-src-list="[imageUrl]"
  z-index="9999"
  custom-css=".el-image-viewer__mask { background-color: rgba(0,0,0,0.8); }"
/>

4. 实战中的性能优化与边界处理

在实际项目中,我们需要考虑更多边界情况和性能优化:

4.1 内存泄漏防护

onUnmounted(() => {
  const viewer = document.querySelector('.el-image-viewer__wrapper')
  if (viewer && viewer.parentNode === document.body) {
    document.body.removeChild(viewer)
  }
  
  if (customStyle.value) {
    document.head.removeChild(customStyle.value)
  }
})

4.2 多实例冲突处理

当页面存在多个图片预览时,需要确保只操作当前激活的预览层:

let activeViewer = null

const handleClick = () => {
  nextTick(() => {
    // 先清理之前的预览层
    if (activeViewer) {
      document.body.removeChild(activeViewer)
    }
    
    const viewers = document.querySelectorAll('.el-image-viewer__wrapper')
    activeViewer = viewers[viewers.length - 1]
    
    if (activeViewer) {
      document.body.appendChild(activeViewer)
    }
  })
}

4.3 响应式样式调整

通过ResizeObserver实现预览层自适应:

const observer = new ResizeObserver(entries => {
  entries.forEach(entry => {
    const viewer = entry.target
    // 根据窗口大小调整预览图片尺寸
    const img = viewer.querySelector('.el-image-viewer__img')
    if (img) {
      img.style.maxWidth = `${window.innerWidth * 0.8}px`
      img.style.maxHeight = `${window.innerHeight * 0.8}px`
    }
  })
})

onMounted(() => {
  const viewer = document.querySelector('.el-image-viewer__wrapper')
  if (viewer) {
    observer.observe(viewer)
  }
})

onUnmounted(() => {
  observer.disconnect()
})

5. 替代方案:完全自定义图片预览实现

当需要最大程度的控制权时,可以完全抛弃Element Plus的预览实现,从头构建:

<template>
  <img :src="imageUrl" @click="openCustomViewer" />
  
  <div v-if="showViewer" class="custom-viewer">
    <div class="viewer-backdrop" @click="closeViewer"></div>
    <img :src="currentImage" class="viewer-image" />
    <button class="viewer-close" @click="closeViewer">×</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const imageUrl = ref('https://example.com/image.jpg')
const showViewer = ref(false)
const currentImage = ref('')

const openCustomViewer = () => {
  currentImage.value = imageUrl.value
  showViewer.value = true
  document.body.style.overflow = 'hidden' // 禁止背景滚动
}

const closeViewer = () => {
  showViewer.value = false
  document.body.style.overflow = ''
}

// 键盘事件监听
const handleKeyDown = (e) => {
  if (e.key === 'Escape') {
    closeViewer()
  }
}

onMounted(() => {
  window.addEventListener('keydown', handleKeyDown)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
})
</script>

<style scoped>
.custom-viewer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
}

.viewer-backdrop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
}

.viewer-image {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
}

.viewer-close {
  position: absolute;
  top: 20px;
  right: 20px;
  background: none;
  border: none;
  color: white;
  font-size: 30px;
  cursor: pointer;
}
</style>

这种方案的优点在于:

  • 完全掌控DOM结构和样式
  • 无第三方依赖,体积更小
  • 可以自由扩展功能(如添加缩略图导航、图片操作工具栏等)

6. 最佳实践与决策树

面对图片预览需求时,如何选择最合适的方案?以下是决策参考:

是否需要基本预览功能?
├─ 是 → 使用Element Plus默认实现
│   ├─ 是否有层级问题?
│   │   ├─ 是 → 添加preview-teleported属性
│   │   └─ 否 → 保持默认
│   └─ 是否需要样式微调?
│       ├─ 是 → 使用preview-class属性自定义
│       └─ 否 → 保持默认
└─ 否 → 需要完全自定义?
    ├─ 是 → 实现自定义预览组件
    └─ 否 → 考虑其他第三方库

性能考量对比表:

方案加载性能运行时性能可维护性灵活性
默认实现★★★★★★★★★★★★★★
teleported属性★★★★★★★★★★★★★★★
手动DOM操作★★★★★★★★★★★★★
完全自定义★★★★★★★★★★★★★

在实际项目中,根据我的经验,80%的情况使用preview-teleported属性就能解决问题。对于特别复杂的场景,才需要考虑手动DOM操作或完全自定义实现。

Element Plus表格图片放大:从ElImage到自定义指令的完整实现方案 在前端开发中,图片预览是提升用户体验的常见需求,尤其在后台管理系统和数据表格场景下。其核心原理是通过监听用户交互事件(如鼠标悬停),动态计算并渲染一个独立于原布局的浮层,以展示高分辨率图片。这项技术能显著提升信息获取效率,广泛应用于电商商品管理、内容审核、数据仪表盘等需要快速查看图片细节的界面。本文聚焦于Vue 3和Element Plus技术栈,深入探讨如何在el-table组件中实现高性能、体验优雅的图片悬停放大功能。通过分析ElImage组件特性、结合ElPopover实现动态定位,并进一步封装为可复 阅读详情

相关推荐

轻量级开票系统实战:Vue+Node手撸PDF生成与邮件发送

电子发票系统是中小企业和自由职业者高频使用的轻量级Web应用,其核心在于表单交互、PDF动态渲染与SMTP邮件集成三大技术能力。基于Vue的响应式机制可高效管理多字段发票表单,配合Node.js的Stream与Nodemailer模块实现低延迟I/O处理;而Puppeteer替代PDFKit则解决了中文字体嵌入、跨平台兼容等典型痛点。该方案不依赖MongoDB或Redis,采用SQLite单文件存储与JWT无状态鉴权,兼顾开发效率与5美元VPS部署可行性。适用于年开票量500张以内、单用户或多终端登录的交付

culh2177的博客 517

vue3创建和挂载实例

这幅图完整的描述了vue3初始化时创建应用实例和挂载实例的流程,以及创建应用实例时的虚拟节点创建、render渲染、patch算法新旧节点和组件比较、虚拟dom创建、lifecycle函数的执行、diff算法等等;接下来详细描述整个执行过程。

weixin_44922480的博客 3605

Vue 3 + Element Plus 全屏播放器里弹窗不显示?手把手教你用Teleport动态挂载搞定

本文深入解析Vue 3全屏模式下弹窗不显示的问题根源,并提供基于Teleport的动态挂载解决方案。通过响应式全屏状态管理和动态计算Teleport目标容器,确保弹窗在全屏模式下正常显示,适用于视频播放器、数据可视化大屏等场景。

weixin_33686714的博客 359

灵光一闪!帮你使用Vue,搞定无法解决的“动态挂载”

在一些特殊场景下,使用组件的时机无法确定,或者无法在Vue的template中确定要我们要使用的组件,这时就需要动态的挂载组件,或者使用运行时编译动态创建组件并挂载。 今天我们将带大家从实际项目出发,看看在实际解决客户问题时,如何将组件进行动态挂载,并为大家展示一个完整的解决动态挂载问题的完整过程。 无法解决的“动态挂载” 我们的电子表格控件SpreadJS在运行时,存在这样一个功能:当用户双击单元格会显示一个输入框用于编辑单元格的内容,用户可以根据需求按照自定义单元格类型的规范自定义输入框的形式,集成任

葡萄城技术团队博客 1239

vue3 + el-image-viewer 图片组件查看

1.vue2+element -ui中 <el-image-viewer v-if="show" :url-list="url" :on-close="closeViewer" /> 注意是on-close 2.vue3+element-plus中 就是closeurl-list:图片数组 <el-image-viewer v-if="show" :url-list="url" ...

weixin_38302828的博客 4051

Vue 3动态创建组件并挂载到DOM节点上

在Vue 3中,我们可以通过动态创建组件并将其挂载到DOM节点上来实现更灵活的组件渲染。这种方式可以让我们在运行时根据需要创建和渲染组件,而不是在模板中静态定义。函数创建了一个虚拟节点,该节点表示了我们要动态创建的组件实例。希望这个例子能帮助你理解如何在Vue 3中动态创建组件并挂载到DOM节点上。函数创建了一个Vue应用实例。在上面的代码中,我们首先定义了一个名为。这样,当页面加载时,Vue会动态创建。组件并将其渲染到指定的DOM节点上。函数将组件实例挂载到id为。的Vue组件,然后使用。

NsbiCs的博客 2674

vue3+elementplus点击按钮使用el-image-viewer图片预览组件

4.点击按钮给showsrcListref赋值即可完成,同时将showImagePreview置为true。1.首先确保你是全局引入,不是全局的需要自主引入该组件。3. showsrcListref:['']格式。2..vue文件中定义组件。

CHENC0518的博客 3746

亚马逊商品评论爬取与情感分析实战:Python+BeautifulSoup高效解析(附反爬技巧)

本文详细介绍了使用Python和BeautifulSoup库高效爬取亚马逊商品评论并进行情感分析的完整实战流程。文章从环境搭建、核心代码编写入手,重点讲解了如何通过设置请求头、添加延迟等防封策略应对反爬机制,确保数据抓取的稳定性。最后,利用TextBlob库对评论文本进行情感分析,并通过可视化图表直观展示产品口碑,为电商选品与市场调研提供数据支持。

weixin_29046611的博客 1164

Vue 3中的Teleport与动态组件:优化页面布局与组件动态挂载!

随着Vue 3的发布,很多新特性和改进都为开发者提供了更强大的功能,尤其是在UI布局、组件渲染和页面性能优化方面。Teleport和动态组件作为Vue 3的重要特性,为开发者提供了全新的方式来管理和渲染组件。Teleport允许将组件渲染到DOM树的不同位置,而动态组件则使得开发者能够在不同情况下动态挂载和卸载组件,从而提升页面交互性与性能。

2201_75863687的博客 1185

用UDP协议在dos命令行里模拟一个聊天程序

/* 需求: 在dos命令行里模拟一个聊天程序 有收数据的部分,和发数据的部分,这两部分需要同时执行。 那就需要用到多线程技术。 一个线程控制收,一个线程控制发。 */ import java.io.*; import java.net.*; class C

s_x_x的记录 1956

轴承故障诊断——领域知识

幅域分析、频域分析及轴承方面的领域知识

qq_58516607的博客 3536

Element Plus图片预览进阶技巧:手动控制DOM挂载位置实战

本文深入探讨Element Plus的el-image组件图片预览功能,针对复杂布局中的DOM挂载问题,提供手动控制DOM挂载位置的实战技巧。通过Vue3组合式API和原生DOM操作,实现预览弹窗的精准挂载,解决样式隔离和层级管理问题,特别适合在表格、模态框等特殊场景下使用。

yhn456789的博客 1223

论文理解【LLM-OR】—— 【PaMOP】Guiding Large Language Models in Modeling Optimization Problem

针对 LLM 求解运筹优化任务,PaMOP 通过约束划分树分离子问题,实现复杂优化问题的分块建模,并结合求解器反馈与反向翻译一致性检查迭代纠错,降低子任务复杂度,提升可执行率与建模准确性。

佚失的诗篇 1008

Element Plus图片预览被遮挡?3种方法让el-image-viewer强制挂载到body节点

本文针对Element Plus中el-image组件图片预览被遮挡的问题,提供了三种实战解决方案:使用preview-teleported属性、动态DOM操作和自定义预览组件。详细分析了问题根源及诊断方法,帮助开发者彻底解决层级冲突,确保图片预览正常显示。特别适合Vue.js开发者处理复杂布局下的图片预览问题。

mqtt6iot的博客 601

【RT-DETR有效改进】计算训练好权重文件对应的FPS、推理每张图片的平均时间(科研必备)

本文给大家带来的改进机制是利用我们训练好的权重文件计算FPS,同时打印每张图片所利用的平均时间,模型大小(以MB为单位),同时支持batch_size功能的选择,对于轻量化模型的读者来说,本文的内容对你一定有帮助,可以清晰帮你展示出模型速度性能的提升以及轻量化的效果(模型大小),对于以提高精度为目的的读者本文也能够帮助大家展示出现阶段的模型速度指标。所以本文的内容是十分有用的机制,对于大家发表论文来说,下面的图片为运行后的效果可以看到,该有的指标均已打印(本文内容为我独家创新,全网无第二份)下面是效果图和文

Snu77的博客 3630

SpringCloud Alibaba - Seata 实现高可用和异地容灾

这里不仅仅要实现高可用,还需要实现异地容灾. 异地容灾就是说,如果你整了好几个节点部署起来,全部放到一个机房里面,那么如果这个机房出了故障,就意味着整个集群就完了,所以对于一个大型的集群来讲,都会把这些服务异地部署.问题2:如果我们要实现异地容灾,也就说某一个机房挂了,需要快速的切换到另一个可用的机房,但是这个配置在配置文件中写死了,如果要改配置文件,还需要重启服务器,这是我们不希望看到的,怎么办?进入 seata/bin 目录,运行 seata-server.bat 文件,默认端口为 8091。

CYK_byte的博客 977

Element Plus图片预览被表格覆盖?3种实战解决方案对比

本文深入解析Element Plus中`el-image`图片预览被表格覆盖的问题,提供三种实战解决方案:z-index快速修复法、`preview-teleported`标准方案和完全自定义预览组件。通过对比分析,帮助开发者根据项目需求选择最佳实践,有效解决`el-image`预览层级冲突问题。

w7x8y9z的博客 223

Open3D 球旋转算法(BPA)三维建模【2026最新版】

球旋转算法,博客长期更新,本文最新更新时间为:2026年4月11日。

点云侠的博客 37万+

Vue 完整版系统知识文档

《Vue全栈开发实战手册》摘要 本手册系统整合Vue2/Vue3全栈知识体系,涵盖基础语法、组件开发、状态管理、工程化等核心内容,适合从入门到精通的完整学习路径。主要特点: 基础核心 详解MVVM架构和响应式原理(Vue2的Object.defineProperty vs Vue3的Proxy) 完整模板语法规则与16种内置指令解析 组件系统核心:通信机制(8种方案)、插槽、动态组件、递归组件 进阶实战 状态管理:Vuex/Pinia完整解决方案 路由开发:动态路由、权限控制、懒加载 工程化:Webpack

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 402

请举手回答,LDO和DC-DC有什么不同?

文章目录1 LDO是什么2 LDO典型电路3 DC-DC是什么4 DC-DC典型电路5 LDO和DC-DC区别10.2.6 小结一下 大家好,我是记得诚。 DC-DC和LDO都是电源芯片,两者差异很大,用法也不同,这篇博客讲述LDO和DC-DC的一些差异,帮助更好的认识LDO和DC-DC并进行选型。 1 LDO是什么 LDO是low dropout regulator的简称,即低压差线性稳压器,这是相对于传统的线性稳压器来说的,传统的稳压器,输入比输出要高出很多,否则无法工作,LDO可能输入比输出高1~2V

记得诚 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

文件协作地图系统:从事件追踪到智能报告的全栈实现

在软件工程和团队协作中,文件流转与版本管理是提升效率、保障一致性的基础。其核心原理在于将离散的交换行为转化为结构化的数据,通过事件驱动模型捕获完整的协作上下文。这一技术价值在于将隐性的工作流程显性化,实现从被动查询到主动感知的转变。在应用场景上,它广泛适用于研发协作、创意设计、项目管理等需要高频文件同步的领域。本文以构建一个文件交换报告与地图系统为例,深入探讨了如何利用 **PostgreSQL** 的 JSONB 字段和关系查询能力来设计数据模型,并通过 **Cytoscape.js** 实现关系图谱的可

weixin_34269583的博客 424

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

给我5分钟,保证教会你在vue3中动态加载远程组件

在一些特殊的场景中(比如低代码、减少小程序包体积、类似于APP的热更新),我们需要从服务端动态加载.vue文件,然后将动态加载的远程vue组件渲染到我们的项目中。今天这篇文章我将带你学会,在vue3中如何去动态加载远程组件。

qq_36348403的博客 3956

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

vue3如何动态把组件添加到dom中

需求很简单,因为一些原因我并不想在template中直接使用子组件,于是我想是否可以通过方法直接把组件插入到dom中呢?当然是可以的了~~但是我又想偷懒,于是我想到element plus也是在一些组件中也在dom插入了组件。于是我就默默的准备copy它的代码了~

编程似海、 3457

vue3动态创建组件,挂载到dom 节点上,修复版本

// 将组件挂在到节点上! const creatComp = (comp:Component,prop:Object)=>{ var app = createApp(comp,{ ...prop }) var divEle = document.createElement("div") // 让我们节点挂在到一个dom元素上 document.body.appendChild(divEle) app.mount(divEle) .

天天的博客 1万+

5分钟了解Vue3 defineAsyncComponent - Vue3 的异步挂载

组件用到时再加载,减少首屏需要下载的代码。异步组件的使用方式与普通组件基本一致。可以处理加载中、加载失败、超时和重试等状态。所以,下次遇到“这个组件很大,但用户不一定会打开”的情况,就可以考虑使用。它不是越多越好,而是应该把异步加载留给那些体积较大、出现较晚、使用频率较低的组件。

李二苟 3万+

vue实现手动动态挂载某个组件

我们在开发中,可能会碰到这样的情况: 我们需要在某个时刻 在一个动态生成的元素上 挂载某个组件,那么我们该怎么实现呢? 例如,我们在点击按钮之后,在某个div上手动挂载一个组件。 <button onclick="handleClick()"></button> <div id="container"></div> import Vue fro...

qq_39852145的博客 8671
上一篇: 警惕!处理人口普查数据时90%人会犯的3个错误(附正确代码示例)
下一篇: ESP32触摸传感器实战:用T0引脚DIY智能触摸灯(附完整代码)
lambda
博客等级 码龄23年 49粉丝 1303原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值