筑基-React 实现一个全选反选功能

1,513 阅读3分钟
需求场景描述:
一个input A 
一个input 列表B 

现在要实现的就是当操作单个input A时
除了自己可以选中和非选中外,还要关联Input 列表B的全部选中和不选中

当然 操作input 列表B中的任意一项,也要关联单个Input A

我们来实现程序

App.js 引入模块

这路由还没引入
还是修改当前页面
import Input2 from './views/Input2';

<Input2/>

新建页面 Input2

vi src/views/Input2/index.jsx
第一步把html 结构实现了
<React.Fragment>
    <h3>全选</h3>
    <label>
        <input type="checkbox"
        />
        全选
    </label>
    <ul>
        <li>
            <label>
                <input type="checkbox"
                />
                内容一
            </label>
         </li>
         <li>
            <label>
                <input type="checkbox"
                />
                内容二
            </label>
         </li>
         <li>
            <label>
                <input type="checkbox"
                />
                内容三
            </label>
         </li>
         
    </ul>
</React.Fragment>

ok 结构完了后,
回想一下我们需求
先定义一下数据结构

多个是数组 单个我们之前也提到过不要直接在state 根上
增加一个隶属关系
所以就有如下结构

this.state = {
    bTrue:{
        allSel:false,
    },
    mvc:[
        {lang:'angular',checked:false},
        {lang:'vue',checked:false},
        {lang:'ember',checked:false},
        {lang:'react',checked:false},
        {lang:'omi',checked:false},
    ]
}
数据结构已定义,那我们把ul 内容给循环一下
<ul>{this.listFn(mvc)}</ul>

 listFn(data){
    return data.map((item,index)=>(
        <li key={index}>
            <label>
                <input type="checkbox"
                />
                {item.lang}
            </label>
        </li>
    ))
}
ok 
这样结构就有了

继续我们给单个input 增加事件以及checked
let {bTrue,mvc} = this.state;

<input type="checkbox"
    name='allSel'
    checked={bTrue.allSel}
    onChange={(e)=>{this.allSelFn(e)}}
    />
首页这个事件没问题吧
checked 也没问题吧
name 为字段内容

以此把多个input 内容也改一下

<li key={index}>
    <label>
        <input type="checkbox"
        name='allSel'
        checked={item.checked}
        onChange={(e)=>{this._allSelFn(e,index)}}
        />
        {item.lang}
    </label>
</li>
为了能区分操作的是哪个事件所以我们把下标传过去了。
ok 这样我们就开始 写函数了

// 单个input
allSelFn(e){
    //首先把target 中的 name 和 checked 解构出来
     let { name , checked } = e.target;
     //接着把state 解构出来
     let {bTrue,mvc} = this.state;
     //第一步让当前可以选中不选中
     //bTrue.allSel = checked;
     //考虑allSel扩展性升级改造成 name 就是我们定义的字段值
     bTrue[name] = checked;
     this.setState({bTrue})
     这样是不是单个input 
}
那如何要操作单个关系多个是不就需要一个循环了
升级一下
// 单个input
allSelFn(e){
    //首先把target 中的 name 和 checked 解构出来
     let { name , checked } = e.target;
     //接着把state 解构出来
     let {bTrue,mvc} = this.state;
     //第一步让当前可以选中不选中
     //bTrue.allSel = checked;
     //考虑allSel扩展性升级改造成 name 就是我们定义的字段值
    /* bTrue[name] = checked;
     如果单个是选中
     ?
     那么都选中
     :
     都不选中
     我们用到forEach
     面试题一般会问forEach 和map 区别,分别有几个参数 ,分别是什么
     */
      mvc.forEach((item, i) => {
            if(checked){
                item.checked = true;
            }else {
                item.checked = false;
            }
     });
     //两个值都setState
     this.setState({bTrue,mvc})
}
此,单个input 可以完全控制多个input 全选或不选
// 多个input
_allSelFn(e,index){
    //和上面单个一个解构出来
        let { name , checked } = e.target;
        let {bTrue,mvc} = this.state;
        第按上面的同样实现本身切换
        //mvc[0].checked = checked;
        //mvc[1].checked = checked;
        mvc[index].checked = checked;
       
        this.setState({mvc})
        这样每一项都可以全选中和不选中了
    }
    继续关联
  _allSelFn(e,index){
    //和上面单个一个解构出来
        let { name , checked } = e.target;
        let {bTrue,mvc} = this.state;
        第按上面的同样实现本身切换
        //mvc[0].checked = checked;
        //mvc[1].checked = checked;
        mvc[index].checked = checked;
       /*关联是不是就是
       bTrue[name] = ture;
       或
       bTrue[name] = false;
       想办法把ture false 变成一个变量
          数据方法中哪个全部成立或有一个不成立
          有的直接想到every 
          有的想到了for 中break
          我们直接用every 了
       */
        let bT = mvc.every((item,index)=>{
            return item.checked;
        })
        bTrue[name] = bT;
        //同样setState
        this.setState({bTrue,mvc})
        这样每一项都可以全选中和不选中了
    }
    这样一个全选和反选的就实现了,

完整代码

src/views/Input2/index.jsx

import React, { Component } from 'react';

class View extends Component {
    constructor(props){
        super(props);
        this.state = {
            bTrue:{
                allSel:false,
            },
            mvc:[
                {lang:'angular',checked:false},
                {lang:'vue',checked:false},
                {lang:'ember',checked:false},
                {lang:'react',checked:false},
                {lang:'omi',checked:false},
            ]
        }
    }
    // 单个input
    allSelFn(e){
        let { name , checked } = e.target;
        let {bTrue,mvc} = this.state;
        bTrue[name] = checked;
        mvc.forEach((item, i) => {
            if(checked){
                item.checked = true;
            }else {
                item.checked = false;
            }
        });
        this.setState({bTrue,mvc})
    }
    // 多个input
    _allSelFn(e,index){
        let { name , checked } = e.target;
        let {bTrue,mvc} = this.state;
        mvc[index].checked = checked;
        let bT = mvc.every((item,index)=>{
            return item.checked;
        })
        bTrue[name] = bT;
        this.setState({bTrue,mvc})
    }
    listFn(data){
        return data.map((item,index)=>(
            <li key={index}>
<label>
    <input type="checkbox"
    name='allSel'
    checked={item.checked}
    onChange={(e)=>{this._allSelFn(e,index)}}
    />
    {item.lang}
</label>
            </li>
        ))
    }
    render(){
        let {bTrue,mvc} = this.state;
        return(
<React.Fragment>
    <h3>全选</h3>
    <label>
        <input type="checkbox"
        name='allSel'
        checked={bTrue.allSel}
        onChange={(e)=>{this.allSelFn(e)}}
        />
        全选
    </label>
    <ul>{this.listFn(mvc)}</ul>
</React.Fragment>
        )
    }

}


export default View;