如何使用 Quill 格式化文本和嵌入视频?

How to format text and embed a video with Quill?

我开始将 WYSIWYG 集成到博客项目中,为此我使用 Quill(我之前没有使用它的经验)。我能够按照需要的方式自定义我的编辑器,我不明白的是如何处理文本格式和嵌入视频。我的 post 表单中有两个字段,"preview" 和 "content"(两个羽毛笔编辑器),同时介绍我可以为其指定格式的文本(header、斜体、下划线。 ..等),当单击嵌入视频选项时,编辑器允许我添加 link 并在那一刻可视化嵌入视频。当我按下保存按钮时,它将 post 存储在我的数据库中,但在我的单个 post 页面中,我可视化所有没有格式的字段(header、斜体、下划线...等)和也没有嵌入视频。我怎样才能给出格式并显示视频?任何帮助将不胜感激。

我阅读了 Quill 文档并试图了解如何使用增量处理此问题,但我不知道如何进行。

我正在使用 Meteor + React,这是我的代码(我将只显示相关代码):

这是我的库,quill.jsx

import React, { Component } from 'react';
import QuillLib from './vendor/quill.js';
import { ud } from '/helpers/lib/main.jsx';

class Quill extends Component {
  constructor(props) {
    super(props);
    this.id = ud.shortUID();
}

componentDidMount() {
  const that = this;
  const toolbarOptions = [
    [{ font: [] }],
    [{ header: 1 }, { header: 2 }],
    [{ header: [1, 2, 3, 4, 5, 6, false] }],
    [{ align: [] }],
    ['bold', 'italic', 'underline', 'strike'],
    ['blockquote', 'code-block'],
    [{ script: 'sub' }, { script: 'super' }],
    [{ indent: '-1' }, { indent: '+1' }],
    [{ color: [] }, { background: [] }],
    ['video'],
    ['image'],
];

const quill = new QuillLib(`#quill-editor-container-${this.id}`, {
  modules: {
    toolbar: toolbarOptions,
  },
  theme: 'snow',
});
const content = this.props.content;
  quill.setContents(content);
  quill.on('text-change', (delta) => {
    if (that.props.onChange) {
      that.props.onChange(quill);
    }
  });
}

render() {
  return (
    <div className="wysiwyg-wrapper">
      <div id={`quill-editor-container-${this.id}`}></div>
    </div>
  );
 }
}
export default Quill;

这是我的输入表单组件,list.jxs

import { Meteor } from 'meteor/meteor';
import { PostSchema } from '/modules/blog/lib/collections.jsx';
import Quill from '/modules/quill/client/main.jsx';

export class BlogCategory extends Component {
  constructor(props) {
    super(props);
    this.state = {
      post: {
        content: '',
        preview: '',
      },
    };
    this.onPreviewChange = this.onPreviewChange.bind(this);
    this.onContentChange = this.onContentChange.bind(this);
  }

  onPreviewChange(content) {
    this.state.post.preview = content.getText();
    this.setState(this.state);
  }
  onContentChange(content) {
    this.state.post.content = content.getText();
    this.setState(this.state);
  }

  save() {
    const content = this.state.post.content;
    const preview = this.state.post.preview;
    const post = new PostSchema();
    post.set({
      content,
      preview,
    });
    if (post.validate(false)) {
      const id = post.save(); 
    }
    console.log(post.getValidationErrors(false));
  }

  renderCreatePostForm() {
   let content;
   if (this.state.showForm) {
     content = (
      <form action="">
        <Quill 
           content={this.state.post.preview} 
           onChange={this.onPreviewChange}
        />
        <Quill
           content={this.state.post.content}
           onChange={this.onContentChange}
        />
      </form>
     );
    }
    return content;
  }
  render() {
    let content = (
      <div className="col-xs-12">
        {this.renderActions()}
      </div>
    );
   if (!this.props.ready) {
    content = <p>LOADING...</p>;
   }
   return content;
  }
}
export default createContainer(() => {
  const handleValidPost = Meteor.subscribe('posts');
  return {
    ready: handleValidPost.ready(),
    posts: PostSchema.find({}).fetch(),
  };
}, BlogCategory);

最后是我的 collections.jsx

import { Mongo } from 'meteor/mongo';
export const PostCollection = new Mongo.Collection('Posts');
export const PostSchema = Astro.Class({
  name: 'PostSchema',
  collection: PostCollection,
  fields: {
    content: {
     validator : Validators.and([
       Validators.required(),
       Validators.string(),
       Validators.minLength(3)
     ])
    },
    preview: {
     validator : Validators.and([
       Validators.required(),
       Validators.string(),
       Validators.minLength(3)
     ])
    },
  }
});

在通过 getText 获取 Quill 内容时,您丢失了文本格式和视频信息。使用 getText,将省略所有非字符串数据。 Quill 数据定义为 Delta(这是一个 JSON 对象)。

您可以通过将 onPreviewChangeonContentChange 更新为使用 getContents 而不是 getText 来解决此问题。将这些 Delta 保存到数据库并再次加载。

  onPreviewChange(content) {
    this.state.post.preview = content.getContents();
    this.setState(this.state);
  }
  onContentChange(content) {
    this.state.post.content = content.getContents();
    this.setState(this.state);
  }