Javascript 当焦点更改为React Select时,React Slate中的文本选择不再标记

Javascript 当焦点更改为React Select时,React Slate中的文本选择不再标记,javascript,reactjs,slate,Javascript,Reactjs,Slate,我不知道这是我们的共同问题还是错误,但也许有人有一个想法: 我们正在用react和slate构建一个HTML编辑器。 用户可以选择一个文本框,然后更改属性。这对于简单的按钮很好。但是,当我打开一个下拉列表(react select)以更改字体大小时,所选文本不再被标记。Slate保留选择,以便更改生效,但这样的用户体验很糟糕 我想这应该是一个石板功能,以保持文本标记,但也许这是我需要应用自己的东西 一些片段,不知道它们是否有用: 编辑器组件初始化字体样式插件并负责序列化 class Editor

我不知道这是我们的共同问题还是错误,但也许有人有一个想法: 我们正在用react和slate构建一个HTML编辑器。 用户可以选择一个文本框,然后更改属性。这对于简单的按钮很好。但是,当我打开一个下拉列表(react select)以更改字体大小时,所选文本不再被标记。Slate保留选择,以便更改生效,但这样的用户体验很糟糕

我想这应该是一个石板功能,以保持文本标记,但也许这是我需要应用自己的东西

一些片段,不知道它们是否有用:

编辑器组件初始化字体样式插件并负责序列化

class Editor extends React.Component {
  constructor(props) {
    super(props);

    this.config = {
      ...mergePluginConfig(PLUGIN_CONFIG, props),
      getEditor: () => this.editor,
      getValue: () => this.state.value,
    };
    this.plugins = initializePlugins(this.config);
    this.htmlSerializer = new HtmlSerializer({
      rules: getSerializationRulesFromPlugins(this.plugins),
    });
    this.schema = getSchemaFromPlugins(this.plugins);
    this.state = {
      value: this.htmlSerializer.deserialize(props.value)
    };



ref = editor => {
    this.editor = editor;
  };


render() {
    return (
      <div>
        <Toolbar>
            <div className="control">
                {renderToolbarElementWithPlugins(this.plugins, 'font-size')}
            </div>
        <!--- more tools --->
      <SlateEditor
            autoFocus={true}
            spellCheck={true}
            placeholder={this.props.placeholder}
            ref={this.ref}
            value={this.state.value}
            onChange={this.onChange}
            onKeyDown={this.onKeyDown}
            plugins={this.plugins}
            schema={this.schema}
       />


onChange = ({ value }) => {
    const {startInline, endInline, document, selection, fragment} = value;
    // holds the correct information
    console.log(fragment.text);
    // ...
    this.setState({ value });
    this.props.onChange(this.htmlSerializer.serialize(value));
 };
类编辑器扩展React.Component{
建造师(道具){
超级(道具);
this.config={
…MergePluginFig(插件配置,道具),
getEditor:()=>this.editor,
getValue:()=>this.state.value,
};
this.plugins=initializePlugins(this.config);
this.htmlSerializer=新的htmlSerializer({
规则:getSerializationRulesFromPlugins(this.plugins),
});
this.schema=getSchemaFromPlugins(this.plugins);
此.state={
value:this.htmlSerializer.deserialize(props.value)
};
ref=编辑器=>{
this.editor=editor;
};
render(){
返回(
{renderToolbarElementWithPlugins(this.plugins,'font-size')}
onChange=({value})=>{
常量{startInline,endInline,document,selection,fragment}=value;
//保存正确的信息
log(fragment.text);
// ...
this.setState({value});
this.props.onChange(this.htmlSerializer.serialize(value));
};
这是字体大小插件,与其他插件一起初始化,并将显示在工具栏中:

export default function initializeFontSizePlugin(options) {
  // this takes care of detecting the current value and applying selected change to the value. 
  // it does not change selection
  const plugin = createStyleBasedMarkPlugin(...); 
  const fontSizeOptions = options.fontSizeOptions || [];

  const handleFontSizeChange = ({value}) => {
    plugin.reapplyFontSize({value: rendererFontSize(value)});
  };

  return {
    ...plugin,

    renderToolbarElement() {
      const {isMixed, fontSize} = plugin.detectFontSize();

      return <Select
        isCreatable={true}
        name='font-size'
        value={isMixed ? undefined : displayFontSize(fontSize)}
        onChange={handleFontSizeChange}
        options={fontSizeOptions}
      />;
    }
  };
}
导出默认函数初始值FontSizePlugin(选项){
//这负责检测当前值并将选定的更改应用于该值。
//它不会改变选择
const plugin=createStyleBasedMarkPlugin(…);
常量fontSizeOptions=options.fontSizeOptions | |[];
常量handleFontSizeChange=({value})=>{
repalyFontSize({value:renderFontSize(value)});
};
返回{
…插件,
renderToolbarElement(){
const{isMixed,fontSize}=plugin.detectFontSize();
返回;
}
};
}
我目前的解决方案是在select打开后立即关注slate,然后告诉select打开,但这感觉有点黑客味,也有缺点(见下文)

const handleFontSizeChange=({value})=>{
repalyFontSize({value:renderFontSize(value)});
handleMenuClose();
};
让menuIsOpen=false;
让firstOpen=false;
常量handleMenuOpen=(编辑器)=>{
firstOpen=true;
如果(!menuIsOpen){
设置超时(()=>{
如果(编辑){
editor.focus();
}
menuIsOpen=true;
}, 1);
}
}
常量handleMenuClose=(编辑器)=>{
如果(!firstOpen){
设置超时(()=>{
如果(菜单打开){
menuIsOpen=false;
如果(编辑){
editor.focus();
}
}
}, 1);
}否则{
firstOpen=false;
}  
}

由于打开了下拉列表,当您将焦点移出编辑器时,Slate不会保留所选内容。现在使用按钮时,它会在重新应用所选内容时有所不同

由于您现在必须手动应用和获取选择,因此,当您尝试从“选择”打开菜单时,一种方法是将编辑器选择存储在状态。当菜单打开时,使用重新应用选择并获取fontSize,您可以再次将其存储在状态中,以在下拉列表中显示聚焦值

现在,应用更改后,需要再次应用选择

您可以遵循中使用的概念

const[selection,setSelection]=useState();
const[menuIsOpen,setMenuIsOpen]=useState(false);
const[fontSize,setFontSize]=useState(plugins.detectFontSize());
常量handleFontSizeChange=({value})=>{
repalyFontSize({value:renderFontSize(value)});
handleMenuClose();
};
}
常量handleMenuOpen=(编辑器)=>{
选举(编辑选择);
setMenuIsOpen(真);
Transforms.setSelection()//在此处传入所需的参数
setFontSize(plugins.detectFontSize());
}
常量handleMenuClose=(编辑器)=>{
setMenuIsOpen(假);
Transforms.setSelection()//根据选择状态在此处传入所需的参数
}

还有一个关于焦点和选择的问题

你能创建一个沙盒来重新生成这个问题吗,这将有助于解决你的问题。@Pete,即使是slateEditor的官方演示也不能处理下拉列表中的选择。我在一个代码沙盒中添加了:顺便问一下,你使用哪个slateEditor库哦,它甚至没有官方支持?但是如何任何用户都应该有一个好的体验,当他们想要应用的一个选择的文本不再被强调的时候?!我们使用的是“SLATE”:“0.47.4”和“SLATE反应”:“0.22.4”,嗯,听起来好像很头痛。我有同情心。我会考虑禁用标准文本选择。(或覆盖css以隐藏通常发生的情况),然后加入您自己的文本选择功能。这将允许您绕过跳转,并以更精细的方式控制高亮显示的文本样式。这样您就可以维护“样式为高亮显示”的文本处于react状态。可能是这样,但修改为react?:感谢您的输入。正如我所说,我已经尝试了这些方法,并且成功了。这只是菜单打开时选项闪烁的一个小缺点,但总比看不到选项要好。@Pete Well编辑器,无论您选择哪一个e有一些或其他缺失的场景。在内部,他们也
const handleFontSizeChange = ({value}) => {
    plugin.reapplyFontSize({value: rendererFontSize(value)});
    handleMenuClose();
  };

  let menuIsOpen = false;
  let firstOpen = false;

  const handleMenuOpen = (editor) => {
    firstOpen = true;
    if(!menuIsOpen) {
      setTimeout(() => {
        if (editor) {
          editor.focus();
        }
        menuIsOpen = true;
      }, 1);
    }
  }
  const handleMenuClose = (editor) => {
    if(!firstOpen) {
      setTimeout(() => {
        if(menuIsOpen) {
          menuIsOpen = false;
          if (editor) {
            editor.focus();
          }
        }
      }, 1);
    } else {
      firstOpen = false;
    }  
  }

<Select
    onMenuOpen={handleMenuOpen.bind(this)}
    onMenuClose={handleMenuClose.bind(this)}
    menuIsOpen={menuIsOpen}
const [selection, setSelection] = useState();
const [menuIsOpen, setMenuIsOpen] = useState(false);
const [fontSize, setFontSize] = useState(plugins.detectFontSize());
const handleFontSizeChange = ({value}) => {
    plugin.reapplyFontSize({value: rendererFontSize(value)});
    handleMenuClose();
  };
}
const handleMenuOpen = (editor) => {
    setSelection(editor.selection);
    setMenuIsOpen(true);
    Transforms.setSelection() // pass in the required params here
    setFontSize(plugins.detectFontSize());
}
const handleMenuClose = (editor) => {
    setMenuIsOpen(false);
    Transforms.setSelection() // pass in the required params here based on selection state
}

<Select
    onMenuOpen={handleMenuOpen.bind(this)}
    onMenuClose={handleMenuClose.bind(this)}
    menuIsOpen={menuIsOpen}
    value={fontSize}
    options={options}
/>