React 的 Quill 组件。
查看现场演示或 Codepen。
这是 ReactQuill v2 的文档 — 以前的版本:v1
? ReactQuill v2
ReactQuill 2 来了,宝贝!它带来了 TypeScript 和 React 16+ 的完整移植、重构的构建系统以及内部逻辑的总体收紧。
我们努力避免引入任何行为改变。对于绝大多数情况,根本不需要迁移。但是,对长期弃用的 props、ReactQuill Mixin 和 Toolbar 组件的支持已被删除。请务必阅读迁移指南。
我们预计此版本将是直接升级 - 如果情况并非如此,请使用v2
标签提交问题。
确保你有react
和react-dom
,以及一些加载样式的方法,比如style-loader。有关更多信息,请参阅有关主题的文档。
npm install react-quill --save
import React , { useState } from 'react' ;
import ReactQuill from 'react-quill' ;
import 'react-quill/dist/quill.snow.css' ;
function MyComponent ( ) {
const [ value , setValue ] = useState ( '' ) ;
return < ReactQuill theme = "snow" value = { value } onChange = { setValue } / > ;
}
< link
rel =" stylesheet "
href =" https://unpkg.com/[email protected]/dist/quill.snow.css "
/>
< script
src =" https://unpkg.com/react@16/umd/react.development.js "
crossorigin
> </ script >
< script
src =" https://unpkg.com/react-dom@16/umd/react-dom.development.js "
crossorigin
> </ script >
< script src =" https://unpkg.com/[email protected]/dist/react-quill.js " > </ script >
< script src =" https://unpkg.com/babel-standalone@6/babel.min.js " > </ script >
< script type =" text/babel " src =" /my-scripts.js " > </ script >
在受控模式下,组件应该防止本地有状态更改,而只能通过onChange
和value
来发生它们。
由于 Quill 处理自己的更改,并且不允许阻止编辑,因此 ReactQuill 必须适应受控模式和非受控模式之间的混合。它无法阻止更改,但只要value
与当前状态不同,它仍然会覆盖内容。
如果您经常需要操作 DOM 或强制使用 Quill API,您可能会考虑切换到完全不受控制的模式。 ReactQuill 将使用defaultValue
初始化编辑器,但之后不会尝试重置它。 onChange
回调仍将按预期工作。
在 React 文档中阅读有关不受控组件的更多信息。
您可以传递 Quill Delta 作为value
和defaultValue
属性,而不是 HTML 字符串。与 HTML 字符串相比,Delta 具有许多优点,因此您可能需要使用它们。但请注意,比较增量的更改比比较 HTML 字符串的成本更高,因此可能值得分析您的使用模式。
请注意,将value
从 HTML 字符串切换为 Delta,反之亦然,无论它们是否表示同一文档,都会触发更改,因此您可能希望坚持使用某种格式并始终一致地使用它。
onChange
事件接收到的delta
对象用作value
。该对象不包含完整文档,而仅包含最后的修改,这样做很可能会触发无限循环,其中一遍又一遍地应用相同的更改。在活动期间使用editor.getContents()
来获取完整文档的增量。 ReactQuill 会防止你犯这样的错误,但是如果你绝对确定这就是你想要的,你可以再次通过new Delta()
传递对象来消除它的污染。
Quill 编辑器支持主题。它包括一个成熟的主题,称为Snow ,这是 Quill 的标准外观,以及一个类似于 Medium 上的内联编辑器的气泡主题。至少,必须包含核心主题才能使工具栏或工具提示等模块正常工作。
要激活主题,请将主题名称传递给theme
属性。传递一个虚假值(例如null
)以使用核心主题。
< ReactQuill theme = "snow" . . . / >
然后,导入您要使用的主题的样式表。
这可能会有所不同,具体取决于应用程序的结构、目录或其他方式。例如,如果您使用 SASS 等 CSS 预处理器,您可能希望将该样式表导入到您自己的样式表中。这些样式表可以在 Quill 发行版中找到,但为了方便起见,它们也链接在 ReactQuill 的dist
文件夹中。
下面是一个使用 Webpack 的 style-loader 或create-react-app
示例,它将自动在页面上注入样式:
import 'react-quill/dist/quill.snow.css' ;
这些样式也可以通过 CDN 获得:
< link
rel =" stylesheet "
href =" https://unpkg.com/[email protected]/dist/quill.snow.css "
/>
Quill 工具栏模块 API 提供了一种使用格式名称数组配置默认工具栏图标的简单方法。
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/JSX 工具栏,其中包含不属于 Quill 主题的自定义元素。
请参阅 Codepen 上的实时示例:自定义工具栏示例
/*
* 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' )
) ;
该组件有两种格式:
formats
属性启用/禁用的默认Quill格式。默认情况下启用所有格式。 import ReactQuill , { Quill } from 'react-quill' ; // ES6
const ReactQuill = require ( 'react-quill' ) ; // CommonJS
/*
* 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 }
/ >
) ;
}
}
如果您实例化没有子项的 ReactQuill,它将为您创建一个<div>
,用作 Quill 的编辑区域。如果您愿意,您可以指定自己的元素供 ReactQuill 使用。请注意,Quill 目前不支持<textarea>
。
注意:此时使用 React 16 作为对等部门时,自定义编辑区域会失去焦点(错误)。
class MyComponent extends React . Component {
render ( ) {
return (
< ReactQuill >
< div className = "my-editing-area" / >
< / ReactQuill >
) ;
}
} ) ;
升级到 ReactQuill v2 应该像更新依赖项一样简单。但是,它还删除了对长期弃用的 props、ReactQuill Mixin 和 Toolbar 组件的支持。
对toolbar
、 styles
、 pollInterval
Quill 选项的支持早已禁用。从这个版本开始,如果您尝试使用它们,ReactQuill 将不再警告您。
ReactQuill Mixin 允许将 ReactQuill 的核心功能注入到您自己的组件中,并创建深度定制的版本。
Mixin 长期以来一直被认为是一种反模式,因此我们决定最终决定弃用它。
没有升级路径。如果您有一个依赖 Mixin 的用例,我们鼓励您提出问题,我们将尝试为您提供新功能以使其成为可能,或者提供专门的支持来迁移它。
Quill 长期以来一直提供对自定义工具栏的内置支持,它取代了 ReactQuill 的(相当不灵活)工具栏组件。
请改用工具栏模块或 HTML 工具栏功能。
// ES6
import ReactQuill , { Quill } from 'react-quill' ;
// CommonJS
const ReactQuill = require ( 'react-quill' ) ;
const { Quill } = ReactQuill ;
Quill
:可以在其上调用register
Quill
命名空间。
id
:应用于 DOM 元素的 ID。
className
:要应用于 DOM 元素的类。
value
:编辑器作为受控组件的值。可以是包含 HTML 的字符串、Quill Delta 实例或表示 Delta 的普通对象。请注意,由于 Quill 的限制,这实际上是一种半控制模式,这意味着不会阻止编辑,但更改value
仍会替换内容。另请注意,在此处传递 Quill Delta,然后传递 HTML 字符串(反之亦然)将始终触发更改,无论它们是否表示同一文档。onChange
事件中的delta
对象作为value
传递,因为这会导致循环。有关详细信息,请参阅使用 Delta。
defaultValue
:编辑器作为不受控制组件的初始值。可以是包含 HTML 的字符串、Quill Delta 或表示 Delta 的普通对象。
readOnly
:如果为 true,编辑器将不允许更改其内容。包装 Quill disable
API。
placeholder
:空编辑器的默认值。注意:Quill API 不支持动态更改此值。使用 refs 和 data-attributes 代替(参见#340)。
modules
:指定启用哪些模块及其配置的对象。编辑器工具栏是一个常见的自定义模块。有关可用模块的更多信息,请参阅 Quill 文档中的模块部分。
formats
:编辑期间要启用的格式数组。默认情况下启用所有实现的格式。请参阅格式以获取列表。从版本 1.0.0 开始,自定义格式不应包含在数组中。相反,它们应该通过 Parchment 创建并使用模块的 Quill 导出进行注册。
style
:具有要应用于编辑器容器的自定义 CSS 规则的对象。规则应该采用 React 的“camelCased”命名风格。
theme
:应用到编辑器的主题名称。默认为snow
,Quill 的标准主题。传递null
以使用最小核心主题。有关包含所需样式表的更多信息,请参阅有关主题的文档。
tabIndex
:在键盘导航期间,编辑器在页面中的其他控件中获得焦点的顺序。
bounds
:Quill 使用选择器或 DOM 元素来限制弹出窗口的位置。默认为document.body
。
children
:单个 React 元素,将用作 Quill 的编辑区域,代替默认的<div>
。请注意,您不能使用<textarea>
,因为它不是受支持的目标。另请注意,更新子项的成本很高,因为它将导致重新创建 Quill 编辑器。如果你想控制编辑器的 html 内容,请设置value
属性。
onChange(content, delta, source, editor)
:在更改后回调编辑器的新内容。它将传递编辑器的 HTML 内容、表示更改的 delta 对象、更改的源,最后传递给编辑器访问器(例如getHTML()
只读代理。delta
对象作为value
,因为它会导致循环。使用editor.getContents()
代替。有关详细信息,请参阅使用 Delta。
onChangeSelection(range, source, editor)
:回调新选定的范围,或者在未获得焦点时为 null。它将传递选择范围、更改源,最后传递给编辑器访问器(例如getBounds()
只读代理。
onFocus(range, source, editor)
:当编辑器获得焦点时调用。它将收到新的选择范围。
onBlur(previousRange, source, editor)
:当编辑器失去焦点时调用。它将接收失去焦点之前的选择范围。
onKeyPress(event)
:按下并释放按键后调用。 :请注意,与本机对应项一样,不会为特殊键(例如shift或Enter )调用此方法。如果您需要这些,请连接onKeyDown
或onKeyUp
。
onKeyDown(event)
:在按下某个键之后但在释放该键之前调用。 :请注意,由于 Quill 的工作原理,您可能不会收到Enter 、 Backspace或delete等键的事件。如果是这种情况,请尝试连接onKeyUp
。
onKeyUp(event)
:释放按键后调用。
preserveWhitespace
:如果为 true,则编辑器区域将使用pre
标签而不是默认的div
标签。这可以防止 Quill 折叠粘贴上的连续空白。相关问题。
如果您有 ReactQuill 节点的引用,您将能够调用以下方法:
focus()
:使编辑器聚焦。
blur()
:从编辑器中移除焦点。
getEditor()
:返回支持编辑器的 Quill 实例。虽然您可以自由地使用它来访问getText()
等方法,但请避免强制操作实例,以避免 ReactQuill 和 Quill 不同步。可以使用更安全的非特权编辑器作为替代。
在 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 实例的引用。通常您不需要使用此方法,因为暴露给事件处理程序的编辑器已经没有特权。
const editor = this . reactQuillRef . getEditor ( ) ;
const unprivilegedEditor = this . reactQuillRef . makeUnprivilegedEditor ( editor ) ;
// You may now use the unprivilegedEditor proxy methods
unprivilegedEditor . getText ( ) ;
在事件期间,ReactQuill 将使 Quill API 的受限子集可用作editor
参数。这可以防止访问破坏性方法,这可能会导致 ReactQuill 与组件不同步。它提供了以下方法,这些方法大多是现有 Quill 方法的代理:
getLength()
:返回编辑器内容的长度,以字符为单位,不包括