vue中使用vue-quill-editor富文本编辑器:自定义行高、选中后工具栏初始化

1、引入组件

<quill-editor
      ref="myQuillEditor"
      v-model="content"
      class="editor ql-editor"
      :options="editorOption"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @change="onEditorChange($event)"
      @ready="ready($event)"
    />
// 工具栏配置
import { quillEditor } from 'vue-quill-editor'
import { Uploads } from '@/api/hpms/qiniu'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

 

2、设置行高

//lineHeight.js
import Quill from "quill";
const Parchment = Quill.import("parchment");
class lineHeightAttributor extends Parchment.Attributor.Style { }
const lineHeightStyle = new lineHeightAttributor("lineHeight", "line-height", {
  scope: Parchment.Scope.INLINE, whitelist: ["1", "2", "3", "4", "5"]
});

export { lineHeightStyle };
import { lineHeightStyle } from "./lineHeight";
ready() {
      Quill.register({ "formats/lineHeight": lineHeightStyle }, true)
    },
editorOption: {
        placeholder: '您想说点什么?',
        theme: 'snow', // or 'bubble'
        modules: {

          toolbar: {
            container: toolbarOptions,
            // container: "#toolbar",
            handlers: {
              lineHeight: (value) => {                 
                if (value) {
                  const quill = this.$refs.myQuillEditor.quill
                  quill.format("lineHeight", value);
                }
              }
   
            }
          }
        }
      },

 

3、行高样式

.ql-snow .ql-picker.ql-lineHeight .ql-picker-label::before {
  content: "行高";
}

.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1"]::before {
  content: "行高1";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.5"]::before,
.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.5"]::before {
  content: "行高1.5";
}

.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.75"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.75"]::before {
  content: "行高1.75";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="2"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="2"]::before {
  content: "行高2";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="3"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="3"]::before {
  content: "行高3";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="4"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="4"]::before {
  content: "行高4";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="5"]::before ,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="5"]::before{
  content: "行高5";
}
.ql-snow .ql-picker.ql-lineHeight {
  width: 70px;
}

 

4、效果图

vue中使用vue-quill-editor富文本编辑器:自定义行高、选中后工具栏初始化

 

5、完整代码

<template>
  <div>
    <!-- 图片上传组件辅助-->
    <el-upload
      v-show="false"
      class="avatar-uploader"
      action="/bmms/web-bm/file"
      name="img"
      accept=".jpg, .png"
      :show-file-list="false"
      :on-change="handleChange"
      :http-request="httpRequest"
      :before-upload="beforeUpload"
    />
    <quill-editor
      ref="myQuillEditor"
      v-model="content"
      class="editor ql-editor"
      :options="editorOption"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @change="onEditorChange($event)"
      @ready="ready($event)"
    />
  </div>
</template>
<script>
// 工具栏配置
import { quillEditor } from 'vue-quill-editor'
import { Uploads } from '@/api/hpms/qiniu'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

import ImageResize from 'quill-image-resize-module'
import * as Quill from 'quill'
import { lineHeightStyle } from "./lineHeight";
var Size = Quill.import('attributors/style/size')
Size.whitelist = ['10px', '12px', '14px', '16px', '18px', '20px', '30px', '32px', '38px', '48px', '64px'] // 引入编辑器
Quill.register(Size, true)
Quill.register('modules/imageResize', ImageResize)

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' }], // 缩进
  [{ size: Size.whitelist }],
  [{ 'align': [] }],
  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色

  ['clean'], // 清除文本格式
  [{ lineHeight: lineHeightStyle.whitelist }], // 对齐方式
  ['image'] // 链接、图片
]
const toolbarTips = [
  { Choice: '.ql-bold', title: '加粗' },
  { Choice: '.ql-italic', title: '倾斜' },
  { Choice: '.ql-underline', title: '下划线' },
  { Choice: '.ql-header', title: '段落格式' },
  { Choice: '.ql-strike', title: '删除线' },
  { Choice: '.ql-blockquote', title: '块引用' },
  { Choice: '.ql-code-block', title: '插入代码段' },
  { Choice: '.ql-size', title: '字体大小' },
  { Choice: '.ql-list[value="ordered"]', title: '编号列表' },
  { Choice: '.ql-list[value="bullet"]', title: '项目列表' },
  { Choice: '.ql-header[value="1"]', title: 'h1' },
  { Choice: '.ql-header[value="2"]', title: 'h2' },
  { Choice: '.ql-align', title: '对齐方式' },
  { Choice: '.ql-color', title: '字体颜色' },
  { Choice: '.ql-background', title: '背景颜色' },
  { Choice: '.ql-image', title: '图像' },
  { Choice: '.ql-video', title: '视频' },
  { Choice: '.ql-link', title: '添加链接' },
  { Choice: '.ql-formula', title: '插入公式' },
  { Choice: '.ql-clean', title: '清除格式' },
  { Choice: '.ql-lineHeight', title: '设置行高' },
  { Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
  { Choice: '.ql-header .ql-picker-label', title: '标题大小' },
  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
  { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
  { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]
export default {
  components: {
    quillEditor
  },
  props: {
    /* 编辑器的内容 */
    value: {
      type: String,
      default: () => {}
    },
    /* 图片大小 */
    maxSize: {
      type: Number,
      default: 4000 // kb
    }
  },

  data () {
    return {
      params: {
        token: '',
        FileName: ''
      },
      content: this.value,
      quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
      editorOption: {
        placeholder: '您想说点什么?',
        theme: 'snow', // or 'bubble'
        modules: {
          imageResize: {
            displayStyles: {
              backgroundColor: 'black',
              border: 'none',
              color: 'white'
            },
            modules: ['Resize', 'DisplaySize', 'Toolbar']
          },
          toolbar: {
            container: toolbarOptions,
            // container: "#toolbar",
            handlers: {
              image: function (value) {
                if (value) {
                  // 触发input框选择图片文件
                  document.querySelector('.avatar-uploader input').click()
                } else {
                  this.quill.format('image', false)
                }
              },
              lineHeight: (value) => {                 
                if (value) {
                  const quill = this.$refs.myQuillEditor.quill
                  quill.format("lineHeight", value);
                }
              }
              // link: function(value) {
              //   if (value) {
              //     var href = prompt('请输入url');
              //     this.quill.format("link", href);
              //   } else {
              //     this.quill.format("link", false);
              //   }
              // },
            }
          }
        }
      },
      serverUrl: this.UploadFile(), // 这里写你要上传的图片服务器地址
      header: {
        // token: sessionStorage.token
      } // 有的图片服务器要求请求头需要有token
    }
  },
  watch: {
    value (val) {
      this.content = this.value
    }
  },
  // computed: {
  //   content () {
  //     return this.value
  //   }
  // },
  mounted () {
    for (let item of toolbarTips) {
      let tip = document.querySelector('.quill-editor ' + item.Choice)
      if (!tip) continue
      tip.setAttribute('title', item.title)
    }
  },
  created () {
    // this.$nextTick(() => {
    //   document.getElementById('self_typt-add-container').scrollTop = 0
    // })
  },
  methods: {
    ready() {
      Quill.register({ "formats/lineHeight": lineHeightStyle }, true)
    },
    UploadFile () {
      return '/bmms/web-bm/file'
    },
    onEditorBlur () {
      // 失去焦点事件
    },
    onEditorFocus (val) {
      // 获得焦点事件
      const quill = this.$refs.myQuillEditor.quill
      quill.format("lineHeight", 3);
      console.log('获得焦点事件----',lineHeightStyle.whitelist)
    },
    onEditorChange () {
      // 内容改变事件
      this.content = this.content.replace(/href=/g, '')
      this.$emit('input', this.content)
    },
    cuFocus () {
      this.$nextTick(function () {
        document.getElementById('self_typt-add-container').scrollTop = 0
      })
    },
    httpRequest (param) {
      const form = new FormData()
      form.append('file', param.file, param.file.name)
      Uploads(form).then(res => {
        if (res.status === 200) {
          const quill = this.$refs.myQuillEditor.quill
          // 如果上传成功
          if (res.status === 200) {
            // 获取光标所在位置
            const length = quill.getSelection().index
            // 插入图片  res.url为服务器返回的图片地址
            quill.insertEmbed(length, 'image', res.data.urlPath)
            // 调整光标到最后
            quill.setSelection(length + 1)
          } else {
            this.$message.error('图片插入失败')
          }
          // loading动画消失
          this.quillUpdateImg = false
        }
      })
    },
    // 富文本图片上传前
    beforeUpload (file) {
      // 显示loading动画
      this.quillUpdateImg = true
      const filetype = file.name.slice(
        file.name.lastIndexOf('.'),
        file.name.length
      )
      if (filetype === '.jpg' || filetype === '.png') {
        const isLt2M = file.size / 1024 / 1024 < 2
        if (!isLt2M) {
          this.$message.error('上传文件大小不能超过 2MB!')
          return false
        } else {
          return true
        }
      } else {
        this.$message.error('请上传PNG,JPG格式文件')
        return false
      }
    },
    handleChange (file, fileList) {
      var fileObj = file
      const form = new FormData()
      form.append('token', 'wnms')
      form.append('FileName', '44324')
      form.append('File', fileObj)
    }
  }
}
</script>

<style lang="scss">
  .ql-container{
    >div:not(.ql-editor){
      >div{
        >span{
          display: none !important;
          border:1px solid red !important;
        }
      }
    }
  }
.editor {
  line-height: normal !important;
  height: 28rem;
  overflow: hidden;
  margin-top: -1vh;
}
.ql-container {
  overflow: auto;
  height: calc(100% - 50px);
}
.ql-editor {
  p{
    img{
      max-width: 100%;
      margin: auto ;
      display: block ;
      float: none !important;
    }
  }
}
.ql-snow .ql-editor,.ql-snow .ql-editor img {
  display: block;
}
.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-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-toolbar {
  white-space: normal;
}
.ql-picker-item[data-value='10px']::before,
.ql-picker-label[data-value='10px']::before {
  content: '10px' !important;
}

.ql-picker-item[data-value='12px']::before,
.ql-picker-label[data-value='12px']::before {
  content: '12px' !important;
}

.ql-picker-item[data-value='14px']::before,
.ql-picker-label[data-value='14px']::before {
  content: '14px' !important;
}

.ql-picker-item[data-value='16px']::before,
.ql-picker-label[data-value='16px']::before {
  content: '16px' !important;
}

.ql-picker-item[data-value='18px']::before,
.ql-picker-label[data-value='18px']::before {
  content: '18px' !important;
}

.ql-picker-item[data-value='20px']::before,
.ql-picker-label[data-value='20px']::before {
  content: '20px' !important;
}

.ql-picker-item[data-value='24px']::before,
.ql-picker-label[data-value='24px']::before {
  content: '24px' !important;
}

.ql-picker-item[data-value='30px']::before,
.ql-picker-label[data-value='30px']::before {
  content: '30px' !important;
}

.ql-picker-item[data-value='32px']::before,
.ql-picker-label[data-value='32px']::before {
  content: '32px' !important;
}
.ql-picker-item[data-value='38px']::before,
.ql-picker-label[data-value='38px']::before {
  content: '38px' !important;
}
.ql-picker-item[data-value='48px']::before,
.ql-picker-label[data-value='48px']::before {
  content: '48px' !important;
}
.ql-picker-item[data-value='64px']::before,
.ql-picker-label[data-value='64px']::before {
  content: '64px' !important;
}
.ql-picker-item[data-value='72px']::before,
.ql-picker-label[data-value='72px']::before {
  content: '72px' !important;
}

.ql-picker-item[data-value='36px']::before,
.ql-picker-label[data-value='36px']::before {
  content: '36px' !important;
}

.ql-editor .ql-indent-1:not(.ql-direction-rtl){
  text-indent: 2em;
  padding-left: 0;
}
.ql-editor .ql-indent-2:not(.ql-direction-rtl){
  text-indent: 4em;
  padding-left: 0;
}
.ql-editor .ql-indent-3:not(.ql-direction-rtl){
  text-indent: 6em;
  padding-left: 0;
}
.ql-editor .ql-indent-4:not(.ql-direction-rtl){
  text-indent: 8em;
  padding-left: 0;
}
.ql-editor .ql-indent-5:not(.ql-direction-rtl){
  text-indent: 10em;
  padding-left: 0;
}
.ql-editor .ql-indent-6:not(.ql-direction-rtl){
  text-indent: 12em;
  padding-left: 0;
}
.ql-editor .ql-indent-7:not(.ql-direction-rtl){
  text-indent: 14em;
  padding-left: 0;
}
.ql-editor .ql-indent-8:not(.ql-direction-rtl){
  text-indent: 16em;
  padding-left: 0;
}

.ql-snow .ql-picker.ql-lineHeight .ql-picker-label::before {
  content: "行高";
}

.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1"]::before {
  content: "行高1";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.5"]::before,
.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.5"]::before {
  content: "行高1.5";
}

.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.75"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.75"]::before {
  content: "行高1.75";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="2"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="2"]::before {
  content: "行高2";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="3"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="3"]::before {
  content: "行高3";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="4"]::before,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="4"]::before {
  content: "行高4";
}
.ql-snow .ql-picker.ql-lineHeight .ql-picker-item[data-value="5"]::before ,.ql-snow .ql-picker.ql-lineHeight .ql-picker-label[data-value="5"]::before{
  content: "行高5";
}
.ql-snow .ql-picker.ql-lineHeight {
  width: 70px;
}
</style>

 

上一篇:MySQL主从复制原理及搭建过程


下一篇:2022年你要掌握的十个Python优质库