• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

我的博客我做主

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Vue3 QuillEditor 富文本编辑器

对于这个组件,我是又爱又恨,上代码:

<template>
  <div>
    <!-- 此处注意写法v-model:content -->
    <QuillEditor ref="myQuillEditor" theme="snow" :content="content" :options="data.editorOption" contentType="html"
      @update:content="setValue" />
    <!-- 使用自定义图片上传 -->
    <input type="file" hidden accept=".jpg,.png" ref="fileBtn" @change="handleUpload" />
  </div>
</template>

<script setup>
import { QuillEditor, Quill } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import { uploadSingleFile } from '@/api/upload'

const props = defineProps(['value'])
const emit = defineEmits(['update:value'])
const myQuillEditor = ref()
const content = ref('')
const fileBtn = ref()
const toolBarOption = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
  ["blockquote", "code-block"], // 引用
  [{ 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
]
const data = reactive({
  content: '',
  editorOption: {
    modules: {
      toolbar: toolBarOption
    },
    placeholder: '请输入内容...'
  }
})
const imgHandler = (state) => {
  if (state) {
    fileBtn.value.click()
  }
}
// 抛出更改内容,此处避免出错直接使用文档提供的getHTML方法
const setValue = () => {
  const text = toRaw(myQuillEditor.value).getHTML()
  emit('update:value', text)
}
const handleUpload = (e) => {
  const files = Array.prototype.slice.call(e.target.files)
  if (!files) {
    return
  }
  const formdata = new FormData()
  formdata.append('file', files[0])
  uploadSingleFile(formdata).then(res => {
    if (res.code == 200 && res.data) {
      const quill = toRaw(myQuillEditor.value).getQuill()
      const length = quill.getSelection().index
      quill.insertEmbed(length, 'image', res.data.url)
      quill.setSelection(length + 1)
    } else {
      proxy.$modal.msgError(res.msg || '发生错误,请稍后重试!')
    }
  })
}
// 初始化编辑器
onMounted(async () => {
  const quill = toRaw(myQuillEditor.value).getQuill()
  if (myQuillEditor.value) {
    quill.getModule('toolbar').addHandler('image', imgHandler)
    await nextTick()
    // TODO fix bug 无法渲染 初始值
    setTimeout(() => {
      myQuillEditor.value.setContents(props.value)
    }, 300)
  }
})
</script>
<style scoped lang="scss">
:deep(.ql-container) {
  height: 400px;
  line-height: normal;
  width: auto;
}

:deep(span.ql-size) {
  max-width: 80px !important;
}

:deep(.ql-tooltip[data-mode="link"]::before) {
  content: "请输入链接地址:";
}

:deep(.ql-snow .ql-tooltip.ql-editing a.ql-action::after) {
  content: "保存";
}

:deep(.ql-snow .ql-tooltip a.ql-action::after) {
  content: "编辑";
}

:deep(.ql-snow .ql-tooltip a.ql-remove::before) {
  content: "移除";
}

:deep(.ql-snow .ql-tooltip::before) {
  content: "链接地址:";

}

:deep(.ql-snow .ql-tooltip[data-mode=link]::before) {
  content: "请输入链接地址:";
}

:deep(.ql-tooltip[data-mode="video"]) {
  left: 0 !important;
}

:deep(.ql-tooltip[data-mode="video"]::before) {
  content: "请输入视频地址:";
}

:deep(.ql-picker.ql-size .ql-picker-label::before,
  .ql-picker.ql-size .ql-picker-item::before) {
  content: "14px";
}

:deep(.ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
  .ql-picker.ql-size .ql-picker-item[data-value="small"]::before) {
  content: "10px";
}

:deep(.ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
  .ql-picker.ql-size .ql-picker-item[data-value="large"]::before) {
  content: "18px";
}

:deep(.ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
  .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before) {
  content: "32px";
}

:deep(.ql-picker.ql-header .ql-picker-label::before,
  .ql-picker.ql-header .ql-picker-item::before) {
  content: "文本";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="1"]::before) {
  content: "标题1";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="2"]::before) {
  content: "标题2";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="3"]::before) {
  content: "标题3";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="4"]::before) {
  content: "标题4";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="5"]::before) {
  content: "标题5";
}

:deep(.ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
  .ql-picker.ql-header .ql-picker-item[data-value="6"]::before) {
  content: "标题6";
}

:deep(.ql-picker.ql-font .ql-picker-label::before,
  .ql-picker.ql-font .ql-picker-item::before) {
  content: "标准字体";
}

:deep(.ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
  .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before) {
  content: "衬线字体";
}

:deep(.ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
  .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before) {
  content: "等宽字体";
}

:deep(.ql-formats) {
  height: 21px;
  line-height: 21px;
}
</style>

作者:胡倩倩0903
出处:https://www.cnblogs.com/kitty-blog/
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

posted on 2023-05-08 15:37  kitty20180903suzhou  阅读(667)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3