更新记录
1.0.2(2026-05-27)
- 修复
<haosns-editor>组件不显示:组件目录统一为components/haosns-editor/ - 移除旧目录
haosns-article-editor,避免 easycom 冲突 - 编辑器内 markdown SDK 改为
@/路径引用 - 格式弹窗显式引入
uni-popup,提升 Vue3 兼容性 - readme 补充 easycom custom 配置与显式 import 接入方式
1.0.0(2026-05-27)
- 首次发布
- 组件
haosns-editor:标题、编辑 / 预览、字数统计 - 组件
haosns-article-format-sheet:格式插入弹窗(标题、样式、列表、对齐、引用等) - 正文插图占位
[图片:n],配合haosns-markdownSDK 预览与详情渲染 - 无 uview-plus 依赖
平台兼容性
uni-app(3.7.8)
| Vue2 | Vue2插件版本 | Vue3 | Vue3插件版本 | Chrome | Chrome插件版本 | Safari | Safari插件版本 | app-vue | app-vue插件版本 | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
haosns-editor
uni-app 长文 Markdown 编辑器组件,支持编辑 / 预览、格式插入、正文插图。基于原生 input / textarea,依赖 uni-popup,不依赖 uview-plus。
平台:uni-app · Vue2 / Vue3 · App · H5 · 小程序
依赖
按以下顺序安装到同一 uni-app 项目的 uni_modules/ 目录:
| 顺序 | 插件 | 说明 |
|---|---|---|
| 1 | haosns-markdown | 解析 SDK,必装 |
| 2 | mp-html | 预览 HTML 渲染 |
| 3 | uni-icons | uni-ui 官方组件 |
| 4 | uni-popup | uni-ui 官方组件 |
| 5 | haosns-editor | 本插件 |
安装方式:DCloud 插件市场「导入 HBuilderX」,或解压 zip 至 uni_modules/。完成后重新运行项目。
组件说明
| 标签 | 说明 |
|---|---|
<haosns-editor> |
标题输入、编辑 / 预览切换、格式与插图工具栏 |
<haosns-article-format-sheet> |
底部格式选择弹窗 |
注册方式(二选一,推荐显式 import)
方式 A · 显式 import(推荐,Vue3 最稳)
import HaosnsEditor from '@/uni_modules/haosns-editor/components/haosns-editor/haosns-editor.vue'
import HaosnsArticleFormatSheet from '@/uni_modules/haosns-editor/components/haosns-article-format-sheet/haosns-article-format-sheet.vue'
export default {
components: { HaosnsEditor, HaosnsArticleFormatSheet }
}
方式 B · easycom
在 pages.json 中配置(不要只依赖 autoscan):
{
"easycom": {
"autoscan": true,
"custom": {
"^haosns-editor$": "@/uni_modules/haosns-editor/components/haosns-editor/haosns-editor.vue",
"^haosns-article-format-sheet$": "@/uni_modules/haosns-editor/components/haosns-article-format-sheet/haosns-article-format-sheet.vue"
}
}
}
修改 pages.json 后需重新运行项目;若仍不显示,请改用方式 A。
快速接入
1. 发帖页
<template>
<view class="page">
<haosns-editor
ref="editor"
:title="title"
:content="content"
:inline-image-map="inlineImageMap"
:inline-image-uploading="uploading"
:format-sheet-visible="formatVisible"
@update:title="title = $event"
@update:content="content = $event"
@toggle-format-sheet="formatVisible = !formatVisible"
@request-insert-image="onInsertImage"
/>
<haosns-article-format-sheet
:visible="formatVisible"
@close="formatVisible = false"
@select="onFormatSelect"
/>
<button @tap="submit">发布</button>
</view>
</template>
<script>
import HaosnsEditor from '@/uni_modules/haosns-editor/components/haosns-editor/haosns-editor.vue'
import HaosnsArticleFormatSheet from '@/uni_modules/haosns-editor/components/haosns-article-format-sheet/haosns-article-format-sheet.vue'
import { embedArticleDraftInlineMap } from '@/uni_modules/haosns-markdown/js_sdk/article-markdown.js'
export default {
components: { HaosnsEditor, HaosnsArticleFormatSheet },
data() {
return {
title: '',
content: '',
formatVisible: false,
inlineImageMap: {},
imageNextId: 1,
uploading: false
}
},
methods: {
onFormatSelect(item) {
this.$refs.editor.insertFormatItem(item)
this.formatVisible = false
},
onInsertImage() {
if (this.uploading) return
this.uploading = true
const id = String(this.imageNextId++)
uni.chooseImage({
count: 1,
success: (res) => {
uni.uploadFile({
url: 'https://api.example.com/upload', // 替换实际上传地址
filePath: res.tempFilePaths[0],
name: 'file',
success: (up) => {
const data = JSON.parse(up.data)
const url = data.url
this.inlineImageMap = { ...this.inlineImageMap, [id]: url }
this.$refs.editor.insertImagePlaceholder(id)
},
complete: () => { this.uploading = false }
})
},
fail: () => { this.uploading = false }
})
},
submit() {
if (!this.title.trim()) {
return uni.showToast({ icon: 'none', title: '请填写标题' })
}
const payload = {
title: this.title,
content: embedArticleDraftInlineMap(this.content, this.inlineImageMap)
}
// 调用业务发帖接口,payload 即为提交数据
}
}
}
</script>
在 pages.json 的 pages 数组中注册该页面路径。
2. 详情页
<template>
<mp-html :content="bodyHtml" />
</template>
<script>
import mpHtml from '@/uni_modules/mp-html/components/mp-html/mp-html.vue'
import {
articleMarkdownToHtml,
applyArticleDetailGallerySplit,
extractArticleDraftInlineMap
} from '@/uni_modules/haosns-markdown/js_sdk/article-markdown.js'
export default {
components: { mpHtml },
data() {
return { detail: null }
},
computed: {
bodyHtml() {
if (!this.detail) return ''
const { content, map } = extractArticleDraftInlineMap(this.detail.content)
const inlineMap = map || this.buildMapFromUrls(this.detail.articleInlineImages)
return articleMarkdownToHtml(content, inlineMap)
}
},
methods: {
buildMapFromUrls(urls) {
const m = {}
;(urls || []).forEach((url, i) => { m[String(i + 1)] = url })
return m
},
onLoad() {
// 接口返回 detail 后:
// this.detail = applyArticleDetailGallerySplit(detail)
}
}
}
</script>
<style>
.article-align-center { text-align: center; }
.article-align-right { text-align: right; }
</style>
3. 列表摘要(可选)
import { articleContentToListPlainText } from '@/uni_modules/haosns-markdown/js_sdk/article-markdown.js'
const summary = articleContentToListPlainText(item.content)
组件 API
haosns-editor
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title |
String | '' |
标题 |
content |
String | '' |
正文 Markdown |
maxlength |
Number | 5000 |
正文字数上限 |
inlineImageMap |
Object | {} |
插图映射 { "1": "url" } |
inlineImageUploading |
Boolean | false |
上传中,禁用插图按钮 |
formatSheetVisible |
Boolean | false |
格式弹窗是否打开(控制按钮高亮) |
editorReadOnly |
Boolean | false |
正文只读 |
titlePlaceholder |
String | 添加标题 |
标题占位符 |
contentPlaceholder |
String | 添加正文,支持 Markdown 语法 |
正文占位符 |
Events
| 名称 | 说明 |
|---|---|
update:title |
标题变更 |
update:content |
正文变更 |
toggle-format-sheet |
点击「格式」按钮 |
request-insert-image |
点击「插图」,由页面实现上传逻辑 |
mode-change |
编辑 / 预览切换,参数 'edit' \| 'preview' |
Methods(通过 ref 调用)
| 名称 | 说明 |
|---|---|
insertFormatItem(item) |
插入选中的格式项 |
insertImagePlaceholder(id) |
在光标处插入 [图片:id] |
switchToEdit() |
切换到编辑模式 |
haosns-article-format-sheet
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
visible |
Boolean | false |
是否显示 |
sheetTitle |
String | 插入格式 |
弹窗标题 |
sections |
Array | 内置格式列表 | 自定义格式分区,不传则使用默认 |
Events
| 名称 | 说明 |
|---|---|
close |
弹窗关闭 |
select |
选中格式项,参数为 item 对象 |
默认格式分区可通过以下方式扩展:
import { ARTICLE_FORMAT_SECTIONS } from '@/uni_modules/haosns-editor/components/haosns-article-format-sheet/haosns-article-format-sheet.vue'
插图流程说明
- 用户点击「插图」→ 触发
request-insert-image - 页面选择图片并上传,得到 URL
- 分配递增 id(如
"1","2"),写入inlineImageMap - 调用
this.$refs.editor.insertImagePlaceholder(id) - 正文中出现
[图片:1],预览与详情通过articleMarkdownToHtml渲染为<img>
顶栏相册图与正文插图需在后端或详情页用 applyArticleDetailGallerySplit 区分,详见 markdown SDK 文档。
常见问题
组件不显示?
- 确认组件目录为
uni_modules/haosns-editor/components/haosns-editor/(1.0.2 已修复旧目录名问题) - 推荐使用 readme 中的显式 import 注册组件
- 或在
pages.json配置 easycomcustom规则 - 删除
unpackage后重新运行项目
预览区域空白?
确认已安装 mp-html;检查 content 是否有内容。
格式弹窗无法打开?
确认已安装 uni-popup,且页面中包含 <haosns-article-format-sheet> 并绑定 visible。
与 uview 能否共存?
可以。本插件不引用 uview,可在已有 uview 项目中直接使用。
Vue2 项目是否支持?
支持。组件使用 Options API,兼容 Vue2 / Vue3。
如何联系作者?
请通过 DCloud 插件市场内置的 uni-im 向作者咨询,勿在 readme、changelog 或插件简介中填写 QQ、微信等第三方联系方式。
更新日志
Markdown 语法与更多 SDK 方法见 haosns-markdown readme。

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 4
赞赏 0
下载 12065387
赞赏 1917
赞赏
京公网安备:11010802035340号