Next.js中Quill插入Object URL仅显示图片图标问题求助
问题排查与修复方案
1. 修复BlotFormatter的动态导入与模块注册
你的BlotFormatter动态导入未正确返回模块实例,且Quill模块注册时机、配置位置有误,这会导致模块无法加载,同时干扰图片渲染逻辑:
- 修正动态导入代码,确保返回模块默认导出:
const BlotFormatter = dynamic( () => import('quill-blot-formatter').then(mod => mod.default), { ssr: false, loading: () => <p>Text Editor Loading...</p> } );
- 将
blotFormatter配置移至modules对象内(useQuill仅接受modules作为配置项,独立传参无效):
const { quill, quillRef, Quill } = useQuill({ modules: { toolbar: { container: TOOLBAR_OPTIONS, }, blotFormatter: {}, // 移至modules中 }, clipboard: { matchVisual: false, }, theme: 'snow', placeholder: 'Describe your question', });
- 调整模块注册时机,确保在Quill初始化前完成注册:
useEffect(() => { if (Quill && !quill) { Quill.register('modules/blotFormatter', BlotFormatter); } if (quill) { quill.getModule('toolbar').addHandler('image', imageHandler); } }, [quill, Quill]);
2. 修正图片插入逻辑的细节
当前insertEmbed调用的Quill.sources.USER可能因作用域问题无法正确访问,直接使用字符串'user'替代即可:
quill.insertEmbed( position, 'image', url, 'user' // 替换Quill.sources.USER,避免引用问题 );
3. 补充内存泄漏防护(可选)
使用URL.createObjectURL后,需在组件卸载时释放内存:
useEffect(() => { return () => { if (quill) { const images = quill.root.querySelectorAll('img'); images.forEach(img => { if (img.src.startsWith('blob:')) { URL.revokeObjectURL(img.src); } }); } }; }, [quill]);
完整修正后的代码
import React, { useEffect, useRef } from 'react'; import dynamic from 'next/dynamic'; import { useQuill } from 'react-quilljs'; const BlotFormatter = dynamic( () => import('quill-blot-formatter').then(mod => mod.default), { ssr: false, loading: () => <p>Text Editor Loading...</p> } ); const TOOLBAR_OPTIONS = [ [{ header: [1, 2, 3, 4, 5, 6, false] }], [{ font: [] }], [{ list: 'ordered' }, { list: 'bullet' }], ['bold', 'italic', 'underline', 'strike'], [{ indent: '-1' }, { indent: '+1' }, { align: [] }], [{ color: [] }, { background: [] }], [{ script: 'sub' }, { script: 'super' }], [{ align: [] }], ['image', 'blockquote', 'code-block'], ['clean'], ]; const QuillEditor = () => { const { quill, quillRef, Quill } = useQuill({ modules: { toolbar: { container: TOOLBAR_OPTIONS, }, blotFormatter: {}, }, clipboard: { matchVisual: false, }, theme: 'snow', placeholder: 'Describe your question', }); const openInputImageRef = useRef(); useEffect(() => { if (Quill && !quill) { Quill.register('modules/blotFormatter', BlotFormatter); } if (quill) { quill.getModule('toolbar').addHandler('image', imageHandler); } return () => { if (quill) { const images = quill.root.querySelectorAll('img'); images.forEach(img => { if (img.src.startsWith('blob:')) { URL.revokeObjectURL(img.src); } }); } }; }, [quill, Quill]); const imageHandler = () => { openInputImageRef.current.click(); }; const quillImageCallback = (e) => { e.preventDefault(); e.stopPropagation(); if (e.currentTarget?.files?.length > 0) { const file = e.currentTarget.files[0]; const formData = new FormData(); formData.append('image', file); const url = URL.createObjectURL(file); quill.focus(); const range = quill.getSelection(); const position = range ? range.index : 0; quill.insertEmbed( position, 'image', url, 'user' ); quill.setSelection(position + 1); } }; return ( <div> <div ref={quillRef} /> <input type="file" accept="image/*" ref={openInputImageRef} onChange={quillImageCallback} className="hidden" /> </div> ); }; export default QuillEditor;
额外说明
BlotFormatter的作用是提供图片拖拽、缩放、对齐等交互功能,本身不影响图片基础显示。你的核心问题是模块注册错误导致Quill图片渲染逻辑异常,修正后图片即可正常显示。若需将图片上传至服务器,可在quillImageCallback中添加异步请求逻辑,用服务器返回的真实地址替换Object URL。
内容的提问来源于stack exchange,提问作者harun wagura
相关产品推荐
相关产品推荐

