资讯

展开

vue引入富文本编辑器

作者:快盘下载 人气:

1、安装依赖

npm i wangeditor;4.7.15 --save

2、在components文件夹下新建文件夹WangEditor;同时新建config.js文件

const defaultConfig = {
  menus: [
    ;head;, // 标题
    ;bold;, // 加粗
    ;fontSize;, // 字号
    ;fontName;, // 字体
    ;italic;, // 斜体
    ;underline;, // 下划线
    ;strikeThrough;, // 删除线
    ;indent;, // 缩进
    ;lineHeight;, // 行高
    ;foreColor;, // 字体颜色
    ;backColor;, // 背景色
    ;link;, // 链接
    ;list;, // 序列
    // ;todo;, // 待办事项
    ;justify;, // 对齐
    ;quote;, // 引用
    // ;emoticon;, // 表情
    ;image;, // 图片
    ;video;, // 视频
    // ;table;, // 表格
    // ;code;, // 代码
    ;splitLine;, // 分割线
    ;undo;, // 撤销
    ;redo;, // 恢复
  ],
  fontNames: [;黑体;, ;仿宋;, ;楷体;, ;宋体;, ;微软雅黑;, ;Arial;], // 常用字体
  lineHeights: [;1;, ;1.15;, ;1.6;, ;2;, ;2.5;, ;3;],
  uploadImgAccept: [;jpg;, ;jpeg;, ;png;, ;gif;, ;bmp;, ;webp;], // 限制图片类型
  uploadVideoAccept: [;mp4;], // 限制视频类型
}
export default {
  defaultConfig,
}

3、新建wLayoutMenu.js文件

import E from ;wangeditor;

const { $, BtnMenu } = E

// 设置默认样式
const initPStyle = ;text-indent: 2em; font-size: 20px !important; line-height: 1.5; font-family: 仿宋;
export default class wLayoutMenu extends BtnMenu {
  constructor(editor) {
    // data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
    const $elem = $(;<div class=;w-e-menu; style=;width: 80px;font-weight: bold;color: #999; data-title=;一键排版;>一键排版</div>;)
    super($elem, editor)
  }

  clickHandler() {
    // 获取富文本编辑区的DOM
    const childDomArr = this.editor.$textElem.elems[0].childnodes
    if (childDomArr.length > 0) {
      childDomArr.forEach((item) => {
        // 富文本编辑的内容默认外层都是由p标签包容;所以直接在p标签上进行设置默认排版的样式
        if (item.nodeName === ;P;) {
          item.style.cssText = initPStyle
        }
        if (item.childNodes.length > 0) {
          // 遍历找到子元素中存在img标签的内容进行设置默认样式
          item.childNodes.forEach((child) => {
            if (child.localName === ;img;) {
              // 获取原图width、height
              const width = child.width
              const height = child.height
              const ratio = width / height
              const setW = 600
              let setH = 0 // 等比计算
              if (setW / setH !== ratio) {
                setH = setW / ratio
              }
              // 给img标签设置行内样式
              child.setAttribute(;width;, setW)
              child.setAttribute(;height;, setH)
              child.style.cssText = ;text-align: center;
            }
          })
        }
      })
    }
  }

  // 菜单是否被激活;如果不需要;这个函数可以空着;
  tryChangeActive() {}
}

4、新建vue文件index

<template>
  <div style=;position: relative; :style=;pareStyle;>
    <div ref=;editor;></div>
    <div v-if=;dataUploading; class=;tips-progress;>
      <el-progress
        style=;width: 60%
        :text-inside=;true;
        :stroke-width=;$px(18);
        :percentage=;uploadProgress;
        :color=;customColors;
        status=;success;
      ></el-progress>
    </div>
  </div>
</template>

<script>
  import WangEditor from ;wangeditor;
  import config from ;./config;
  import wLayoutMenu from ;./wLayoutMenu;
  import emitter from ;element-ui/src/mixins/emitter;
  import axios from ;axios;

  export default {
    name: ;WangEditor;,
    mixins: [emitter],
    props: {
      value: {
        type: String,
        default: ;;,
      },
      height: {
        type: Number,
        default: 200,
      },
      // M
      uploadImgMaxSize: {
        type: Number,
        default: 5,
      },
      // M
      uploadVideoMaxSize: {
        type: Number,
        default: 500,
      },
      placeholder: {
        type: String,
        default: ;请输入内容...;,
      },
      config: {
        type: Object,
        default: () => {
          return {}
        },
      },
    },
    data() {
      return {
        editorE: ;;, // 编辑器的对象
        dataUploading: false,
        uploadProgress: 0,
        pareStyle: {},
        focused: false,
        customColors: [
          {
            color: ;#f56c6c;,
            percentage: 20,
          },
          {
            color: ;#e6a23c;,
            percentage: 40,
          },
          {
            color: ;#5cb87a;,
            percentage: 60,
          },
          {
            color: ;#1989fa;,
            percentage: 80,
          },
          {
            color: ;#6f7ad3;,
            percentage: 100,
          },
        ],
      }
    },
    computed: {
      needConfig() {
        return { ...config.defaultConfig, ...this.config }
      },
    },
    watch: {
      value(val) {
        // 普通的watch监听
        if (val !== this.editorE.txt.html()) {
          this.editorE.txt.html(val)
        }
      },
    },
    mounted() {
      const that = this
      // 初始化编辑框
      that.init()
      window.addEventListener(;resize;, () => {
        that.editorE.destroy()
        that.editorE = null
        that.pareStyle = {}
        that.init()
      })
    },
    beforeDestroy() {
      // 销毁编辑器
      this.editorE.destroy()
      this.editorE = null
    },
    methods: {
      init() {
        const that = this
        /* 实例化 */
        that.editorE = new WangEditor(that.$refs.editor)
        // 设置富文本的高度
        that.editorE.config.height = that.height
        // 取消自动 focus
        that.editorE.config.focus = false
        // 注册菜单
        that.editorE.menus.extend(;shortcutLayout;, wLayoutMenu)
        // 配置菜单
        that.editorE.config.menus = that.needConfig.menus
        // 配置字体
        that.editorE.config.fontNames = that.needConfig.fontNames
        // 默认提示
        that.editorE.config.placeholder = that.placeholder
        // 配置全屏功能 默认全屏
        that.editorE.config.showFullScreen = true
        //  配置行高
        that.editorE.config.lineHeights = that.needConfig.lineHeights
        // 设置菜单栏提示为上标还是下标
        that.editorE.config.menuTooltipPosition = ;down;
        // 配置element ui message提示
        that.editorE.config.customAlert = (s, t) => {
          switch (t) {
            case ;success;:
              that.$message.success(s)
              break
            case ;info;:
              that.$message.info(s)
              break
            case ;warning;:
              that.$message.warning(s)
              break
            case ;error;:
              that.$message.error(s)
              break
            default:
              that.$message.info(s)
              break
          }
        }

        // 图片上传
        // 隐藏插入网络图片功能
        that.editorE.config.showLinkImg = false
        // 默认限制图片大小是 5M
        that.editorE.config.uploadImgMaxSize = that.uploadImgMaxSize * 1024 * 1024
        // 限制图片类型
        that.editorE.config.uploadImgAccept = that.needConfig.uploadImgAccept
        // 限制一次最多能传几张图片
        that.editorE.config.uploadImgMaxLength = 1
        that.editorE.config.customUploadImg = function(resultFiles, insertImgFn) {
          that.uploadProgress = 0
          that.dataUploading = true
          const file = resultFiles[0]
          axios
            .post(;xxxx;, file, {
              onUploadProgress: (progressEvent) => {
                // 图片上传进度
                const percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0
                that.uploadProgress = percent
              },
            })
            .then((res) => {
              const { status, data } = res
              // 不管上没上传成功都关闭进度条
              that.dataUploading = false
              if (status === 201) {
                insertImgFn(data.url)
              } else {
                that.$message.error(;图片上传失败;)
              }
            })
        }

        // 视频上传
        // 隐藏插入网络视频功能
        that.editorE.config.showLinkVideo = false
        // 限制视频大小
        that.editorE.config.uploadVideoMaxSize = that.uploadVideoMaxSize * 1024 * 1024
        // 限制视频类型
        that.editorE.config.uploadVideoAccept = that.needConfig.uploadVideoAccept
        // 自定义视频上传;由于视频一般较大;需要显示进度;就不用编辑器定义的上传了
        that.editorE.config.customUploadVideo = function(resultFiles, insertVideoFn) {
          that.uploadProgress = 0
          that.dataUploading = true
          const file = resultFiles[0]
          axios
            .post(;xxxx;, file, {
              onUploadProgress: (progressEvent) => {
                // 视频上传进度
                const percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0
                that.uploadProgress = percent
              },
            })
            .then((res) => {
              const { status, data } = res
              // 不管上没上传成功都关闭进度条
              that.dataUploading = false
              if (status === 201) {
                insertVideoFn(data.url)
              } else {
                that.$message.error(;视频上传失败;)
              }
            })
        }

        // 粘贴处理
        // 关闭粘贴样式的过滤
        that.editorE.config.pasteFilterStyle = false
        // 自定义处理粘贴的文本内容
        that.editorE.config.pasteTextHandle = function(pasteStr) {
          // 对粘贴的文本进行处理;然后返回处理后的结果
          const htmlDom = document.createElement(;div;)
          htmlDom.innerHTML = pasteStr
          const imgDomArr = htmlDom.querySelectorAll(;img[src];)
          imgDomArr.forEach((img) => {
            img.style.maxWidth = ;100%
          })
          const result = htmlDom.innerHTML
          htmlDom.remove()
          return result
        }
        // 创建编辑器
        that.editorE.create()
        that.$nextTick(() => {
          const offsetHeight = that.$refs.editor.offsetHeight
          const offsetWidth = that.$refs.editor.offsetWidth
          that.pareStyle = {
            height: ;${offsetHeight}px;,
            width: ;${offsetWidth}px;,
          }
          that.editorE.txt.html(this.value)
        })
        // 监控变化;同步更新到文本 向上传递更新
        that.editorE.config.onchange = function(html) {
          that.$emit(;input;, html)
        }
        // 失去焦点处理
        that.editorE.config.onblur = function(newHtml) {
          // 用于el-form表单验证;具体参考el-input
          if (that.focused) {
            that.focused = false
            that.dispatch(;ElFormItem;, ;el.form.blur;, [newHtml])
          }
        }
        // 聚焦处理
        that.editorE.config.onfocus = function() {
          that.focused = true
        }
      },
    },
  }
</script>
<style scoped lang=;scss;>
  .tips-progress {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%
    height: 100%
    line-height: 100%
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  ::v-deep .w-e-toolbar {
    border-color: #d4d4d4 !important;
  }

  ::v-deep .w-e-text-container {
    border-color: #d4d4d4 !important;
  }
</style>

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!