受控组件与非受控组件
1. 区别
通过props控制的组件称为受控组件; 而通过state控制的组件称为非受控组件。也就是说存在父子组件通信的就是受控组件。
2. 受控组件
React表单内置了受控组件的行为:
- value + onChange
- 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状态值发生改变才会显示到输入框中。
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
执行结果:
3. 组件实操
实现如图所示的任务列表:
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
运行效果: