JavaScript EasyDialog弹出层插件实战源码集

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:EasyDialog是一款基于JavaScript的轻量级弹窗插件,支持创建警告、确认、提示及自定义输入等多种弹出层,提升前端交互体验。本源码包包含丰富的EasyDialog使用示例,涵盖基础对话框到复杂用户交互场景,帮助开发者快速掌握其API调用方式与实际应用技巧。通过学习这些经过测试的demo源码,开发者可熟练运用EasyDialog实现美观、响应式的弹出层,并结合jQuery等库优化前端交互逻辑,提高开发效率与用户体验。

EasyDialog插件:从机制设计到工程落地的全链路解析

在现代前端开发中,弹窗(Modal/Dialog)早已不再是简单的“提示一下”那么简单。它承载着信息传递、用户决策、数据输入乃至流程引导的核心职责。一个设计精良的弹窗系统,不仅能提升用户体验,更能成为产品稳定性的关键支撑。

而在这其中, EasyDialog 作为一款轻量级但功能强大的 JavaScript 弹出层插件,凭借其模块化架构、灵活配置与良好的可扩展性,在众多同类工具中脱颖而出。它不依赖任何大型框架,却能通过巧妙的设计实现媲美 Vue 或 React 组件级别的控制力——这背后到底藏着怎样的技术哲学?

今天,我们就来一次深度拆解:从它的底层运行机制,到高级功能延展;从心理学层面的交互考量,再到真实项目中的工程集成。你会发现,这个看似“小而美”的插件,其实是一套完整的 前端交互基础设施


模块封装的艺术:如何优雅地避免全局污染?

我们先来看一段最基础的代码:

const dialogEl = document.createElement('div');
dialogEl.className = 'easy-dialog modal fade';
document.body.appendChild(dialogEl);

是不是看起来平平无奇?但这短短几行,已经揭示了 EasyDialog 的核心思想之一: 动态注入 DOM

不过真正让它变得“健壮”的,并不是这段逻辑本身,而是整个库是如何被组织和封装的。你有没有想过,如果直接把所有函数暴露在全局作用域下会发生什么?

🤯 “ showDialog() 冲突了?”
config 被别的脚本改掉了?”
“内存泄漏查不到源头?”

为了解决这些问题,EasyDialog 使用了一个经典模式: 立即执行函数表达式(IIFE)

(function (global) {
  // 私有变量
  const DEFAULTS = { /* ... */ };
  let instances = [];

  // 私有方法
  function createDialog(config) { /* ... */ }
  function injectToDOM(html) { /* ... */ }

  // 公共接口暴露
  global.EasyDialog = {
    open: function (options) { /* 使用私有方法 */ },
    close: function () { /* ... */ }
  };

})(window);

看到没?所有内部实现都包裹在一个匿名函数内,外部无法访问 DEFAULTS instances ,只有明确导出的方法才可通过 EasyDialog.open() 调用。这种写法不仅防止了命名冲突,还天然支持状态管理——比如我们可以轻松追踪当前有多少个弹窗实例正在显示。

而且更妙的是,这套结构完全兼容多种引入方式:

  • CDN 直连 <script src="https://cdn.example.com/easydialog.min.js"></script>
  • NPM 安装 npm install easydialog + import EasyDialog from 'easydialog'
  • 本地静态引用 :适合内网或安全隔离环境

也就是说,无论你是老派 HTML 页面开发者,还是现代化构建体系下的 SPA 工程师,都能无缝接入。

那问题来了:既然 DOM 是动态创建的,样式怎么保证一致性?别急,这就引出了另一个关键点—— CSS3 动画 + Flexbox 布局


视觉体验的灵魂:为什么你的弹窗“不够丝滑”?

想象这样一个场景:用户点击按钮后,弹窗“啪”地一下跳出来,毫无过渡。再关闭时又是瞬间消失……这样的交互会给人一种“卡顿感”,哪怕性能再好,心理上也会觉得“慢”。

而 EasyDialog 的解决方案非常干净利落: 使用 CSS3 过渡动画

默认情况下,它会给 .easy-dialog 添加 fade 类,配合以下样式实现淡入淡出效果:

.easy-dialog {
  opacity: 0;
  visibility: hidden;
  transition: all 0.3s ease;
}

.easy-dialog.show {
  opacity: 1;
  visibility: visible;
}

简单?是的。但高效!因为这是由浏览器原生渲染引擎处理的动画,不会阻塞 JS 主线程,帧率稳定在 60fps 几乎毫无压力 💨。

但光有动画还不够。移动端适配才是真正的考验。

还记得那个几乎每个前端人都写过的 meta 标签吗?

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

没错,就是它!EasyDialog 默认开发环境基于 HTML5 语义化结构与 Flexbox 布局,结合这个视口设置,确保在手机、平板甚至折叠屏设备上都能自适应显示。

举个例子,警告弹窗的内容区域采用 display: flex; align-items: center; justify-content: space-between; ,图标、文本、关闭按钮自动排列整齐,无需额外媒体查询。


开发调试也很重要:你能看清自己的代码吗?

再好的设计,如果没有可观测性,也等于空中楼阁。

所以 EasyDialog 在设计之初就考虑到了调试友好性。推荐做法是结合 Chrome DevTools 的 Sources 面板断点 console.debug() 日志输出,来追踪实例初始化流程与生命周期钩子的调用顺序。

比如你可以这样加日志:

new EasyDialog({
  onShow: function () {
    console.debug('[EasyDialog] 弹窗已显示,开始加载数据...');
  },
  onDestroy: function () {
    console.debug('[EasyDialog] 实例销毁,清理资源完成');
  }
});

这样一来,当你在复杂单页应用(SPA)中排查“为什么弹窗没关掉?”、“资源为什么没释放?”这类问题时,就能快速定位瓶颈。

而且更进一步地说—— 这些生命周期钩子不仅仅是调试用的,它们本身就是功能拓展的关键入口

接下来我们就深入聊聊:EasyDialog 是如何通过这三个钩子( onShow , onHide , onDestroy ),让一个“静态提示框”蜕变为“智能交互容器”的。


三种基本弹窗类型,藏着多少设计细节?

在 Web 应用中,最常见的弹窗无非三类:

  1. 警告型(Warn)
  2. 确认型(Confirm)
  3. 输入型(Prompt)

听起来很简单对吧?但你知道吗,每一种的背后,其实都融合了人机交互的心理学原理、视觉层级设计以及安全性防护策略。

我们先从最常用的 警告型对话框 说起。

图标比文字更快抓住注意力?科学依据在这里!

根据 Nielsen Norman Group 的研究,带有图标的警告信息被注意到的概率比纯文本高出 47%

🧠 原因在于人类大脑的感知路径:我们首先识别颜色、形状、位置等基本特征,然后再去理解含义。这就是所谓的“自下而上”的认知过程。

所以当我们在警告弹窗里放一个黄色三角形+感叹号时,用户还没读文字就知道:“哦,这里有需要注意的事。”

但如果用了红色叉号呢?反而可能引发焦虑情绪 —— 因为红色通常代表“错误”或“危险”。一个小细节,情绪感受完全不同 😬。

Fitts 定律也告诉我们:目标越大、越靠近操作点,越容易被点击。因此,警告弹窗应出现在页面中央或右上角通知区,并保持足够的尺寸和对比度。

Miller 的认知负荷理论更是提醒我们:短期记忆只能记住 7±2 个信息块。所以警告内容必须简洁明了,不能堆一堆术语。

把这些心理学洞察转化为开发规范,就成了下面这些规则:

规范 实现建议
图标与文本间距 16px 左右,不要太挤
颜色搭配 白底黑字 + 黄标,高对比度
显示时间 3~5 秒自动关闭(非阻塞型)
手动关闭 提供 × 按钮

这些不是随便定的,而是经过大量 UX 测试验证的最佳实践。

视觉权重分配:让用户一眼看懂重点

在一个典型的警告弹窗中,用户的视线流动应该是这样的:

👉 图标 → 标题 → 正文 → 操作按钮

EasyDialog 利用 Flexbox 实现了这一布局流:

<div class="easydialog-warn">
  <i class="icon icon-warning"></i>
  <div class="content">
    <h3>警告</h3>
    <p>您正在进行的操作可能导致数据丢失。</p>
  </div>
  <button class="btn-close">×</button>
</div>

对应的 CSS 设置了清晰的字号、颜色和粗细差异:

.content h3 {
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.content p {
  font-size: 14px;
  color: #666;
}
元素 字号 颜色 权重 说明
图标 20px 橙色 (#ff9800) 视觉锚点
标题 16px 深灰 (#333) 中高 语义分类
正文 14px 灰 (#666) 补充说明
背景 - 浅黄 (#fff8e1) 区块隔离

再加上左侧 4px 的橙色边框,整体警示属性立刻拉满 ✅,完全符合 Material Design 的设计语言。

📌 小贴士:移动端记得给图标区域加上至少 44×44pt 的触摸热区,不然手指点不准可是要被产品经理骂的 😅。


模板字符串的力量:安全又高效的动态生成

前面说了这么多 UI 设计,那代码层面是怎么实现的呢?

EasyDialog 采用了 JavaScript 的 模板字符串(Template Literals) 来动态构建 HTML 结构。相比传统的字符串拼接,这种方式更加清晰、易维护。

function createWarnDialog(config) {
  const {
    title = '警告',
    message = '',
    showIcon = true,
    autoClose = true,
    duration = 3000
  } = config;

  const iconHTML = showIcon 
    ? `<i class="icon icon-warning"></i>` 
    : '';

  const closeBtnHTML = autoClose 
    ? '' 
    : `<button class="btn-close" data-role="close">×</button>`;

  const template = `
    <div class="easydialog easydialog-type-warn" role="alert">
      ${iconHTML}
      <div class="easydialog-content">
        <h3>${escapeHtml(title)}</h3>
        <p>${escapeHtml(message)}</p>
      </div>
      ${closeBtnHTML}
    </div>
  `;

  return injectToDOM(template, { autoClose, duration });
}

这里有几个关键点值得深挖:

  1. 解构赋值 + 默认值 :调用者可以只传部分参数,其余自动补全。
  2. 条件渲染 showIcon 控制是否插入图标节点,避免无效 DOM。
  3. XSS 防护 :所有用户输入都经过 escapeHtml() 处理。

说到 escapeHtml() ,它的实现非常巧妙:

function escapeHtml(text) {
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

利用浏览器原生的文本内容编码机制,将 <script> 等特殊字符转成实体,比如 < 变成 &lt; ,从根本上杜绝脚本注入风险。

💡 更进一步的做法是使用 DOMParser 解析 HTML 字符串,而不是直接用 innerHTML 插入,这样可以在解析阶段就过滤掉潜在恶意标签。

function injectToDOM(htmlString, options) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, 'text/html');
  const element = doc.body.firstElementChild;

  document.body.appendChild(element);

  if (options.autoClose) {
    setTimeout(() => fadeOutAndRemove(element), options.duration);
  }

  return element;
}

这种方法虽然稍重一点,但在处理不可信内容时更为安全。


生命周期钩子:让你掌控每一个关键时刻

如果说模板和样式决定了弹窗的“颜值”,那么 生命周期钩子 就赋予了它“灵魂”。

EasyDialog 提供了三个核心钩子:

  • onShow : 弹窗完全显示后触发
  • onHide : 即将隐藏前执行
  • onDestroy : DOM 移除后清理资源

这三个钩子构成了一个完整的状态流转闭环。我们来看一张详细的时序图:

sequenceDiagram
    participant User
    participant EasyDialog
    participant DOM
    participant Callback

    User->>EasyDialog: showDialog(config)
    EasyDialog->>EasyDialog: 初始化配置 merge(defaults, config)
    EasyDialog->>DOM: 创建弹窗容器与内容节点
    EasyDialog->>Callback: 执行 beforeShow() 钩子(如有)
    EasyDialog->>DOM: 将弹窗插入body
    EasyDialog->>DOM: 触发CSS过渡动画
    EasyDialog->>Callback: onShow() 回调执行
    Callback-->>EasyDialog: 可执行异步任务(如API请求)
    User->>EasyDialog: closeDialog()
    EasyDialog->>Callback: onHide() 回调执行
    EasyDialog->>DOM: 移除DOM节点
    EasyDialog->>Callback: onDestroy() 资源清理回调

注意看: onShow 是在 CSS 动画结束后才触发的!这意味着你在这个钩子里做任何事情,都不会影响动画流畅性。

举个实际例子:

const dialog = new EasyDialog({
  content: '正在加载用户信息...',
  onShow: function () {
    console.log('✅ [onShow] 弹窗已显示');
    fetch('/api/user/profile')
      .then(res => res.json())
      .then(data => {
        this.setContent(`欢迎回来,${data.name}!`);
      })
      .catch(err => {
        this.setContent('加载失败,请重试。');
      });
  },
  onDestroy: function () {
    console.log('🧹 [onDestroy] 实例资源已释放');
  }
});

dialog.show();

这个模式非常适合“懒加载”场景:先展示一个 loading 态,等数据回来再更新内容。既提升了响应速度,又避免了白屏尴尬。


高级玩法:不只是弹个框那么简单

你以为 EasyDialog 只能弹纯文本?Too young too simple 😏。

它最大的魅力在于支持 任意 HTML 内容注入 ,甚至可以嵌入图表、视频、表单等复杂组件。

但这也带来了新的挑战:性能、安全、样式冲突……

怎么办?EasyDialog 给出了三套解决方案。

方案一:DocumentFragment 批量插入,减少重排

如果你要动态生成一个包含 100 个选项的列表,用 innerHTML 逐个拼接会导致多次 reflow,页面卡顿明显。

更好的做法是使用 DocumentFragment

function createCustomContent(items) {
  const fragment = document.createDocumentFragment();
  const container = document.createElement('ul');
  container.className = 'custom-list';

  items.forEach(text => {
    const li = document.createElement('li');
    li.textContent = text;
    container.appendChild(li);
  });

  fragment.appendChild(container);
  return fragment;
}

这样所有的 DOM 操作都在内存中完成,最后一次性挂载,性能提升显著 ⚡️。

方案二:沙箱式脚本执行,拒绝 XSS 攻击

虽然允许 <script> 标签听起来很酷,但它也是 XSS 攻击的主要入口。所以 EasyDialog 默认禁用脚本解析。

正确的做法是: 分离 HTML 与 JS 逻辑 ,通过 onShow 手动加载外部库。

例如嵌入 ECharts 图表:

new EasyDialog({
  content: '<div id="chart-placeholder" style="width:400px;height:300px;"></div>',
  onShow: function () {
    import('https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js')
      .then(() => {
        const chart = echarts.init(document.getElementById('chart-placeholder'));
        chart.setOption({ /* 配置项 */ });
      })
      .catch(err => console.error('加载失败:', err));
  }
}).show();

好处显而易见:

  • 脚本按需加载,不污染全局
  • 执行时机可控,避免提前报错
  • 完全绕过 innerHTML 解析风险

方案三:Shadow DOM 实现样式隔离

第三方内容最容易出问题的就是样式冲突。别人写的 .card { margin: 0; } 会不会把你整个页面搞乱?

解决办法就是 Shadow DOM:

class IsolatedDialog {
  constructor(htmlContent) {
    this.content = htmlContent;
  }

  show() {
    const host = document.createElement('div');
    const shadowRoot = host.attachShadow({ mode: 'open' });

    shadowRoot.innerHTML = `
      <style>
        :host { display: block; padding: 16px; }
        .card { background: #f0f0f0; border-radius: 8px; padding: 12px; }
      </style>
      <div class="card">${this.content}</div>
    `;

    new EasyDialog({
      content: host,
      width: 500,
      height: 300
    }).show();
  }
}

Shadow DOM 内部的样式不会泄露出去,也不会受到外部样式影响,真正实现了“组件级封装”。

方法 是否原生支持 隔离强度 兼容性
Shadow DOM ✅ 是 ⭐⭐⭐⭐⭐ 现代浏览器
CSS Modules ❌ 需构建工具 ⭐⭐⭐⭐ 广泛
BEM 命名法 ✅ 是 ⭐⭐⭐ 手动维护成本高

推荐优先使用 Shadow DOM,尤其在微前端或多团队协作项目中。


可访问性不容忽视:键盘党 & 屏幕阅读器用户怎么办?

一个好的弹窗,不仅要看得舒服,还得“摸得着”。

特别是对于视障用户或习惯用键盘操作的人来说,焦点管理和快捷键支持至关重要。

自动聚焦 + 焦点循环

理想状态下,弹窗打开后应该自动把焦点移到第一个可操作元素上(比如“确定”按钮),并且禁止 Tab 键跳出到背景内容。

let lastFocusElement = null;

const dialog = new EasyDialog({
  onShow: function () {
    lastFocusElement = document.activeElement;
    const firstBtn = this.element.querySelector('#confirm-btn');
    firstBtn.focus();
  },
  onHide: function () {
    if (lastFocusElement && lastFocusElement.focus) {
      lastFocusElement.focus();
    }
  }
});

// 实现焦点循环
dialog.element.addEventListener('keydown', function (e) {
  if (e.key === 'Tab') {
    const buttons = dialog.element.querySelectorAll('button');
    const first = buttons[0];
    const last = buttons[buttons.length - 1];

    if (e.target === last && !e.shiftKey) {
      e.preventDefault();
      first.focus();
    } else if (e.target === first && e.shiftKey) {
      e.preventDefault();
      last.focus();
    }
  }
});

这样一来,键盘用户也能顺畅完成操作,不会“迷失”在页面中。

快捷键支持:ESC 关闭,Enter 确认

标准行为约定:

  • Escape → 关闭弹窗
  • Enter → 触发默认按钮点击
dialog.element.addEventListener('keydown', function (e) {
  if (e.key === 'Escape') {
    dialog.close();
  } else if (e.key === 'Enter' && e.target.tagName === 'BUTTON') {
    e.target.click();
  }
});

注意:Enter 只有在按钮上按下才触发,避免在输入框里误提交。

ARIA 支持:让屏幕阅读器“读懂”弹窗

最后一步,加上无障碍属性:

<div role="dialog" aria-modal="true" aria-labelledby="dlg-title">
  <h3 id="dlg-title">警告</h3>
  <p>检测到非法输入,请修正后再提交。</p>
  <button>确定</button>
</div>
ARIA 属性 作用
role="dialog" 告知屏幕阅读器这是一个对话框
aria-modal="true" 表示模态,背景不可访问
aria-labelledby 指定标题,便于语音朗读

这几行代码,能让千万用户的体验上升一个台阶 🌍。


和 jQuery 共舞:如何在旧项目中焕发新生?

尽管现在主流是 React/Vue,但仍有大量企业级项目使用 jQuery。EasyDialog 对此非常友好。

统一绑定多个触发按钮

$('.trigger-btn').on('click', function () {
  const config = {
    title: '操作提示',
    content: $(this).data('message') || '默认提示',
    type: 'warn',
    onOk: () => console.log('用户确认')
  };
  EasyDialog.open(config);
});

利用 jQuery 的事件委托机制,轻松实现批量绑定,还能动态读取 data-* 属性传参。

自定义动画效果

想换个滑动进入的效果?没问题!

$.fn.easyAlert = function (msg, options) {
  const defaults = {
    animateIn: ($el) => $el.hide().slideDown(300),
    animateOut: ($el, done) => $el.fadeOut(200, done)
  };

  const config = $.extend({}, defaults, options, { content: msg });
  return EasyDialog.open(config);
};

$('#alert-trigger').click(() => {
  $.easyAlert('这是一条滑动进入的消息!');
});

封装成 jQuery 插件后,还能支持链式调用,开发效率翻倍!

注册全局消息方法

为了降低团队使用门槛,可以注册一套语义化 API:

(function ($) {
  window.$msg = {
    warn: (text, cb) => EasyDialog.open({ type: 'warn', content: text, onOk: cb }),
    confirm: (text, okFn, cancelFn) => EasyDialog.open({
      type: 'confirm',
      content: text,
      onOk: okFn,
      onCancel: cancelFn
    }),
    success: (text) => EasyDialog.open({
      type: 'success',
      content: text,
      autoClose: 2000
    })
  };
})(jQuery);

从此以后,调用只需要一句话:

$btn.click(() => {
  $msg.confirm('是否删除?', 
    () => $msg.success('删除成功!'), 
    () => console.warn('取消')
  );
});

👏 简洁、清晰、统一,新人接手也不怕!

flowchart TD
    A[用户点击按钮] --> B{判断操作类型}
    B -->|警告类| C[调用$msg.warn()]
    B -->|确认类| D[调用$msg.confirm()]
    B -->|成功反馈| E[调用$msg.success()]
    C --> F[打开Warn弹窗]
    D --> G[等待用户选择]
    G --> H[执行对应回调]
    E --> I[自动两秒后关闭]

这张流程图清楚展示了封装后的调用路径,大大增强了可维护性。


写在最后:一个优秀插件的自我修养

EasyDialog 看似只是一个“弹窗工具”,但实际上它的设计理念涵盖了:

  • 🛠️ 模块化封装
  • 🎨 视觉与交互设计
  • 🔐 安全防护机制
  • 🧠 用户认知模型
  • ⚙️ 生命周期控制
  • 📱 移动端适配
  • ♿ 无障碍支持
  • 🔄 工程化集成

每一个细节都不是偶然,而是长期打磨的结果。

它告诉我们: 真正的“轻量级”,不是代码少,而是责任清晰、边界明确、易于组合

未来,随着微前端、低代码平台的发展,这类高内聚、低耦合的独立组件将会越来越重要。

也许有一天,你的项目里不再需要引入整个 UI 框架,而是像搭积木一样,用一个个像 EasyDialog 这样的“小而美”模块,拼出属于你自己的交互宇宙 🚀。

而现在,你已经掌握了其中一块关键拼图。

🎉 所以,还等什么?赶紧去试试吧!

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:EasyDialog是一款基于JavaScript的轻量级弹窗插件,支持创建警告、确认、提示及自定义输入等多种弹出层,提升前端交互体验。本源码包包含丰富的EasyDialog使用示例,涵盖基础对话框到复杂用户交互场景,帮助开发者快速掌握其API调用方式与实际应用技巧。通过学习这些经过测试的demo源码,开发者可熟练运用EasyDialog实现美观、响应式的弹出层,并结合jQuery等库优化前端交互逻辑,提高开发效率与用户体验。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Delphi 12.3 作为一款面向 Windows 平台的成开发环境,由 Embarcadero Technologies 负责其持续演进。该环境以 Object Pascal 语言为核心,并依托 Visual Component Library(VCL)框架,广泛应用于各类桌面软件、数据库系统及企业级解决方案的开发。在此生态中,Excel4Delphi 作为一个重要的社区开源项目,致力于搭建 Delphi 与 Microsoft Excel 之间的高效桥梁,使开发者能够在自研程序中直接调用 Excel 的文档处理、工作表管理、单元格操作及宏执行等功能。 该项目以库文件与组件包的形式提供,开发者将其成至 Delphi 工程后,即可通过封装良好的接口实现对 Excel 的编程控制。具体功能涵盖创建与编辑工作簿、格式化单元格、批量导入导出数据,乃至执行内置公式与宏指令等高级操作。这一机制显著降低了在财务分析、报表自动生成、数据整理等场景中实现 Excel 功能成的技术门槛,使开发者无需深入掌握 COM 编程或 Excel 底 API 即可完成复杂任务。 使用 Excel4Delphi 需具备基础的 Delphi 编程知识,并对 Excel 对象模型有一定理解。实践中需注意不同 Excel 版本间的兼容性,并严格遵循项目文档进行环境配置与依赖部署。此外,操作过程中应遵循文件访问的最佳实践,例如确保目标文件未被独占锁定,并实施完整的异常处理机制,以防数据损毁或程序意外中断。 该项目的持续维护依赖于 Delphi 开发者社区的体贡献,通过定期更新以适配新版开发环境与 Office 套件,并修复已发现的问题。对于需要深度融合 Excel 功能的 Delphi 应用而言,Excel4Delphi 提供了经过充分测试的可靠代码基础,使开发团队能更专注于业务逻辑与用户体验的优化,从而提升整体开发效率与软件质量。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值