Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比
Vue和React hooks实现Select批量选择、选中条数、全选、反选实现对比
批量选择、全选、反选这些功能使用频率还是很高的,下面直接看看Vue和React分别怎么实现吧。
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,
}), {})
}
})
效果如下
- 分类:
- Web前端
相关文章
邮箱收件人组件成长历程(二)(React hooks升级版)
记得自己之前写过一篇 《邮箱收件人组件(vue版)成长历程(一)》 记得当时里面写到了自己使用的是可编辑div来进行输入的,同时提到 当时出于挑战自己和青铜的倔强,想试着换个方案,完全使用可编辑di 阅读更多…
用在线IDE写vue代码
上周末无意中发现了一个新的在线IDE,网址glitch.com,个人感觉很不错,于是顺便关注了下其它的在线IDE,比如codesandbox.io也不错,没有细看,可能自己已经先入为主的喜欢上glit 阅读更多…
React router用hooks读取routeName、根据routeName跳转
在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeNam 阅读更多…
命令式组件Message、Dialog的主流写法分析
这里还是以element-ui为例,那我们就看看里面的Message。 它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/ 阅读更多…
从vuecli3学习webpack记录(一)vue-cli-serve机制
最近看了看vuecli3,把自己的学习记录下来。 首先看入口 npm run dev 即是 vue-cli-service serve ,之所以能运行 vue-cli-service 命令,就是 阅读更多…
深入学习React时间切片,任务调度scheduler
背景 最近想起月初看到的 魔术师卡颂 (微信号:kasong999)的一个公开直播—— 《手写React优先级调度算法》 ,虽然我更倾向于认为直播内容是演示如何利用React官方同款调度库手写代 阅读更多…