配置选项
本指南详细介绍 UEditor Plus Designer 的所有配置选项。
DesignerConfig
主配置对象,用于初始化编辑器。
typescript
interface DesignerConfig {
ueditorPath?: string
ueditorConfig?: UEditorConfig
categoryLoader?: () => Promise<MaterialCategory[]>
styleLoader?: (params?: MaterialQueryParams) => Promise<StyleListData>
onReady?: () => void
onChange?: (content: string) => void
}ueditorPath
UEditor Plus 静态文件的路径。
- 类型:
string - 默认值:
'/ueditor-plus' - 必需: 否
javascript
const config = {
ueditorPath: '/static/ueditor-plus'
}提示
路径应该指向包含 ueditor.config.js 的目录。
ueditorConfig
UEditor 编辑器的配置选项,会透传给 UEditor 实例。
- 类型:
UEditorConfig - 默认值:
{} - 必需: 否
常用配置:
javascript
const config = {
ueditorConfig: {
// 禁用自动高度
autoHeightEnabled: false,
// 初始高度
initialFrameHeight: 600,
// 初始宽度
initialFrameWidth: '100%',
// 自定义工具栏
toolbars: [
[
'source', '|',
'undo', 'redo', '|',
'bold', 'italic', 'underline', 'strikethrough', '|',
'forecolor', 'backcolor', '|',
'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|',
'insertorderedlist', 'insertunorderedlist', '|',
'link', 'unlink', '|',
'simpleupload', 'insertimage', '|',
'removeformat', 'formatmatch'
]
],
// 服务器地址(如果需要上传功能)
serverUrl: '/api/ueditor',
// 禁用图片弹出层
imagePopup: false,
// 自定义 iframe 样式
iframeCssStylesAddition: [
'body { background: #f5f5f5; padding: 20px; }'
]
}
}完整的 UEditor 配置选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
autoHeightEnabled | boolean | true | 是否自动长高 |
initialFrameHeight | number | 320 | 初始化编辑器高度 |
initialFrameWidth | string|number | '100%' | 初始化编辑器宽度 |
toolbars | string[][] | - | 自定义工具栏按钮 |
serverUrl | string | - | 服务器统一请求地址 |
imagePopup | boolean | true | 图片操作的弹出层开关 |
iframeCssStylesAddition | string[] | - | 给 iframe 添加额外样式 |
zIndex | number | 900 | 编辑器层级 |
themePath | string | - | 主题路径 |
lang | string | 'zh-cn' | 语言配置 |
更多配置请参考 UEditor 文档。
categoryLoader
自定义分类数据加载函数。
- 类型:
() => Promise<MaterialCategory[]> - 默认值: 内置默认加载器
- 必需: 否
返回值: 返回一个 Promise,resolve 为分类数组。
javascript
const categoryLoader = async () => {
const response = await fetch('/api/categories')
const data = await response.json()
return data.map(item => ({
id: item.id, // 分类ID
title: item.name, // 分类名称
pid: item.parentId, // 父分类ID(可选)
sort: item.order, // 排序(可选)
_child: [] // 子分类(可选)
}))
}
const config = {
categoryLoader
}MaterialCategory 接口:
typescript
interface MaterialCategory {
id: number | string // 分类ID
title: string // 分类名称
pid?: number | string // 父分类ID
sort?: number // 排序
_child?: MaterialCategory[] // 子分类
}styleLoader
自定义素材数据加载函数。
- 类型:
(params?: MaterialQueryParams) => Promise<StyleListData> - 默认值: 内置默认加载器
- 必需: 否
参数: 查询参数对象
typescript
interface MaterialQueryParams {
categoryId?: number | string // 分类ID
keywords?: string // 搜索关键词
page?: number // 页码
pageSize?: number // 每页数量
}返回值: 返回一个 Promise,resolve 为分页数据。
javascript
const styleLoader = async (params) => {
const response = await fetch('/api/materials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
categoryId: params?.categoryId,
keyword: params?.keywords,
page: params?.page || 1,
pageSize: params?.pageSize || 20
})
})
const data = await response.json()
return {
records: data.items.map(item => ({
id: item.id, // 素材ID
title: item.name, // 素材名称
html: item.content, // 素材HTML内容
categoryId: item.categoryId, // 所属分类
cover: item.thumbnail // 缩略图(可选)
})),
total: data.total, // 总数
page: data.page, // 当前页
pageSize: data.pageSize // 每页数量
}
}
const config = {
styleLoader
}StyleListData 接口:
typescript
interface StyleListData {
records: MaterialItem[] // 素材列表
total: number // 总数
page: number // 当前页
pageSize: number // 每页数量
}
interface MaterialItem {
id: number | string // 素材ID
title: string // 素材名称
html: string // HTML内容
categoryId?: number | string // 分类ID
cover?: string // 缩略图URL
[key: string]: any // 其他自定义字段
}onReady
编辑器初始化完成的回调函数。
- 类型:
() => void - 默认值:
undefined - 必需: 否
javascript
const config = {
onReady: () => {
console.log('编辑器已就绪')
// 可以在这里调用实例方法
}
}提示
Vue 组件中推荐使用 @ready 事件,React 中使用 onReady prop。
onChange
内容变化的回调函数。
- 类型:
(content: string) => void - 默认值:
undefined - 必需: 否
javascript
const config = {
onChange: (content) => {
console.log('内容已更改,长度:', content.length)
// 可以在这里保存内容
localStorage.setItem('content', content)
}
}配置示例
最简配置
javascript
const config = {
ueditorPath: '/ueditor-plus'
}基础配置
javascript
const config = {
ueditorPath: '/ueditor-plus',
ueditorConfig: {
autoHeightEnabled: false,
initialFrameHeight: 600
},
onReady: () => {
console.log('编辑器已就绪')
},
onChange: (content) => {
console.log('内容已更改')
}
}完整配置
javascript
const config = {
// UEditor 路径
ueditorPath: '/static/ueditor-plus',
// UEditor 配置
ueditorConfig: {
autoHeightEnabled: false,
initialFrameHeight: 800,
initialFrameWidth: '100%',
toolbars: [
[
'source', '|',
'undo', 'redo', '|',
'bold', 'italic', 'underline', '|',
'forecolor', 'backcolor', '|',
'justifyleft', 'justifycenter', 'justifyright', '|',
'insertorderedlist', 'insertunorderedlist', '|',
'link', 'unlink', '|',
'simpleupload', 'insertimage'
]
],
serverUrl: '/api/ueditor',
imagePopup: false,
iframeCssStylesAddition: [
'body { background: #ffffff; padding: 20px; }',
'.pb-section { margin-bottom: 20px; }'
]
},
// 自定义分类加载器
categoryLoader: async () => {
try {
const response = await fetch('/api/categories')
if (!response.ok) throw new Error('请求失败')
const data = await response.json()
return data.map(item => ({
id: item.id,
title: item.name,
pid: item.parentId,
sort: item.order
}))
} catch (error) {
console.error('加载分类失败:', error)
return []
}
},
// 自定义素材加载器
styleLoader: async (params) => {
try {
const response = await fetch('/api/materials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
categoryId: params?.categoryId,
keyword: params?.keywords,
page: params?.page || 1,
pageSize: params?.pageSize || 20
})
})
if (!response.ok) throw new Error('请求失败')
const data = await response.json()
return {
records: data.items.map(item => ({
id: item.id,
title: item.name,
html: item.content,
categoryId: item.categoryId,
cover: item.thumbnail
})),
total: data.total,
page: data.page,
pageSize: data.pageSize
}
} catch (error) {
console.error('加载素材失败:', error)
return {
records: [],
total: 0,
page: 1,
pageSize: 20
}
}
},
// 回调函数
onReady: () => {
console.log('编辑器初始化完成')
},
onChange: (content) => {
// 防抖保存
clearTimeout(window.saveTimer)
window.saveTimer = setTimeout(() => {
localStorage.setItem('editor-content', content)
console.log('自动保存成功')
}, 1000)
}
}环境变量配置
Vite 项目
在开发环境使用环境变量:
javascript
// .env.development
VITE_UEDITOR_PATH=/ueditor-plus
// .env.production
VITE_UEDITOR_PATH=https://cdn.example.com/ueditor-plusjavascript
// 使用环境变量
const config = {
ueditorPath: import.meta.env.VITE_UEDITOR_PATH
}Webpack 项目
javascript
// webpack.config.js
new webpack.DefinePlugin({
'process.env.UEDITOR_PATH': JSON.stringify(
process.env.NODE_ENV === 'production'
? 'https://cdn.example.com/ueditor-plus'
: '/ueditor-plus'
)
})javascript
// 使用环境变量
const config = {
ueditorPath: process.env.UEDITOR_PATH
}最佳实践
1. 错误处理
在加载器中始终进行错误处理:
javascript
const categoryLoader = async () => {
try {
const response = await fetch('/api/categories')
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return await response.json()
} catch (error) {
console.error('加载分类失败:', error)
// 返回空数组而不是抛出错误
return []
}
}2. 加载状态
在加载器中可以设置加载状态:
javascript
const styleLoader = async (params) => {
// 显示加载指示器
showLoading()
try {
const response = await fetch('/api/materials')
const data = await response.json()
return data
} catch (error) {
console.error('加载失败:', error)
showError('加载素材失败')
return { records: [], total: 0, page: 1, pageSize: 20 }
} finally {
// 隐藏加载指示器
hideLoading()
}
}3. 缓存策略
对于不常变化的数据,可以使用缓存:
javascript
let categoryCache = null
const categoryLoader = async () => {
// 使用缓存
if (categoryCache) {
return categoryCache
}
const response = await fetch('/api/categories')
const data = await response.json()
// 缓存结果
categoryCache = data
return data
}4. 请求取消
对于可能频繁调用的加载器,使用 AbortController:
javascript
let controller = null
const styleLoader = async (params) => {
// 取消之前的请求
if (controller) {
controller.abort()
}
controller = new AbortController()
try {
const response = await fetch('/api/materials', {
method: 'POST',
body: JSON.stringify(params),
signal: controller.signal
})
return await response.json()
} catch (error) {
if (error.name === 'AbortError') {
console.log('请求已取消')
}
return { records: [], total: 0, page: 1, pageSize: 20 }
}
}常见问题
UEditor 路径配置不生效?
确保路径指向包含 ueditor.config.js 的目录,并且该目录可访问。
工具栏按钮不显示?
检查 toolbars 配置中的按钮名称是否正确,参考 UEditor 官方文档的按钮列表。
自定义加载器不工作?
- 检查函数是否返回 Promise
- 检查返回数据格式是否正确
- 查看浏览器控制台是否有错误
- 确保 API 端点可访问