如何不使用Hooks实现ShadCN复选框的全选/取消全选功能
ShadCN 无Hook实现全选复选框方案
核心思路
借助HTML表单的原生DOM能力,结合ShadCN Checkbox组件的checked和onChange原生参数,直接通过DOM API管理复选框状态,完全不需要React的useState或useReducer。
实现代码
import { Checkbox } from "@/components/ui/checkbox" export function SelectAllDemo() { // 全选框变更事件:批量设置所有子复选框状态 const handleSelectAllToggle = (e: React.ChangeEvent<HTMLInputElement>) => { const form = e.target.form if (!form) return // 取出所有name为"list-item"的复选框 const itemCheckboxes = form.elements.namedItem("list-item") as HTMLInputElement[] | HTMLInputElement const checkboxes = Array.isArray(itemCheckboxes) ? itemCheckboxes : [itemCheckboxes] checkboxes.forEach(box => box.checked = e.target.checked) } // 单个复选框变更事件:同步更新全选框状态 const handleItemToggle = (e: React.ChangeEvent<HTMLInputElement>) => { const form = e.target.form if (!form) return const itemCheckboxes = form.elements.namedItem("list-item") as HTMLInputElement[] | HTMLInputElement const checkboxes = Array.isArray(itemCheckboxes) ? itemCheckboxes : [itemCheckboxes] const selectAllBox = form.elements.namedItem("select-all") as HTMLInputElement // 判断所有子复选框是否全选 const isAllChecked = checkboxes.every(box => box.checked) selectAllBox.checked = isAllChecked } return ( <form className="space-y-4"> {/* 全选复选框 */} <div className="flex items-center gap-2"> <Checkbox id="select-all" name="select-all" onChange={handleSelectAllToggle} /> <label htmlFor="select-all" className="cursor-pointer">全选</label> </div> {/* 列表项复选框组 */} <div className="space-y-2"> {["项目A", "项目B", "项目C", "项目D"].map((item, idx) => ( <div key={idx} className="flex items-center gap-2"> <Checkbox id={`item-${idx}`} name="list-item" onChange={handleItemToggle} /> <label htmlFor={`item-${idx}`} className="cursor-pointer">{item}</label> </div> ))} </div> </form> ) }
方案说明
- 依赖HTML表单的
form属性关联所有复选框,无需React状态存储,直接操作DOM元素的checked属性 - 全选框的
onChange事件触发时,通过表单的elements集合批量修改子复选框状态 - 单个复选框的
onChange事件触发时,遍历所有子复选框判断选中状态,同步更新全选框的checked值 - 完全基于ShadCN组件的原生参数和浏览器DOM API实现,没有引入额外状态管理逻辑
内容的提问来源于stack exchange,提问作者Roronoa Zoro
相关产品推荐
相关产品推荐

