登录 主页

React select

2024-06-20 03:49PM

参考:https://fr.react.dev/reference/react-dom/components/select#select

React select

浏览器的内置<select>通过使用组件,可以呈现包含option的选择框

<select>
  <option value="someOption">Some option</option>
  <option value="otherOption">Other option</option>
</select>

1.用法

1)显示带有选项的选择框

2)为选择框提供label属性

3)提供选项初始值

4)支持多选

5)提交表单时读取选择框的值

6)使用State控制选择框

2.props

<select>支持所有常见的props element

2.1你可以通过传递value属性以控制选择框:

  • value:一个字符串(如果指定multiple={true},那么value也可以是一个字符串数组)。当某一个选项(option)被选中时,value为其对应的值,每个字符串值都与嵌套<select>内的<option>value属性想匹配

当你传递value时,必须同时传递一个onChange处理函数,用于更新传递的值。

2.2如果<select>是非受控组件,那么你应该传递defaultValue参数:

  • defaultValue:一个字符串(如果指定了multiple={true},那么defaultValue也可以是一个字符串数组)。defaultValue表示初始选中的选项(option)

以下<select>属性均可用于受控与非受控选择框组件:

1)autoComplete:字符串,用于指定可能的自动完成行为之一。

2)autoFocus:布尔值。如果为true,React将挂载时聚焦该元素。

3)children<select>接受<option><optgroup><datalist>组件作为子元素。只要最终渲染的是其中之一,你就可以传递自己的组件。如果最终渲染的是<option>,则每个<option>都必须具有value属性。

4)disable:布尔值,如果为true,选择框将不会交互并展示为暗淡状态(dimmed)。

5)form:字符串,表示选择框所属的<form>id。如果未指定,则为最近的父表单。

6)multiple:布尔值。如果为true,则浏览器允许多选。

7)name:字符串,用于指定此选择框的名称,该名称将在提交表单时一起提交。

8)onChange:一个Event处理函数,其对于受控选择框时必需的。当用户选择不同的选择项时立即触发。此行为类似于浏览器input事件。

9)onChangeCapture:与onChange类似,但是是在捕获阶段触发的。

10)onInput:一个Event处理函数。当用户更改值时立即触发。由于历史原因,在React习惯于使用onChange,工作方式类似。

11)onInputCapture:与onInput类似,但是是在捕获阶段触发的。

12)onInvalid:一个Event处理函数。如果输入的内容在表单提交时未通过验证,则会触发此事件。与内置的invalid事件不同,React的onInvalid事件可以进行冒泡。

13)onInvalidCapture:与onInvalid类似,但是是在捕获阶段触发的。

14)require:布尔值。如果为true,则必须提供值才能提交表单。

15)size:数字。当指定multiple={true}时可选,表示同时可见的项目数。

注意:

1)与HTML不同,在<option>上传递selected属性将不受支持,你应该使用<select defaultValue>处理非受控选择框;而使用<select value>处理受控选择框

2)如果选择狂收到value属性,它将被视为受控组件

3)选择框不能同时受控与非受控

4)选择框在其生命周期内无法在受控与非受控之间切换

5)每个受控选择框都需要onChange事件处理程序,它会同步更新其后备值。

3.用法:

3.1 显示带有选项的选择框

渲染一个包含一系列<option>组件的<select>,来展示一个选择框,并给每个<option>都设置一个value属性,表示要与表单一起提交数据。

src/pages/select.jsx 文件的代码内容如下:

import React from 'react';

export default function FruitPicker() {
  return (
    <label>
      选择一个水果:
      <select name="精选水果">
        <option value="苹果">苹果</option>
        <option value="香蕉">香蕉</option>
        <option value="桃子">桃子</option>
      </select>
    </label>
  );
}

页面展示情况如下:

没有点击下拉单:

点击下拉单选择其他水果:

3.2 为选择框提供label属性

一般而言,应该将每个<select>标签都放在<label>标签内,表示此标签与该选择框相关联。当用户单击标签是,浏览器将会自动读取下拉单,这对于用户访问也非常重要:当用户点击下拉单时,浏览器将显示标题

如果无法将<select>放置在<label>内,请通过将相同的ID传递给<select id>与<label htmlFor>来将他们关联起来。为了避免一个组件的多个实例之间的冲突,使用useId生成这样的ID

src/pages/selectLabel.jsx 文件的代码内容如下:

import React, { useId } from 'react';

export default function Form() {
  const vegetableSelectId = useId();
  return (
    <>
      <label>
        请选择一种水果:
        <select name="精选水果">
          <option value="桃子">桃子</option>
          <option value="芒果">芒果</option>
          <option value="西瓜">西瓜</option>
        </select>
      </label>
      <hr />
      <label htmlFor={vegetableSelectId}>
        请选择一种蔬菜:
      </label>
      <select id={vegetableSelectId} name="精选蔬菜">
        <option value="土豆">土豆</option>
        <option value="生菜">生菜</option>
        <option value="玉米">玉米</option>
      </select>
    </>
  );
}

页面展示情况如下:

没有点击下拉单:

点击下拉单选择其他水果和蔬菜:

 

3.3 提供选项初始值

在默认情况下,浏览器会把select第一个<option>作为初始值。你可以将其他<option>的value作为defaultValue传递给<select>组件

src/pages/selectDefaultValue.jsx 文件的代码内容如下:

import React from 'react';

export default function FruitPickerDefault() {
  return (
    <label>
      选择一个水果:
      <select name="精选水果" defaultValue="菠萝蜜">
        <option value="百香果">百香果</option>
        <option value="哈密瓜">哈密瓜</option>
        <option value="菠萝蜜">菠萝蜜</option>
      </select>
    </label>
  );
}

页面展示情况如下:

没有点击下拉单:

点击下拉单选择其他水果:

3.4 支持多选

你可以通过在<select>指定multiple={true}设置多选。但如果这样做,那么你也应该向defaultValue传递一个字符串,以指定选中初始值

src/pages/selectMultiple.jsx 文件的代码内容如下:

import React from 'react';

export default function FruitPickerMultiple() {
  return (
    <>
      <label>
        选择一些水果:
      </label><br/>
      <select
        name="精选水果"
        defaultValue={['榴莲', '西柚']}
        multiple={true}
      >
        <option value="柠檬">柠檬</option>
        <option value="榴莲">榴莲</option>
        <option value="西柚">西柚</option>
      </select>
    </>
  );
}

页面展示情况如下:

3.5 提交表单时读取选择框的值

在选择框周围添加一个包含<button type="submit">按钮的<form>组件,这将调用<form onSubmit>时间处理程序。默认情况下,浏览器将向当前URL发送表单数据并刷新页面。你可以通过哦调用e.preventDefault()取消此默认行为,并使用new

FormData(e.target)读取表单数据。

src/pages/editPost.jsx 文件的代码内容如下:

import React from 'react';

export default function EditPost() {
  function handleSubmit(e) {
    // 阻止浏览器重新加载页面
    e.preventDefault();
    // 读取表单数据
    const form = e.target;
    const formData = new FormData(form);
    // 你可以直接将 formData 作为fetch的请求body
    fetch('/some-api', { method: form.method, body: formData});
    // 你可以像浏览器默认的一样,将其转换为URL
    console.log(new URLSearchParams(formData).toString());
    // 也可以使用普通的对象
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson); // (!)这并不包含多选值
    // 或者你可以使用name与value相匹配的数组对
    console.log([...formData.entries()]);
  }
  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        选择你喜欢的水果:
        <select name="精选水果" defaultValue="橘子">
          <option value="苹果">苹果</option>
          <option value="香蕉">香蕉</option>
          <option value="橘子">橘子</option>
        </select>
      </label>
      <hr/>
      <label>
        选择你所有喜欢的蔬菜:
        <select name="精选蔬菜" multiple={true} value={['玉米', '番茄']}>
          <option value="黄瓜">黄瓜</option>
          <option value="玉米">玉米</option>
          <option value="番茄">番茄</option>
        </select>
      </label>
      <hr/>
      <button type="reset">重置</button>
      <button type="submit">提交</button>
    </form>
  );
}

页面展示情况如下:

没有点击下拉单:

点击下拉单之后,查看控制台日志:

给<select>添加name属性,例如:<select name="selectedFruit"/>指定的name将作为表单数据中的一个键,例如{ selectedFruit: "orange"}

如果使用了<select multiple={true}>那么你从表单中读取的FormData将会将每个选项作为单独name与value相匹配的键值对包含在内。仔细查看上面示例中的控制台日志

注意:默认情况下,<form>内的任何<button>都可以提交表单。如果你有自定义Button组件,请考虑使用<button type="button">而不是<button>,如果你想要明确指定提交表单的按钮,请使用<button type="submit">

3.6 使用state控制选择框

像<select />这样的选择框是非受控的。即使你传递了初始值,比如<select defaultValue="orange" />,你的JSX也只是指定了初始值,而非当前时刻的值

如果要渲染一个受控选择框,请传递value属性给选择框。通常,你可以通过声明一个state来控制选择框:

src/pages/selectState.jsx 文件的代码内容如下:

import React, { useState } from 'react';

export default function SelectState() {
  // 声明一个state变量
  const [selectedFruit, setSelectedFruit] = useState('香蕉')

  return (
    <select
      // 强制选择框的值与state相匹配
      value={selectedFruit}
      // 并在每次改变(change)时更新state
      onChange={(e) => setSelectedFruit(e.target.value)}
    >
      <option value="苹果">苹果</option>
      <option value="香蕉">香蕉</option>
      <option value="梨">梨</option>
    </select>
  );
}

页面展示情况如下:

点击下拉单选择其他水果:

这可以帮助你在每次选择时都触发重新渲染

src/pages/selectFruitState.jsx 文件的代码内容如下:

import React, { useState } from 'react';

export default function SelectFruitState() {
  const [selectedFruit, setSelectedFruit] = useState('橘子');
  const [selectedVegs, setSelectedVegs] = useState(['豆角', '冬瓜']);
  return (
    <>
      <label>
        选择一个水果:
        <select
          value={selectedFruit}
          onChange={e => setSelectedFruit(e.target.value)}
        >
          <option value="苹果">苹果</option>
          <option value="香蕉">香蕉</option>
          <option value="橘子">橘子</option>
        </select>
      </label>
      <hr />
      <label>
        选择所有你喜欢的蔬菜:
        <select
          multiple={true}
          value={selectedVegs}
          onChange={e => {
            const options = [...e.target.selectedOptions];
            const values = options.map(option => option.value);
            setSelectedVegs(values);
          }}
        >
          <option value="豆角">豆角</option>
          <option value="菠菜">菠菜</option>
          <option value="冬瓜">冬瓜</option>
        </select>
      </label>
      <hr />
      <p>你最喜欢的水果是:{selectedFruit}</p>
      <p>你最喜欢的蔬菜是:{selectedVegs.join(',')}</p>
    </>
  );
}

页面展示情况如下:

点击下拉单选择其他水果和蔬菜:

注意:如果传递了value但没有传递onChange,那么将无法选择选项。当你通过传递value来控制选择框是,你需要保证选择框始终具有你传递的值。因此,如果你将一个state作为value传递,但在onChange事件处理程序中忘记同步更新该状态变量,

React将在每次按键后将选择框恢复到你指定的value。

与HTML不同,在<option>上传递selected属性将不受支持。

返回>>

登录

请登录后再发表评论。

评论列表:

目前还没有人发表评论