vue 富文本使用介绍

507 阅读2分钟

主要介绍了2种富文本的使用,一种轻量级,一种重量级,看实际情况选择,例子贴出来的只是主要代码。

vue2-editor 封装了Quill 轻量级别

下载 vue2-editor、quill-image-drop-module、quill-image-resize-module 包

npm install vue2-editor quill-image-drop-module quill-image-resize-module --save

封装到 src/components/editor/app-vue-editor.vue

<template>
  <vue-editor id="editor"
    class="vue-editor-wrap"
    useCustomImageHandler
    v-model="content"
    @image-added="handleImageAdded"
    :editor-toolbar="customToolbar"
    :editorOptions="editorSettings"
    />
</template>

<script lang="ts">
import Vue from 'vue';
import { VueEditor, Quill } from 'vue2-editor';
import thirdPartyApi from '@/thirdPartyApi/index.ts';
import { ImageDrop } from 'quill-image-drop-module';
import ImageResize from 'quill-image-resize-module';

Quill.register('modules/imageDrop', ImageDrop);
Quill.register('modules/imageResize', ImageResize);

export default Vue.extend({
  components: {
    VueEditor,
  },
  props: {
    initContent: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      content: '',
      // 重置面板
      customToolbar: [
       [{
         header: [false, 1, 2, 3, 4, 5, 6],
        }], ['bold', 'italic', 'underline', 'strike'], // toggled buttons
        [{
          align: '',
        }, {
          align: 'center',
        }, {
          align: 'right',
        }, {
          align: 'justify',
        }], ['blockquote', 'code-block'], [{
          list: 'ordered',
        }, {
          list: 'bullet',
        }, {
          list: 'check',
        }], [{
          indent: '-1',
        }, {
          indent: '+1',
        }], // outdent/indent
        [{ color: [] }, { background: [] }], // dropdown with defaults from theme
        ['link', 'image',
        // 'video'
        ],
        ['clean'], // remove formatting button
      ],
      editorSettings: {
        modules: {
          imageDrop: true,
          imageResize: {},
        },
      },
    };
  },
  watch: {
    initContent: {
      handler(v) {
        this.content = v;
      },
      immediate: true,
    },
    content(v) {
      this.$emit('update:initContent', v);
      this.$emit('change');
    },
  },
  methods: {
  // 添加图片
    handleImageAdded(file: any, Editor: any, cursorLocation: any, resetUploader: any) {
      const formData = new FormData();
      formData.append('file', file);

      thirdPartyApi.fileMgr.saveFile(formData).then((result) => {
        const url = thirdPartyApi.fileMgr.getFile + result.data;
        Editor.insertEmbed(cursorLocation, 'image', url);
        resetUploader();
      });
    },
  },
});
</script>
<style lang="scss" scoped>
.vue-editor-wrap{
  /deep/ .ql-toolbar.ql-snow .ql-formats{
    margin-right: 8px;
  }
  /deep/ .quillWrapper .ql-snow.ql-toolbar .ql-formats{
    margin-bottom: 0;
  }
}

</style>

// 使用

<template>
  <div>
   <AppVueEditor :initContent.sync="params.mailContent" @change="handleContentChange"></AppVueEditor>
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import AppVueEditor from '@/components/editor/app-vue-editor.vue';


export default Vue.extend({
  components: {
    AppVueEditor,
  },
  data() {
    return {
      params: {
        mailContent: '',
      },
      rules: {
        mailContent: [
          { required: true, message: '消息内容不能为空!', trigger: ['blur', 'change'] },
        ],
      },
    };
  },
  methods: {
    handleContentChange() {
      ...
      if (this.$refs.ruleForm) {
        (this.$refs.ruleForm as any).validateField('mailContent');
      }
      ...
    },
  },
});
</script>

vue-ueditor-wrap 封装了ueditor 重量级

下载 vue-ueditor-wrap 包

npm install vue-ueditor-wrap --save

下载ueditor 并放置到/public/UE/xxx (文件位置 在 @/utils/ueditorTool 里面的 UEDITOR_HOME_URL 可配置)
下载地址: github.com/fex-team/ue… (有一些无用的文件可以删掉)

// src/components/ueditor/app-editor.vue

<template>
  <div class="ueditor-wrap">
      <vue-ueditor-wrap
        v-model="content"
        :config="config"
        class="editor"
      ></vue-ueditor-wrap>
  </div>
</template>
<script>
  import config from '@/utils/ueditorTool'
  import VueUeditorWrap from 'vue-ueditor-wrap'
export default {
  props: {
    initContent: {
      type: String,
      default: ''
    },
  },
  components: {
    VueUeditorWrap
  },
  data () {
    return {
      config,
      content: ''
    }
  },
  watch: {
    initContent: {
      handler (v) {
        this.content = v
      },
      immediate: true
    },
    content (v) {
      this.$emit('update:initContent', v)
      this.$emit('change')
    }
  }
}
</script>
<style lang="scss" scoped>
.ueditor-wrap{
  /deep/ .edui-default .edui-toolbar .edui-combox .edui-combox-body{
    height:20px;
  }
  /deep/ .edui-default .edui-button-body, .edui-splitbutton-body, .edui-menubutton-body, .edui-combox-body{
    height:20px;
  }
}
</style>
//@/utils/ueditorTool

const toolbars = [
  [
      // 'anchor', // 锚点
      'undo', // 撤销
      'redo', // 重做
      'bold', // 加粗
      'indent', // 首行缩进
      // 'snapscreen', // 截图
      'italic', // 斜体
      'underline', // 下划线
      'strikethrough', // 删除线
      'subscript', // 下标
      'fontborder', // 字符边框
      'superscript', // 上标
      'formatmatch', // 格式刷
      // 'source', // 源代码
      'blockquote', // 引用
      'pasteplain', // 纯文本粘贴模式
      'selectall', // 全选
      // 'print', // 打印
      // 'preview', // 预览
      'horizontal', // 分隔线
      'removeformat', // 清除格式
      'time', // 时间
      'date', // 日期
      'unlink', // 取消链接
      'insertrow', // 前插入行
      'insertcol', // 前插入列
      'mergeright', // 右合并单元格
      'mergedown', // 下合并单元格
      'deleterow', // 删除行
      'deletecol', // 删除列
      'splittorows', // 拆分成行
      'splittocols', // 拆分成列
      'splittocells', // 完全拆分单元格
      'deletecaption', // 删除表格标题
      'inserttitle', // 插入标题
      'mergecells', // 合并多个单元格
      'deletetable', // 删除表格
      'cleardoc', // 清空文档
      'insertparagraphbeforetable', // "表格前插入行"
      'insertcode', // 代码语言
      'fontfamily', // 字体
      'fontsize', // 字号
      'paragraph', // 段落格式
      // 'simpleupload', // 单图上传
      // 'insertimage', // 多图上传
      'edittable', // 表格属性
      'edittd', // 单元格属性
      'link', // 超链接
      // 'emotion', // 表情
      'spechars', // 特殊字符
      'searchreplace', // 查询替换
      // 'map', // Baidu地图
      // 'gmap', // Google地图
      // 'insertvideo', // 视频
      'help', // 帮助
      'justifyleft', // 居左对齐
      'justifyright', // 居右对齐
      'justifycenter', // 居中对齐
      'justifyjustify', // 两端对齐
      'forecolor', // 字体颜色
      'backcolor', // 背景色
      'insertorderedlist', // 有序列表
      'insertunorderedlist', // 无序列表
      'fullscreen', // 全屏
      'directionalityltr', // 从左向右输入
      'directionalityrtl', // 从右向左输入
      'rowspacingtop', // 段前距
      'rowspacingbottom', // 段后距
      'pagebreak', // 分页
      'insertframe', // 插入Iframe
      'imagenone', // 默认
      'imageleft', // 左浮动
      'imageright', // 右浮动
      // 'attachment', // 附件
      // 'imagecenter', // 居中
      // 'wordimage', // 图片转存
      'lineheight', // 行间距
      'edittip ', // 编辑提示
      'customstyle', // 自定义标题
      'autotypeset', // 自动排版
      // 'webapp', // 百度应用
      'touppercase', // 字母大写
      'tolowercase', // 字母小写
      'background', // 背景
      // 'template', // 模板
      // 'scrawl', // 涂鸦
      // 'music', // 音乐
      'inserttable' // 插入表格
      // 'drafts', // 从草稿箱加载
      // 'charts' // 图表
  ]
]
const config = {
  UEDITOR_HOME_URL: '/UE/',
  zIndex: 999999,
  initialFrameHeight: 350,
  toolbars,
  // serverUrl: '/storage/ueditor/upload'
  serverUrl: '/' // 图片上传需要配置,后端也需要根据ueditor的使用来,vue2-editor 不需要
}
export default config

// 使用

<template>
  <div>
    <AppUeditor
      :initContent.sync="params.content"
      @change="handleContentChange"
    ></AppUeditor>
  </div>
</template>

<script>
import AppUeditor from '@/components/ueditor/app-ueditor'

export default {
  components: {
    AppUeditor
  },
  data () {
    return {
      params: {
        content: ''
      },
      rules: {
        content: [
          { required: true, message: '邮件内容不能为空!', trigger: 'blur' }]
      }
    }
  },
  methods: {
    handleContentChange () {
      this.$refs.ruleForm && this.$refs.ruleForm.validateField('content')
    },
  }
}
</script>