7

save我在页面和按钮上有一个编辑器。我希望save仅在有更改时才出现按钮(自上次保存以来)。因此,当您保存时,我设置this.setState({hasChanges: false})并在onChange功能中设置hasChangestrue.

这一切都很好。问题是onChange当编辑器获得焦点时编辑器将触发事件(但内容尚未更改)。而且,根据他们的文档,这是预期的行为

组件内的事件监听器将观察焦点变化并按预期通过 onChange 传播它们,因此状态和 DOM 将保持正确同步。

有什么方法可以知道onChange方法内部的内容是否发生了变化,还是只有选择发生了变化?

4

3 回答 3

12

我今天早些时候在 github 上发布了对您问题的答案,但我也会在此处添加它以供将来参考:

你是对的,每次editorState更改时都会调用 onChange 。并且由于同时editorState包含 theselectionStatecontentState,所以当有内容编辑时以及选择/焦点发生变化时,它都会发生变化。

如果您想知道触发该onChange方法的更改是否在contentState或 中selectionState,您可以将它们与它们的旧值进行比较:

function onChange(newState) {
  const currentContentState = this.state.editorState.getCurrentContent()
  const newContentState = newState.getCurrentContent()

  if (currentContentState !== newContentState) {
    // There was a change in the content  
  } else {
    // The change was triggered by a change in focus/selection
  }
}

现在,如果您知道更改发生在 中,您可以通过调用newState.getLastChangeType()contentState获取更多信息。它应该返回任何这些值(除非您或您添加的某些插件创建了新的更改类型)。

于 2016-12-01T21:31:50.333 回答
2

但是,有时只是条件 if (currentContentState !== newContentState)不起作用并且不会检测到更改,例如当您使用Entity.mergeDatawith 修改内容状态时,forceSelection因为此更改存储在实体内部并且没有暴露在contentState.

所以你可以额外做类似的事情。

this.currentEntityMap = null;

function onChange(newEditorState) {

 const currentContentState = editorState.getCurrentContent();
 const newContentState = newEditorState.getCurrentContent();
 const newContentStateRaw = convertToRaw(newContentState);
 const newEntityMap = newContentStateRaw ? newContentStateRaw.entityMap : null;

//so if you have the two entity maps, you can to compare it, here an example function.
 const isEntityMapChanged = this.isEntityMapChanged(newEntityMap);

 this.currentEntityMap = newEntityMap;  
}

 isEntityMapChanged(newEntityMap) {
        let isChanged = false;
        if (this.currentEntityMap) {
            loop1:
            for (const index of Object.keys(newEntityMap)) {
                if (this.currentEntityMap[index] && newEntityMap[index].type === this.currentEntityMap[index].type) {
                    loop2:
                    for (const prop of Object.keys(newEntityMap[index].data)) {
                        if (newEntityMap[index].data[prop] !== this.currentEntityMap[index].data[prop]) {
                            isChanged = true;
                            break loop1;
                        }
                    }
                } else {
                    isChanged = true;
                    break loop1;
                }
            }
        }

        return isChanged;
    }

然后使用标志isEntityMapChanged和第一个条件进行保存。

于 2018-05-09T21:10:11.303 回答
0

you should use code follow:

  const onChange = newState => {
    if (
      // when content change or line style change will change the state
      !newState.getCurrentContent().equals(editorState.getCurrentContent()) ||
      !newState
        .getCurrentInlineStyle()
        .equals(editorState.getCurrentInlineStyle())
    ) {
      setEditorState(newState);
    }
  };

if you just use content equal ,then line style change will not on effect.

于 2020-09-25T03:17:06.647 回答