文档地址:
ttps://vueup.github.io/vue-quill/guide/
https://www.kancloud.cn/liuwave/quill/1409364

使用:
1、安装

npm install @vueup/vue-quill@latest --save
# OR
yarn add @vueup/vue-quill@latest

2、使用注册 vue3
全局注册

import { createApp } from 'vue'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css';

const app = createApp()
app.component('QuillEditor', QuillEditor)
<div id="app">
  <quill-editor theme="snow"></quill-editor>
</div>

局部注册

import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css';

export default {
  components: {
    QuillEditor
  }
}
<template>
  <QuillEditor theme="snow" />
</template>

3、vuequill的封装

<template>
  <div class="editor-container">
    <input
      name="files"
      id="img-upload"
      ref="uploadRef"
      style="height: 1px; display: none"
      @change="handlerUploadChange"
      :multiple="multiple"
      :accept="accept"
      type="file"
    />
    //只有局部注册时,才能用otpions这一属性
    <QuillEditor ref="editorRef" :options="options" @update:content="handlerContentChange" />
  </div>
</template>
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import axios from 'axios'
const editorRef = ref()
const uploadRef = ref()
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  toolbar: {
    type: Array,
    default: () => {
      return [
        ['bold', 'italic', 'underline', 'strike'], // toggled buttons
        ['blockquote', 'code-block'],
        [{ header: 1 }, { header: 2 }], // custom button values
        [{ list: 'ordered' }, { list: 'bullet' }],
        [{ script: 'sub' }, { script: 'super' }], // superscript/subscript
        [{ indent: '-1' }, { indent: '+1' }], // outdent/indent
        [{ direction: 'rtl' }], // text direction
        [{ size: ['small', false, 'large', 'huge'] }], // custom dropdown
        [{ header: [1, 2, 3, 4, 5, 6, false] }],
        [{ color: [] }, { background: [] }], // dropdown with defaults from theme
        [{ font: [] }],
        [{ align: [] }],
        ['clean'],
        ['image']
      ]
    }
  },
  theme: {
    type: String,
    default: 'snow'
  },
  readOnly: {
    type: String,
    default: false
  },
  placeholder: {
    type: String,
    default: ''
  },
  accept: {
    type: String,
    default: 'image/jpeg, image/jpg, image/png'
  },
  multiple: {
    type: Boolean,
    default: true
  },
  defaultContent:{//默认内容
  type:String, 
  default:''
})
const emits = defineEmits(['update:modelValue', 'change'])
const options = computed(() => {
  return {
    // debug: 'info',
    debug: 'error',
    modules: {
      toolbar: {
        container: props.toolbar,
        handlers: { //点击上传图片的tool会触发这个函数,为了自定义处理函数,触发时触发img-upload input 上传触发handlerUploadChange   (自定义上传图片的函数 用后端上传接口上传图片 返回http图片地址,不是base64地址,以免地址太长)
          image: function (value) {
            if (value) {
              //console.log(document.querySelector('#img-upload'))
              document.querySelector('#img-upload').click()
            } else {
              this.quill.format('image', false)
            }
          }
        }
      }
    },
    placeholder: props.placeholder,
    readOnly: props.readOnly,
    theme: props.theme,
    contentType: 'html',
    scrollingContainer: '.ql-container'
  }
})
const handlerContentChange = (content) => {
//此处content 返回的是dalta obj格式,一般传给后台是html字符串,所以用getHTML获取
  emits('update:modelValue', editorRef.value.getHTML())
  emits('change', editorRef.value.getHTML())
}
const handlerUploadChange = async (event) => {
  if (props.readOnly) return
  console.log('handlerRichUploadChange', event)
  const getImages = async (_) => { //上传多张图片时,确保图片顺序与上传顺序一致
    let upload = function (i) {
      let param = new FormData()
      param.append('files', event.target.files[i])
      return axios({
        url: apiUrl + '/upload',
        method: 'POST',
        data: param
      })
        .then(({ data }) => {
          if (data.code === 1) {
            let { id, path } = data.data.info
            let quill = editorRef.value.getQuill()
            let length = quill.getSelection().index
            quill.insertEmbed(length, 'image', path)
            quill.setSelection(length + 1)
          }
        })
        .catch((err) => {
          console.log(err)
        })
    }

    for (let i = 0; i < event.target.files.length; i++) {
      await upload(i)
    }
  }
  getImages()
}
const setHeight = () => {
//quill分为 ql-toolbar和ql-container ql-toolbar和ql-container高度不确定 css写固定不利于改变动态高度
  let toolHeight = document.getElementsByClassName('ql-toolbar')[0].offsetHeight
  // let editorHeight = document.getElementsByClassName('editor-container')[0].offsetHeight
  let qlContainer = document.getElementsByClassName('ql-container')[0]
  // let height = parseInt(editorHeight) - parseInt(toolHeight)
  qlContainer.style.height = `calc(100% - ${parseInt(toolHeight)}px)`
  // console.log('setHeight', editorHeight, toolHeight)
}
watch(
  () => props.defaultContent,
  (newVal) => {
    nextTick(() => {
      editorRef.value.setHTML(newVal)
    })
  },
  {
    immediate: true
  }
)
onMounted(() => {
  console.log('onMounted', props.readOnly)
  //editorRef.value.setHTML(props.modelValue) //回显 如果请求数据 生命周期原因 数据传过来时 该组件已过这一生命周期
  window.addEventListener('resize', setHeight) //窗口变化时,高度变化
  setHeight()
})
onUnmounted(() => {
  window.removeEventListener('resize', setHeight)
})
defineExpose({
  editorRef,
  setHeight
})
Logo

前往低代码交流专区

更多推荐