wangeditor 富文本 使用及 上传本地图片的方法

文章标题:Vue组件实现富文本编辑器

文章摘要:本文介绍了如何使用Vue和Wangeditor插件实现富文本编辑器组件,并详细解释了组件中的各个部分和功能。

Vue组件实现富文本编辑器 在Web开发中,富文本编辑器是一个非常常见的功能,它能够让用户以所见即所得的方式编辑和排版文本内容。本文将介绍如何使用Vue和Wangeditor插件实现一个富文本编辑器组件。

  1. 安装依赖 首先,我们需要安装@wangeditor/editor-for-vue插件,该插件提供了与Vue集成的富文本编辑器组件。可以通过以下命令来安装:

npm install @wangeditor/editor-for-vue

  1. 创建富文本编辑器组件 在Vue项目中,创建一个名为RichTextEditor的组件,用于展示富文本编辑器界面和处理相关逻辑。

组件模板代码如下:

html 复制代码
<template>
  <div v-if="newVisible">
    <div class="container"></div>
    <div style="border: 1px solid #ccc">
      <!-- 工具栏 -->

      <Toolbar
        :editor="editorRef"
        style="border-bottom: 1px solid #ccc"
        :defaultConfig="toolbarConfig"
      />
      <!-- 编辑器 -->
      <Editor
        v-model="valueHtml"
        :defaultConfig="editorConfig"
        style="height: 500px; overflow-y: hidden"
        @onCreated="handleCreated"
      />
    </div>
    <div class="btn-container">
      <CBotton type="primary" @click="save">保存</CBotton>
      <CBotton type="dashed" @click="cancel">取消</CBotton>
    </div>
  </div>
</template>

在上述代码中,我们通过v-if指令控制编辑器组件的显示和隐藏。组件包含一个工具栏和一个编辑器,并在底部添加了保存和取消按钮。

  1. 定义组件的数据和方法在标签中,我们需要定义组件的数据和方法。首先,引入所需的依赖:
javascript 复制代码
<script setup>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { uploadFile } from "@/api/base";
import { submitUploadInfoApi, getHelpContent } from "@/api/sale/help-set.ts";
import { message } from "ant-design-vue";
import {
  onBeforeUnmount,
  shallowRef,
  defineProps,
  ref,
  computed,
  defineEmits,
  reactive,
  watch,
} from "vue";
</script>
接着,定义组件需要的数据和方法:

javascript
// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef();
const photoGalleryDialogVisible = ref();
const spinning = ref(false);

// 内容 HTML
const valueHtml = ref("");

const props = defineProps({
  visible: { type: Boolean, default: false },
  info: { type: Object, default: null },
  content: { type: Object, default: null },
});
const emit = defineEmits(["confirm", "update:visible", "select"]);

const newVisible = computed({
  get() {
    // 传过来的一行
    return props.visible;
  },
});

watch(
  () => props.visible,
  (val) => {
    console.log("val: ", props.info);
    if (val) {
      if (props?.content?.content) {
        valueHtml.value = props.content.content;
      }
    } else {
    }
  }
);

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

const save = async () => {
  // 保存逻辑
  const p = {
    categoryId: props.info.id,
    contentType: 1,
    content: valueHtml.value,
  };
  const res = await submitUploadInfoApi(p);
  if (res.code == 0) {
    cancel();
    emit("select", props.info.id);
    return message.success(res.msg);
  }
};

const cancel = () => {
  // 取消逻辑
  console.log("取消编辑");
  emit("update:visible", false);
  valueHtml.value = "";
};

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

在上述代码中,我们使用了Vue 3中的Composition API来定义组件的数据和方法。其中,editorRef用于保存编辑器实例,valueHtml用于存储编辑器中的HTML内容。

save方法用于保存编辑的内容,首先将内容发送到后端进行保存,并在保存成功后触发select事件。cancel方法用于取消编辑操作,清空内容并隐藏编辑器。

最后,我们使用onBeforeUnmount钩子函数,在组件销毁前及时销毁编辑器实例。

  1. 配置工具栏和编辑器 在上述代码中,我们还需要配置编辑器的工具栏和编辑器本身的相关属性。代码如下:
javascript 复制代码
<script setup>
// 工具栏配置
const toolbarConfig = {
  toolbarKeys: [
    // 一些常用的菜单 key
    "bold", // 加粗
    "italic", // 斜体
    "through", // 删除线
    "underline", // 下划线
    "bulletedList", // 无序列表
    "numberedList", // 有序列表
    "color", // 文字颜色
    "fontSize", // 字体大小
    "lineHeight", // 行高
    "uploadImage", // 上传图片
    "delIndent", // 缩进
    "indent", // 增进
    "deleteImage", //删除图片
    "divider", // 分割线
    "justifyCenter", // 居中对齐
    "justifyJustify", // 两端对齐
    "justifyLeft", // 左对齐
    "justifyRight", // 右对齐
    "undo", // 撤销
    "redo", // 重做
    "clearStyle", // 清除格式
  ],
};

// 编辑器配置
const editorConfig = {
  placeholder: "",
  MENU_CONF: {
    uploadImage: {
      server: uploadFile.url,
      headers: { Authorization: uploadFile.Authorization },
      "tenant-id": "1",
      fieldName: "file",
      customInsert(res, insertFn) {
        if (res.code == 0) {
          insertFn(res.data, null, res.data);
        }
      },
    },
  },
};
</script>

在上述代码中,我们通过toolbarConfig配置对象定义了工具栏的显示菜单,包括加粗、斜体、删除线、下划线、无序列表、有序列表、文字颜色、字体大小、行高、上传图片等功能。

editorConfig用于配置编辑器的相关属性,包括占位符文本(placeholder)以及上传图片的配置。

  1. 添加样式 最后,在组件的标签中,我们可以添加一些样式来美化富文本编辑器的界面。例如:
html 复制代码
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style>
.btn-container {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  margin-top: 60px;
}
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

h1 {
  text-align: center;
  font-size: 28px;
}
</style>

以上代码中,我们引入了Wangeditor默认的样式文件,并自定义了一些样式来调整按钮容器和编辑器容器的布局。

  1. 使用富文本编辑器组件 完成以上步骤后,我们就可以在其他Vue组件中使用RichTextEditor组件了。例如:
html 复制代码
        <Editor
            v-show="onsitesVisible"
            :info="onsiteActive"
            :content="content"
            v-model:visible="onsitesVisible"
            @confirm="getLists"
            @select="selects"
          />

在上述代码中,我们将RichTextEditor组件作为子组件引入,并通过:visible、:info和:content属性来传递组件需要的参数。同时,可以监听select事件来处理富文本编辑器中的选中操作。

结语 在本文中,我们介绍了如何使用Vue和Wangeditor插件实现一个富文本编辑器组件,并详细解释了组件中的各个部分和功能。通过这个组件,用户可以方便地进行富文本内容的编辑和排版。希望本文能对你理解和使用富文本编辑器有所帮助!

完整代码

html 复制代码
<template>
  <div v-if="newVisible">
    <div class="container"></div>
    <div style="border: 1px solid #ccc">
      <!-- 工具栏 -->

      <Toolbar
        :editor="editorRef"
        style="border-bottom: 1px solid #ccc"
        :defaultConfig="toolbarConfig"
      />
      <!-- 编辑器 -->
      <Editor
        v-model="valueHtml"
        :defaultConfig="editorConfig"
        style="height: 500px; overflow-y: hidden"
        @onCreated="handleCreated"
      />
    </div>
    <div class="btn-container">
      <CBotton type="primary" @click="save">保存</CBotton>
      <CBotton type="dashed" @click="cancel">取消</CBotton>
    </div>
  </div>
</template>
<script setup>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { uploadFile } from "@/api/base";
import { submitUploadInfoApi, getHelpContent } from "@/api/sale/help-set.ts";
import { message } from "ant-design-vue";
import {
  onBeforeUnmount,
  shallowRef,
  defineProps,
  ref,
  computed,
  defineEmits,
  reactive,
  watch,
} from "vue";

// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef();
const photoGalleryDialogVisible = ref();
const spinning = ref(false);

// 内容 HTML
const valueHtml = ref("");

const props = defineProps({
  visible: { type: Boolean, default: false },
  info: { type: Object, default: null },
  content: { type: Object, default: null },
});
const emit = defineEmits(["confirm", "update:visible", "select"]);

const newVisible = computed({
  get() {
    // 传过来的一行
    return props.visible;
  },
});
watch(
  () => props.visible,
  (val) => {
    console.log("val: ", props.info);
    if (val) {
      if (props?.content?.content) {
        valueHtml.value = props.content.content;
      }
    } else {
    }
  }
);
const handleCreated = (editor) => {
  editorRef.value = editor; // 记录 editor 实例,重要!
};
const save = async () => {
  // 保存逻辑
  const p = {
    categoryId: props.info.id,
    contentType: 1,
    content: valueHtml.value,
  };
  const res = await submitUploadInfoApi(p);
  if (res.code == 0) {
    cancel();
    emit("select", props.info.id);
    return message.success(res.msg);
  }
};

const cancel = () => {
  // 取消逻辑
  console.log("取消编辑");
  emit("update:visible", false);
  valueHtml.value = "";
};

// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
// 工具栏配置
const toolbarConfig = {
  toolbarKeys: [
    // 一些常用的菜单 key
    "bold", // 加粗
    "italic", // 斜体
    "through", // 删除线
    "underline", // 下划线
    "bulletedList", // 无序列表
    "numberedList", // 有序列表
    "color", // 文字颜色
    "fontSize", // 字体大小
    "lineHeight", // 行高
    "uploadImage", // 上传图片
    "delIndent", // 缩进
    "indent", // 增进
    "deleteImage", //删除图片
    "divider", // 分割线
    "justifyCenter", // 居中对齐
    "justifyJustify", // 两端对齐
    "justifyLeft", // 左对齐
    "justifyRight", // 右对齐
    "undo", // 撤销
    "redo", // 重做
    "clearStyle", // 清除格式
  ],
};
// 编辑器配置

const editorConfig = {
  placeholder: "",
  MENU_CONF: {
    uploadImage: {
      server: uploadFile.url,
      headers: { Authorization: uploadFile.Authorization },
      "tenant-id": "1",
      fieldName: "file", // 这里有个坑,如果返回的响应结果是没有上传文件,跟这里关系很大
      customInsert(res, insertFn) {
        if (res.code == 0) {
          insertFn(res.data, null, res.data);
        }
      },
    },
  },
};
</script>

<!-- 别忘了引入样式 -->
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style>
.btn-container {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  margin-top: 60px;
}
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

h1 {
  text-align: center;
  font-size: 28px;
}
</style>
相关推荐
奔跑的web.3 分钟前
TypeScript 全面详解:对象类型的语法规则
开发语言·前端·javascript·typescript·vue
江上月5137 分钟前
JMeter中级指南:从数据提取到断言校验全流程掌握
java·前端·数据库
代码猎人8 分钟前
forEach和map方法有哪些区别
前端
恋猫de小郭9 分钟前
Google DeepMind :RAG 已死,无限上下文是伪命题?RLM 如何用“代码思维”终结 AI 的记忆焦虑
前端·flutter·ai编程
m0_4711996318 分钟前
【小程序】订单数据缓存 以及针对海量库存数据的 懒加载+数据分片 的具体实现方式
前端·vue.js·小程序
编程大师哥19 分钟前
Java web
java·开发语言·前端
A小码哥20 分钟前
Vibe Coding 提示词优化的四个实战策略
前端
Murrays21 分钟前
【React】01 初识 React
前端·javascript·react.js
大喜xi24 分钟前
ReactNative 使用百分比宽度时,aspectRatio 在某些情况下无法正确推断出高度,导致图片高度为 0,从而无法显示
前端
helloCat24 分钟前
你的前端代码应该怎么写
前端·javascript·架构