Skip to content

Commit

Permalink
优化全选逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
Ouchuxuan committed Jul 17, 2021
1 parent bca8ce3 commit dd93094
Show file tree
Hide file tree
Showing 14 changed files with 849 additions and 11 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"antd": "^4.16.7",
"axios": "^0.21.1",
"fastclick": "^1.0.6",
"proptypes": "^1.1.0",
"rc-checkbox": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"uuid": "^8.3.2",
"web-vitals": "^1.0.1"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>红包雨</title>
<title>测试</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
17 changes: 11 additions & 6 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ import RedPacket from './views/RedPacket';
// import RedPacket2 from './views/RedPacket2';
import Demo3 from './views/Demo3';
import Nav from './views/Nav';
import Demo4 from './views/Demo4';
import { ListState } from './store/ListState';
import './App.scss'
function App() {
return (
<div className="App">
<Router>
<Route path="/demo1" component={RedPacket}/>
{/* <Route path="/demo2" component={RedPacket2}/> */}
<Route path="/demo3" component={Demo3}/>
<Route path="/" exact component={Nav}/>
</Router>
<ListState>
<Router>
<Route path="/demo1" component={RedPacket} />
{/* <Route path="/demo2" component={RedPacket2}/> */}
<Route path="/demo3" component={Demo3} />
<Route path="/demo4" component={Demo4} />
<Route path="/" exact component={Nav} />
</Router>
</ListState>
</div>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/App.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@import '~antd/dist/antd.css';
.App{
width: 100%;
height: 100%;
overflow: hidden;
}
82 changes: 82 additions & 0 deletions src/components/List/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useContext, useEffect, useRef, useCallback } from 'react';
import { Checkbox } from 'antd';
import Proptypes from 'proptypes';
import { ListStateContext } from '../../store/ListState';
import './index.scss';
const toBottom = (scrollContainer, scrollDom) => {
const scrollContainerHeight = scrollContainer.offsetHeight;
const scrollTop = scrollContainer.scrollTop;
const scrollDomHeight = scrollDom.offsetHeight;
return (scrollDomHeight - scrollTop - scrollContainerHeight) <= 0;
}

export default function List(props) {
const scrollContainer = useRef();
const scrollDom = useRef();
const { onScroll } = props;
const { listState, dispatch: dispatchListState } = useContext(ListStateContext);
const onListScroll = () => {
const isToBottom = toBottom(scrollContainer.current, scrollDom.current);
onScroll(isToBottom);
}
const onCheckBoxChange = useCallback((event) => {
const checked = event.target.checked;
const id = event.target.id;
const result = listState.listData.map(item => {
if (item.id === id) {
return {
...item,
checked: checked
}
} else {
return item;
}
})
console.log('---', result);
dispatchListState({ type: 'setList', value: result });
}, [dispatchListState, listState.listData])

// 当前页全选状态切换
useEffect(() => {
// 这里被执行了
let isNotAllChecked;
if (listState.listData.length === 0) {
isNotAllChecked = true;
} else {
isNotAllChecked = listState.listData.some(item => {
return !item.checked
})
}
console.log(1111, !isNotAllChecked);
dispatchListState({ type: 'allCurrentPage', value: !isNotAllChecked })
}, [dispatchListState, listState.listData]);
return (
<div className="list-layout" onScroll={onListScroll} ref={scrollContainer}>
<div className="list-wrapper" ref={scrollDom}>
{
listState.listData.map(item => {
return (
<div className="list-item" key={item.id}>
<Checkbox
className="check-box"
checked={item.checked}
onChange={onCheckBoxChange}
id={item.id}
/>
<div className="list-item-detail">
{item.name}
</div>
</div>
)
})
}
</div>
</div>
)
}
// List.defaultProps = {
// dataSource: []
// }
List.propTypes = {
onScroll: Proptypes.func,
}
23 changes: 23 additions & 0 deletions src/components/List/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.list-layout {
width: 100%;
height: 500px;
border-bottom: 1px solid #ccc;
overflow-y: auto;
.list-item {
height: 30px;
border-bottom: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 10px;
.list-item-detail {
margin-left: 20px;
height: 100%;
flex: 1;
display: flex;
align-items: center;
font-size: 12px;
color: #ddd;
}
}
}
7 changes: 7 additions & 0 deletions src/components/SwitchType/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';
import './index.scss';
export default function SwitchType(props){
return (
<div className="switch-type-layout">switchtypes</div>
)
}
Empty file.
50 changes: 50 additions & 0 deletions src/store/ListState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { createContext, useReducer } from 'react';

// 创建context
export const ListStateContext = createContext({});

const reducer = (state, action) => {
switch (action.type) {
case 'allCurrentPage':
return {
...state,
selectCurrentPage: action.value
}
case 'allPage':
return {
...state,
selectAll: action.value
}
case 'setList':
return {
...state,
listData: action.value
}
case 'addList':
return {
...state,
listData:[...state.listData, ...action.value]
}
default:
return state;
}
}
const initState = {
selectCurrentPage: false,
selectAll: false,
listData: []
}

/**
* 创建一个 ListState 组件
* ListState 组件包裹的所有子组件都可以通过调用 ListStateContext 访问到 value
*/
export const ListState = props => {
const [listState, dispatch] = useReducer(reducer, initState)
return (
<ListStateContext.Provider value={{ listState, dispatch }}>
{props.children}
</ListStateContext.Provider>
)
}

18 changes: 18 additions & 0 deletions src/utils/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { v4 as uuid } from 'uuid';
export const randomNum = (min, max) => {
return Math.floor(Math.random() * (max - min + 1) + min);
}
export const getData = (count) => {
return new Promise(resolve => {
let list = [];
for (let i = 0; i < count; i++) {
const id = uuid();
list.push({
id,
money: randomNum(10, 10000),
name: id
});
}
resolve(list);
})
}
81 changes: 81 additions & 0 deletions src/views/Demo4/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useEffect, useState, useCallback, useContext, useRef} from 'react';
import { Checkbox } from 'antd';
import List from '../../components/List'
import SwitchType from '../../components/SwitchType';
import { getData } from '../../utils/data';
import { ListStateContext } from '../../store/ListState';
import './index.scss';

export default function Demo4() {
const [toBottom, setToBottom] = useState(false);
const currentListData = useRef([]);
const { listState, dispatch: dispatchListState } = useContext(ListStateContext);

const handleToBottom = useCallback((isToBottom) => {
setToBottom(isToBottom);
}, [])

const loadMore = () => {
getData(20).then(res => {
if (res.length) {
dispatchListState({type:'addList', value:res})
}
})
}

const onSelectCurrentPage = useCallback((event) => {
const checked = event.target.checked;
const result = currentListData.current.map(item=>{
return {
...item,
checked:checked,
}
})
dispatchListState({type:'setList',value:result});
dispatchListState({ type: 'allCurrentPage', value: checked });

}, [dispatchListState]);

const onSelectAll = useCallback((event) => {
const checked = event.target.checked;
dispatchListState({ type: 'allPage', value: checked })
}, [dispatchListState]);

useEffect(() => {
getData(20).then(res => {
dispatchListState({type:'setList', value:res})
})
}, [dispatchListState])

useEffect(() => {
setToBottom(false);
}, [listState.listData])

// 缓存全选状态切换时当前列表数据
useEffect(()=>{
currentListData.current = listState.listData
},[listState.listData, listState.selectCurrentPage])

// 当前页全选状态切换(这里有问题啦)
useEffect(()=>{

},[dispatchListState, listState.selectCurrentPage])

return (
<div className="demo-layout">
<div className="operation-bar">
<div className="operation-item">
<Checkbox className="check-box" checked={listState.selectCurrentPage} onChange={onSelectCurrentPage} />
<div className="label">本页全选</div>
</div>
<div className="operation-item">
<Checkbox className="check-box" checked={listState.selectAll} onChange={onSelectAll} />
<div className="label">全部全选</div>
</div>
</div>
<List onScroll={handleToBottom} />
{toBottom && (<div className="load-more" onClick={loadMore}>加载更多</div>)}
<SwitchType></SwitchType>
</div>
)
}
42 changes: 42 additions & 0 deletions src/views/Demo4/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.demo-layout {
width: 600px;
height: 660px;
margin: 0 auto;
margin-top: 10px;
border: 1px solid #ccc;
.operation-bar {
width: 100%;
height: 30px;
border-bottom: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 10px;
background-color: rgb(236, 174, 174);
.operation-item {
height: 100%;
display: flex;
align-items: center;
font-size: 12px;
margin-right: 20px;
.label{
color: #2b2828;
}
.check-box{
margin-right: 5px;
}
}
}
.load-more{
cursor: pointer;
font-size: 14px;
width: 80px;
height: 30px;
border-radius: 3px;
line-height: 30px;
text-align: center;
margin: 0 auto;
margin-top: 5px;
background-color:rgb(143, 219, 166);
}
}
1 change: 1 addition & 0 deletions src/views/Nav/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default function Nav(props) {
<Link to='/demo1'>跳转到demo1</Link>
{/* <Link to='/demo2'>跳转到demo2</Link> */}
<Link to='/demo3'>跳转到demo3</Link>
<Link to='/demo4'>跳转到demo4</Link>
</div>
)
}
Loading

0 comments on commit dd93094

Please sign in to comment.