1:App.js
import React, { useState, useEffect } from 'react';
import { Select } from 'antd';
import classnames from 'classnames/bind';
import BScroll from 'react-custom-scrollbars';
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import style from './App.module.scss';
const cb = classnames.bind(style);
const { Option } = Select;
const datas = {
111: {
layerName: '前端基础课程',
名称: 'JAVASCRIPT',
价格: '100',
作者: '陈旺山100'
},
222: {
layerName: '后端基础课程',
名称: 'JAVA',
价格: '200',
作者: '陈旺山200',
名称2: 'JAVA2',
价格2: '2002',
作者2: '陈旺山2002'
},
333: {
layerName: '服务端基础课程',
名称: 'NODEJS',
价格: '300',
作者: '陈旺山300'
}
}
function App() {
const [value, setValue] = useState(null);
const [liContent, setLiContent] = useState(null);
const [keys, setKeys] = useState([]);
const [idx, setIdx] = useState(0);
useEffect(() => {
const keys = Object.keys(datas);
setKeys(keys);
setValue(keys[0]);
}, []);
useEffect(() => {
if (!value) {
return;
}
const liItems = Object.entries(datas[value]);
const content = liItems.map((liItem, index) => {
if (liItem[0] !== 'layerName') {
return <li key={index}>
<label>{liItem[0]}</label>
<span>{liItem[1]}</span>
</li>
}
});
setLiContent(content);
}, [value, datas]);
useEffect(() => {
setValue(keys[idx])
}, [idx, keys]);
const options = keys.map((key) => {
const { layerName } = datas[key];
return <Option key={key} value={key}>{layerName}</Option>
});
function onChange(value) {
const index = keys.findIndex(item => {
return item === value;
});
setIdx(index);
setValue(value);
}
const prevOption = () => {
if (idx === 0) {
return;
}
setIdx(idx - 1);
}
const nextOption = () => {
if (idx === keys.length - 1) {
return;
}
setIdx(idx + 1);
}
const leftIconClassName = cb({
icon: true,
forbid: idx === 0
});
const rightIconClassName = cb({
icon: true,
forbid: idx === keys.length - 1
});
return (
<div className={style.properties}>
<div className={style.header}>
<LeftOutlined className={leftIconClassName} onClick={prevOption} disabled={true} />
<Select
style={{ width: 200 }}
value={value}
onChange={onChange}
>
{options}
</Select>
<RightOutlined className={rightIconClassName} onClick={nextOption} />
</div>
<div className={style.content}>
<BScroll
autoHeight
autoHeightMin={0}
autoHeightMax={162}>
<ul>
{liContent}
</ul>
</BScroll>
</div>
<div className={style.triangle}></div>
</div>
);
}
export default App;
2: App.module.scss
.properties {
position: absolute;
top: 150px;
left: 350px;
width: 260px;
border-radius: 3px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
.header {
height: 34px;
background: #1890ff;
display: flex;
align-items: center;
justify-content: center;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
:global {
.ant-select-selector {
background: #1890ff;
color: #fff;
border: none;
}
.ant-select-open {
color: #fff;
}
.ant-select-selection-item {
text-align: center;
}
.ant-select-arrow {
color: #fff;
}
}
.icon {
color: #fff;
cursor: pointer;
transition: all 0.3s;
}
.forbid {
color: #a5a5a5;
cursor: default;
}
}
.content {
padding: 5px 15px;
ul {
margin-bottom: 0;
li {
display: flex;
flex-direction: column;
padding: 5px 0px;
label {
color: #bbb;
}
span {
color: #000;
}
}
}
}
.triangle {
position: absolute;
left: 40px;
width: 0;
height: 0;
border-top: 30px solid #fff;
border-right: 30px solid transparent;
}
}
3: 效果展示