Braft Editor 是基於draft-js開發的富文本編輯器,適用於 React 框架。
1. 安裝
使用npm
npm install braft-editor --save
使用yarn
yarn add braft-editor
2. 基本使用
import React, { Component } from 'react'
import BraftEditor from 'braft-editor'
import 'braft-editor/dist/index.css'
export default class Main extends Component {
state = {
editorState: BraftEditor.createEditorState('<p>初始值</p>'), // 設置編輯器初始內容
outputHTML: '<p></p>' // 編輯器輸出內容
}
componentDidMount () {
this.setState({
editorState: BraftEditor.createEditorState('<p>hello,<b>world!</b><p>')
})
}
handleChange = (editorState) => {
this.setState({
editorState: editorState,
outputHTML: editorState.toHTML()
}, () => {
console.log(editorState)
console.log(this.state.outputHTML)
})
}
render () {
const { editorState, outputHTML } = this.state
return (
<div>
<div className="editor-wrapper">
<BraftEditor
value={editorState}
onChange={this.handleChange}
/>
</div>
</div>
)
}
}
2. 自定義內置控件
Braft Editor使用 controls 屬性指定需要展示的控件;使用contentStyle調整編輯區域的高度。
render () {
const controls = [
'undo', 'redo', 'separator',
'font-size', 'line-height', 'letter-spacing', 'separator',
'text-color', 'bold', 'italic', 'underline', 'strike-through', 'separator',
'superscript', 'subscript', 'remove-styles', 'emoji', 'separator', 'text-indent', 'text-align', 'separator',
'headings', 'list-ul', 'list-ol', 'blockquote', 'code', 'separator',
'link', 'separator', 'hr', 'separator',
'media',
'separator',
'clear'
]
return (
<div className="editor-wrapper">
<BraftEditor
controls={controls}
contentStyle={{height: 210, boxShadow: 'inset 0 1px 3px rgba(0,0,0,.1)'}}
/>
</div>
)
}
3. 集成 Ant Design 上傳組件
Braft Editor上傳圖片會默認轉成base64, 下面將使用Ant Design 的上傳組件改成上傳到服務器的方法:
- 使用ContentUtils來將上傳后的圖片插入到編輯器,安裝:
yarn add braft-utils
- 使用component類型的extendControls將Upload組件集成到編輯器工具欄
import React, { Component } from 'react'
import BraftEditor from 'braft-editor'
import 'braft-editor/dist/index.css'
export default class Main extends Component {
state = {
editorState: BraftEditor.createEditorState(null)
}
componentDidMount () {
this.setState({
editorState: BraftEditor.createEditorState('<p>hello,<b>world!</b><p>')
})
}
onOk = () => {
this.props.form.validateFields((err, fieldsValue) => {
if (!err) {
console.log(fieldsValue)
}
})
}
beforeUpload = file => {
this.props.form.setFieldsValue({
content: ContentUtils.insertMedias(this.props.form.getFieldValue('content'), [{
type: 'IMAGE',
url: imgUrl, // imgUrl 為上傳成功后 后台返回的url地址
}])
return false
}
render () {
const {
form: { getFieldDecorator },
} = this.props
const { editorState } = this.state
const formItemLayout = {
labelCol: {
sm: { span: 4 },
},
wrapperCol: {
sm: { span: 20 },
},
}
const controls = [
'undo', 'redo', 'separator',
'font-size', 'line-height', 'letter-spacing', 'separator',
'text-color', 'bold', 'italic', 'underline', 'strike-through', 'separator',
'superscript', 'subscript', 'remove-styles', 'emoji', 'separator', 'text-indent', 'text-align', 'separator',
'headings', 'list-ul', 'list-ol', 'blockquote', 'code', 'separator',
'link', 'separator', 'hr', 'separator',
// 'media',
'separator',
'clear'
]
const extendControls = [
{
key: 'antd-uploader',
type: 'component',
component: (
<Upload
accept="image/*"
showUploadList={false}
beforeUpload={this.beforeUpload}
>
{/* 這里的按鈕最好加上type="button",以避免在表單容器中觸發表單提交,用Antd的Button組件則無需如此 */}
<button type="button" className="control-item button upload-button" data-title="插入圖片">
<Icon type="picture" theme="filled" />
</button>
</Upload>
)
}
]
return (
<div>
<div className="editor-wrapper">
<Form {...formItemLayout}>
<Form.Item label="標題">
{getFieldDecorator(`title`, {
initialValue: '',
rules: [{ required: true, message: '請輸入標題' }],
})(
<Input placeholder="請輸入" allowClear style={{ width: 300 }} />
)}
</Form.Item>
<Form.Item label="內容">
{getFieldDecorator(`content`, {
validateTrigger: 'onBlur',
initialValue: editorState,
rules: [{ required: true, message: '請輸入內容' }],
})(
<BraftEditor
className={styles.editorStyle}
contentStyle={{ height: 160, boxShadow: 'inset 0 1px 3px rgba(0,0,0,.1)' }}
controls={controls}
extendControls={extendControls}
placeholder="請輸入正文內容"
/>
)}
</Form.Item>
<Form.Item>
<Button type="primary" onClick={this.onOk}>
確定
</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
}