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()
:傳回編輯器內容的長度,以字元為單位,不包括