news 2026/10/20 10:07:10

Qt基础学习总结软件:界面框架、信号槽与数据存储实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qt基础学习总结软件:界面框架、信号槽与数据存储实战解析

简介:面向Qt初学者的基础学习总结工程,通过登录管理、控件布局、窗口切换等典型场景串联核心知识点,适合正在学习C++/Qt桌面开发、希望对照真实工程理解信号与槽、事件循环、模型视图等机制的人群。包内含34个文件,压缩包大小约2.33MB,其中5个cpp源文件与4个h头文件构成主要程序逻辑,4个ui界面文件对应各窗口设计,14个png图片与2张jpg背景图提供界面素材,另有qrc资源清单、pro工程配置及gif动态预览图,便于直接打开工程查看结构。项目已有114人浏览学习,可作为从基础语法过渡到实际开发的参考样例。通过对照源码、界面与资源文件,可快速掌握Qt工程组织方式、跨窗口协作写法以及图片资源管理流程,适合课后巩固或期末综合练习时使用。

1. 从 Qt 基础学习到可运行的总结软件:资源包里到底有什么

Qt 基础学习最怕什么?不是 API 记不住,而是学完一遍回头发现笔记散落各处,代码样例根本对不上知识点。这套「Qt 基础学习总结软件」就是干这个的——把 Qt 控件、信号槽、布局、事件处理的笔记与代码样例整合进一个可运行的桌面程序,左侧目录树按知识点分类,右侧显示对应笔记与可复现代码,还内置了一批笔记范文模板和示例素材,拿来即用。适合刚学完 Qt 基础、正在做第一个综合项目的人,也适合导师拿它当教学案例模板。工程纯 Qt Widgets 实现,不依赖第三方库,Qt 5.15 及以上就能编译。后面按「结构 → 运行 → 避坑 → 改造」的顺序展开。

2. 核心模块拆解:界面框架、信号槽与数据存储怎么选

2.1 主窗口架构:QSplitter 加 QTreeWidget 的组合逻辑

打开 MainWindow.cpp 第一眼就能看到界面组装代码。总结软件的界面没有用 QTabWidget 做多页签,而是用 QSplitter 把窗口分成左右两块:左边是 QTreeWidget 目录树,右边是 QTextEdit 内容区。这种布局在知识管理类工具里很常见,原因有两个。

第一,QTabWidget 的页签栏在条目多时横向溢出,而且每加一个知识点就要新增一个页面对象,代码量成倍增长。QTreeWidget 加 QSplitter 的方案里,左侧树节点只存标题和 ID,右侧 QTextEdit 统一承接内容显示,新增条目只需要往树里插入一行数据。

第二,QSplitter 允许用户拖动分栏比例,窗口窄的时候可以把左侧目录收窄,这个交互 QTabWidget 给不了。常见做法是用 setStretchFactor 控制初始比例:

QSplitter *splitter = new QSplitter(Qt::Horizontal, this); splitter->addWidget(treeWidget); splitter->addWidget(contentEdit); splitter->setStretchFactor(0, 1); // 左侧目录占 1 份 splitter->setStretchFactor(1, 3); // 右侧内容占 3 份 splitter->setCollapsible(0, false); // 禁止完全收起左栏

setStretchFactor 的参数是 (index, stretch),index 从 0 开始,stretch 是权重比。设成 1:3,窗口拉大时右侧内容区获得更多空间。setCollapsible(0, false) 防止用户把左侧栏拖没后找不到目录树,这个坑等到了第 4 章细说。

内容区用 QTextEdit 而不是 QPlainTextEdit,因为总结软件里要展示代码片段,QTextEdit 支持富文本渲染,可以给代码块加底色和等宽字体。如果只需要纯文本,换成 QPlainTextEdit 性能更好,大文件打开不卡。树节点存储这块,建议用 Qt::UserRole 保存条目 ID,不要拼在显示文本里,后续做搜索和定位时免得反复解析字符串。QTreeWidget 默认样式比较朴素,建议调用 setHeaderHidden(true) 隐藏列头,纯目录导航用不上;想区分信号槽、布局、事件这些大分类,可以用 setForeground 按分类给文字染色,扫一眼就能定位。

提示:QSplitter 的 setStretchFactor 只在子控件未被用户拖过时生效。用户手动调整过一次比例后,程序里设置的权重会被覆盖,想恢复默认比例需要调用 splitter->setSizes({200, 600})。

2.2 信号槽连接:三种写法与各自边界

Qt 基础学习里信号槽是重头戏。总结软件三处典型连接正好覆盖三种写法。第一处是树节点点击:

// MainWindow 构造函数中 connect(treeWidget, &QTreeWidget::itemClicked, this, &MainWindow::onTreeItemClicked);

这是函数指针写法,编译期检查信号和槽签名是否匹配,推荐优先用。注意 itemClicked 的信号参数是 (QTreeWidgetItem*, int),槽函数签名必须一致,参数个数对不上编译器直接报错。旧式 SIGNAL/SLOT 宏写法参数类型是字符串比对,int 和 bool 这种不同基础类型不会被判定匹配,连接在运行期失败、编译期不报错,排查起来很费劲,新代码不建议用。

第二处是搜索框的实时过滤,用 lambda 写法:

connect(searchEdit, &QLineEdit::textChanged, this, [this](const QString &text) { // 顶层节点逐个匹配标题,不匹配的隐藏 for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) { QTreeWidgetItem *item = treeWidget->topLevelItem(i); item->setHidden(!item->text(0).contains(text, Qt::CaseInsensitive)); } });

lambda 写法适合槽逻辑短、没必要单独声明成员函数的场景。注意这里捕获了 this,lambda 里访问 treeWidget 等成员变量,必须保证接收者对象存活。QObject 父子关系会在析构时自动断开连接,只要接收者是 this 的子对象或父对象就安全。如果 lambda 捕获的是局部变量且接收者不是 this,生命周期就要格外小心,局部变量销毁后 lambda 还在执行就是野指针问题。

第三处是自定义信号,比如内容编辑后的「已修改」标记。做法是继承 QTextEdit 重写键盘事件:

class ContentEditor : public QTextEdit { Q_OBJECT signals: void modified(); protected: void keyPressEvent(QKeyEvent *event) override { QTextEdit::keyPressEvent(event); if (!event->text().isEmpty()) emit modified(); } };

自定义信号触发时机要斟酌:键盘事件里每次按键都发信号,高频输入会把界面拖慢。实际项目里一般配合 QTimer 做防抖,300 毫秒内没有新输入才真正触发保存。emit modified() 只负责通知,实际保存逻辑放在槽函数里,信号和实现解耦,后续加自动保存、手动保存多入口都方便。

2.3 数据存储:JSON 方案还是 QSettings

总结软件的笔记数据有两个存储方向。QSettings 适合存配置项——窗口大小、分栏比例、最近打开的条目,底层是注册表或 ini 文件封装。笔记正文是结构化、可嵌套的内容,用 JSON 文件更合适。两者的适用边界如下:

对比维度QSettingsJSON 文件 (QJsonDocument)
适合数据窗口位置、分栏比例、最近打开项笔记正文、嵌套结构、可分发内容
存储位置注册表 / ini 文件,位置由系统定自定义路径,随程序分发
读写方式setValue / value 键值对序列化 / 反序列化整个对象树
可读性键值扁平,一般Indented 模式可读性好,便于调试
跨平台差异Windows 注册表、Linux 配置文件,位置不同路径自行控制,行为一致

资源包用的是 QJsonDocument 写文件。核心保存函数大概长这样:

void MainWindow::saveData(const QTreeWidget *tree, const QString &filePath) { QJsonArray rootArray; // 最外层是分类数组 for (int i = 0; i < tree->topLevelItemCount(); ++i) { QTreeWidgetItem *topItem = tree->topLevelItem(i); QJsonObject topObj; topObj["category"] = topItem->text(0); QJsonArray childArray; // 分类下的笔记列表 for (int j = 0; j < topItem->childCount(); ++j) { QTreeWidgetItem *child = topItem->child(j); QJsonObject childObj; childObj["title"] = child->text(0); childObj["content"] = child->data(0, Qt::UserRole).toString(); childArray.append(childObj); } topObj["items"] = childArray; rootArray.append(topObj); } QFile file(filePath); if (file.open(QIODevice::WriteOnly)) { file.write(QJsonDocument(rootArray).toJson(QJsonDocument::Indented)); } }

关键设计:笔记正文存在 QTreeWidgetItem 的 data(0, Qt::UserRole) 里而不是显示文本里。显示文本是标题,UserRole 存正文,树节点列表不会因为正文很长而渲染卡顿。Qt::UserRole 是自定义数据起始 role 枚举值,从它开始往上都可以自由使用。QJsonDocument::Indented 让文件带缩进和换行,调试时可读性高;笔记文件到了几 MB 以上再改成 Compact 减少体积和写入耗时。

读文件用 QJsonDocument::fromJson 配合 QJsonParseError 做错误接住——路径写错或文件被外部编辑器改坏时,至少能弹出提示而不是静默崩溃。加载完成后建议校验根节点类型是 QJsonArray,防止拿了个空对象就直接遍历导致逻辑异常。

3. 把模板跑起来:环境配置、qmake 编译与首屏验证

3.1 工程文件与构建流程

先说环境。这套工程走 qmake 体系,不是 CMake,工程文件后缀是 .pro。拿到源码包先确认目录结构,心里有数再动手:

QtSummary/ ├── QtSummary.pro ├── main.cpp ├── MainWindow.h ├── MainWindow.cpp ├── resources.qrc ├── assets/ │ ├── add.png │ └── search.png ├── seed.json └── README.md

seed.json 是预置的知识点种子数据,第一次运行程序时复制为 notes.json。assets 目录放界面图标,通过 resources.qrc 打进二进制。工程文件是理解构建逻辑的入口:

QT += core gui widgets TARGET = QtSummary TEMPLATE = app CONFIG += c++11 SOURCES += \ main.cpp \ MainWindow.cpp HEADERS += \ MainWindow.h RESOURCES += \ resources.qrc

几个点。QT += widgets 在 Qt 5 及以上必须显式写,漏掉的话 QMainWindow、QTextEdit 全部不可用,报错却常是「找不到头文件」而不是「模块未引入」,很迷惑。CONFIG += c++11 给老工具链兜底,编译器默认 C++17 就不受影响。TARGET 决定生成的可执行文件名字,这里叫 QtSummary。

命令行构建流程(Windows 下用 Qt 自带命令提示符,MinGW 版打开 MinGW 提示符,MSVC 版打开 x64 Native Tools 提示符):

mkdir build && cd build qmake ../QtSummary.pro -spec win32-g++ # MinGW 用 win32-g++,MSVC 用 win32-msvc mingw32-make -j4 # MSVC 环境对应 nmake

qmake 的 -spec 参数指定编译器描述文件,选错最直接的后果是生成的目标文件格式跟当前编译器不匹配。如果提示 qmake 不是内部或外部命令,就是 Qt 的 bin 目录没加进 PATH,用 Qt 自带的命令提示符启动不会有这个问题。Qt Creator 里直接打开 .pro 选套件构建当然更省事,命令行方式适合想理解构建过程、后面要写自动化脚本的人。Qt Creator 默认开启 shadow build,构建目录和源码目录分离,产物在 build-QtSummary-xxx 下;命令行手动构建时建议模仿这个习惯,在 build 目录里跑 qmake,保持源码目录干净。debug 构建保留 qDebug 输出和完整调试信息,release 构建体积小、速度快,但资源加载失败这类提示在 release 下可能看不到,排查问题优先用 debug 构建。

3.2 资源文件系统:qrc 路径的边界与陷阱

resources.qrc 管理图标和示例图片。qrc 本质是 XML 格式:

<RCC> <qresource prefix="/icons"> <file alias="add.png">assets/add.png</file> <file alias="search.png">assets/search.png</file> </qresource> </RCC>

加进 qrc 后,代码里引用路径是 :/icons/add.png,冒号开头是 Qt 资源系统固定前缀。prefix 属性把散落的图片目录映射成虚拟路径,alias 可以重命名避免文件名冲突。qrc 文件里的路径是相对 qrc 文件所在目录写的,不是相对工程根目录——很多人第一次写就在这里踩坑。对应代码里的加载方式是:

QIcon addIcon(":/icons/add.png"); ui->addButton->setIcon(addIcon);

常见误区是把图片放工程目录就觉得能直接加载,运行时用相对路径 "assets/add.png" 去读,程序部署到别的目录后图片全丢。qrc 资源编译进二进制,不存在部署路径问题,这是它最大优势。但缺点也明显:图片更新必须重新编译整个程序。所以头像、壁纸这类用户自定义资源要放外部目录,程序里优先检查外部路径,找不到再回退到 qrc。另外 qrc 默认启用 zlib 压缩,小图标影响不大,图片很多时可以对比一下压缩开关对资源体积和加载速度的影响。

3.3 编译运行与功能验证清单

编译通过后运行程序,按下面的清单逐项验证,每一项都对应总结软件的核心功能:

验证项操作预期结果
启动加载直接运行程序左侧树显示预置分类,每类至少两条笔记
内容显示点击任意笔记标题右侧显示对应正文,代码片段正常渲染
搜索过滤输入「lambda」树节点即时过滤,只保留标题匹配项
新增笔记点击新增按钮,填标题与正文树中多出新节点,内容区同步刷新
持久化关闭程序重新打开新增笔记仍在,原有数据不丢失

第五步验证的是 saveData/loadData 两个函数。如果重启后新笔记消失,优先检查工作目录下有没有生成 notes.json——程序崩溃或任务管理器强制结束进程时 saveData 没机会执行,容易被误判成保存逻辑有 bug。我一般会在 saveData 入口加一行 qDebug() << "saveData called" 确认是否走到写文件逻辑,比反复重启排查快得多。运行目录和源码目录不是同一个位置时,还要确认 notes.json 到底生成在哪,别找错地方。

如果程序启动就闪退,先查 main.cpp 里有没有在 QApplication 创建前调用依赖事件循环的 API;再查 seed.json 是不是被改成了非法 JSON,loadSeedData 解析失败后直接 return,窗口还没显示就退出。这类空白窗口一闪而过的情况,最容易让人误以为是 Qt 环境本身坏了。

4. 避坑指南:Qt 新手最容易翻车的五个现场

下面这五条是新手期血泪经验换来的,每一条按「现象 → 原因 → 解决」说清楚,照着排查能省下大半天时间。

4.1 中文乱码:源文件编码与字符串处理的连锁反应

现象:界面按钮和标题显示成乱码,MSVC 下编译报 C2001 或 C2143 错误,注释没事但字符串常量就出错。

原因:源文件是 UTF-8 编码,编译器按本地代码页(GBK)解析字符串字面量,中文字符被拆成多字节解析,字符串引号配对错乱。Qt 5 里 QStringLiteral 宏声明了源码按 UTF-8 处理,但不声明时默认走本地编码。

解决:统一三件事——源文件保存为 UTF-8(带 BOM 更稳),工程文件加 CONFIG += utf8_source(MSVC 环境生效),显示层用 tr() 或 QStringLiteral 包住中文字符串。MinGW 对 UTF-8 源文件支持比 MSVC 好,问题集中在 Windows + MSVC 组合。项目里已经写了很多裸中文字符串的,最省事是全局替换成 tr("中文"),配上 lupdate/lrelease 生成翻译文件,顺手把多语言支持做掉。

4.2 信号槽连了没反应:重载与类型不匹配

现象:connect 写在构造函数里,编译过了,运行不报错,但点击按钮、拖动滑块就是没反应。

原因:两种情况最常见。一是信号或槽是重载函数,connect 时没有指定具体重载版本,匹配到错误的一个;二是旧式 SIGNAL/SLOT 宏写法下,信号和槽的参数类型必须字符串完全匹配,int 和 bool 这种不同类型不会被判定匹配,连接在运行期静默失败。

解决:优先用新式函数指针语法,让编译器做类型检查。重载场景用 QOverload ::of(&QComboBox::currentIndexChanged) 显式指定。排查连接是否生效,最快的是在槽函数第一行加 qDebug(),运行时看输出面板有没有打印。没打印就把 connect 调用点往前移,检查是不是对象还没创建就 connect,比如 connect 写在成员初始化列表之前。还有一个隐蔽场景:类没加 Q_OBJECT 宏,moc 处理不了元对象信息,新式语法 connect 会直接报编译错,虽然是编译期报错,但容易让人摸不着头脑,看到跟 moc 相关的错误先查 Q_OBJECT。

4.3 布局失效:setGeometry 和 addWidget 混用的后果

现象:窗口拉大后控件不跟着变,或者控件叠在一起,只显示最后一个设过位置的控件。

原因:代码里先用了 setFixedSize 或 setGeometry 给控件设绝对位置,又 addWidget 加进布局。布局管理器接管后,绝对几何设置部分保留、部分被覆盖,表现就是控件「各有各的想法」。

解决:二选一。全走布局:删掉所有 setGeometry 调用,控件 addWidget 时不传父对象,布局设置完调用 setLayout(this)。或者放弃布局:手动在 resizeEvent 里计算坐标,适合自定义绘制控件,不适合普通按钮和文本框。总结软件这类工具界面,守一条规矩——布局优先,用 setMinimumSize/setMaximumSize 约束边界范围,不用 setFixedSize,除非是固定尺寸的对话框。

4.4 资源路径玄学:qrc 路径写错却不报错

现象:程序能编译,运行不崩,但图标空白、图片加载不出来,控制台也没提示。

原因:qrc 里写了 assets/add.png ,但 assets 目录实际在工程根目录之外,或者 qrc 里的相对路径算错了层数;代码里写的是 "://icons/add.png"(双冒号)或漏了开头冒号。资源加载失败的 qDebug 提示只在 debug 构建输出,release 构建下静默失败。

解决:第一步,确认 qrc 内文件路径是相对 qrc 文件所在目录写的,不是相对工程根目录。第二步,代码里统一 QIcon(":/icons/add.png") 完整路径,别省略前缀。第三步,Qt Creator 里双击 qrc 文件,看资源树有没有红色感叹号,有就说明对应文件没找到。第四步,还查不出来就建临时 test.qrc 只放一张图逐步验证,加载成功再往上加内容。

4.5 高 DPI 下界面发糊:缩放策略没设置

现象:2K/4K 显示器上文字发虚,图片边缘有锯齿,Windows 缩放比不是 100% 时尤其明显。

原因:Qt 5 默认不开启高 DPI 缩放,程序按逻辑像素绘制,系统缩放后直接在位图上拉伸。Qt 5.6 起提供高 DPI 支持但默认关闭,Qt 6 默认开启。这套工程跑 Qt 5.15,不设置的话高分屏体验就是糊的。

解决:main.cpp 里、QApplication 构造之前加:

#include <QApplication> int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif QApplication app(argc, argv); // ... }

AA_EnableHighDpiScaling 让 Qt 按系统缩放比自动调整 DPI,AA_UseHighDpiPixmaps 让图标在高分屏下使用高分辨率版本。setAttribute 必须在 QApplication 创建之前调用,写在构造之后无效。Qt 6 已默认开启,所以用宏隔开版本差异。改完后在 150% 缩放的机器上跑一遍,按钮、图标、文字都应该清晰锐利。

5. 扩展改造:把总结软件变成自己的学习工具

拿到能跑的模板,下一步是改造成贴合自己学习节奏的工具。总结软件的核心价值不是「看别人的笔记」,而是「往里填自己的笔记」。我建议分三个阶段。

第一阶段,数据驱动。启动时检测笔记文件:存在就加载,不存在就把预置种子数据写入。这样反复删改内容都不怕把模板改坏,随时恢复初始状态:

if (!QFile::exists("notes.json")) { loadSeedData(); // 从 qrc 读 seed.json,写入工作目录 } else { loadData("notes.json"); }

第二阶段,编辑器增强。把 QTextEdit 换成 QTextBrowser 加编辑模式切换,或者用 QTextDocument::setMarkdown 直接支持 Markdown 渲染(Qt 5.14 起可用)。配合 QTimer 做自动保存:停止输入 500 毫秒后保存当前条目,避免手动保存遗漏,也不用担心高频写文件。

第三阶段,检索增强。把树过滤升级为全文搜索,遍历每个节点的 UserRole 正文,用 QString::contains 做大小写不敏感匹配。几百条笔记以内性能没问题,超过一千条建议上 SQLite,Qt 的 QSQLITE 插件是默认自带的基础驱动。

验证方法我习惯这样做:改完一个功能,先跑手工清单(启动、加载、增删改查、重启持久化),再开 Qt Creator 的 debug 构建把警告清零,最后把构建产物复制到一台没装 Qt 的干净机器跑一遍。干净环境能跑,才算确认依赖没漏。

路径处理是每次必查点。总结软件里文件读写写成相对路径的话,程序工作目录可能和可执行文件目录不一致——资源管理器双击启动时工作目录是 exe 所在目录,命令行带 cd 启动时又是另一个目录。最可靠的做法是用 applicationDirPath 拼绝对路径:

#include <QDir> QString dataDir = QCoreApplication::applicationDirPath() + "/data"; QDir().mkpath(dataDir); // 目录不存在则创建 QString dataFile = dataDir + "/notes.json";

从那以后我每次改 Qt 项目,第一件事就是检查所有外部文件引用是否都经过了 applicationDirPath,强制自己走一遍这个流程,至少省下十几次「明明路径没错却找不到文件」的排查时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 10:06:41

股票行情保存为 Parquet,目录怎么设计?Python 量化数据存储实战

一句话结论&#xff1a; 对于大多数 Python 量化研究项目&#xff0c;建议按照市场、数据类型和交易日期组织 Parquet 文件&#xff0c;避免将所有股票行情堆进一个目录&#xff0c;也不要为每只股票的每个交易日创建大量零散文件。目录结构应优先服务于实际查询方式&#xff0…

作者头像 李华
网站建设 2026/10/20 10:06:40

C# OPC UA客户端源码实战:西门子机床与KepServer对接指南

简介&#xff1a;C# OPC UA客户端源码&#xff0c;是一个面向工业通讯开发者的可直接运行参考工程&#xff0c;既可用于连接西门子机床自带OPC UA服务器&#xff0c;也兼容Kepware KepServer等第三方OPC UA服务&#xff0c;重点弥补了网上大多源码不支持西门子用户名密码或加密…

作者头像 李华
网站建设 2026/10/20 10:06:14

tester-army/e2e:面向生产环境的多智能体端到端测试框架

1. 项目概述&#xff1a;这不是又一个“跑个 demo 就吹爆”的框架&#xff0c;而是真正在工程现场能扛住压测的 agentic 测试新范式“实测&#xff5c;2026 最火的 agentic 测试框架 tester-army/e2e&#xff0c;我 10 分钟跑通了第一个用例”——这个标题里藏着三个关键信号&a…

作者头像 李华
网站建设 2026/10/20 10:05:59

威伦触摸屏直连变频器:基于MODBUS RTU的RS485通信组态与调试全攻略

威伦触摸屏直连变频器这件事&#xff0c;我第一次听说时也觉得不靠谱。当时手头有个设备改造&#xff0c;三台变频器控制收卷、牵引、放卷&#xff0c;客户不想加PLC&#xff0c;说触摸屏能不能直接干。我翻了一圈资料&#xff0c;又拿手头的威伦屏实测了一个下午&#xff0c;发…

作者头像 李华
网站建设 2026/10/20 10:05:13

间接提示注入:2026年AI安全最大危机与分层防御实战指南

1. 间接提示注入&#xff1a;凭什么被称为2026年AI安全最大危机1.1 先说清楚什么是间接提示注入做AI安全的同行应该对“提示注入”这个词不陌生。简单说&#xff0c;就是有人故意在发给大模型的文本里&#xff0c;藏一段足以改变模型行为的指令&#xff0c;让模型放弃原来被交代…

作者头像 李华
网站建设 2026/10/20 10:04:44

Vue前端用pdf-lib实现PDF盖章签名下载:坐标系避坑与完整指南

简介&#xff1a;这是一份基于Vue.js实现PDF上传、盖章与签名功能的完整项目源码包&#xff0c;面向需要为合同、审批等文档流程引入在线签章能力的开发者&#xff0c;适合具备一定Vue基础、希望快速落地的前端学习者。压缩包共19个文件&#xff0c;含5个Vue组件、5个JavaScrip…

作者头像 李华