我开始使用 React Quill 将 WYSIWYG 集成到我的博客项目中,之前我没有使用它的经验,并试图在互联网的帮助下做到最大。实际上,从加载图像(使用图像处理程序)到将其保存到数据库(Rails 中的 PostgreSQL),一切都运行良好。我将内容保存为 HTML 而不是 Delta 格式,但每当我尝试通过从数据库加载它来查看它时,所有格式、对齐和缩进都消失了,但(标题、斜体、下划线、粗体、文本颜色)存在,并且所有内容都左对齐
任何帮助,将不胜感激。
我阅读了 Quill 文档并试图了解如何处理此问题,但我不知道如何使其工作。
我正在使用 React + Rails
这是我的代码(我将只显示相关代码):
CreateBlog.jsx
文件
import axios from 'axios'
import React, { useState } from "react";
import PageLoader from '../PageLoader'
import CreateForm from './CreateForm'
export default function CreateBlog({history}) {
const [title, setTitle] = useState("")
const [body, setBody] = useState("")
const [loading, setLoading] = useState(false)
const handleChange = (value)=>{
setBody(value)
console.log(value)
}
const handleSubmit = async (event) => {
event.preventDefault()
const variables = {
title: title,
body: body,
}
try{
const response = await axios.post("/blogs",variables)
setLoading(false)
history.push("/blogs")
} catch(error){
console.log(error)
setLoading(false)
}
}
return (
<CreateForm
setTitle={setTitle}
setBody={setBody}
body={body}
loading={loading}
handleSubmit={handleSubmit}
handleChange={handleChange}
/>
)
}
CreateForm.jsx
文件
import React,{useMemo,useRef} from 'react'
import Input from '../Input'
import Button from '../Button'
import 'react-quill/dist/quill.snow.css'
import ReactQuill,{Quill} from "react-quill";
import ImageResize from 'quill-image-resize-module-react';
import Editor from "./Editor";
Quill.register('modules/imageResize', ImageResize);
export default function CreateForm(
{
type="create",
setTitle,setBody,loading,handleSubmit,
handleChange,body
}) {
const editorRef = useRef(null);
const modules = useMemo(()=>({
imageResize: {
parchment: Quill.import('parchment'),
modules: ['Resize', 'DisplaySize', 'Toolbar']
},
toolbar:{
container: [
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline'],
[
{ 'list': 'ordered' },
{ 'list': 'bullet' },
{ 'indent': "-1" },
{ 'indent': "+1" }
],
[{ 'align': [] }],
['link', 'image', 'video'],
['clean'],
[{ 'color': [] }]
],
handlers: {
image: imageHandler,
},
clipboard: {
matchVisual: false,
}
}
}));
const imageHandler = (a) => {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.click();
input.onchange = () => {
const file = input.files[0];
// file type is only image.
if (/^image\//.test(file.type)) {
console.log("image file type",file)
saveToServer(file);
} else {
console.warn("You could only upload images.");
}
};
};
function saveToServer(file) {
const fd = new FormData();
fd.append("upload", file);
const xhr = new XMLHttpRequest();
xhr.open("POST", "/blogs", true);
xhr.upload.onprogress = function(event){
const progress =event.loaded / event.total * 100;
}
xhr.onload = () => {
if (xhr.status === 201) {
const data = JSON.parse(xhr.responseText);
const url = data.url
console.log("Image url",url)
setImage(url)
insertToEditor(url);
}
};
xhr.send(fd);
console.log("formdata",fd)
}
function insertToEditor(url) {
editorRef.current.getEditor().insertEmbed(null, "image", url);
}
return (
<form className="max-w-full" onSubmit={handleSubmit}>
<Input
label="Title"
placeholder="Blog Title (Max 50 Characters Allowed)"
onChange={e => setTitle(e.target.value)}
/>
<ReactQuill
theme="snow"
placeholder="Write your story"
modules={modules}
forwardedRef={editorRef}
onChange={handleChange}
value={body}
/>
<Button
type="submit"
buttonText={type === "create" ? "Create Blog" : "Update Blog"}
loading={loading}
/>
</form>
)
}
当我编辑此图像中的内容时,一切正常
While editing
但是在保存帖子并再次查看它之后,它的类似内容(但粗体、斜体、下划线)显示为所需但有序列表和无序列表、对齐、引号......等未按预期显示。
View after saving
查看内容的代码是
ShowBlog.jsx
import React,{useState,useEffect} from 'react'
import { useParams } from 'react-router-dom'
import blogsApi from '../apis/blogs'
import axios from 'axios'
import parse from 'html-react-parser';
export default function ShowBlog() {
const componentMounted = true
const {id} = useParams()
const [blogDetails, setBlogDetails] = useState([])
const [loading, setLoading] = useState(true)
const [blogCreator, setBlogCreator] = useState('')
const source = axios.CancelToken.source()
const fetchBlogDetails = async()=>{
try{
const response = await axios.get(`/blogs/${id}`, {cancelToken:source.token})
setBlogDetails(response.data.blog)
setBlogCreator(response.data.blog_creator)
setLoading(false)
console.log("Show Blog details",response)
} catch(error){
if(axios.isCancel(error)){
console.log('cancelled')
}else{
throw error
}
console.log(error)
} finally {
setLoading(false)
}
}
useEffect(()=>{
fetchBlogDetails()
return () => {
source.cancel()
}
}, [])
if(loading){
return <PageLoader />
}
return (
<div className="bg-white">
<div className="max-w-6xl mx-auto mt-10">
<div className="relative max-w-4xl mx-auto items-center justify-between">
<div className="flex flex-col ">
<div className="w-full ">
<h2 className="text-gray-800 ">
{blogDetails?.title}
</h2>
<div className="flex ">
<span>by {blogCreator?.username}</span>
</div>
<div>
{parse(blogDetails.body)}
</div>
</div>
</div>
</div>
</div>
</div>
)
}