Skip to content

受控组件与非受控组件

1. 区别

通过props控制的组件称为受控组件; 而通过state控制的组件称为非受控组件。也就是说存在父子组件通信的就是受控组件。

2. 受控组件

React表单内置了受控组件的行为:

  1. value + onChange
  2. checked + onChange
jsx
import { useState } from 'react'

function App() {
  const [value, setValue] = useState('')
  const handleClick = (e) => {
    console.log(e.target.value)
    // setValue(e.target.value)
  }
  return (
    <div>
      hello App
      {/*input并不是普通的html标签,而是React封装的组件*/}
      <input value={value} onChange={handleClick} />
    </div>
  )
}
export default App

所谓受控组件,可见输入并没有显示到输入框中,因为input子组件的value受到React控制,需要value状态值发生改变才会显示到输入框中。 Alt text

jsx
import { useState } from 'react'

function App() {
  const [checked, setChecked] = useState(false)
  const handleClick = (e) => {
    console.log(e.target.checked)
    setChecked(e.target.checked)
  }
  return (
    <div>
      hello App
      <input type="checkbox" checked={checked} onChange={handleClick} />
    </div>
  )
}
export default App

执行结果:
Alt text

3. 组件实操

实现如图所示的任务列表:
Alt text

3.1 代码实现

jsx
import { useState } from 'react'

function App() {
  const [taskList, setTaskList] = useState([])
  const handleAdd = (msg) => {
    const newTaskList = [...taskList, {id: taskList.length + 1, name: msg, checked: false}]
    console.log(newTaskList)
    setTaskList(newTaskList)
  }
  const [msg, setMsg] = useState('')
  const handleChange = (e) => {
    setMsg(e.target.value)
  }
  const handleChecked = (e, taskId) => {
    const newTaskList = [...taskList]
    newTaskList.forEach((task) => {
      if(task.id === taskId){
        task.checked = e.target.checked
      }
    })
    setTaskList(newTaskList)
  }
  const unDoList = taskList.filter((task) => !task.checked)
  const doneList = taskList.filter((task) => task.checked)
  console.log(doneList)
  return (
    <div>
      hello App
      <input type="text" value={msg} onChange={handleChange} />
      <button type="button" onClick={(e) => handleAdd(msg)}>添加任务</button>
      <ul>
        {
          unDoList.map((task) =>
            <li key={task.id}>
              <input type="checkbox" checked={task.checked} onChange={(e) => handleChecked(e, task.id)} />
              {task.name}
            </li>
          )
        }
      </ul>
      <div>已完成任务:</div>
      <ul>
        {
          doneList.map((task) =>
              <li key={task.id}>
                <input type="checkbox" checked={task.checked} onChange={(e) => handleChecked(e, task.id)} />
                {task.name}
              </li>
          )
        }
      </ul>
    </div>
  )
}

export default App

运行效果:
Alt text