千峰React:案例一
做这个案例捏
因为需要用到样式,所以创建一个样式文件:
//29_实战.module.css
.active{
text-decoration:line-through
}
然后创建jsx文件,修改main文件:导入Todos,写入Todos组件
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import Todos from './28_实战'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Todos />
</StrictMode>
)
Todos.jsx文件需要先写渲染组件的基本结构:
function Todos() {
return (
<div>
</div>
)
}
export default Todos
观察案例,首先需要一个添加任务的文本框、点击添加任务的按钮、用value使用可控组件改变value值,记得加onChange:
return (
<div>
<input type='text' value={msg} onChange={handleChange} />
<button onClick={handleClick}>点击添加任务</button>
</div>
)
改变value的值、使用Immer整合更改
const [msg, setMsg] = useState('')
const [list, setList] = useImmer([])
const handleChange = (e) => {
setMsg(e.target.value)
}
const handleClick = () => {
setList((draft) => {
draft.unshift({ id: list.length, task: msg, checked: false })
})
setMsg('')
}
复选框功能:
const unCompleteList = list.filter((item) => !item.checked)
const completeList = list.filter((item) => item.checked)
const handleChecked = (e, id) => {
setList((draft) => {
draft.find((item) => item.id === id).checked = e.target.checked //更改对应id的数据的复选框状态
})
}
return(
<div>
{/* {未完成的列表} */}
<CompleteList
title={<h2>未完成的任务:{unCompleteList.length}个</h2>}
handleChecked={handleChecked}
list={unCompleteList}
/>
{/* {已完成的列表} */}
<CompleteList
title={<h2>已完成的任务:{completeList.length}个</h2>}
list={completeList}
handleChecked={handleChecked}
/>
</div>)
列表的组件
function CompleteList({
title = '',
list = [],
handleChecked = function () {},
}) {
return (
<>
{title}
<ul>
{list.map((item) => {
return (
<li
key={item.id}
className={classNames({ [style.active]: item.checked })}
>
<input
type='checkbox'
checked={item.checked}
onChange={(e) => handleChecked(e, item.id)}
/>
{item.task}
</li>
)
})}
</ul>
</>
)
}
整体的代码
import { func } from 'prop-types'
import { useState } from 'react'
import { useImmer } from 'use-immer'
import classNames from 'classnames'
import style from './29_实战.module.css'
function CompleteList({
title = '',
list = [],
handleChecked = function () {},
}) {
return (
<>
{title}
<ul>
{list.map((item) => {
return (
<li
key={item.id}
className={classNames({ [style.active]: item.checked })}
>
<input
type='checkbox'
checked={item.checked}
onChange={(e) => handleChecked(e, item.id)}
/>
{item.task}
</li>
)
})}
</ul>
</>
)
}
function Todos() {
const [msg, setMsg] = useState('')
const [list, setList] = useImmer([])
const unCompleteList = list.filter((item) => !item.checked)
const completeList = list.filter((item) => item.checked)
const handleChange = (e) => {
setMsg(e.target.value)
}
const handleClick = () => {
setList((draft) => {
draft.unshift({ id: list.length, task: msg, checked: false })
})
setMsg('')
}
const handleChecked = (e, id) => {
setList((draft) => {
draft.find((item) => item.id === id).checked = e.target.checked //更改对应id的数据的复选框状态
})
}
return (
<div>
<input type='text' value={msg} onChange={handleChange} />
<button onClick={handleClick}>点击添加任务</button>
{/* {未完成的列表} */}
<CompleteList
title={<h2>未完成的任务:{unCompleteList.length}个</h2>}
handleChecked={handleChecked}
list={unCompleteList}
/>
{/* {已完成的列表} */}
<CompleteList
title={<h2>已完成的任务:{completeList.length}个</h2>}
list={completeList}
handleChecked={handleChecked}
/>
</div>
)
}
export default Todos
效果: