当前位置: 首页 > article >正文

Vue3使用vue-quill富文本编辑器

安装依赖

npm install @vueup/vue-quill quill quill-image-uploader

自定义字体

把自定义字体样式放入font.css中在main.js中导入

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
    content: "宋体";
    font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
	content: "黑体";
	font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
	content: "微软雅黑";
	font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
	content: "楷体";
	font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
	content: "仿宋";
	font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
	content: "Arial";
	font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
	content: "Times New Roman";
	font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
	content: "sans-serif";
	font-family: "sans-serif";
}
 
.ql-font-SimSun {
  	font-family: "SimSun";
}
.ql-font-SimHei {
  	font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
  	font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
  	font-family: "KaiTi";
}
.ql-font-FangSong {
  	font-family: "FangSong";
}
.ql-font-Arial {
  	font-family: "Arial";
}
.ql-font-Times-New-Roman {
  	font-family: "Times New Roman";
}
.ql-font-sans-serif {
  	font-family: "sans-serif";
}

注册自定义字体到quill

案例

<template>
  <div class="publish-form-container">
    <div class="publish-form">
      <form @submit.prevent="submitForm">
        <div class="form-group">
          <label for="content">内容</label>
          <QuillEditor v-model="content" :options="editorOption" class="quill-editor" />
        </div>
        <button type="submit" class="submit-btn">提交</button>
      </form>
    </div>
  </div>
</template>

<script>
import { QuillEditor, Quill } from '@vueup/vue-quill';
import ImageUploader from 'quill-image-uploader';
import '@vueup/vue-quill/dist/vue-quill.snow.css';

// 注册自定义字体到 Quill
const Font = Quill.import('formats/font');
Font.whitelist = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif'];
Quill.register(Font, true);

// 注册图片上传模块
Quill.register("modules/imageUploader", ImageUploader);

// 模拟上传API
const uploadFileAPI = async (fileData) => {
  // 模拟上传返回URL
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ data: { filePath: 'https://lalallalal.com/' + fileData.file.name } });
    }, 1000);
  });
};

// 将本地文件转换为URL
const getLocalImageURL = (file) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      resolve(e.target.result);
    };
    reader.readAsDataURL(file);
  });
};

export default {
  components: {
    QuillEditor,
  },
  data() {
    return {
      title: '',
      type: '',
      content: '',
      editorOption: {
        modules: {
          imageUploader: {
            upload: async (file) => {
              const localUrl = await getLocalImageURL(file);
              return localUrl; // 返回本地图片的 URL 进行预览
            },
          },
          toolbar: [
            [{ font: Font.whitelist }], // 字体
            ['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: [] }], // 字体颜色,背景颜色
            [{ align: [] }], // 对齐
            ['clean'], // 清除格式
            ['link', 'image', 'video'], // 链接,图片,视频
          ],
        },
      },
    };
  },
  methods: {
    // 提交表单方法
    async submitForm() {
      // 创建虚拟 DOM 来解析内容
      const parser = new DOMParser();
      const doc = parser.parseFromString(this.content, 'text/html');

      // 查找所有的本地图片
      const images = doc.querySelectorAll('img');
      const imageUploadPromises = [];

      images.forEach((img) => {
        const localSrc = img.getAttribute('src');
        
        // 如果是本地图片,上传图片并替换URL
        if (localSrc.startsWith('data:')) {
          const uploadPromise = uploadFileAPI({ file: this.dataURLtoFile(localSrc, 'image.png') }).then((res) => {
            img.setAttribute('src', res.data.filePath); // 替换成服务器上的图片URL
          });
          imageUploadPromises.push(uploadPromise);
        }
      });

      // 等待所有图片上传完成后提交表单
      try {
        await Promise.all(imageUploadPromises);

        // 上传完成后,更新内容
        const updatedContent = doc.body.innerHTML;

        const payload = {
          title: this.title,
          content: updatedContent,
          type: this.type,
        };

        console.log("提交的内容:", payload);

        const response = await fetch("/api/posts", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(payload),
        });
        const data = await response.json();
        console.log("发布成功", data);
      } catch (error) {
        console.error("发布失败", error);
      }
    },

    // 将 dataURL 转换为 File 对象的辅助函数
    dataURLtoFile(dataurl, filename) {
      const arr = dataurl.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
  },
};
</script>

<style lang="less" scoped>
//TODO
</style>

参考:在vue中Quill富文本编辑器的使用(主题、自定义工具栏、自定义字体选项、图片拖拽上传、图片改变大小)_quill-editor修改工具栏图标颜色-CSDN博客

Vue3使用vue-quill富文本编辑器并实现图片自定义上传替换默认base64格式图片_vue3 quill-CSDN博客


http://www.kler.cn/a/320355.html

相关文章:

  • ASP.NET MVC宠物商城系统
  • 【C++】【算法基础】Nim游戏
  • 机器学习基础04
  • 黑马智数Day10
  • 【原创】如何备份和还原Ubuntu系统,非常详细!!
  • Python蓝桥杯刷题1
  • 商业终端架构技术-未来之窗行业应用跨平台架构
  • js进阶——作用域闭包
  • LoadRunner实战测试解析:记录一次性能测试过程
  • 监控IDS和IPS增强网络安全性
  • pyformat - 格式美化 Python 代码
  • iptables和nftables
  • C++学习笔记(43)
  • react hooks--React.memo
  • 表格的大小和什么相关
  • 删除搜狗拼音输入法,右键菜单打印及pdf操作
  • matlab的‌基础语法和数据类型
  • Python 将数据写入 excel(新手入门)
  • x-cmd pkg | eza - ls 命令的现代替代品,终端用户必备工具
  • HTML和CSS中的浮动以及边框塌陷解决方案(内置练习及答案)
  • 前端框架对比、分析与选择
  • linux 下域名解析错误
  • 计算机毕业设计Hadoop+Spark知识图谱美团美食推荐系统 美团餐厅推荐系统 美团推荐系统 美食价格预测 美团爬虫 美食数据分析 美食可视化大屏
  • Linux中使用Docker容器构建Tomcat容器完整教程
  • 【计算机网络 - 基础问题】每日 3 题(二十四)
  • 神经网络(三):VGG16