vue使用wangEditor创建富文本

安装

javascript 复制代码
npm install @wangeditor/editor --save
npm install @wangeditor/editor-for-vue --save
npm install @wangeditor/plugin-upload-attachment//附件使用

vue

图片上传、视频上传、附件上传

javascript 复制代码
<template lang="html">
    <div style="border: 1px solid #ccc;width:840px" class="editors">
        <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" />
        <Editor style="height: 400px; overflow-y: hidden;" v-model="html" @input="handleInput"
            :defaultConfig="editorConfig" :mode="mode" @onCreated="onCreated" @onChange="onChange"
            @onMaxLength="onMaxLength" />
    </div>
</template>
<script>
import Vue from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { DomEditor } from "@wangeditor/editor";
import "@wangeditor/editor/dist/css/style.css";
import { getToken } from "@/utils/auth";
export default Vue.extend({
  components: { Editor, Toolbar },
  model: {
    prop: "value", // v-model 接收的值=props的message属性接收的值
    event: "change", // v-model 发生变化时触发的方法
  },
  props: {
    value: {
      // 富文本数据
      type: String,
      default: "",
    },
    id: {
      type: String,
      default: "",
    },
    maxLength: {
      type: Number,
      default: 10000000,
    },
  },
  watch: {
    value: function (value) {
      // 如果值不相等再进行赋值,避免多次赋值造成闪烁
      if (value !== this.html) {
        this.html = this.value;
      }
    },
    // value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
  },
  data() {
    return {
      editor: null,
      html: "",
      textLength: 0,
      // 编辑器模式
      mode: "default", // or 'simple'
      toolbarConfig: {
        // 排除工具栏配置
        excludeKeys: [
          // 全屏,网络视频,本地视频,表情,代码,待办,代码块,插入图片
          "fullScreen",
          // "uploadVideo",
          // "group-video",
          // "emotion",
          // "code",
          // "todo",
          // "codeBlock",
          "insertImage",
        ],
        insertKeys: {
          index: 22, // 自定义插件在工具栏显示的位置
          keys: ["uploadAttachment"], // 查看名称
        },
        hoverbarKeys: {
          attachment: {
            menuKeys: ["downloadAttachment"], // "下载附件"菜单
          },
        },
      },
      italicButton: null,
      editorConfig: {
        placeholder: "请输入内容...",
        maxLength: this.maxLength, // 限制富文本输入文本字数
        MENU_CONF: {
          uploadImage: {
            server: process.env.VUE_APP_BASE_API + "/file",
            timeout: 100000,
            maxFileSize: 10000 * 1024 * 1024, 
            base64LimitSize: 50000 * 1024,
          },
          uploadVideo: {
            fieldName: "file",
            server: process.env.VUE_APP_BASE_API + "/file",
            timeout: 1000000,
            maxFileSize: 10000 * 1024 * 1024, // 1M
            base64LimitSize: 50000 * 1024,
            headers: {
              Authorization: getToken(),
            },
            async customInsert(insertFn, result) {
              if (insertFn.code === 0) {
                result(insertFn.data[0]);
              } else {
                this.$message.error("视频上传失败,请重新上传!");
              }
            },
          },
          uploadAttachment: {
            fieldName: "file",
            server: process.env.VUE_APP_BASE_API + "/file",
            timeout: 1000000,
            headers: {
              Authorization: getToken(),
            },
            async customInsert(res, file,insertFn) {
              insertFn(
                file.name,
                res.data[0]
              );
            },
          },
          fontFamily: {
            fontFamilyList: [
              { name: "仿宋", value: "fangsong" },
              { name: "黑体", value: "Arial" },
              { name: "仿手写", value: "cursive" },
              "serif",
              "sans-serif",
            ],
          },
        },
      },
      // Toolbar对象
      curToolbarConfig: null,
    };
  },

  methods: {
    onCreated(editor) {
      this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
      this.$nextTick(() => {
        const toolbar = DomEditor.getToolbar(this.editor);
        this.curToolbarConfig = toolbar.getConfig();
      });
    },
    handleInput(value) {
      this.$emit("input", value); // 将内容同步到父组件中
    },
    onChange(editor) {
      // 监听富文本输入
      const text = editor.getText().replace(/\n|\r/gm, "");
      this.textLength = text.length;
    },
    onMaxLength(editor) {
      // 当输入值达到限制值时触发事件
      this.$message.warning("输入文本数已到达最大值!");
    },
  },
  mounted() {},
  beforeDestroy() {
    const editor = this.editor;
    if (editor == null) return;
    editor.destroy(); // 组件销毁时,及时销毁编辑器
  },
});
</script>
<style lang="scss" scoped>
::v-deep .w-e-textarea-video-container {
  background-image: none;
}
</style>

main.js

javascript 复制代码
import {Boot} from '@wangeditor/editor'
import attachmentModule from '@wangeditor/plugin-upload-attachment'
Boot.registerModule(attachmentModule)
相关推荐
尾善爱看海3 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
weixin_BYSJ19873 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Bs_MoneyMagnet3 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
驳是4 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea4 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持4 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者4 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn5 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
Bs_MoneyMagnet6 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师6 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端