Javascript 如何在编辑器中显示保存的草稿JS数据?(反应和流星)
我试图将保存的内容保存在编辑器中(例如刷新后)Javascript 如何在编辑器中显示保存的草稿JS数据?(反应和流星),javascript,mongodb,reactjs,meteor,draftjs,Javascript,Mongodb,Reactjs,Meteor,Draftjs,我试图将保存的内容保存在编辑器中(例如刷新后) 当前,内容从DB发送到console.log,并按预期显示 但我不能把它放在编辑部 [编辑]删除了草稿项目链接,请参阅下面的解决方案 我正在使用: 以下是~/imports/collections/bins.js import { Mongo } from 'meteor/mongo'; Meteor.methods({ 'bins.insert': function() { return Bi
- 当前,内容从DB发送到console.log,并按预期显示李>
- 但我不能把它放在编辑部
以下是~/imports/collections/bins.js
import { Mongo } from 'meteor/mongo';
Meteor.methods({
'bins.insert': function() {
return Bins.insert({
createdAt: new Date(),
content: '',
sharedWith: [],
ownerId: this.userId
});
},
'bins.remove': function(bin) {
return Bins.remove(bin);
},
'bins.update': function(bin, content) {
return Bins.update(bin._id, { $set: { content } });
}
});
export const Bins = new Mongo.Collection('bins');
~/client/components/bin/bin\u main.js
import React, { Component } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Bins } from '../../../imports/collections/bins';
import BinsEditor from './bins_editor';
class BinsMain extends Component {
render() {
if (!this.props.bin) { return <div>Loading...</div>; }
return (
<div>
<BinsEditor bin={this.props.bin} />
</div>
);
}
}
export default createContainer((props) => {
const { binId } = props.params;
Meteor.subscribe('bins');
return { bin: Bins.findOne(binId) };
}, BinsMain);
import React,{Component}来自'React';
从“meteor/react meteor数据”导入{createContainer};
从“../../../imports/collections/Bins”导入{Bins};
从“/bins_editor”导入BinsEditor;
类扩展了主组件{
render(){
如果(!this.props.bin){返回加载…;}
返回(
);
}
}
导出默认createContainer((道具)=>{
const{binId}=props.params;
Meteor.subscribe(“BIS”);
返回{bin:Bins.findOne(binId)};
},宾斯曼);
以下是一个使用草稿JS+React+Meteor+Material UI+帐户UI+Material UI帐户的完整示例
你可以
- 创建链接到用户帐户的bin(如果已登录)
- 编辑垃圾箱
- 编辑时自动保存仓位
import React from "react";
import {Editor, EditorState, ContentState, RichUtils, convertToRaw, convertFromRaw} from "draft-js";
export default class BinsEditor extends React.Component {
constructor(props) {
super(props);
let editorState;
if (!this.props.bin.content) {
this.state = {editorState: EditorState.createEmpty()};
console.log('empty');
} else {
const rawContent = this.props.bin.content;
const parsedContent = convertFromRaw(JSON.parse(rawContent));
this.state = {editorState: EditorState.createWithContent(parsedContent)};
console.log('not empty');
}
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => {
this.setState({editorState});
const contentState = editorState.getCurrentContent();
const rawContent = JSON.stringify(convertToRaw(contentState));
Meteor.call('bins.update', this.props.bin, rawContent);
console.log(rawContent);
}
this.handleKeyCommand = (command) => this._handleKeyCommand(command);
this.toggleBlockType = (type) => this._toggleBlockType(type);
this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
}
_handleKeyCommand(command) {
const {editorState} = this.state;
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
_toggleBlockType(blockType) {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,
blockType
)
);
}
_toggleInlineStyle(inlineStyle) {
this.onChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
inlineStyle
)
);
}
render() {
const {editorState} = this.state;
// If the user changes block type before entering any text, we can
// either style the placeholder or hide it. Let's just hide it now.
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (contentState.getBlockMap().first().getType() !== 'unstyled') {
className += ' RichEditor-hidePlaceholder';
}
}
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
editorState={editorState}
onToggle={this.toggleInlineStyle}
/>
<div className={className} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
placeholder="Tell a story..."
ref="editor"
spellCheck={true}
/>
</div>
<div>{JSON.stringify(convertToRaw(editorState.getCurrentContent()))}</div>
</div>
);
}
}
// Custom overrides for "code" style.
const styleMap = {
CODE: {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
fontSize: 16,
padding: 2,
},
};
function getBlockStyle(block) {
switch (block.getType()) {
case 'blockquote': return 'RichEditor-blockquote';
default: return null;
}
}
class StyleButton extends React.Component {
constructor() {
super();
this.onToggle = (e) => {
e.preventDefault();
this.props.onToggle(this.props.style);
};
}
render() {
let className = 'RichEditor-styleButton';
if (this.props.active) {
className += ' RichEditor-activeButton';
}
return (
<span className={className} onMouseDown={this.onToggle}>
{this.props.label}
</span>
);
}
}
const BLOCK_TYPES = [
{label: 'H1', style: 'header-one'},
{label: 'H2', style: 'header-two'},
{label: 'H3', style: 'header-three'},
{label: 'H4', style: 'header-four'},
{label: 'H5', style: 'header-five'},
{label: 'H6', style: 'header-six'},
{label: 'Blockquote', style: 'blockquote'},
{label: 'UL', style: 'unordered-list-item'},
{label: 'OL', style: 'ordered-list-item'},
{label: 'Code Block', style: 'code-block'},
];
const BlockStyleControls = (props) => {
const {editorState} = props;
const selection = editorState.getSelection();
const blockType = editorState
.getCurrentContent()
.getBlockForKey(selection.getStartKey())
.getType();
return (
<div className="RichEditor-controls">
{BLOCK_TYPES.map((type) =>
<StyleButton
key={type.label}
active={type.style === blockType}
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
)}
</div>
);
};
var INLINE_STYLES = [
{label: 'Bold', style: 'BOLD'},
{label: 'Italic', style: 'ITALIC'},
{label: 'Underline', style: 'UNDERLINE'},
{label: 'Monospace', style: 'CODE'},
];
const InlineStyleControls = (props) => {
var currentStyle = props.editorState.getCurrentInlineStyle();
return (
<div className="RichEditor-controls">
{INLINE_STYLES.map(type =>
<StyleButton
key={type.label}
active={currentStyle.has(type.style)}
label={type.label}
onToggle={props.onToggle}
style={type.style}
/>
)}
</div>
);
};
从“React”导入React;
从“草稿js”导入{Editor、EditorState、ContentState、RichUtils、convertToRaw、convertFromRaw};
导出默认类BinsEditor扩展React.Component{
建造师(道具){
超级(道具);
让编辑陈述;
如果(!this.props.bin.content){
this.state={editorState:editorState.createEmpty()};
console.log('empty');
}否则{
const rawContent=this.props.bin.content;
const parsedContent=convertFromRaw(JSON.parse(rawContent));
this.state={editorState:editorState.createWithContent(parsedContent)};
console.log('notempty');
}
this.focus=()=>this.refs.editor.focus();
this.onChange=(editorState)=>{
this.setState({editorState});
const contentState=editorState.getCurrentContent();
const rawContent=JSON.stringify(convertToRaw(contentState));
Meteor.call('bin.update',this.props.bin,rawContent);
console.log(rawContent);
}
this.handleKeyCommand=(command)=>this.\u handleKeyCommand(command);
this.toggleBlockType=(type)=>this.\u toggleBlockType(type);
this.toggleInlineStyle=(style)=>this.\u toggleInlineStyle(style);
}
_handleKeyCommand(命令){
const{editorState}=this.state;
const newState=RichUtils.handleKeyCommand(editorState,command);
如果(新闻状态){
这个.onChange(newState);
返回true;
}
返回false;
}
_切换块类型(块类型){
这是一次改变(
RichUtils.toggleBlockType(
这个州,编辑州,
块状
)
);
}
_切换inlineStyle(inlineStyle){
这是一次改变(
RichUtils.toggleInlineStyle(
这个州,编辑州,
内联式
)
);
}
render(){
const{editorState}=this.state;
//如果用户在输入任何文本之前更改块类型,我们可以
//要么设置占位符的样式,要么隐藏它。让我们现在就隐藏它。
让className='RichEditor';
var contentState=editorState.getCurrentContent();
如果(!contentState.hasText()){
if(contentState.getBlockMap().first().getType()!='unstyled'){
className+='RichEditor hidePlaceholder';
}
}
返回(
{JSON.stringify(convertToRaw(editorState.getCurrentContent())}
);
}
}
//“代码”样式的自定义替代。
常量样式映射={
代码:{
背景颜色:“rgba(0,0,0,0.05)”,
fontFamily:“‘Inconcolata’、‘Menlo’、‘Consolas’、‘monospace’,
尺寸:16,
填充:2,
},
};
函数getBlockStyle(块){
开关(block.getType()){
案例'blockquote':返回'RichEditor blockquote';
默认值:返回null;
}
}
类StyleButton扩展了React.Component{
构造函数(){
超级();
this.onToggle=(e)=>{
e、 预防默认值();
this.props.ontogle(this.props.style);
};
}
render(){
让className='RichEditor styleButton';
如果(此.props.active){
className+='RichEditor activeButton';
}
返回(
{this.props.label}
);
}
}
常量块类型=[
{标签:'H1',样式:'header one'},
{标签:'H2',样式:'header two'},
{标签:'H3',样式:'header three'},
{标签:'H4',样式:'header-four'},
{标签:'H5',样式:'header five'},
{标签:'H6',样式:'header six'},
{标签:'Blockquote',样式:'Blockquote'},
{标签:“UL”,样式:“无序列表项”},
{标签:'OL',样式:'ordered list item'},
{标签:'代码块',样式:'代码块'},
];
const BlockStyleControls=(道具)=>{
const{editorState}=props;
const selection=editorState.getSelection();
常量块类型=编辑器状态
.getCurrentContent()
.getBlockForKey(selection.getStartKey())
.getType();
返回(
{BLOCK_TYPES.map((type)=>
)}
);
};
变量内联_样式=[
{标签:'Bold',样式:'Bold'},
{标签:'