vue+element_ui中使用富文本编辑器

富文本编辑器中实现功能:基本文本格式、上传图片、上传视频、链接等。

  1. 安装富文本编辑器
cnpm install --save vue-quill-editor
  1. 引入富文本编辑器
import QuillEditor from 'vue-quill-editor'

Vue.use(QuillEditor)

注:可以放到main.js中全局引用,也可以放到对应页面中。

  1. 使用
    自定义一个组件,代码中有详细注释。完整代码:
<template>
  <el-card v-loading="quillUpdateImg">
    <div slot="header" class="clearfix">
      <el-button style="float: left; padding: 3px 0" class="el-icon-arrow-left" type="text" @click="$router.go(-1)">返回</el-button>
      <span>{{moduleTitle}}</span>
      <el-button style="float: right; padding: 3px 0" class="el-icon-check" type="text" @click="submit">提交</el-button>
    </div>
    <el-form ref="editor" :model="editor" :rules="rules" label-width="100px" label-position="right">
      <el-form-item class="form-item-title" prop="editor_title" label="文章标题:">
        <el-input v-model="editor.editor_title" placeholder="文章标题" @change="handleEditorChange"/>
      </el-form-item>
      <el-form-item class="form-item-content" prop="editor_content" label="文章内容:">
        <quill-editor class="editor" v-model="editor.editor_content" ref="myQuillEditor" :options="editorOption"
          @change="handleEditorChange">
        </quill-editor>
      </el-form-item>
    </el-form>
    <el-upload
      class="avatar-uploader"
      action
      name="pic"
      :show-file-list="false"
      :http-request="handleUpload">
    </el-upload>
  </el-card>
</template>
<script>
// 工具栏配置
const toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
  ['blockquote', 'code-block'], // 引用  代码块
  [{ header: 1 }, { header: 2 }], // 1、2 级标题
  [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
  [{ script: 'sub' }, { script: 'super' }], // 上标/下标
  [{ indent: '-1' }, { indent: '+1' }], // 缩进
  // [{'direction': 'rtl'}],                         // 文本方向
  [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  [{ font: [] }], // 字体种类
  [{ align: [] }], // 对齐方式
  ['clean'], // 清除文本格式
  // ['link', 'image', 'video'] // 链接、图片、视频
  ['link', 'image'] // 链接、图片
]

export default {
  props: {
    loading: false,
    moduleTitle: {  // 编辑器标题
      type: String,
      default: '富文本编辑器'
    },
    uploadApi: {  // 文件服务器上传接口
      type: String,
      default: ''
    },
    downloadApi: { // 文件服务器下载接口
      type: String,
      default: ''
    },
    title: { // 文本标题
      type: String,
      default: ''
    },
    content: { // 文本内容
      type: String,
      default: ''
    },
    maxSize: { // 文本大小
      type: Number,
      default: 4000 // 单位:kb
    }
  },
  data () {
    return {
      quillUpdateImg: this.loading, // 根据图片上传状态来确定是否显示loading动画
      editor: { // 编辑器中数据
        editor_title: this.title,
        editor_content: this.content
      },
      rules: { // 表单校验规则
        editor_title: [{required: true, message: '请输入文章标题'}, {max: 100, message: '长度不超过100个字符'}],
        editor_content: [{required: true, message: '请输入文章内容'}, {max: 10000, message: '长度不超过10000个字符'}]
      },
      editorOption: { // 编辑框操作事件
        theme: 'snow', // or 'bubble'
        placeholder: '您想说点什么?',
        modules: {
          toolbar: {
            container: toolbarOptions,
            // container: '#toolbar',
            handlers: {
              image: function (value) { // 上传图片
                if (value) {
                  document.querySelector('.avatar-uploader input').click()  // 触发input框选择图片文件
                } else {
                  this.quill.format('image', false)
                }
              },
              link: function (value) { // 添加链接
                if (value) {
                  var href = prompt('请输入url')
                  this.quill.format('link', href)
                } else {
                  this.quill.format('link', false)
                }
              }
            }
          }
        }
      }
    }
  },
  methods: {
    handleEditorChange () { // 编辑器中内容改变时,触发的事件。冒泡到父组件,参数为编辑器中内容
      this.$emit('editor-change', this.editor)
    },
    handleUpload (param) { // 上传图片
      if (!this.uploadApi || this.uploadApi === '') {
        this.$message.error('无上传文件地址')
      }
      let formData = new FormData()
      formData.append('files', param.file)
      this.quillUpdateImg = true
      this.$axios.post(
        this.uploadApi, formData
      ).then(({data}) => {
        if (data.statusCode === 233) {
          let quill = this.$refs.myQuillEditor.quill // 获取富文本组件实例
          let length = quill.getSelection().index // 获取光标所在位置
          quill.insertEmbed(length, 'image', this.downloadApi + data.data.name) // 插入图片  res.url为服务器返回的图片地址
          quill.setSelection(length + 1) // 调整光标到最后
        } else {
          this.$message.error('上传失败')
        }
        this.quillUpdateImg = false
      })
    },
    submit () { // 提交,冒泡到父组件处理
      this.$refs.editor.validate(valid => {
        if (valid) {
          this.$emit('do-submit')
        } else {
          return false
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
  .el-card {
    height: 100%;
    /deep/ .el-card__header {
      padding: 10px;
    }
    /deep/ .el-card__body {
      padding: 10px;
      overflow: auto;
      height: calc(100% - 60px);
      .el-form {
        height: 100%;
        .el-form-item {
          margin-bottom: 20px;
        }
        .form-item-title {
          height: 40px;
          line-height: 40px;
        }
        .form-item-content {
          height: calc(100% - 60px - 20px);
          .el-form-item__content {
            height: 100%;
          }
          .editor {
            height: 100%;
            line-height: normal !important;
            .ql-toolbar {
              height: 70px;
              padding: 10px;
              text-align: left;
            }
            .ql-container {
              overflow: auto;
              height: calc(100% - 70px);
            }
          }
        }
      }
      .avatar-uploader {
        height: 0;
      }
      .ql-snow .ql-tooltip[data-mode=link]::before {
        content: '请输入链接地址:';
      }
      .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
          border-right: 0px;
          content: '保存';
          padding-right: 0px;
      }

      .ql-snow .ql-tooltip[data-mode=video]::before {
          content: '请输入视频地址:';
      }

      .ql-snow .ql-picker.ql-size .ql-picker-label::before,
      .ql-snow .ql-picker.ql-size .ql-picker-item::before {
        content: '14px';
      }
      .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
      .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
        content: '10px';
      }
      .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
      .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
        content: '18px';
      }
      .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
      .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
        content: '32px';
      }

      .ql-snow .ql-picker.ql-header .ql-picker-label::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item::before {
        content: '文本';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
        content: '标题1';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
        content: '标题2';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
        content: '标题3';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
        content: '标题4';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
        content: '标题5';
      }
      .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
      .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
        content: '标题6';
      }

      .ql-snow .ql-picker.ql-font .ql-picker-label::before,
      .ql-snow .ql-picker.ql-font .ql-picker-item::before {
        content: '标准字体';
      }
      .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
      .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
        content: '衬线字体';
      }
      .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
      .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
        content: '等宽字体';
      }
    }
  }
</style>

注:编辑器中无法实现行距的设置,待进一步完善。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值