如何限制草稿js的最大长度

How to limit Max Length of Draft js

如何限制草稿js中的最大字符数?

我可以这样获取状态的长度,但是如何停止更新组件?

var length = editorState.getCurrentContent().getPlainText('').length;

您应该定义 handleBeforeInput and handlePastedText 道具。在处理程序函数中,您检查当前内容的长度 + 粘贴文本的长度,如果达到最大值,您应该 return 'handled' string.

UPD 21.03.2018:升级到 react/react-dom (16.2.0) 和 Draft.js (0.10.5) 的最新版本。

工作示例 - https://jsfiddle.net/Ln1hads9/11/

const {Editor, EditorState} = Draft;

const MAX_LENGTH = 10;

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      editorState: EditorState.createEmpty()
    };
  }
  render() {
    return (
      <div className="container-root">
        <Editor
          placeholder="Type away :)"
          editorState={this.state.editorState}
          handleBeforeInput={this._handleBeforeInput}
          handlePastedText={this._handlePastedText}
          onChange={this._handleChange}
        />
      </div>
    );
  }

  _getLengthOfSelectedText = () => {
    const currentSelection = this.state.editorState.getSelection();
    const isCollapsed = currentSelection.isCollapsed();

    let length = 0;

    if (!isCollapsed) {
      const currentContent = this.state.editorState.getCurrentContent();
      const startKey = currentSelection.getStartKey();
      const endKey = currentSelection.getEndKey();
      const startBlock = currentContent.getBlockForKey(startKey);
      const isStartAndEndBlockAreTheSame = startKey === endKey;
      const startBlockTextLength = startBlock.getLength();
      const startSelectedTextLength = startBlockTextLength - currentSelection.getStartOffset();
      const endSelectedTextLength = currentSelection.getEndOffset();
      const keyAfterEnd = currentContent.getKeyAfter(endKey);
      console.log(currentSelection)
      if (isStartAndEndBlockAreTheSame) {
        length += currentSelection.getEndOffset() - currentSelection.getStartOffset();
      } else {
        let currentKey = startKey;

        while (currentKey && currentKey !== keyAfterEnd) {
          if (currentKey === startKey) {
            length += startSelectedTextLength + 1;
          } else if (currentKey === endKey) {
            length += endSelectedTextLength;
          } else {
            length += currentContent.getBlockForKey(currentKey).getLength() + 1;
          }

          currentKey = currentContent.getKeyAfter(currentKey);
        };
      }
    }

    return length;
  }

  _handleBeforeInput = () => {
    const currentContent = this.state.editorState.getCurrentContent();
    const currentContentLength = currentContent.getPlainText('').length;
    const selectedTextLength = this._getLengthOfSelectedText();

    if (currentContentLength - selectedTextLength > MAX_LENGTH - 1) {
      console.log('you can type max ten characters');

      return 'handled';
    }
  }

  _handlePastedText = (pastedText) => {
    const currentContent = this.state.editorState.getCurrentContent();
    const currentContentLength = currentContent.getPlainText('').length;
    const selectedTextLength = this._getLengthOfSelectedText();

    if (currentContentLength + pastedText.length - selectedTextLength > MAX_LENGTH) {
      console.log('you can type max ten characters');

      return 'handled';
    }
  }

  _handleChange = (editorState) => {
    this.setState({ editorState });
  }
}

ReactDOM.render(<Container />, document.getElementById('react-root'))

Mikhail 的方法是正确的,但处理程序 return 值不正确。 'not_handled'是一个fall-through case,让Editor组件可以正常处理输入。在这种情况下,我们要停止编辑器处理输入。

在旧版本的 DraftJS 中,处理代码中似乎存在评估为 'true' 的字符串,因此上述代码的行为正确。在 DraftJS 的更高版本中,上面的 fiddle 不起作用 - 我在这里没有 post 比 Fiddle 更多的声誉,但尝试使用 Mikhail 的 v0.10 代码要复制的 DraftJS。

要更正此问题,return 'handled' 或当您不希望编辑器继续处理输入时为真。

Fiddle with corrected return values

例如,

_handleBeforeInput = () => {
  const currentContent = this.state.editorState.getCurrentContent();
  const currentContentLength = currentContent.getPlainText('').length

  if (currentContentLength > MAX_LENGTH - 1) {
    console.log('you can type max ten characters');
    return 'handled';
  }
}

有关可取消处理程序的更多信息,请参阅 DraftJS 文档。

让我们考虑一下。什么叫做做出改变?你的onChange,对吧?好的。我们也知道length。正确的?我们攻击 "worker" 即 onChange:

const length = editorState.getCurrentContent().getPlainText('').length;

// Your onChange function:   
onChange(editorState) {
 const MAX_LENGTH = 10;
 const length = editorState.getCurrentContent().getPlainText('').length;

 if (length <= MAX_LENGTH) {
  this.setState({ editorState }) // or this.setState({ editorState: editorState })
 }
} else {
 console.log(`Sorry, you've exceeded your limit of ${MAX_LENGTH}`)
}

我没试过,但我的第六感说它很好用。

这是一个有点老的帖子,但我想我会为其他在粘贴文本时遇到字符限制和行为问题的人分享一个解决方案...

根据 Mikhail 的上述代码快速组合一些东西来处理这个对我有用的用例 - 虽然我没有做任何尝试优化它的工作。

句柄粘贴的文本基本上是这样的:

      const __handlePastedText = (pastedText: any) => {
        const currentContent = editorState.getCurrentContent();
        const currentContentLength = currentContent.getPlainText('').length;
        const selectedTextLength = _getLengthOfSelectedText();
    
        if (currentContentLength + pastedText.length - selectedTextLength > MAX_LENGTH) {
            const selection = editorState.getSelection()
            const isCollapsed = selection.isCollapsed()
            const tempEditorState = !isCollapsed ? _removeSelection() : editorState
            _addPastedContent(pastedText, tempEditorState)
          return 'handled';
        }
        return 'not-handled'
      }

我们有一个辅助函数来处理在粘贴新字符之前删除选择,returns 新编辑器声明:

      const _removeSelection = () => {
        const selection = editorState.getSelection()
        const startKey = selection.getStartKey()
                const startOffset = selection.getStartOffset()
                const endKey = selection.getEndKey()
                const endOffset = selection.getEndOffset()
                if (startKey !== endKey || startOffset !== endOffset) {
                    const newContent = Modifier.removeRange(editorState.getCurrentContent(), selection, 'forward')
                    const tempEditorState = EditorState.push(
                        editorState,
                        newContent,
                        "remove-range"
                    )
                    setEditorState(
                        tempEditorState
                    )
                    return tempEditorState
                }
                return editorState
      }

最后是添加有限制的粘贴文本的功能:

      const _addPastedContent = (input: any, editorState: EditorState) => {
        const inputLength = editorState
        .getCurrentContent()
        .getPlainText().length;
        let remainingLength = MAX_LENGTH - inputLength;

        const newContent = Modifier.insertText(
            editorState.getCurrentContent(),
            editorState.getSelection(),
            input.slice(0,remainingLength)
        ); 
        setEditorState(
            EditorState.push(
                editorState,
                newContent,
                "insert-characters"
            )
        )
      }

Link 工作示例: https://codesandbox.io/s/objective-bush-1h9x6

所述,您需要处理键入和粘贴文本。这是两个处理程序。请注意,粘贴处理程序将保留不超出限制的文本

function handleBeforeInput(text: string, state: EditorState): DraftHandleValue {
    const totalLength = state.getCurrentContent().getPlainText().length + text.length;
    return totalLength > MAX_LENGTH ? 'handled' : 'not-handled';
  }

function handlePastedText(text: string, _: string, state: EditorState): DraftHandleValue {
    const overflowChars = text.length + state.getCurrentContent().getPlainText().length - MAX_LENGTH;

    if (overflowChars > 0) {
      if (text.length - overflowChars > 0) {
        const newContent = Modifier.insertText(
          state.getCurrentContent(),
          state.getSelection(),
          text.substring(0, text.length - overflowChars)
        );
        setEditorState(EditorState.push(state, newContent, 'insert-characters'));
      }
      return 'handled';
    } else {
      return 'not-handled';
    }
  }