React 图层属性popup实现

1 篇文章 0 订阅

 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: 效果展示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值