11

Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比

 3 years ago
source link: https://www.daozhao.com/9987.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

批量选择、全选、反选这些功能使用频率还是很高的。

Vue

在使用Vue的时候是很容易实现的,我们以下列数据格式为例:

const dataList = [{
    id: 1,
    label: '第一个',
}, {
    id: 2,
    label: '第二个',
}, {
    id: 3,
    label: '第三个',
}]

批量选择在Vue中我们一般喜欢格外增加一个属性来标记是否已被选择,可以在每条数据item被勾选时,比如第一条的话就是 Vue.set(dataList[0], 'checked', !!dataList[0].checked) ; 选中条数

const count = dataList.filter(item => item.checked).length;

全选

dataList.forEach(item => Vue.set(item, 'checked', true));

反选

dataList.forEach(item => Vue.set(item, 'checked', false));

React实现一

在React中怎么实现呢? 如果只是简单按照同样的方式的话,你就会失望了。

因为React不是跟Vue采用观察者模式来处理数据更新后的视图变更逻辑的,它更多是需要进行全量更新数据的。

对应数组而言,是引用类型数据,尽管里面某个元素发生了变更,但是对于整体数组的引用地址并未变更,React也就无法进行视图更新。

我们以使用 useReducer 为例

import React, { useReducer, useMemo } from 'react';

const [state, dispatch] = useReducer({
    dataList: [],
}, (state, reducer) => {
    switch(reducer.type) {
     case 'update':
         return {
            ...state,
            ...reducer.payload
         }
     case default:
         return state;
    } 

})

批量选择在React中我们也可以选择格外增加一个属性来标记是否已被选择,可以在每条数据item被勾选时,比如第一条的话就是:

state.dataList[0].checked = !!state.dataList[0].checked;
dispatch({
    type: 'update',
    payload: {
        dataList: state.dataList.slice()
    }
})

对的,我们需要额外增加 state.dataList.slice() 这一步,这样我们就使用了新的数组引用了。 同理,下面的这些都需要额外增加这一步,或者要实现类似的功能。 选中条数

const count = useMemo(() => {
    state.dataList.filter(item => item.checked).length
}, [state.dataList]);

全选

dispatch({
    type: 'update',
    payload: {
        dataList: state.dataList.map(item => ({
            ...item,
            checked: true,
        }))
    }
})

反选

dispatch({
    type: 'update',
    payload: {
        dataList: state.dataList.map(item => ({
            ...item,
            checked: false,
        }))
    }
})

React实现二

网上也有不少网友借助一个存储对象来实现上述批量选择、选中条数、全选、反选的功能的,也简单看下具体实现。

import React, { useReducer, useMemo } from 'react';

const [state, dispatch] = useReducer({
    dataList: [],
    checkedMap: {}, // 新增 用来存储选中数据关系
}, (state, reducer) => {
    switch(reducer.type) {
     case 'update':
         return {
            ...state,
            ...reducer.payload
         }
     case default:
         return state;
    } 

})

批量选择在每条数据item被勾选时通过变更 checkedMap 记录存储关系,比如第一条的话,如果选中就是 {0: true} ,否则就是未选中,具体实现如下:

dispatch({
    type: 'update',
    payload: {
        checkedMap: {
            ...state.checkedMap,
            0: !!state.checkedMap[0]
        }
    }
})

我们不需要变更 dataList 里面的数据,只用变更 checkedMap

选中条数

const count = useMemo(() => {
 Object.keys(state.checkedMap).filter(item => state.checkedMap[item]).length
}, [state.checkedMap]);

全选

dispatch({
    type: 'update',
    payload: {
        checkedMap: state.dataList.reduce((acc, curr) => ({
            ...acc,
            [curr.id]: true,
        }), {})
    }
})

反选

dispatch({
    type: 'update',
    payload: {
        checkedMap: state.dataList.reduce((acc, curr) => ({
            ...acc,
            [curr.id]: false,
        }), {})
    }
})

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK