如何根据文本选择更新下拉列表中的值

How to update value in dropdown based on text selection

我正在开发一个 React-based Google 文档克隆作为副项目。我正在使用 TipTap 作为基础。

我想尝试模仿 Google 文档中的功能,其中 select 字段将根据用户 select 的任何文本更新为适当的值(例如, “标题 1”会出现在 select 字段(如果用户使用

样式突出显示文本)。

这是我想模仿的功能的小视频:https://i.gyazo.com/18cc57f0285c8c5cd80d5dd6051f0ee7.mp4

这是我目前使用用于 select 字段的 React Hook 的代码:

const [font, setFont] = useState('sans-serif')
const handleFontChange = (e) => {
   setFont(e.target.value)
   editor.chain().focus().setFontFamily(e.target.value).run()
}

return (
   <select value={font} onChange={handleFontChange}>
    {fontFamilies.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
   </select>
) 

我试图全神贯注于 React Hooks 和选择 API,但我被卡住了。这在 Javascript/React 中完全可行吗?

编辑:

我从 Tiptap 的 API 中找到了一个函数,它完全符合我的要求。我想现在的问题是如何将该值更新为 select?这是我的新代码:

const font = [
     { value: 'sans-serif', label: 'Sans-serif' }, ...
   ]

const [selectedFont, setSelectedFont] = useState([])

const handleFontChange = (obj) => {
    setSelectedFont(obj)
    editor.chain().focus().setFontFamily(obj.value).run()
    console.log(editor.isActive('textStyle', {fontFamily: selectedFont.value})) // prints true if the user clicked on text with the property active, otherwise prints false
}

return (
    <Select
       name="fontFamily"
       options={font}
       isClearable="true"
       isSearchable="true"
       value={selectedFont}
       onChange={(option) => handleFontChange(option)}
    />
)

感觉解决方案很简单,但我只是想多了。

所以我终于想出了该怎么做。我需要传递一个遍历数组的值函数:

const fontList = [
    { label: 'Sans-serif', value: 'sans-serif' },
    ...
]

<Select
    name="fontFamily"
    placeholder="Select font..."
    value={
      editor.isActive('textStyle', {fontFamily: font}) ? (
        selectedFont.find(index => fontList[index])
      ) : ''
    }
    options={fontList}
    onChange={({value: fontSel}) => {
      setFont(fontSel)
      editor.chain().focus().setFontFamily(fontSel).run()
    }}
  />

我只用了整整一个星期的时间就把头发扯掉了……很高兴终于完成了。

除此之外,我还能够在 Vue 中对带有下拉菜单的 select 标题执行以下操作。

<select
    :value="editor.isActive('heading') ? editor.getAttributes('heading').level : 0"
    @input="setSelectedHeading"
  >
    <option
      v-for="heading in headings"
      :key="heading.value"
      :label="heading.label"
      :value="heading.value"
    />
</select>

headings: [
    { value: 0, label: 'Normal text' },
    { value: 1, label: 'Heading 1' },
    { value: 2, label: 'Heading 2' },
    { value: 3, label: 'Heading 3' },
    { value: 4, label: 'Heading 4' },
    { value: 5, label: 'Heading 5' },
    { value: 6, label: 'Heading 6' }
  ]

setSelectedHeading (selected) {
  if (selected === 0) {
    const selectedLevel = this.editor.getAttributes('heading').level
    return this.editor.chain().focus().toggleHeading({ level: selectedLevel }).run()
  }
  return this.editor.chain().focus().setHeading({ level: selected }).run()
}