簡體   English   中英

當焦點更改為 React Select 時,React Slate 中的文本選擇不再標記

[英]Text selection in React Slate no longer marked when focus changes to React Select

我不知道這是一個常見問題還是我們的錯誤,但也許有人有一個想法:我們正在構建一個帶有 react 和 slate 的 HTML 編輯器。 用戶可以 select 一個文本框然后更改屬性。 這適用於簡單的按鈕。 但是,當我打開一個下拉列表(react-select)以更改字體大小時,所選文本不再被標記。 Slate 保留選擇以使更改生效,但這樣的用戶體驗很糟糕。

恕我直言,這應該是保持文本標記的石板功能,但也許這是我需要自己應用的東西。

一些片段,不知道他們是否有幫助:

Editor 組件初始化字體樣式插件並負責序列化。

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));
 };

這是與其他插件一起初始化的字體大小插件,將顯示在工具欄中:

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}
      />;
    }
  };
}

我目前的解決方案是在 select 打開后立即關注 slate,然后告訴 select 打開,但這感覺很糟糕並且有缺點(見下文)

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}

我必須使用超時來超出反應生命周期,並且我必須添加一個額外的標志,因為失去對 select 組件的關注也會關閉它。 就像我說的那樣有缺點: - 在焦點切換期間所選文本有點閃爍 - select 中的下拉框顏色錯誤(明顯沒有聚焦) - 切換到另一個下拉框(如對齊)不會關閉另一個,因為已經沒有焦點:

附加信息:我們必須在 0.47 版本中使用 slate 和slate-react ,因為我們需要的slate-html-serializer不支持更高版本。 也許這已經在更高版本中解決了?

所以,我有一個有點工作的版本,但我更喜歡一個解決方案,其中 slate 可以“本地”處理選擇,而無需我處理焦點。 我認為應該有可能沒有選定的文本flickering和關閉 colors。

由於打開了下拉菜單,當您將注意力移出編輯器時,Slate 不會保留選擇。 現在有了按鈕,它就不同了,因為它重新應用了選擇

由於您現在必須手動應用和獲取選擇,因此當您嘗試從 select 打開菜單時,將編輯器選擇存儲在 state 中。 打開菜單后,使用Transforms.setSelection重新應用選擇並獲取可以存儲在 state 中的 fontSize 以在下拉列表中顯示焦點值

現在,一旦應用更改,您需要再次應用選擇

您可以遵循此 PR中使用的概念

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}
/>

另請查看有關焦點和選擇的github 問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM