文章列表

11k 10 分钟

# Vue + Express 头像上传部分思考实现 # 📖 前言 在 Web 应用中,头像上传是一个常见的功能需求。本文将详细介绍如何在 Vue 3 + Express + MySQL 的技术栈中实现一个完整的头像上传功能,包括前端预览、后端存储、文件管理和资源清理等全流程。 # 🎯 核心设计思路 我们的设计遵循以下原则: 延迟上传:用户选择图片后,只在前端显示预览,不立即上传 统一处理:只有在保存数据时才上传图片,避免无效上传 资源管理:自动清理旧图片,避免文件系统垃圾 性能优化:存储相对路径而非 base64,减少数据库和网络传输压力 # 📋 技术栈 前端:Vue 3 +...
6.9k 6 分钟

# 为 Markdown 代码块添加语言标签和复制功能 # 前言 在现代的 AI 聊天应用中,代码块的展示是一个重要的功能。用户不仅需要看到语法高亮的代码,还需要能够快速识别代码语言类型,并且能够一键复制代码。本文将详细介绍如何在 Vue 3 + markdown-it + highlight.js 的技术栈中,为代码块添加语言标签和复制功能。 # 技术栈 Vue 3 - 前端框架 markdown-it - Markdown 解析器 highlight.js - 代码语法高亮库 TypeScript - 类型支持 # 核心挑战 # 1. markdown-it...
5.1k 5 分钟

# 代码高亮实现原理详解 # 整体架构 代码高亮的实现涉及三个核心组件: markdown-it - Markdown 解析器 highlight.js - 代码高亮引擎 CSS 样式 - 视觉呈现 # 一、Markdown-it 的工作原理 # 1.1 Markdown-it 是什么? markdown-it 是一个 Markdown 解析器,它将 Markdown 文本转换为 HTML。 # 1.2 基本工作流程 原始 Markdown 文本 ↓ markdown-it 解析器 ↓ AST (抽象语法树) ↓ 渲染器 (Renderer) ↓ HTML 字符串 # 1.3...
1.8k 2 分钟

至于我为什么会想要来证明这个呢 最近在看 vue 文档,遇到了一个 vue 的示例点击此跳转 示例抽象:对于一个数据对象,需要根据数据对象的 value 属性 来构建一个雷达图 雷达图:在一个圆周上,平局分出 n 个点,然后把这 n 个点连接起来,对内部进行填充 问题抽象:已知有 n 个点,起始点坐标为 (x_0, y_0) ,求出绕点 (0, 0) 旋转后的终点坐标 # 问题剖分 既然要平均分成 n 个点,那么每个点的角度增量为 360 / n 度,我们设为 θ 然后又已知起始点的坐标为 (x_0, y_0) 那么终点的坐标为 (x_1, y_1) 我们就是要求这个 (x_1,...
9.4k 9 分钟

本文主要介绍如何用原生 Node.js http 模块和前端 fetch API 实现一个健壮的、类似 ChatGPT 效果的流式 AI 响应服务 以及本人在实际操作过程中遇到的一些问题和解决方法 # 第一步:搭建基础 - 一个简单的 HTTP 服务 首先,我们需要一个能响应客户端请求的服务器。我们使用 Node.js 内置的 http 模块,因为它无需任何外部依赖,能让我们更专注于底层的流式数据处理 server.js - 版本 1 import http from 'http';const hostname = '127.0.0.1';const port...
4.5k 4 分钟

本文也是在阅读红宝书中了解到了 web component,文中提及的 lit-html 再上篇文章中已经提及过 web components 提供了一个官方的、原生的解决方案。它不是一个库,而是一套浏览器内置的标准,让我们能够创建独立、可复用、且不受任何框架限制的 UI 组件 目标:构建具备以下功能的 my-counter 可复用:使用自定义标签 样式隔离:使用 Shadow DOM 高性能:使用 lit-html 高效更新 UI 可配置:通过属性自定义初始值、步长等 # Part 1:Web Component 的三大支柱 # Step 1:搭建骨架 --Custom...
1.3k 1 分钟

本文主要简单聊聊 lit-html 的核心原理 在之前,我了解到的只有 React 的虚拟 dom。 "每次渲染生成新树 -> 对比两棵树 -> 找出差异 -> 更新真实 dom" 但是, lit-html 走了一条完全不同的路。没有虚拟 dom,不进行复杂的树对比,却能够实现极高的性能 # 核心一:ES6 的 -- 标签模板字面量 ES6 的一个新特性,标签模板字面量。 当写出如下代码时 const name = "ay";html`<h1>Hello,...
2.1k 2 分钟

本文主要通过两个例子拆解如何使用异步生成器创建一个慢速数据源,并通过 pipeThrough 管道和 TextEncoderStream 、 TextDecoderStream 实现数据的编码解码 # 基础概念:流的三位一体 可读流(ReadableStream):数据的源头。数据从这里流出 可写流(WritableStream):数据的终点。数据流入这里并被处理 Transform 流(TransformStream):数据的中间处理器。它接收一种格式的输入流,并输出另一种格式的流(例如:输入字符串 →\rightarrow→ 输出字节) #...
2.1k 2 分钟

本文主要是在阅读红宝书时,里面提到了 IntersectionObserver 可以实现图片懒加载,所以就想自己实现一下。 之前了解到的主要还是监听 scroll 事件,调用 getBoundingClientRect 方法来判断图片是否进入到视口 而 IntersectionObserver 它提供了一种异步观察目标元素与其祖先元素或顶级文档视口交叉状态变化的方法,它的性能也远超传统的 scroll 事件监听 # 使用 IntersectionObserver 实现图片懒加载 # 第一步:准备 HTML 核心是,不直接在 img 标签上添加 src 属性,而是添加一个自定义属性,例如...
2.4k 2 分钟

# 使用 Async Generator 打造事件流 # 引言:异步编程的范式转换 传统的 addEventListener 方法为事件绑定回调函数虽然有效,但当我们处理复杂的、有时序的事件序列时,代码很快就会变得难以维护。 本文介绍使用 Async Generator 打造事件流,展示了如何将异步事件转换为可迭代的序列 # 核心代码:将事件转化为 Observable Stream type ResolveFunction<T> = (value: T | PromiseLike<T>) => void;class Observable...