5分钟搞定:用Quill.js快速搭建一个支持图片上传的富文本编辑器
从零到一用Quill.js构建一个支持云端图片上传的现代富文本编辑器如果你正在为一个内容管理后台、博客系统或者用户反馈模块寻找一个既轻量又强大的富文本编辑器那么Quill.js很可能就是你一直在找的答案。它不像一些老牌编辑器那样臃肿却提供了足够丰富的API和模块化设计让你能快速集成并深度定制。特别是当项目需求涉及到图片、视频等多媒体内容的上传时如何优雅地处理这些非文本内容往往是决定编辑器体验好坏的关键。今天我们就抛开那些复杂冗长的配置文档直接切入核心看看如何用最短的时间打造一个不仅能用而且好用的、支持图片上传的编辑器。1. 为什么选择Quill.js不仅仅是另一个RTE库在开源富文本编辑器Rich Text Editor, RTE的生态里TinyMCE和CKEditor无疑是知名度最高的两位“老大哥”。它们功能全面企业级支持完善但随之而来的往往是庞大的体积和相对复杂的配置。对于许多现代Web应用尤其是那些对首屏加载速度和包体积有严格要求的项目来说一个更轻量、更“现代化”的选择变得尤为重要。Quill.js正是在这种背景下脱颖而出的。它的核心设计哲学是可扩展性和简洁的API。与直接操作document.execCommand这种略显“古老”的方式不同Quill自己维护了一套称为“Parchment”的文档模型。这套模型将编辑器内容抽象为一系列可序列化的操作Delta格式这使得实现协同编辑、历史记录追踪等功能变得异常清晰。对于开发者而言这意味着你不再需要与混乱的HTML字符串和浏览器兼容性问题直接搏斗而是通过一套稳定、可预测的API来操作内容。提示Delta是Quill内部用于描述内容变化的JSON格式。一个简单的Delta对象可能长这样{ ops: [{ insert: Hello }, { insert: World, attributes: { bold: true } }] }。这种结构化的数据格式远比原始的HTML字符串更易于处理、存储和传输。从技术栈适配性来看Quill也做得相当出色。它本身不依赖任何前端框架可以轻松集成到React、Vue或Angular项目中。社区也提供了相应的封装库如react-quill、vue-quill-editor进一步降低了集成成本。下表对比了Quill与另外两个流行库在几个关键维度的差异特性维度Quill.jsTinyMCECKEditor 5核心包大小 (gzipped)~45 KB~290 KB~500 KBAPI设计哲学基于Delta的声明式API命令式/配置驱动模块化、面向对象自定义扩展难度较低模块化设计中等较高学习曲线陡峭内置图片上传无需通过模块扩展有高级功能需付费有功能强大协同编辑支持优秀Delta天然适合需插件/企业版需插件/企业版开源协议BSD 3-ClauseGPL / 商业许可GPL / 商业许可从表格可以看出Quill在轻量和灵活性上优势明显。它没有试图把所有功能都塞进核心包而是通过模块Modules和格式Formats系统让你按需引入。这种“自带电池但可更换”的理念非常适合需要快速启动并拥有定制化需求的现代前端项目。2. 五分钟快速启动你的第一个Quill编辑器理论说得再多不如动手敲几行代码来得实在。让我们从一个最基础的HTML文件开始见证一个功能完整的编辑器是如何在几分钟内诞生的。首先你需要通过CDN引入Quill的核心库和它的默认“雪”主题样式。将以下代码保存为一个index.html文件。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title我的第一个Quill编辑器/title !-- 引入Quill样式 -- link hrefhttps://cdn.quilljs.com/1.3.7/quill.snow.css relstylesheet style body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif; padding: 2rem; } #editor-container { height: 350px; margin-bottom: 2rem; } /style /head body h1试试这个编辑器/h1 div ideditor-container p在这里写下你的想法.../p /div button idget-content获取编辑器内容/button pre idoutput/pre !-- 引入Quill核心库 -- script srchttps://cdn.quilljs.com/1.3.7/quill.js/script script // 初始化Quill编辑器 const quill new Quill(#editor-container, { theme: snow, // 使用“雪”主题它自带工具栏 placeholder: 开始创作吧..., modules: { toolbar: [ [{ header: [1, 2, 3, false] }], // 标题下拉菜单 [bold, italic, underline, strike], // 粗体、斜体等 [{ list: ordered}, { list: bullet }], // 列表 [link, blockquote, code-block], // 链接、引用、代码块 [clean] // 清除格式 ] } }); // 绑定按钮获取并显示编辑器内容Delta格式和HTML格式 document.getElementById(get-content).addEventListener(click, function() { const delta quill.getContents(); // 获取Delta操作集 const html quill.root.innerHTML; // 获取HTML字符串 const output document.getElementById(output); output.textContent Delta格式:\n${JSON.stringify(delta, null, 2)}\n\nHTML格式:\n${html}; }); /script /body /html用浏览器打开这个文件一个具备基本格式工具栏的编辑器就呈现在眼前了。你可以输入文字尝试加粗、添加列表、插入链接。点击“获取编辑器内容”按钮控制台会同时输出两种格式的内容结构化的Delta和渲染用的HTML。这个简单的例子揭示了Quill工作的两个层面数据层Delta和表现层HTML。Delta格式这是Quill的灵魂。它精确记录了从空白文档到当前状态的所有操作。无论是插入字符、应用格式还是删除内容都被表示为一个个op操作。这种设计使得实现“撤销/重做”变得非常简单——本质上就是操作栈的入栈和出栈。HTML格式这是我们最终需要存储或展示给用户的形式。通过quill.root.innerHTML可以获取到编辑器内容对应的HTML字符串。注意直接使用innerHTML获取的内容是未经处理的如果直接将用户输入的这部分HTML渲染到页面其他位置可能存在XSS风险。在生产环境中务必在服务端或前端使用如DOMPurify这样的库进行净化处理。3. 核心挑战实现图片上传而非简单插入URL现在我们的编辑器已经有了文字处理能力。但一个现代的内容编辑器图片上传是刚需。Quill默认的图片处理逻辑非常基础点击工具栏的图片图标会弹出一个提示框让你输入图片URL。这显然不符合实际需求——用户需要的是从本地上传。解决这个问题的思路是拦截Quill默认的图片插入行为替换为我们自定义的上传流程。具体来说我们需要做以下几件事隐藏或替换默认的图片处理模块Quill的工具栏按钮行为是由对应的“处理器”定义的我们需要覆盖它。创建一个文件输入框当用户点击图片按钮时触发一个隐藏的input typefile元素让用户选择本地图片。上传文件到服务器使用FormData和fetch或XMLHttpRequest将选中的图片文件发送到你的后端接口。将服务器返回的图片URL插入编辑器上传成功后从响应中获取图片的在线地址并使用Quill的API将其插入到当前光标位置。下面是一个完整的、可运行的示例它模拟了从点击按钮到图片插入的完整前端流程。为了演示我们使用了一个免费的模拟上传API。!-- 在之前的HTML文件中替换toolbar配置和增加脚本 -- script const quill new Quill(#editor-container, { theme: snow, placeholder: 开始创作吧..., modules: { toolbar: { container: [ [bold, italic, underline], [blockquote, code-block], [{ list: ordered}, { list: bullet }], [link, image], // 保留图片按钮但我们将自定义其行为 [clean] ], handlers: { // 关键覆盖默认的图片处理器 image: function() { selectLocalImage(); } } } } }); function selectLocalImage() { // 创建一个隐藏的文件输入元素 const input document.createElement(input); input.setAttribute(type, file); input.setAttribute(accept, image/*); // 只接受图片文件 input.click(); // 模拟点击打开文件选择对话框 // 监听文件选择变化 input.onchange function() { const file input.files[0]; if (!file) return; // 在这里你可以先进行前端验证比如文件大小、类型 if (file.size 5 * 1024 * 1024) { // 限制5MB alert(图片大小不能超过5MB); return; } // 可选在等待上传时先插入一个占位符或显示加载状态 const range quill.getSelection(); const placeholderText ![上传中...]; quill.insertText(range.index, placeholderText); // 调用上传函数 uploadImageToServer(file, range.index, placeholderText.length); }; } function uploadImageToServer(file, insertIndex, placeholderLength) { // 创建一个FormData对象用于构建表单数据 const formData new FormData(); formData.append(image, file); // image需要与后端接口参数名对应 // 你可以附加其他参数如用户token // formData.append(token, userToken); // 使用一个免费的图片上传模拟API进行演示 // 注意此API仅用于演示生产环境请替换为你自己的后端接口 const uploadUrl https://api.imgbb.com/1/upload?key你的API_KEY; // 需要去imgbb申请免费key fetch(uploadUrl, { method: POST, body: formData }) .then(response response.json()) .then(result { // 假设API返回的数据结构为 { data: { url: https://... } } const imageUrl result.data.url; // 1. 删除之前插入的占位符文本 quill.deleteText(insertIndex, placeholderLength); // 2. 将光标重新定位到原位置 quill.setSelection(insertIndex); // 3. 插入图片 quill.insertEmbed(insertIndex, image, imageUrl); // 可选插入后将光标移动到图片后面 quill.setSelection(insertIndex 1); }) .catch(error { console.error(上传失败:, error); // 上传失败删除占位符并给出提示 quill.deleteText(insertIndex, placeholderLength); quill.setSelection(insertIndex); quill.insertText(insertIndex, [图片上传失败]); }); } /script这段代码的核心在于toolbar配置中的handlers对象。我们通过为image键指定一个新的处理函数完全接管了图片按钮的点击事件。在uploadImageToServer函数中我们使用了fetch进行异步上传并在成功回调中使用quill.insertEmbed方法插入图片。insertEmbed是Quill用于插入非文本内容如图片、视频的核心API。4. 进阶优化提升上传体验与编辑器健壮性基础功能实现后我们可以从用户体验和代码健壮性角度进行一系列优化。一个优秀的编辑器细节决定成败。4.1 上传进度反馈与图片预览用户上传图片时如果没有任何反馈会感到焦虑。我们可以提供进度提示和本地预览。function uploadImageToServer(file, insertIndex, placeholderLength) { const formData new FormData(); formData.append(image, file); // 创建并显示一个进度条容器 const progressContainer document.createElement(div); progressContainer.style.cssText background:#f3f3f3; border-radius:5px; margin:5px 0;; const progressBar document.createElement(div); progressBar.style.cssText height:4px; background:#4CAF50; width:0%; border-radius:5px; transition: width 0.3s;; progressContainer.appendChild(progressBar); // 将进度条作为Quill的一个“嵌入”内容临时插入这需要一点技巧。 // 更简单的做法是在编辑器外部固定位置显示一个全局进度提示。 console.log(开始上传...); // 临时用控制台日志代替 // 使用XMLHttpRequest以支持进度事件 const xhr new XMLHttpRequest(); xhr.open(POST, 你的上传接口); // 监听上传进度 xhr.upload.addEventListener(progress, function(event) { if (event.lengthComputable) { const percentComplete Math.round((event.loaded / event.total) * 100); console.log(上传进度: ${percentComplete}%); progressBar.style.width ${percentComplete}%; // 更新进度条宽度 } }); xhr.onload function() { if (xhr.status 200) { const result JSON.parse(xhr.responseText); const imageUrl result.data.url; // ... 插入图片逻辑同上 ... console.log(上传成功); } else { // 处理错误 console.error(上传失败状态码:, xhr.status); } // 移除进度条 progressContainer.remove(); }; xhr.onerror function() { console.error(网络请求失败); progressContainer.remove(); }; xhr.send(formData); }同时在用户选择文件后、上传前可以使用FileReader在本地生成一个预览图给用户即时反馈。input.onchange function() { const file input.files[0]; if (!file) return; // 本地预览 const reader new FileReader(); reader.onload function(e) { const previewUrl e.target.result; // 可以在这里先插入一个base64格式的预览图上传成功后再替换为远程URL // 注意base64图片很长会污染Delta数据建议仅作为临时预览不上传到服务器。 const range quill.getSelection(); quill.insertEmbed(range.index, image, previewUrl); // 记录这个预览图的索引上传成功后需要替换它 currentPreviewIndex range.index; }; reader.readAsDataURL(file); // 读取文件为Data URL // 然后开始上传流程... };4.2 处理粘贴与拖拽上传除了点击工具栏按钮用户还可能直接从剪贴板粘贴图片或者将图片文件拖拽到编辑器中。Quill本身对粘贴HTML内容有很好的支持但默认不会处理粘贴中的图片文件它通常会将图片转为base64嵌入这可能不是我们想要的。我们可以通过监听Quill的paste事件来自定义处理逻辑。quill.root.addEventListener(paste, function(event) { const clipboardItems event.clipboardData.items; for (let item of clipboardItems) { // 检查粘贴的内容中是否有图片文件 if (item.type.indexOf(image) ! -1) { event.preventDefault(); // 阻止默认粘贴行为 const file item.getAsFile(); if (file) { // 使用我们之前写好的上传函数 const range quill.getSelection(); uploadImageToServer(file, range.index, 0); // 没有占位符 } break; // 假设一次只处理一张图片 } } // 如果不是图片则允许Quill执行默认的文本粘贴行为 });对于拖拽上传我们可以监听编辑器的drop事件。quill.root.addEventListener(drop, function(event) { event.preventDefault(); const files event.dataTransfer.files; for (let file of files) { if (file.type.indexOf(image) ! -1) { const range quill.getSelection(true); // 获取拖拽释放位置的选区 uploadImageToServer(file, range.index, 0); break; // 简化处理只上传第一个图片文件 } } });4.3 构建可复用的图片上传模块随着项目增长你可能在多个地方用到这个编辑器。将图片上传逻辑抽象成一个独立的、可配置的模块是更好的选择。我们可以利用Quill的模块系统来创建一个自定义模块。// 定义一个自定义的图片上传模块 class ImageUploadModule { constructor(quill, options) { this.quill quill; this.options options; // 可以传入上传接口地址、请求头等配置 this.quill.getModule(toolbar).addHandler(image, this.handleImageClick.bind(this)); this.bindPasteAndDropEvents(); } handleImageClick() { this.selectLocalImage(); } selectLocalImage() { // ... 同前文件选择逻辑 ... // 调用 this.uploadImage(file) } uploadImage(file) { // ... 同前上传逻辑但使用 this.options 中的配置 ... const formData new FormData(); formData.append(this.options.fileFieldName || file, file); fetch(this.options.uploadUrl, { method: POST, headers: this.options.headers || {}, body: formData }) .then(/* ... */) .then(imageUrl { const range this.quill.getSelection(); this.quill.insertEmbed(range.index, image, imageUrl); }) .catch(/* ... */); } bindPasteAndDropEvents() { // ... 同前粘贴和拖拽事件绑定逻辑 ... } } // 在初始化Quill时注册这个模块 const quill new Quill(#editor, { theme: snow, modules: { toolbar: { /* ... 工具栏配置必须包含image按钮 ... */ }, // 注册自定义模块键名可以任意例如 imageUpload imageUpload: { uploadUrl: /api/upload/image, headers: { Authorization: Bearer your-token-here }, fileFieldName: image } } }); // 手动将模块附加到Quill实例如果Quill没有自动加载 // Quill.register(modules/imageUpload, ImageUploadModule); // 实际上更标准的做法是使用Quill.register来注册然后在modules配置中直接写imageUpload即可。通过模块化我们将功能解耦配置集中管理代码也更容易维护和测试。你甚至可以将这个模块打包发布供其他项目使用。4.4 错误处理与用户体验兜底网络请求总有可能失败。一个健壮的上传功能需要完善的错误处理。网络超时为fetch或XMLHttpRequest设置超时时间超时后取消请求并提示用户。服务器错误处理HTTP状态码非200的情况如401未授权、413文件过大、500服务器内部错误并给出友好的提示。文件类型/大小校验在前端选择文件后立即校验避免无效的上传请求。上传中断对于大文件可以考虑支持断点续传但这需要后端配合复杂度较高。一个更简单的方案是提供“取消上传”的按钮。// 在uploadImageToServer函数中增强错误处理 .catch(error { if (error.name AbortError) { console.log(上传已被用户取消); // 更新UI提示上传已取消 showToast(上传已取消, info); } else if (error.message Network request failed) { console.error(网络连接失败请检查网络); showToast(网络连接失败请重试, error); } else { console.error(上传过程发生错误:, error); showToast(上传失败请稍后重试, error); } // 清理占位符等临时状态 removePlaceholder(); }); // 一个简单的Toast提示函数示例 function showToast(message, type info) { // 实现一个简单的提示框可以使用第三方库如toastr或自己创建div const toast document.createElement(div); toast.textContent message; toast.style.cssText position:fixed; top:20px; right:20px; padding:1rem; background:${typeerror?#f44336:#4CAF50}; color:white; border-radius:4px; z-index:9999;; document.body.appendChild(toast); setTimeout(() toast.remove(), 3000); }5. 从开发到生产安全、性能与集成考量当编辑器准备投入生产环境时我们需要考虑更多工程化的问题。安全性是第一要务。我们之前提到过XSS风险。除了对从编辑器获取的HTML进行净化外图片上传接口本身也需要严格防护文件类型验证后端必须做不能只依赖前端的accept属性或文件后缀名。应该在服务端通过检查文件魔数Magic Number或使用专业的库来验证文件真实类型。文件重命名避免使用用户上传的原文件名防止路径遍历和覆盖攻击。建议生成随机的文件名如UUID。访问控制上传接口需要有身份验证如JWT防止恶意用户滥用。图片处理考虑使用SharpNode.js或PillowPython等库对上传的图片进行压缩、生成缩略图并限制最大尺寸以节省存储空间和带宽。性能优化也不容忽视图片压缩在上传前可以使用浏览器端的库如compressorjs对图片进行有损压缩显著减少上传流量和时间对用户体验提升巨大。CDN加速上传后的图片应存储在图床或对象存储如AWS S3、阿里云OSS、腾讯云COS并搭配CDN分发确保全球用户都能快速加载。编辑器内容懒加载如果编辑器用于展示已有的大量带图内容可以考虑只渲染可视区域内的图片使用类似Intersection Observer的技术实现图片懒加载。与前端框架集成时需要注意生命周期和数据绑定。以React为例使用react-quill时避免在onChange事件中直接进行上传操作因为这可能导致频繁的渲染和状态更新。更好的做法是将图片上传逻辑与内容变化逻辑分离。import React, { useRef } from react; import ReactQuill from react-quill; import react-quill/dist/quill.snow.css; function MyEditor() { const quillRef useRef(null); const imageHandler () { const input document.createElement(input); input.setAttribute(type, file); input.setAttribute(accept, image/*); input.click(); input.onchange async () { const file input.files[0]; // 使用独立的函数处理上传不直接setState const imageUrl await uploadImage(file); const editor quillRef.current.getEditor(); const range editor.getSelection(); editor.insertEmbed(range.index, image, imageUrl); }; }; const modules { toolbar: { container: [...], handlers: { image: imageHandler } } }; return ReactQuill ref{quillRef} modules{modules} /; }最后别忘了无障碍访问A11y。确保工具栏按钮有清晰的aria-label图片插入后有替代文本alt text的输入提示。Quill本身对键盘导航有一定的支持但自定义的按钮和上传流程也需要考虑键盘用户的操作体验。回过头看我们从一行CDN引入的代码开始逐步构建了一个支持自定义上传、拥有良好反馈、并考虑了生产环境需求的富文本编辑器。Quill.js的魅力就在于它用简洁的API为你搭建了一个稳固的舞台而真正的表演——如何上传图片、如何与后端交互、如何优化体验——则由你自由发挥。这比直接使用一个开箱即用但黑盒的解决方案更能满足现代Web应用灵活多变的需求。

相关新闻

告别提示词烦恼!AI头像生成器一键生成详细头像设计文案

告别提示词烦恼!AI头像生成器一键生成详细头像设计文案

告别提示词烦恼!AI头像生成器一键生成详细头像设计文案 你是不是也遇到过这样的问题:想用Midjourney或者Stable Diffusion生成一个酷炫的头像,但对着输入框却不知道怎么写提示词?要么写得太简单,生成的头像平平无奇&a…

2026/7/4 5:45:37 阅读更多 →
QT5.12实战:Dalsa线扫相机二次开发避坑指南(附完整Demo)

QT5.12实战:Dalsa线扫相机二次开发避坑指南(附完整Demo)

QT5.12实战:Dalsa线扫相机二次开发避坑指南(附完整Demo) 如果你正在用QT框架对接Dalsa线扫相机,并且已经对着官方那堆MFC示例和晦涩的SDK文档头疼不已,那么这篇文章就是为你准备的。线扫相机在工业检测、印刷、纺织等领…

2026/5/17 9:04:04 阅读更多 →
Ubuntu服务器上快速部署crAPI靶场:从Docker配置到端口放行全流程

Ubuntu服务器上快速部署crAPI靶场:从Docker配置到端口放行全流程

在Ubuntu服务器上构建crAPI实战环境:从零到精通的部署与安全探索指南 最近在和朋友交流API安全测试时,大家不约而同地提到了一个名字:crAPI。这个由OWASP维护的现代化API靶场,几乎成了检验安全工程师对API漏洞理解深度的“试金石”…

2026/7/3 22:59:14 阅读更多 →

最新新闻

web安全-SSTI(服务器模板注入)

web安全-SSTI(服务器模板注入)

1. 核心概念与分类SSTI的本质是用户输入被作为模板内容直接拼接并渲染。根据结果可分为:有回显:注入的表达式结果直接显示在页面上。盲注/无回显:结果不显示,需通过DNS外带、时间延迟等方式判断。2. 常见模板引擎与测试Payload&am…

2026/7/4 18:03:13 阅读更多 →
AI运动APP站位预检功能设计与实现

AI运动APP站位预检功能设计与实现

1. 运动APP中的站位预检功能设计在开发AI运动类APP时,站位预检功能是提升用户体验的关键环节。这个功能的主要目的是在用户开始运动前,通过摄像头检测用户的站立位置、姿势角度等关键参数,确保用户处于最佳的运动起始状态。1.1 为什么需要站位…

2026/7/4 18:03:13 阅读更多 →
Web安全入门实战:从零挖掘SRC漏洞的标准化流程与高频漏洞解析

Web安全入门实战:从零挖掘SRC漏洞的标准化流程与高频漏洞解析

1. 项目概述:从零到一,挖到你的第一个SRC漏洞很多刚接触Web安全的朋友,心里都憋着一股劲,看着别人在漏洞响应平台(SRC)上提交漏洞、获得认可甚至奖金,自己却不知从何下手。网上的教程要么太散&a…

2026/7/4 18:01:13 阅读更多 →
机器学习入门者最缺的不是知识,而是业务认知框架

机器学习入门者最缺的不是知识,而是业务认知框架

1. 这不是教程,是我在教了七年机器学习后,凌晨三点改完第37版课程大纲时写下的肺腑之言 “My Honest Advice to Beginner ML Students”——这个标题没用任何技术术语,没堆砌“从零到一”“手撕算法”“保姆级”这类流量词,但它恰…

2026/7/4 18:01:13 阅读更多 →
D3keyHelper:基于AutoHotkey的自动化按键系统架构解析

D3keyHelper:基于AutoHotkey的自动化按键系统架构解析

D3keyHelper:基于AutoHotkey的自动化按键系统架构解析 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 在动作角色扮演游戏的高强度操作环…

2026/7/4 18:01:13 阅读更多 →
GPT-Image-1.5 vs Nano Banana Pro:真实工作流中的AI图像模型选型指南

GPT-Image-1.5 vs Nano Banana Pro:真实工作流中的AI图像模型选型指南

1. 项目概述:当“跑分王”撞上真实工作流,为什么GPT-Image-1.5在实战中频频失焦?2025年底那场AI图像模型的“双雄会”,表面看是OpenAI和Google在技术参数上的隔空对垒,实则是一次对整个行业工作流理解的深度拷问。我从…

2026/7/4 17:59:12 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻