@4leaf.njm/react-quill 中文文档教程

发布于 4年前 浏览 26 项目主页 更新于 3年前

反应奎尔 构建状态npm

npm downloads

Quill 组件 反应

查看现场演示密码本

  1. Quick start
  2. Import the component
  3. Import the stylesheet
  4. Use the component
  5. Using Deltas
  6. Controlled vs Uncontrolled Mode
  7. Options
  8. Theme
  9. Custom Toolbar
  10. Custom Formats
  11. Custom Editing Area
  12. Mixin
  13. Upgrading to React-Quill v1.0.0
  14. API reference
  15. Exports
  16. Props
  17. Methods
  18. Browser support
  19. Building and testing
  20. Bundling with Webpack
  21. Changelog
  22. Contributors
  23. License

??? React Quill 现在支持 Quill v1.0.0! 感谢@clemmy 和@alexkrolick 完成了这个期待已久的更改。 有许多重大更改,因此请务必阅读迁移指南


npm install react-quill
yarn add react-quill

特别感谢在 1.0.0 发布周期中做出贡献的每一个人!

Quick Start

Import the component

import ReactQuill from 'react-quill'; // ES6
import * as ReactQuill from 'react-quill'; // Typescript
const ReactQuill = require('react-quill'); // CommonJS

Import the stylesheet

下面显示了两个常见示例。 样式表如何包含在您的应用程序中取决于构建系统(Webpack、SCSS、LESS 等)。 有关详细信息,请参阅关于主题的文档。

Fetching styles from the CDN

<link rel="stylesheet" href="//cdn.quilljs.com/1.2.6/quill.snow.css">

Using css-loader with Webpack or create-react-app

require('react-quill/dist/quill.snow.css'); // CommonJS
import 'react-quill/dist/quill.snow.css'; // ES6

Use the component

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.state = { text: '' } // You can also pass a Quill Delta here
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(value) {
    this.setState({ text: value })
  }

  render() {
    return (
      <ReactQuill value={this.state.text}
                  onChange={this.handleChange} />
    )
  }
}

Using Deltas

您可以通过 Quill Delta,而不是 HTML 字符串,作为 valuedefaultValue 属性。 与 HTML 字符串相比,Delta 有很多优势,因此您可能希望改用它们。 但是请注意,比较增量变化比比较 HTML 字符串代价更高,因此分析您的使用模式可能是值得的。

请注意,将 value 从 HTML 字符串切换为 Delta,反之亦然,将触发更改,无论它们是否代表相同的文档,因此您可能希望坚持一种格式并继续使用它贯穿始终。

⚠️ 不要使用从 onChange 事件收到的 delta 对象作为 value。 该对象不包含完整的文档,而只包含最后的修改,这样做很可能会触发一个无限循环,在该循环中一遍又一遍地应用相同的更改。 在事件期间使用 editor.getContents() 来获取完整文档的 Delta。 ReactQuill 会阻止你犯这样的错误,但是如果你完全确定这是你想要的,你可以再次通过 new Delta() 传递对象以取消污染它。

Controlled vs Uncontrolled Mode

如果您需要使用 DOM 或 Quill APIdefaultValue 而不是 value >s 命令式地操作编辑器状态。 在这种“不受控制”的模式下,ReactQuill 使用 prop 作为初始值,但允许元素在此之后发生偏差。 onChange 回调仍然正常工作。

  • Read more about uncontrolled components in the React docs.
  • Read more about the available props.

Options

Theme

Quill 编辑器支持主题。 它包括一个名为 snow 的完整主题,这是 Quill 的标准外观,一个类似于 Medium 上的内联编辑器的 bubble 主题,以及一个 core 主题仅包含允许工具栏或工具提示等模块工作的基本要素。

这些样式表可以在 Quill 发行版中找到,但为了方便起见,它们也链接在 React Quill 的 dist 文件夹中。 通常情况下,您可以通过设置主题 prop 来激活主题。 传递虚假值 (null) 以禁用主题。

<ReactQuill theme="snow" /> // or "bubble", null to use minimal core theme

然后链接适当的样式表(仅链接您要使用的主题的 CSS):

<link rel="stylesheet" href="node_modules/react-quill/dist/quill.snow.css">
<link rel="stylesheet" href="node_modules/react-quill/dist/quill.bubble.css">
<link rel="stylesheet" href="node_modules/react-quill/dist/quill.core.css">

这可能因应用程序的结构、目录或其他方式而异。 例如,如果您使用像 SASS 这样的 CSS 预处理器,您可能希望将该样式表导入您自己的样式表。

Custom Toolbar

Default Toolbar Elements

Quill 工具栏模块 API 提供了一种使用格式名称数组配置默认工具栏图标的简便方法。

Example Code

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "",
    }
  }

  modules = {
    toolbar: [
      [{ 'header': [1, 2, false] }],
      ['bold', 'italic', 'underline','strike', 'blockquote'],
      [{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
      ['link', 'image'],
      ['clean']
    ],
  },

  formats = [
    'header',
    'bold', 'italic', 'underline', 'strike', 'blockquote',
    'list', 'bullet', 'indent',
    'link', 'image'
  ],

  render() {
    return (
      <div className="text-editor">
        <ReactQuill theme="snow"
                    modules={this.modules}
                    formats={this.formats}>
        </ReactQuill>
      </div>
    );
  }
}

export default MyComponent;

HTML Toolbar

您还可以使用不属于 Quill 主题的自定义元素提供您自己的 HTML/JSX 工具栏。

在 Codepen 上查看此示例:自定义工具栏示例

Example Code

/*
 * Custom "star" icon for the toolbar using an Octicon
 * https://octicons.github.io
 */
const CustomButton = () => <span className="octicon octicon-star" />

/*
 * Event handler to be attached using Quill toolbar module
 * http://quilljs.com/docs/modules/toolbar/
 */
function insertStar () {
  const cursorPosition = this.quill.getSelection().index
  this.quill.insertText(cursorPosition, "★")
  this.quill.setSelection(cursorPosition + 1)
}

/*
 * Custom toolbar component including insertStar button and dropdowns
 */
const CustomToolbar = () => (
  <div id="toolbar">
    <select className="ql-header" defaultValue={""} onChange={e => e.persist()}>
      <option value="1"></option>
      <option value="2"></option>
      <option selected></option>
    </select>
    <button className="ql-bold"></button>
    <button className="ql-italic"></button>
    <select className="ql-color">
      <option value="red"></option>
      <option value="green"></option>
      <option value="blue"></option>
      <option value="orange"></option>
      <option value="violet"></option>
      <option value="#d0d1d2"></option>
      <option selected></option>
    </select>
    <button className="ql-insertStar">
      <CustomButton />
    </button>
  </div>
)

/*
 * Editor component with custom toolbar and content containers
 */
class Editor extends React.Component {
  constructor (props) {
    super(props)
    this.state = { editorHtml: '' }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange (html) {
      this.setState({ editorHtml: html });
  }

  render() {
    return (
      <div className="text-editor">
        <CustomToolbar />
        <ReactQuill
          onChange={this.handleChange}
          placeholder={this.props.placeholder}
          modules={Editor.modules}
        />
      </div>
    )
  }
}

/*
 * Quill modules to attach to editor
 * See http://quilljs.com/docs/modules/ for complete options
 */
Editor.modules = {
  toolbar: {
    container: "#toolbar",
    handlers: {
      "insertStar": insertStar,
    }
  }
}

/*
 * Quill editor formats
 * See http://quilljs.com/docs/formats/
 */
Editor.formats = [
  'header', 'font', 'size',
  'bold', 'italic', 'underline', 'strike', 'blockquote',
  'list', 'bullet', 'indent',
  'link', 'image', 'color',
]

/*
 * PropType validation
 */
Editor.propTypes = {
  placeholder: React.PropTypes.string,
}

/*
 * Render component on page
 */
ReactDOM.render(
  <Editor placeholder={'Write something or insert a star ★'}/>,
  document.querySelector('.app')
)

Custom Formats

该组件有两种类型的格式:

  1. The default Quill formats that are enabled/disabled using the formats prop. All formats are enabled by default.
  2. Custom formats created using Parchment and registered with your component's Quill instance

Example Code

const ReactQuill = require('react-quill'); // CommonJS
import ReactQuill, { Quill } from 'react-quill'; // ES6
/*
 * Example Parchment format from
 * https://quilljs.com/guides/cloning-medium-with-parchment/
 * See the video example in the guide for a complex format
 */
let Inline = Quill.import('blots/inline');
class BoldBlot extends Inline { }
BoldBlot.blotName = 'bold';
BoldBlot.tagName = 'strong';
Quill.register('formats/bold', BoldBlot);

const formats = ["bold"] // add custom format name + any built-in formats you need

/*
 * Editor component with default and custom formats
 */
class MyComponent extends React.Component {
  constructor(props) {
    this.formats = formats
    this.state = { text: '' }
  }

  handleChange(value) {
    this.setState({text: value})
  }

  render() {
    return (
      <ReactQuill
        value={this.state.text}
        onChange={this.handleChange}
        formats={this.formats}
      />
    )
  }
}

Custom editing area

如果你实例化没有孩子的 ReactQuill,它会为你创建一个

,用作 Quill 的编辑区域。 如果你愿意,你可以指定你自己的元素供 ReactQuill 使用。 请注意,此时 Quill 不支持

注意:此时使用 React 16 作为 peer dep 时,自定义编辑区域会失去焦点(bug)。

class MyComponent extends React.Component {

  render() {
    return (
      <ReactQuill>
        <div className="my-editing-area"/>
      </ReactQuill>
    );
  }

});

Mixin

该模块导出一个 mixin,可用于创建自定义编辑器组件。 (请注意,mixin 将在 React 的未来版本中被弃用)。

Example Code

ReactQuill 默认组件是使用 mixin 构建的。 请参阅 component.js 获取源代码。

import {Mixin} from 'react-quill'

var MyComponent = React.createClass({
  mixins: [ ReactQuill.Mixin ],

  componentDidMount: function() {
    var editor = this.createEditor(
      this.getEditingArea(),
      this.getEditorConfig()
    );
    this.setState({ editor:editor });
  },

  componentWillReceiveProps: function(nextProps) {
    if ('value' in nextProps && nextProps.value !== this.props.value) {
      this.setEditorContents(this.state.editor, nextProps.value);
    }
  },

});

Upgrading to React-Quill v1.0.0

在大多数情况下,ReactQuill 会发出有用的警告来帮助您执行任何必要的迁移步骤。

请注意,许多到 Quill v1.0 的迁移步骤 也可能适用。

Expand Upgrade Guide

The toolbar module

在 v1.0.0 中,Quill 采用了一种新的工具栏配置格式,React Quill 将委托所有工具栏功能,并且现在是自定义工具栏的首选方式。

以前,可以通过将 toolbar 属性传递给 React Quill 来设置工具栏属性。 改为传递与 modules.toolbar 相同的选项。

Read More

+ modules: {
    toolbar: [
       ...
    ],
+ },

  <ReactQuill
-   toolbar={this.toolbar}
+   modules={this.modules}
  />

如果您曾经提供自己的 HTML 工具栏组件,您仍然可以这样做:

+ modules: {
+   toolbar: '#my-toolbar-component',
+ },

  <ReactQuill
-   toolbar="#my-toolbar-component"
+   modules={this.modules}
  />

请注意,不再可能将工具栏组件作为子组件传递给 ReactQuill。

以前,如果您将配置对象作为 toolbar 属性传递,React Quill 会为您创建自定义 HTML 工具栏。 这不会再发生了。 您仍然可以显式创建一个 ReactQuill.Toolbar

+ modules: {
+   toolbar: '#my-quill-toolbar',
+ },

+ <ReactQuill.Toolbar
+   id='my-quill-toolbar'
+   items={this.oldStyleToolbarItems}
+ />

  <ReactQuill
-   toolbar={this.oldStyleToolbarItems}
+   modules={this.modules}
  />

但是,请考虑改用新的 Quill 格式,或者提供您自己的工具栏组件

React Quill 现在紧密遵循 Quill 工具栏格式。 有关所有受支持选项的完整参考,请参阅 Quill 工具栏文档

Custom editing areas and refs

以前,要为 Quill 提供挂载的自定义元素,必须传递由特定 ref: editor 标识的子项。

现在这是不必要的,因此如果不需要,可以完全省略 ref 。 此外,您保留的任何 ref 都不会再从所有者组件中被盗。

但是请注意,React Quill 现在将确保该元素与 Quill 兼容。 这意味着传递

Passing children to ReactQuill

以前,可以将任意组件作为 React Quill 的子组件传递。 他们的 ref 会将它们标识为自定义工具栏或自定义编辑区域。

这已经不可能了,现在您唯一可以传递的子元素是可选的 自定义编辑区域 元素。

Adding custom formats with the formats property is deprecated

从 1.0.0 开始,使用 Parchment 定义新格式。 使用模块中的 Quill export 来注册和扩展格式:

Quill.register('formats/CustomFormat', MyCustomFormat);

The styles property

以前,允许通过向 styles 属性提供对象来注入 CSS 样式. 此选项已从 Quill 1.0 中删除,并且 React Quill 中对它的支持也已消失。 如果您需要注入样式,请改为链接外部样式表。

请参阅 Quill 发行说明

The pollInterval property

此属性先前设置了 Quill 轮询 DOM 以获取更改的频率。 它不再有任何作用,可以安全地从道具中移除。

API reference

Exports

const ReactQuill = require('react-quill'); // CommonJS
const {Quill, Mixin, Toolbar} = ReactQuill;

import ReactQuill, { Quill, Mixin, Toolbar } from 'react-quill'; // ES6

混合 : 提供 React 和 Quill 之间的桥梁。 ReactQuill 实现了这个mixin; 以同样的方式,您可以使用它来构建自己的组件,或者替换它来为默认组件实现一个新的核心。 请注意,混合在 React 中已被弃用,此导出将在未来由 HOC 替换。

工具栏 :呈现自定义 ReactQuill 工具栏的组件。 项目和颜色样本的默认集合分别作为 ReactQuill.Toolbar.defaultItemsReactQuill.Toolbar.defaultColors 提供。 ⚠️ Toolbar 组件自 v1.0.0 起已弃用。 请参阅升级到 React Quill v1.0.0

羽毛笔 : Quill 命名空间,您可以在其上调用 registerModule 等。

Props

<代码>编号 :要应用于 DOM 元素的 ID。

<代码>类名 :要应用于 DOM 元素的类。

<代码>值 :编辑器作为受控组件的价值。 可以是包含 HTML 的字符串、Quill Delta 实例或表示 Delta 的普通对象。 请注意,由于 Quill 的限制,这实际上是一种半控制 模式,这意味着不会阻止编辑,但更改 value 仍会替换内容。 还要注意,在这里传递一个 Quill Delta,然后传递一个 HTML 字符串,反之亦然,将始终触发更改,无论它们是否代表相同的文档。 ⚠️ 不要将 onChange 事件中的 delta 对象作为 value 传递,因为它会导致循环。 有关详细信息,请参阅使用增量

<代码>默认值 : 编辑器作为非受控组件的初始值。 可以是包含 HTML 的字符串、Quill Delta 或表示 Delta 的普通对象。

<代码>只读 :如果为真,编辑器将不允许更改其内容。 包装 Quill disable API

<代码>占位符 :空编辑器的默认值。 注意:Quill API 不支持动态改变这个值。 请改用 refs 和数据属性(参见 #340)。

<代码>模块 :指定启用哪些模块及其配置的对象。 编辑器工具栏是一个通常定制的模块。 有关可用模块的更多信息,请参阅 Quill 文档中的模块部分

<代码>格式 : 在编辑过程中启用的格式数组。 默认情况下启用所有已实现的格式。 有关列表,请参阅格式。 从 1.0.0 版开始,自定义格式不应包含在数组中。 相反,它们应该通过 Parchment 创建并在模块的 Quill 导出 中注册。

<代码>风格 :具有自定义 CSS 规则的对象,可应用于编辑器的容器。 规则应该采用 React 的“驼峰式”命名风格。

<代码>主题 :应用于编辑器的主题名称。 默认为 snow,Quill 的标准主题。 传递 null 以使用最小的核心主题。 有关包含所需样式表的更多信息,请参阅主题文档

<代码>标签索引 :在键盘导航期间,编辑器以及页面中其他控件获得焦点的顺序。

<代码>边界 : Quill 用来限制弹出窗口位置的选择器或 DOM 元素。 默认为 document.body

<代码>孩子们 : 将用作 Quill 编辑区域的单个 React 元素,代替默认的

。 请注意,您不能使用

onChange(内容、增量、来源、编辑器) : 以编辑器更改后的新内容回调。 它将传递编辑器的 HTML 内容、表示更改的增量对象、更改源,最后是编辑器访问器 例如 getHTML()。 ⚠️ 不要将这个delta对象作为value,否则会造成循环。 请改用 editor.getContents()。 有关详细信息,请参阅使用增量

onChangeSelection(范围,来源,编辑器) : 使用新选择的范围回调,或在未聚焦时为 null。 它将传递选择范围、更改源,最后是编辑器访问器的只读代理,例如 getBounds()

onFocus(范围,来源,编辑器) :当编辑器获得焦点时调用。 它将接收新的选择范围。

onBlur(previousRange, source, editor) :当编辑器失去焦点时调用。 它将接收到失去焦点之前的选择范围。

onKeyPress(事件) :在按下并释放一个键后调用。 : 请注意,与它的本地对应项一样,不会为特殊键调用它,例如 shiftenter。 如果您需要这些,请挂接到 onKeyDownonKeyUp

<代码>onKeyDown(事件) :在按下键后但在释放键之前调用。 :请注意,由于 Quill 的工作方式,您可能不会收到诸如 enterbackspacedelete 等键的事件。 如果是这种情况,请尝试连接到 onKeyUp

onKeyUp(事件) :在释放键后调用。

保留空白 :如果为 true,则 pre 标签将用于编辑器区域,而不是默认的 div 标签。 这可以防止 Quill 折叠粘贴上的连续空白。 相关问题

Methods

如果你有 ReactQuill 节点的 ref,你将能够调用以下命令方法:

<代码>焦点() : 聚焦编辑器。

<代码>模糊() :从编辑器中移除焦点。

<代码>获取编辑器() :返回支持编辑器的 Quill 实例。 虽然您可以自由地使用它来访问诸如 getText() 之类的方法,但请避免强制操作实例,以避免 ReactQuill 和 Quill 不同步。 一个更安全的 非特权编辑器 可以作为替代品。

Example

在 Codepen 上查看此示例

class Editor extends React.Component {
  constructor(props) {
    super(props)
    this.quillRef = null;      // Quill instance
    this.reactQuillRef = null; // ReactQuill component
  }

  componentDidMount() {
    this.attachQuillRefs()
  }

  componentDidUpdate() {
    this.attachQuillRefs()
  }

  attachQuillRefs = () => {
    if (typeof this.reactQuillRef.getEditor !== 'function') return;
    this.quillRef = this.reactQuillRef.getEditor();
  }

  insertText = () => {
    var range = this.quillRef.getSelection();
    let position = range ? range.index : 0;
    this.quillRef.insertText(position, 'Hello, World! ')
  }

  render() {
    return (
      <div>
        <ReactQuill 
          ref={(el) => { this.reactQuillRef = el }}
          theme={'snow'} />
        <button onClick={this.insertText}>Insert Text</button>
      </div>
    )
  }
}

makeUnprivilegedEditor : 创建一个非特权编辑器。 从 getEditor 向此方法传递对 Quill 实例的引用。 通常你不需要使用这个方法,因为暴露给事件处理程序的编辑器已经没有特权了。

Example

const editor = this.reactQuillRef.getEditor();
const unprivilegedEditor = this.reactQuillRef.makeUnprivilegedEditor(editor);
// You may now use the unprivilegedEditor proxy methods
unprivilegedEditor.getText();

The unprivileged editor

在事件期间,ReactQuill 会将 Quill API 的一个受限子集作为 editor 参数提供。 这可以防止访问破坏性方法,这可能会导致 ReactQuill 与组件不同步。 它提供了以下方法,这些方法主要是现有Quill方法的代理:

getLength() : 返回编辑器内容的长度,以字符为单位,不包括任何 HTML 标签。

<代码>获取文本() : 返回编辑器的字符串内容,不包括任何 HTML 标签。

<代码>getHTML() : 返回编辑器的完整 HTML 内容。

<代码>获取内容() :返回完整文档的 Quill Delta

<代码>获取选择() : 返回当前选择范围,如果编辑器未聚焦,则返回 null

<代码>getBounds() :返回给定位置处选择的相对于编辑器容器和尺寸的像素位置。

Building and testing

您可以运行自动化测试套件:

npm test

并构建源代码的缩小版本:

npm run build

Makefile 上提供了更多任务:

lint: lints the source
spec: runs the test specs
coverage: runs the code coverage test
test: lint, spec and coverage threshold test
build: builds the minified version

请注意 dist 在中被忽略版本 1.0.0 的 git 存储库。 如果您需要在不从 NPM 下载包的情况下使用构建的文件,您可以自己运行构建任务或使用像 unpkg

Bundling with Webpack

Quill 仅提供一个预构建的 javascript 文件,因此 Webpack 在构建捆绑包后会报错:

Error: ./~/react-quill/~/quill/dist/quill.js
Critical dependencies:
6:478-485 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
@ ./~/react-quill/~/quill/dist/quill.js 6:478-485

警告是无害的,但如果你想消除它,你可以通过将其添加到 Webpack 配置中来避免解析 Quill:

module: {
  // Shut off warnings about using pre-built javascript files
  // as Quill.js unfortunately ships one as its `main`.
  noParse: /node_modules\/quill\/dist/
}

请参阅 #7 了解更多详情。

Browser support

请检查上游 Quill 依赖项的浏览器支持表。 代码库的 React 部分与 ES5 兼容。

Changelog

Full changelog

Contributors

如果没有许多人的贡献,React Quill 不会有今天的成就,我们非常感谢:

  • @zenoamaro (maintainer)
  • @alexkrolick (maintainer)
  • @clemmy
  • @asiniy
  • @webcarrot
  • @druti
  • @e-jigsaw
  • @zhang-z
  • @Sajam
  • @0bird512
  • @jacktrades
  • @1000hz
  • @kkerr1
  • @csk157
  • @Janekk
  • @AndyTheGiant
  • @chrismcv
  • @wouterh
  • @tdg5
  • @jrmmnr
  • @l3kn
  • @rpellerin
  • @sandbochs
  • @wouterh
  • @MattKunze

Roadmap

  • [x] React 0.14 support
  • [x] Quill v1.0.0+ support
  • [x] Tests!
  • [x] Compatibility with React 16
  • [ ] Additional APIs for working with Quill

License

麻省理工学院许可证 (MIT)

版权所有 (c) 2016 , zenoamaro zenoamaro@gmail.com

特此免费授予任何获得此软件和相关文档文件副本(“软件”),不受限制地处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,并允许软件的使用人提供这样做,但须满足以下条件:

上述版权声明和本许可声明应包含在本软件的所有副本或重要部分中。

本软件“按原样”提供,不提供任何明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和非侵权的保证。 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,由软件或软件的使用或其他交易引起、由软件引起或与之相关软件。

React-Quill Build Statusnpm

npm downloads

A Quill component for React.

See a live demo or Codepen.

  1. Quick start
  2. Import the component
  3. Import the stylesheet
  4. Use the component
  5. Using Deltas
  6. Controlled vs Uncontrolled Mode
  7. Options
  8. Theme
  9. Custom Toolbar
  10. Custom Formats
  11. Custom Editing Area
  12. Mixin
  13. Upgrading to React-Quill v1.0.0
  14. API reference
  15. Exports
  16. Props
  17. Methods
  18. Browser support
  19. Building and testing
  20. Bundling with Webpack
  21. Changelog
  22. Contributors
  23. License

???? React Quill now supports Quill v1.0.0! Thanks to @clemmy and @alexkrolick for landing this much-awaited change. There are many breaking changes, so be sure to read the migration guide.


npm install react-quill
yarn add react-quill

Special thank you to everyone who contributed during the 1.0.0 release cycle!

Quick Start

Import the component

import ReactQuill from 'react-quill'; // ES6
import * as ReactQuill from 'react-quill'; // Typescript
const ReactQuill = require('react-quill'); // CommonJS

Import the stylesheet

Two common examples are shown below. How stylesheets are included in your app depends on build system (Webpack, SCSS, LESS, etc). See the documentation on Themes for more information.

Fetching styles from the CDN

<link rel="stylesheet" href="//cdn.quilljs.com/1.2.6/quill.snow.css">

Using css-loader with Webpack or create-react-app

require('react-quill/dist/quill.snow.css'); // CommonJS
import 'react-quill/dist/quill.snow.css'; // ES6

Use the component

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.state = { text: '' } // You can also pass a Quill Delta here
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(value) {
    this.setState({ text: value })
  }

  render() {
    return (
      <ReactQuill value={this.state.text}
                  onChange={this.handleChange} />
    )
  }
}

Using Deltas

You can pass a Quill Delta, instead of an HTML string, as the value and defaultValue properties. Deltas have a number of advantages over HTML strings, so you might want use them instead. Be aware, however, that comparing Deltas for changes is more expensive than comparing HTML strings, so it might be worth to profile your usage patterns.

Note that switching value from an HTML string to a Delta, or vice-versa, will trigger a change, regardless of whether they represent the same document, so you might want to stick to a format and keep using it consistently throughout.

⚠️ Do not use the delta object you receive from the onChange event as value. This object does not contain the full document, but only the last modifications, and doing so will most likely trigger an infinite loop where the same changes are applied over and over again. Use editor.getContents() during the event to obtain a Delta of the full document instead. ReactQuill will prevent you from making such a mistake, however if you are absolutely sure that this is what you want, you can pass the object through new Delta() again to un-taint it.

Controlled vs Uncontrolled Mode

Pass defaultValue instead of value if you need to use DOM or Quill APIs to imperatively manipulate the editor state. In this "uncontrolled" mode ReactQuill uses the prop as the initial value but allows the element to deviate after that. The onChange callback still works normally.

  • Read more about uncontrolled components in the React docs.
  • Read more about the available props.

Options

Theme

The Quill editor supports themes. It includes a full-fledged theme, called snow, that is Quill's standard appearance, a bubble theme that is similar to the inline editor on Medium, and a core theme containing only the bare essentials to allow modules like toolbars or tooltips to work.

These stylesheets can be found in the Quill distribution, but for convenience they are also linked in React Quill's dist folder. In a common case you would activate a theme by setting the theme prop. Pass a falsy value (null) to disable the theme.

<ReactQuill theme="snow" /> // or "bubble", null to use minimal core theme

And then link the appropriate stylesheet (only link the CSS for the themes you want to use):

<link rel="stylesheet" href="node_modules/react-quill/dist/quill.snow.css">
<link rel="stylesheet" href="node_modules/react-quill/dist/quill.bubble.css">
<link rel="stylesheet" href="node_modules/react-quill/dist/quill.core.css">

This may vary depending how application is structured, directories or otherwise. For example, if you use a CSS pre-processor like SASS, you may want to import that stylesheet inside your own.

Custom Toolbar

Default Toolbar Elements

The Quill Toolbar Module API provides an easy way to configure the default toolbar icons using an array of format names.

Example Code

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "",
    }
  }

  modules = {
    toolbar: [
      [{ 'header': [1, 2, false] }],
      ['bold', 'italic', 'underline','strike', 'blockquote'],
      [{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
      ['link', 'image'],
      ['clean']
    ],
  },

  formats = [
    'header',
    'bold', 'italic', 'underline', 'strike', 'blockquote',
    'list', 'bullet', 'indent',
    'link', 'image'
  ],

  render() {
    return (
      <div className="text-editor">
        <ReactQuill theme="snow"
                    modules={this.modules}
                    formats={this.formats}>
        </ReactQuill>
      </div>
    );
  }
}

export default MyComponent;

HTML Toolbar

You can also supply your own HTML/JSX toolbar with custom elements that are not part of the Quill theme.

See this example live on Codepen: Custom Toolbar Example

Example Code

/*
 * Custom "star" icon for the toolbar using an Octicon
 * https://octicons.github.io
 */
const CustomButton = () => <span className="octicon octicon-star" />

/*
 * Event handler to be attached using Quill toolbar module
 * http://quilljs.com/docs/modules/toolbar/
 */
function insertStar () {
  const cursorPosition = this.quill.getSelection().index
  this.quill.insertText(cursorPosition, "★")
  this.quill.setSelection(cursorPosition + 1)
}

/*
 * Custom toolbar component including insertStar button and dropdowns
 */
const CustomToolbar = () => (
  <div id="toolbar">
    <select className="ql-header" defaultValue={""} onChange={e => e.persist()}>
      <option value="1"></option>
      <option value="2"></option>
      <option selected></option>
    </select>
    <button className="ql-bold"></button>
    <button className="ql-italic"></button>
    <select className="ql-color">
      <option value="red"></option>
      <option value="green"></option>
      <option value="blue"></option>
      <option value="orange"></option>
      <option value="violet"></option>
      <option value="#d0d1d2"></option>
      <option selected></option>
    </select>
    <button className="ql-insertStar">
      <CustomButton />
    </button>
  </div>
)

/*
 * Editor component with custom toolbar and content containers
 */
class Editor extends React.Component {
  constructor (props) {
    super(props)
    this.state = { editorHtml: '' }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange (html) {
      this.setState({ editorHtml: html });
  }

  render() {
    return (
      <div className="text-editor">
        <CustomToolbar />
        <ReactQuill
          onChange={this.handleChange}
          placeholder={this.props.placeholder}
          modules={Editor.modules}
        />
      </div>
    )
  }
}

/*
 * Quill modules to attach to editor
 * See http://quilljs.com/docs/modules/ for complete options
 */
Editor.modules = {
  toolbar: {
    container: "#toolbar",
    handlers: {
      "insertStar": insertStar,
    }
  }
}

/*
 * Quill editor formats
 * See http://quilljs.com/docs/formats/
 */
Editor.formats = [
  'header', 'font', 'size',
  'bold', 'italic', 'underline', 'strike', 'blockquote',
  'list', 'bullet', 'indent',
  'link', 'image', 'color',
]

/*
 * PropType validation
 */
Editor.propTypes = {
  placeholder: React.PropTypes.string,
}

/*
 * Render component on page
 */
ReactDOM.render(
  <Editor placeholder={'Write something or insert a star ★'}/>,
  document.querySelector('.app')
)

Custom Formats

The component has two types of formats:

  1. The default Quill formats that are enabled/disabled using the formats prop. All formats are enabled by default.
  2. Custom formats created using Parchment and registered with your component's Quill instance

Example Code

const ReactQuill = require('react-quill'); // CommonJS
import ReactQuill, { Quill } from 'react-quill'; // ES6
/*
 * Example Parchment format from
 * https://quilljs.com/guides/cloning-medium-with-parchment/
 * See the video example in the guide for a complex format
 */
let Inline = Quill.import('blots/inline');
class BoldBlot extends Inline { }
BoldBlot.blotName = 'bold';
BoldBlot.tagName = 'strong';
Quill.register('formats/bold', BoldBlot);

const formats = ["bold"] // add custom format name + any built-in formats you need

/*
 * Editor component with default and custom formats
 */
class MyComponent extends React.Component {
  constructor(props) {
    this.formats = formats
    this.state = { text: '' }
  }

  handleChange(value) {
    this.setState({text: value})
  }

  render() {
    return (
      <ReactQuill
        value={this.state.text}
        onChange={this.handleChange}
        formats={this.formats}
      />
    )
  }
}

Custom editing area

If you instantiate ReactQuill without children, it will create a <div> for you, to be used as the editing area for Quill. If you prefer, you can specify your own element for ReactQuill to use. Note that <textarea>s are not supported by Quill at this time.

Note: Custom editing areas lose focus when using React 16 as a peer dep at this time (bug).

class MyComponent extends React.Component {

  render() {
    return (
      <ReactQuill>
        <div className="my-editing-area"/>
      </ReactQuill>
    );
  }

});

Mixin

The module exports a mixin which can be used to create custom editor components. (Note that mixins will be deprecated in a future version of React).

Example Code

The ReactQuill default component is built using the mixin. See component.js for source.

import {Mixin} from 'react-quill'

var MyComponent = React.createClass({
  mixins: [ ReactQuill.Mixin ],

  componentDidMount: function() {
    var editor = this.createEditor(
      this.getEditingArea(),
      this.getEditorConfig()
    );
    this.setState({ editor:editor });
  },

  componentWillReceiveProps: function(nextProps) {
    if ('value' in nextProps && nextProps.value !== this.props.value) {
      this.setEditorContents(this.state.editor, nextProps.value);
    }
  },

});

Upgrading to React-Quill v1.0.0

In most cases, ReactQuill will raise useful warnings to help you perform any necessary migration steps.

Please note that many migration steps to Quill v1.0 may also apply.

Expand Upgrade Guide

The toolbar module

With v1.0.0, Quill adopted a new toolbar configuration format, to which React Quill will delegates all toolbar functionality, and which is now the preferred way to customize the toolbar.

Previously, toolbar properties could be set by passing a toolbar prop to React Quill. Pass the same options as modules.toolbar instead.

Read More

+ modules: {
    toolbar: [
       ...
    ],
+ },

  <ReactQuill
-   toolbar={this.toolbar}
+   modules={this.modules}
  />

If you used to provide your own HTML toolbar component, you can still do the same:

+ modules: {
+   toolbar: '#my-toolbar-component',
+ },

  <ReactQuill
-   toolbar="#my-toolbar-component"
+   modules={this.modules}
  />

Note that it is not possible to pass a toolbar component as a child to ReactQuill anymore.

Previously, React Quill would create a custom HTML toolbar for you if you passed a configuration object as the toolbar prop. This will not happen anymore. You can still create a ReactQuill.Toolbar explicitly:

+ modules: {
+   toolbar: '#my-quill-toolbar',
+ },

+ <ReactQuill.Toolbar
+   id='my-quill-toolbar'
+   items={this.oldStyleToolbarItems}
+ />

  <ReactQuill
-   toolbar={this.oldStyleToolbarItems}
+   modules={this.modules}
  />

However, consider switching to the new Quill format instead, or provide your own toolbar component.

React Quill now follows the Quill toolbar format closely. See the Quill toolbar documentation for a complete reference on all supported options.

Custom editing areas and refs

Previously, to provide a custom element for Quill to mount on, it was necessary to pass a child identified by a specific ref: editor.

This is now unnecessary, so you can omit the ref entirely if you don't need it. In addition, any ref you keep won't be stolen from the owner component anymore.

Note, however, that React Quill will now ensure that the element is compatible with Quill. This means that passing a <textarea> now produces an error.

Passing children to ReactQuill

Previously, it was possible to pass arbitrary components as children of React Quill. Their ref would identify them as either a custom toolbar or a custom editing area.

This is not possible anymore, and the only child you can pass now is an optional custom Editing Area element.

Adding custom formats with the formats property is deprecated

As of 1.0.0, use Parchment to define new formats. Use the Quill export from the module to register and extend formats:

Quill.register('formats/CustomFormat', MyCustomFormat);

The styles property

Previously, it was allowed to inject CSS styles by providing an object to the styles property. This option has been removed from Quill 1.0, and support for it in React Quill has gone as well. If you need to inject styles, link an external stylesheet instead.

See the Quill Release Notes.

The pollInterval property

This property previously set the frequency with which Quill polled the DOM for changes. It does not have any effect anymore, and can safely be removed from the props.

API reference

Exports

const ReactQuill = require('react-quill'); // CommonJS
const {Quill, Mixin, Toolbar} = ReactQuill;

import ReactQuill, { Quill, Mixin, Toolbar } from 'react-quill'; // ES6

Mixin : Provides the bridge between React and Quill. ReactQuill implements this mixin; in the same way you can use it to build your own component, or replace it to implement a new core for the default component. Note that mixins are deprecated in React and this export will be replaced by an HOC in the future.

Toolbar : The component that renders the custom ReactQuill toolbar. The default collection of items and color swatches is available as ReactQuill.Toolbar.defaultItems and ReactQuill.Toolbar.defaultColors respectively. ⚠️ The Toolbar component is deprecated since v1.0.0. See upgrading to React Quill v1.0.0.

Quill : The Quill namespace on which you can call registerModule and such.

Props

id : ID to be applied to the DOM element.

className : Classes to be applied to the DOM element.

value : Value for the editor as a controlled component. Can be a string containing HTML, a Quill Delta instance, or a plain object representing a Delta. Note that due to limitations in Quill, this is actually a semi-controlled mode, meaning that the edit is not prevented, but changing value will still replace the contents. Also note that passing a Quill Delta here, and then an HTML string, or vice-versa, will always trigger a change, regardless of whether they represent the same document. ⚠️ Do not pass the delta object from the onChange event as value, as it will cause a loop. See Using Deltas for details.

defaultValue : Initial value for the editor as an uncontrolled component. Can be a string containing HTML, a Quill Delta, or a plain object representing a Delta.

readOnly : If true, the editor won't allow changing its contents. Wraps the Quill disable API.

placeholder : The default value for the empty editor. Note: The Quill API does not support changing this value dynamically. Use refs and data-attributes instead (see #340).

modules : An object specifying which modules are enabled, and their configuration. The editor toolbar is a commonly customized module. See the modules section over the Quill documentation for more information on what modules are available.

formats : An array of formats to be enabled during editing. All implemented formats are enabled by default. See Formats for a list. Custom formats should not be included in the array as of version 1.0.0. Instead they should be created through Parchment and registered with the module's Quill export.

style : An object with custom CSS rules to apply on the editor's container. Rules should be in React's "camelCased" naming style.

theme : The name of the theme to apply to the editor. Defaults to snow, Quill's standard theme. Pass null to use the minimal core theme. See the docs on themes for more information on including the required stylesheets.

tabIndex : The order in which the editor becomes focused, among other controls in the page, during keyboard navigation.

bounds : Selector or DOM element used by Quill to constrain position of popups. Defaults to document.body.

children : A single React element that will be used as the editing area for Quill in place of the default, which is a <div>. Note that you cannot use a <textarea>, as it is not a supported target. Also note that updating children is costly, as it will cause the Quill editor to be recreated. Set the value prop if you want to control the html contents of the editor.

onChange(content, delta, source, editor) : Called back with the new contents of the editor after change. It will be passed the HTML contents of the editor, a delta object expressing the change, the source of the change, and finally a read-only proxy to editor accessors such as getHTML(). ⚠️ Do not use this delta object as value, as it will cause a loop. Use editor.getContents() instead. See Using Deltas for details.

onChangeSelection(range, source, editor) : Called back with the new selected range, or null when unfocused. It will be passed the selection range, the source of the change, and finally a read-only proxy to editor accessors such as getBounds().

onFocus(range, source, editor) : Called when the editor becomes focused. It will receive the new selection range.

onBlur(previousRange, source, editor) : Called when the editor loses focus. It will receive the selection range it had right before losing focus.

onKeyPress(event) : Called after a key has been pressed and released. : Note that, like its native counterpart, this won't be called for special keys such as shift or enter. If you need those, hook onto onKeyDown or onKeyUp.

onKeyDown(event) : Called after a key has been pressed, but before it is released. : Note that, due to how Quill works, it's possible that you won't receive events for keys such as enter, backspace or delete. If that's the case, try hooking onto onKeyUp instead.

onKeyUp(event) : Called after a key has been released.

preserveWhitespace : If true, a pre tag is used for the editor area instead of the default div tag. This prevents Quill from collapsing continuous whitespaces on paste. Related issue.

Methods

If you have a ref to a ReactQuill node, you will be able to invoke the following methods:

focus() : Focuses the editor.

blur() : Removes focus from the editor.

getEditor() : Returns the Quill instance that backs the editor. While you can freely use this to access methods such as getText(), please avoid from imperatively manipulating the instance, to avoid getting ReactQuill and Quill out-of-sync. A much-safer unprivileged editor is available as replacement.

Example

View this example on Codepen

class Editor extends React.Component {
  constructor(props) {
    super(props)
    this.quillRef = null;      // Quill instance
    this.reactQuillRef = null; // ReactQuill component
  }

  componentDidMount() {
    this.attachQuillRefs()
  }

  componentDidUpdate() {
    this.attachQuillRefs()
  }

  attachQuillRefs = () => {
    if (typeof this.reactQuillRef.getEditor !== 'function') return;
    this.quillRef = this.reactQuillRef.getEditor();
  }

  insertText = () => {
    var range = this.quillRef.getSelection();
    let position = range ? range.index : 0;
    this.quillRef.insertText(position, 'Hello, World! ')
  }

  render() {
    return (
      <div>
        <ReactQuill 
          ref={(el) => { this.reactQuillRef = el }}
          theme={'snow'} />
        <button onClick={this.insertText}>Insert Text</button>
      </div>
    )
  }
}

makeUnprivilegedEditor : Creates an unprivileged editor. Pass this method a reference to the Quill instance from getEditor. Normally you do not need to use this method since the editor exposed to event handlers is already unprivileged.

Example

const editor = this.reactQuillRef.getEditor();
const unprivilegedEditor = this.reactQuillRef.makeUnprivilegedEditor(editor);
// You may now use the unprivilegedEditor proxy methods
unprivilegedEditor.getText();

The unprivileged editor

During events, ReactQuill will make a restricted subset of the Quill API available as the editor argument. This prevents access to destructive methods, which might cause ReactQuill to get out-of-sync with the component. It provides the following methods, which are mostly proxies of existing Quill methods:

getLength() : Returns the length of the editor contents, in characters, not including any HTML tag.

getText() : Returns the string contents of the editor, not including any HTML tag.

getHTML() : Returns the full HTML contents of the editor.

getContents() : Returns a Quill Delta of the complete document.

getSelection() : Returns the current selection range, or null if the editor is unfocused.

getBounds() : Returns the pixel position, relative to the editor container, and dimensions, of a selection, at a given location.

Building and testing

You can run the automated test suite:

npm test

And build a minificated version of the source:

npm run build

More tasks are available on the Makefile:

lint: lints the source
spec: runs the test specs
coverage: runs the code coverage test
test: lint, spec and coverage threshold test
build: builds the minified version

Note that dist is ignored in the git repository as of version 1.0.0. If you need to use the built files without downloading the package from NPM, you can run the build tasks yourself or use a CDN like unpkg.

Bundling with Webpack

Quill ships only a pre-built javascript file, so Webpack will complain after building a bundle:

Error: ./~/react-quill/~/quill/dist/quill.js
Critical dependencies:
6:478-485 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
@ ./~/react-quill/~/quill/dist/quill.js 6:478-485

The warning is harmless, but if you want to silence it you can avoid parsing Quill by adding this to your Webpack configuration:

module: {
  // Shut off warnings about using pre-built javascript files
  // as Quill.js unfortunately ships one as its `main`.
  noParse: /node_modules\/quill\/dist/
}

See #7 for more details.

Browser support

Please check the browser support table for the upstream Quill dependency. The React part of the codebase is ES5-compatible.

Changelog

Full changelog

Contributors

React Quill would not be where it is today without the contributions of many people, which we are incredibly grateful for:

  • @zenoamaro (maintainer)
  • @alexkrolick (maintainer)
  • @clemmy
  • @asiniy
  • @webcarrot
  • @druti
  • @e-jigsaw
  • @zhang-z
  • @Sajam
  • @0bird512
  • @jacktrades
  • @1000hz
  • @kkerr1
  • @csk157
  • @Janekk
  • @AndyTheGiant
  • @chrismcv
  • @wouterh
  • @tdg5
  • @jrmmnr
  • @l3kn
  • @rpellerin
  • @sandbochs
  • @wouterh
  • @MattKunze

Roadmap

  • [x] React 0.14 support
  • [x] Quill v1.0.0+ support
  • [x] Tests!
  • [x] Compatibility with React 16
  • [ ] Additional APIs for working with Quill

License

The MIT License (MIT)

Copyright (c) 2016, zenoamaro zenoamaro@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文