由一个react tree点击各层高亮状态显示想到的

今天有这样一个需求:

注意:每次点击每个层级。点击的项高亮。层级之间相互不干扰。

最初的实现思路:

设置一个currentIndex。点击该项的时候通过currentIndex==item对应的index就ok了。但是问题是层级很多呢?那需要在useState中维护多个index。一一对应、这样非常不科学。

后来有了个思路:

在useState中定义一个数组 ids= [a,b,c,d]分别表示各个层级的当前点击时的项目id。每次点击的时候更改这个数组对应的id。而我们高亮的判断条件就是当前点击项的id是否在我们记录跟踪的数组ids中。如果在则给其添加高亮样式。

代码如下:

定义数据


        const [ids,setIds]=useState([])   //该数组记录每次点击时各个层级点击的当前项id
        const [arr1,setArr1]=useState(oneList)  //第一层数据
        const [arr2,setArr2]=useState(tList)     //第二层数据
        const [arr3,setArr3]=useState(treList)   //第三层数据

dom结构

  <div className="table-wrap">
                        <div className="attr-head">
                            <div className="table-head">一级类目</div>
                            <div className="tree-list">
                                {arr1.map(item=>{
                                    return (
                                        <div  className={classnames("list-item",{"active":ids.includes(item.id)})} onClick={()=>handlerClickItem("1",item)}>
                                            <div className="list-item-name">{item.name}</div>
                                            <div className="list-item-icon">{item.children?<Iconfont type="icon-xiangyou"></Iconfont>:''}</div>
                                        </div>
                                    )
                                })}
                            </div>
                        </div>
                        <div className="value-head">
                            <div className="table-head">二级类目</div>
                            <div className="tree-list">
                            {arr2.map(item=>{
                                    return (
                                        <div onClick={()=>handlerClickItem("2",item)} className={classnames("list-item",{"active":ids.includes(item.id)})}>
                                            <div className="list-item-name">{item.name}</div>
                                            <div className="list-item-icon">{item.children?<Iconfont type="icon-xiangyou"></Iconfont>:''}</div>
                                        </div>
                                    )
                                })}
                            </div>
                        </div>
                        <div className="catagory-head">
                            <div className="table-head catagory-table-head">三级类目</div>
                            <div className="tree-list">
                            {arr3.map(item=>{
                                    return (
                                        <div onClick={()=>handlerClickItem("3",item)}  className={classnames("list-item",{"active":ids.includes(item.id)})}>
                                            <div className="list-item-name">{item.name}</div>
                                            <div className="list-item-icon">{item.children?<Iconfont type="icon-xiangyou"></Iconfont>:''}</div>
                                        </div>
                                    )
                                })}
                            </div>
                        </div>
                    </div>

注意:我们在点击事件里传入了一个参数用来表示当前点击的是那个层级。好对应更改ids

逻辑处理:

const handlerClickItem=(type,item)=>{
            let newIds=JSON.parse(JSON.stringify(ids));
            switch(type){
                case "1":
                    newIds[0]=item.id;
                    break;
                case "2":
                    newIds[1]=item.id;
                    break;
                case "3":
                    newIds[0]=item.id;
                    break;
                default:
            }

            setIds(newIds)
        }

注意这里我们做了一个深拷贝ids。对于useState的更新。如果是同一个引用地址。则无法更新。通过深拷贝。我们得到一个全新的引用地址,原因就在于React组件的更新机制对state只进行浅对比,也就是更新某个复杂类型数据时只要它的引用地址没变,那就不会重新渲染组件

坦白说。react的更新机制,的确没有vue的双向绑定来的直接简单。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 useState 来存储当前选择的颜色和尺码,然后在渲染时根据当前选择状态来添加高亮样式。 具体代码如下: ```javascript import React, { useState } from 'react'; function ColorAndSizeSelector() { const [selectedColor, setSelectedColor] = useState(null); const [selectedSize, setSelectedSize] = useState(null); const handleColorSelect = (color) => { setSelectedColor(color); } const handleSizeSelect = (size) => { setSelectedSize(size); } return ( <div> <h2>Select Color:</h2> <button onClick={() => handleColorSelect('red')} className={selectedColor === 'red' ? 'selected' : ''}>Red</button> <button onClick={() => handleColorSelect('green')} className={selectedColor === 'green' ? 'selected' : ''}>Green</button> <button onClick={() => handleColorSelect('blue')} className={selectedColor === 'blue' ? 'selected' : ''}>Blue</button> <h2>Select Size:</h2> <button onClick={() => handleSizeSelect('small')} className={selectedSize === 'small' ? 'selected' : ''}>Small</button> <button onClick={() => handleSizeSelect('medium')} className={selectedSize === 'medium' ? 'selected' : ''}>Medium</button> <button onClick={() => handleSizeSelect('large')} className={selectedSize === 'large' ? 'selected' : ''}>Large</button> </div> ); } export default ColorAndSizeSelector; ``` 在上述代码中,我们使用了 useState 来分别存储当前选择的颜色和尺码状态。handleColorSelect 和 handleSizeSelect 两个函数分别用来更新对应的状态。 在渲染时,我们通过判断当前选择状态来添加 selected 类名,从而实现高亮效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值