目的: 使用Popover制作动态的变色和控制Visable
引入相关文件
import React, { useState } from 'react';
import cxs from 'classnames'
import { Popover } from 'antd';
import '../../iconfont/iconfont.css'
import "./popovers.css";
function Popovers() {
const [chooseIndex, setChooseIndex] = useState(undefined)
const list = [
{ "name": "Rose", "age": 22 },
{ "name": "Eric", "age": 18 },
{ "name": "Mary", "age": 25 },
{ "name": "Lucy", "age": 28 },
{ "name": "Alice", "age": 21 },
{ "name": "Jack", "age": 29 },
{ "name": "Bruce", "age": 27 },
{ "name": "Tian", "age": 25 },
{ "name": "JuDiao", "age": 24 },
{ "name": "Niuheng", "age": 31 },
{ "name": "KaiDi", "age": 26 },
{ "name": "Haohao", "age": 26 },
{ "name": "Wind", "age": 23 }
]
const closeList = (index) => {
console.log('close')
setChooseIndex() // 每次关闭也会重新return? 渲染的是全部视图还是局部视图
// stopPropagation 阻止事件冒泡
}
const renderContent = (item, index) => { // 函数组件的函数,还必须const
console.log(item)
return <div className={cxs('content-wrap')}>
<div className={cxs("content-top")}>
<div className={cxs('content-top-left')}><h1>Name:</h1><p>{item.name}</p></div>
<div
onClick={(e) => {
e.stopPropagation() // 此处必须阻止冒泡事件,否则会触发父元素的点击事件,导致子元素的点击事件点击了但是没效果
closeList(index) // ***这是因为事件冒泡触发父元素点击对值重新赋值了***
}}
className={cxs('content-top-right')}>
<i className="icon iconfont"></i>
</div>
</div>
<div className={cxs("content-bottom")}>
<h2>Have a good nice Day !</h2>
</div>
</div>
}
const changeColorAndIndex = (item, index) => {
// console.log(item, index)
// console.log('changeIndex')
setChooseIndex(index) // 中间值与下标相等了 ,完成了两件事,被点击元素变色,被点击元素的pop显示,其他不显示!
}
return (
<div className={cxs('wrap')}>
<header>点名</header>
{list.map( (item, index) => {
return <div
key={index}
id='item-info'
className={cxs({"activeIndex": chooseIndex === index})} //1. 若类名与中间值相等,就出现变化的背景色
onClick={() => {changeColorAndIndex(item, index)}} //3. 使中间值和下标相等的事件。触发器
>
<Popover
content={renderContent(item, index)}
trigger="click"
getPopupContainer={() => document.getElementById("item-info")} // 绑定渲染父级
visible={chooseIndex === index} //2. 同理,若下标和中间值相同就显示
>
<div className={cxs("item-onfo1")}>
<div className={cxs('item-info-left')}>{item.name}</div>
<div className={cxs('item-info-right')}>{item.age}</div>
</div>
</Popover>
</div>
})}
</div>
)
}
export default Popovers
关于为什么popover要绑定父级
// popover的默认渲染父级是body ,这在有些时候会出问题,例如元素错位(当然在目前看来是没有问题的,为了严谨)
getPopupContainer={() => document.getElementById("item-info")}
css:
// 给父级元素相对定位,高度
// 给子元素向左的距离
.ant-popover {
left: 415px !important;
top: 0 !important;
}
.ant-popover-arrow{
display: none !important;
}
.ant-popover-inner-content{
padding: 0 !important;
width: 400px;
height: 270px;
}
完整css
.wrap{
width: 400px;
height: 900px;
margin-top: 40px;
margin-left: 50px;
background: rgba(0, 0, 0, .6);
}
header{
height: 50px;
margin-bottom: 15px;
/* text-align: center; */
line-height: 50px;
font-size: 18px;
color: seagreen;
padding-left: 16px;
font-weight: 700;
}
#item-info{
height: 40px;
padding: 0 16px;
position: relative;
}
.activeIndex{
background: #cccccc;
}
.item-onfo1{
height: 100%;
display: flex;
font-size: 14px;
padding: 11px 0;
justify-content: space-between;
border-bottom: 1px solid #cccccc;
}
.item-info-left{
color: blueviolet;
}
.item-info-right{
color: brown;
}
.ant-popover {
left: 415px !important;
top: 0 !important;
}
.ant-popover-arrow{
display: none !important;
}
.ant-popover-inner-content{
padding: 0 !important;
width: 400px;
height: 270px;
}
/* content */
.content-wrap{
padding: 14px 16px;
height: 100%;
}
.content-top{
height: 50px;
display: flex;
justify-content: space-between;
}
.content-bottom{
/* less 预编译 要 calc(~"100% - 50px") */
height: calc(100% - 50px);
}
.content-top-left{
display: flex;
}
.content-top-left p{
margin-left: 20px;
line-height: 50px;
}
.content-top-left h1{
color: crimson;
}
.content-top-right {
line-height: 50px;
}
.content-top-right i {
color: lightseagreen;
font-weight: 800;
}
.content-bottom h2{
color: dodgerblue;
}