Skip to content

配置选项

本指南详细介绍 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 配置选项

选项类型默认值说明
autoHeightEnabledbooleantrue是否自动长高
initialFrameHeightnumber320初始化编辑器高度
initialFrameWidthstring|number'100%'初始化编辑器宽度
toolbarsstring[][]-自定义工具栏按钮
serverUrlstring-服务器统一请求地址
imagePopupbooleantrue图片操作的弹出层开关
iframeCssStylesAdditionstring[]-给 iframe 添加额外样式
zIndexnumber900编辑器层级
themePathstring-主题路径
langstring'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-plus
javascript
// 使用环境变量
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 官方文档的按钮列表。

自定义加载器不工作?

  1. 检查函数是否返回 Promise
  2. 检查返回数据格式是否正确
  3. 查看浏览器控制台是否有错误
  4. 确保 API 端点可访问

Released under the Apache License 2.0. 压缩版免费使用,商用或源码需授权。