软件教程 2025年08月6日
0 收藏 0 点赞 468 浏览 7668 个字
摘要 :

文章目录 一、组件结构 (一)导入依赖 (二)组件属性(Props) (三)核心配置 二、主要功能实现 (一)图片上传功能 (二)视频上传功能 (三)预览功能 三、使……




  • 一、组件结构
    • (一)导入依赖
    • (二)组件属性(Props)
    • (三)核心配置
  • 二、主要功能实现
    • (一)图片上传功能
    • (二)视频上传功能
    • (三)预览功能
  • 三、使用方法详解
    • (一)基础使用
    • (二)禁用模式
    • (三)格式化内容
  • 四、特殊功能说明
    • (一)内容格式化
    • (二)样式处理
  • 五、使用过程中的注意事项
    • (一)安装依赖
    • (二)权限验证
    • (三)生命周期处理
    • (四)文件上传限制
  • 六、完整代码展示

文本编辑器是常见且实用的组件,今天,咱们就来深入聊聊基于Vue3和tdesign封装的WangEditor富文本编辑器组件,看看它是如何实现各种功能的,以及在实际项目中该怎么使用。

一、组件结构

(一)导入依赖

在开始构建组件时,导入必要的依赖是第一步。

import \"@wangeditor/editor/dist/css/style.css\"; // 引入WangEditor的样式文件,让编辑器拥有美观的界面
import { Editor, Toolbar } from \"@wangeditor/editor-for-vue\"; // 从WangEditor的Vue适配库中引入编辑器组件和工具栏组件

(二)组件属性(Props)

组件的属性(Props)就像是给编辑器设定的“开关”和“参数”,可以根据需求来调整编辑器的外观和行为。

const props = defineProps({
  height: {
    type: String,
    default: \"300\" // 编辑器的高度,默认设置为300px,开发者可以根据实际布局需求修改
  },
  disabled: {
    type: Boolean,
    default: false // 是否禁用编辑器,默认是不禁用,在某些场景下可以设置为true来禁止用户编辑
  }
});

(三)核心配置

1.工具栏配置
工具栏配置决定了编辑器工具栏上展示的功能。

const toolbarConfig = { excludeKeys: [\"fullScreen\"] }; // 这里配置移除了全屏功能,让工具栏更符合项目需求

2. 编辑器配置
编辑器配置涉及到更多的细节,包括提示信息、文件上传设置等。

const editorConfig = {
  placeholder: \"请输入内容...\", // 当编辑器为空时显示的提示文本
  MENU_CONF: {
    uploadImage: {
      // 图片上传的相关配置
      server: \"/api/admin/sys/file/upload\", // 图片上传的服务器接口地址
      maxFileSize: 20 * 1024 * 1024, // 最大允许上传的图片文件大小为20MB
      // ... 其他配置
    },
    uploadVideo: {
      // 视频上传的相关配置
      server: \"/api/admin/sys/file/upload\", // 视频上传的服务器接口地址,和图片上传可以是同一个
      maxFileSize: 100 * 1024 * 1024, // 最大允许上传的视频文件大小为100MB
      maxNumberOfFiles: 5, // 最多允许同时上传5个视频文件
      // ... 其他配置
    }
  }
};

 

二、主要功能实现

(一)图片上传功能

图片上传功能是富文本编辑器的重要部分,它有一些限制和自定义的操作。

uploadImage: {
  // 支持的图片格式检查
  onBeforeUpload(file) {
    const fileSuffixList = [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"]; // 允许上传的图片后缀名列表
    const keys = Object.keys(file);
    const ext = \".\" + file[keys[0]].extension; // 获取文件的后缀名
    return fileSuffixList.includes(ext.toLowerCase()) ? file : false; // 判断文件后缀名是否在允许列表内,是则返回文件进行上传,否则禁止上传
  },
  // 自定义图片插入
  customInsert(res, insertFn) {
    let url = res.data.url; // 从服务器返回结果中获取图片的URL
    let alt = res.data.name; // 获取图片的替代文本
    let href = res.data.url; // 获取图片的链接
    insertFn(url, alt, href); // 使用插入函数将图片插入到编辑器中
  }
}

 

(二)视频上传功能

视频上传功能和图片上传类似,但也有自己的特点。

uploadVideo: {
  // 支持的视频格式检查
  onBeforeUpload(file) {
    const fileSuffixList = [\".mp4\", \".webm\", \".ogg\"]; // 允许上传的视频后缀名列表
    const keys = Object.keys(file);
    const ext = \".\" + file[keys[0]].extension; // 获取文件的后缀名
    return fileSuffixList.includes(ext.toLowerCase()) ? file : false; // 判断文件后缀名是否在允许列表内,决定是否上传
  }
}

通过这段代码,编辑器能够识别并限制可上传的视频格式。

(三)预览功能

预览功能让用户在保存或提交内容前,能提前查看编辑效果。

const modalVisible = ref(false); // 定义一个响应式变量,用于控制预览弹窗的显示和隐藏
const openPreview = () => {
  modalVisible.value = true; // 点击预览按钮时,将变量设置为true,显示预览弹窗
};

 

三、使用方法详解

(一)基础使用

在项目中使用该组件的基础方式很简单。

<template>
  <CustomEditor
    v-model=\"content\"
    height=\"500\"
  />
</template>

<script setup>
import { ref } from \'vue\';
import CustomEditor from \'@/components/CustomEditor.vue\';

const content = ref(\'\'); // 定义一个响应式变量,用于存储编辑器的内容
</script>

 

(二)禁用模式

如果在某些场景下不需要用户编辑,可以使用禁用模式。

<template>
  <CustomEditor
    v-model=\"content\"
    :disabled=\"true\"
  />
</template>

 

(三)格式化内容

有时候需要对编辑器的内容进行格式化处理。

<template>
  <CustomEditor
    v-model.format=\"content\"
  />
</template>

通过这种方式,可以按照设定的规则对内容进行格式化,让内容的样式更统一。

四、特殊功能说明

(一)内容格式化

在内容格式化方面,组件做了一些特殊处理。

const [valueHtml, modifiers] = defineModel({
  set(value) {
    if (modifiers.format) {
      // 将 text-align: justify 转换为 text-align: initial
      value = value.replace(
        /(<p\\s+[^>]*style=\"[^\"]*?)text-align:\\s*justify\\s*;?([^\"]*?\">)/gi,
        \"$1text-align: initial;$2\"
      );
    }
    return value;
  },
});

 

(二)样式处理

样式处理确保了编辑器中的内容在展示时保持正确的样式。

.custom-editor {
  // 保持标题样式
  h1, h2, h3, h4, h5, h6 {
    font-size: revert;
    font-weight: revert;
    line-height: normal;
    color: initial;
  }

  // 保持媒体元素样式
  img, svg, video, canvas, audio, iframe, embed, object {
    display: revert;
  }
}

 

五、使用过程中的注意事项

(一)安装依赖

在使用该组件前,需要安装相关的依赖。

npm install @wangeditor/editor @wangeditor/editor-for-vue

 

(二)权限验证

由于涉及文件上传,需要进行权限验证。

headers: {
  Authorization: localStorage.getItem(\"token\")
}

通过在请求头中携带token,服务器可以验证用户的身份,确保上传操作的安全性。

(三)生命周期处理

在组件销毁时,需要清理编辑器实例。

// 组件销毁时清理编辑器实例
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

 

(四)文件上传限制

需要注意文件上传的限制,图片最大20MB,支持png/jpg/jpeg/gif/bmp格式;视频最大100MB,支持mp4/webm/ogg格式,最多同时上传5个。在使用过程中,要确保上传的文件符合这些限制,否则可能会出现上传失败的情况。

六、完整代码展示

为了方便大家查看和参考,这里给出完整的组件代码(CustomEditor.vue)。

// CustomEditor.vue
<script setup>
import \"@wangeditor/editor/dist/css/style.css\"; // 引入 css
import {
  onMounted,
  onBeforeUnmount,
  shallowRef,
  defineProps,
  reactive,
  defineModel,
  ref
} from \"vue\";
import { Editor, Toolbar } from \"@wangeditor/editor-for-vue\";
const props = defineProps({
  height: {
    type: String,
    default: \"300\"
  },
  disabled: {
    type: Boolean,
    default: false
  }
});
const editorStyle = reactive({
  height: props.height + \"px\",
  overflowY: \"hidden\"
});

// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef();

// 内容 HTML
const [valueHtml, modifiers] = defineModel({
  set(value) {
    if (modifiers.format) {
      // 格式化
      // 处理 p 标签上的样式
      // style 中如果有 \"text-align: justify;\"
      // 如果碰到上面代码,会自动转换为 \"text-align: initial;\"
      value = value.replace(
        /(<p\\s+[^>]*style=\"[^\"]*?)text-align:\\s*justify\\s*;?([^\"]*?\">)/gi,
        \"$1text-align: initial;$2\"
      );
      return value;
    }
    return value;
  },
});

// 模拟 ajax 异步获取内容
onMounted(() => {
  setTimeout(() => {
    console.log(editorRef.value.getConfig(), editorRef.value.config);
    if (props.disabled) editorRef.value.disable();
  }, 0);
});

const toolbarConfig = { excludeKeys: [\"fullScreen\"] };
const editorConfig = {
  placeholder: \"请输入内容...\",
  MENU_CONF: {
    uploadImage: {
      server: \"/api/admin/sys/file/upload\",
      fieldName: \"file\",
      // 单个文件的最大体积限制,默认为 2M
      maxFileSize: 20 * 1024 * 1024, // 10M
      headers: {
        Authorization: localStorage.getItem(\"token\")
      },
      onBeforeUpload(file) {
        // TS 语法
        // onBeforeUpload(file) {    // JS 语法
        // file 选中的文件,格式如 { key: file }
        // 图片限制 .png, .jpg, .jpeg, .gif, .bmp
        const fileSuffixList = [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"];
        const keys = Object.keys(file);
        const ext = \".\" + file[keys[0]].extension;
        if (fileSuffixList.includes(ext.toLowerCase())) {
          return file;
        } else {
          return false;
        }

        // 可以 return
        // 1. return file 或者 new 一个 file ,接下来将上传
        // 2. return false ,不上传这个 file
      },
      // 自定义插入图片
      customInsert(res, insertFn) {
        // JS 语法
        // res 即服务端的返回结果

        // 从 res 中找到 url alt href ,然后插入图片
        console.log(res);
        let url = res.data.url;
        let alt = res.data.name;
        let href = res.data.url;
        insertFn(url, alt, href);
      },
    },
    uploadVideo: {
      server: \"/api/admin/sys/file/upload\",
      // form-data fieldName ,默认值 \'wangeditor-uploaded-video\'
      fieldName: \"file\",

      // 单个文件的最大体积限制,默认为 10M
      maxFileSize: 100 * 1024 * 1024, // 100M

      // 最多可上传几个文件,默认为 5
      maxNumberOfFiles: 5,

      // 选择文件时的类型限制,默认为 [\'video/*\'] 。如不想限制,则设置为 []
      allowedFileTypes: [\"video/*\"],

      // 自定义增加 http  header
      headers: {
        Authorization: localStorage.getItem(\"token\")
      },
      onBeforeUpload(file) {
        // JS 语法
        // file 选中的文件,格式如 { key: file }
        // 视频格式
        const fileSuffixList = [\".mp4\", \".webm\", \".ogg\"];
        const keys = Object.keys(file);
        const ext = \".\" + file[keys[0]].extension;
        if (fileSuffixList.includes(ext.toLowerCase())) {
          return file;
        } else {
          return false;
        }

        // 可以 return
        // 1. return file 或者 new 一个 file ,接下来将上传
        // 2. return false ,不上传这个 file
      },
      // 自定义插入视频
      customInsert(res, insertFn) {
        // JS 语法
        // res 即服务端的返回结果

        // 从 res 中找到 url poster ,然后插入视频
        console.log(res);
        let url = res.data.url;
        let alt = res.data.name;
        let href = res.data.url;
        insertFn(url, alt, href);
      },
    },
  },
};

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

const handleCreated = (editor) => {
  editorRef.value = editor; // 记录 editor 实例,重要!
};

const modalVisible = ref(false);
const openPreview = () => {
  modalVisible.value = true;
};
</script>
<template>
  <div class=\"custom-editor\">
    <Toolbar
      style=\"border-bottom: 1px solid #ccc\"
      :editor=\"editorRef\"
      :defaultConfig=\"toolbarConfig\"
    />
    <div class=\"flex justify-end my-2\">
      <t-button variant=\"outline\" @click=\"openPreview\" :disabled=\"false\">
        <template #icon><t-icon name=\"browse\"></t-icon></template>
        预览
      </t-button>
    </div>
    <Editor
      :style=\"editorStyle\"
      v-model=\"valueHtml\"
      :defaultConfig=\"editorConfig\"
      @onCreated=\"handleCreated\"
    />
    <t-dialog
      v-model:visible=\"modalVisible\"
      width=\"754px\"
      :cancelBtn=\"null\"
      :confirmBtn=\"null\"
      placement=\"center\"
      header=\"预览\"
    >
      <div class=\"w-full h-70vh overflow-y-auto\" v-html=\"valueHtml\"></div>
    </t-dialog>
  </div>
</template>
<style lang=\"scss\">
.custom-editor {
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    font-size: revert;
    font-weight: revert;
    line-height: normal;
    color: initial;
  }

  img,
  svg,
  video,
  canvas,
  audio,
  iframe,
  embed,
  object {
    display: revert;
  }
}
</style>

这个基于Vue3和tdesign封装的WangEditor富文本编辑器组件,为项目提供了完整的富文本编辑解决方案。在实际应用中,根据具体需求合理配置和使用,能够满足大多数富文本编辑场景的需求。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6840.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号