react 级联选择器/支持多选/单选
src/Type 有完整演示
npm i react-cascader-popover
或者
yarn add react-cascader-popover
https://react-cascader-popover-eyrp.vercel.app/
import { useRef, useState } from "react";
import { province } from "../data";
import {
Cascader,
CascaderOption,
CascaderRefProps,
} from "react-cascader-popover";
function Default() {
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);
const [valueAllPath, setValueAllPath] = useState<CascaderOption[]>([]);
const [value, setValue] = useState("120103");
const cascaderRef = useRef<CascaderRefProps>(null);
// 点击展开
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
// change 事件
const handleChange = (
value: CascaderOption | null,
valueAll: CascaderOption[]
) => {
setValue(value ? value.value : "");
setValueAllPath(valueAll);
};
// 清空选中
const handleClear = () => {
setValueAllPath([]);
// 两种都可以清空
// setValue("");
cascaderRef.current?.clearValue();
};
// 设置选中
const handleSet = () => {
setValue("11010333555");
};
const open = Boolean(anchorEl);
return (
<>
<div style={{ width: "500px" }}>
<div className="cascader">
<div className="cascader_input_box" onClick={handleClick}>
{valueAllPath.length ? (
<div className="cascader_input">
{valueAllPath.map((e) => e.label).join(" - ")}
</div>
) : (
<div className="placeholder">请选择</div>
)}
</div>
</div>
</div>
<Cascader
ref={cascaderRef}
value={value}
open={open}
anchorEl={anchorEl}
options={province}
onClose={() => setAnchorEl(null)}
onChange={handleChange}
/>
</>
);
}
export default Default;
import { useRef, useState } from "react";
import {
Cascader,
CascaderOption,
CascaderRefProps,
} from "react-cascader-popover";
import { province } from "../data";
function Multiple() {
const value = "130102";
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);
const [valueAll, setValueAll] = useState<CascaderOption[]>([]);
const cascaderRef = useRef<CascaderRefProps>(null);
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
const handleChange = (
_: CascaderOption | null,
valueAll: CascaderOption[]
) => {
console.log(valueAll);
setValueAll(valueAll);
};
const handleClear = () => {
// cascaderRef.current?.setValue([]);
cascaderRef.current?.clearValue();
};
const handleSetValue = () => {
const data = [
{
value: "120101",
label: "和平区",
},
{
value: "120102",
label: "河东区",
},
];
cascaderRef.current?.setValue(data.map((e) => e.value));
};
const open = Boolean(anchorEl);
return (
<>
<div style={{ width: "500px" }}>
<h3>多选 </h3>
{valueAll.length ? (
<>
<button onClick={handleClear}>清空VALUE</button>
<div>
当前选中【{valueAll.map((e) => JSON.stringify(e) + ",")}】
</div>
</>
) : (
<button onClick={handleSetValue}>设置VALUE选中</button>
)}
<div className="cascader">
<div className="cascader_input_box" onClick={handleClick}>
{valueAll.length ? (
<div className="cascader_input">
{valueAll.map((e) => e.label).join(" , ")}
</div>
) : (
<div className="placeholder">请选择</div>
)}
</div>
</div>
</div>
<Cascader
ref={cascaderRef}
value={value}
open={open}
anchorEl={anchorEl}
multiple
options={province}
onClose={() => setAnchorEl(null)}
onChange={handleChange}
/>
</>
);
}
export default Multiple;
import { useRef, useState } from "react";
import {
Cascader,
CascaderOption,
CascaderRefProps,
} from "react-cascader-popover";
function Default() {
const options = [
{
value: "120000",
label: "天津市",
isLoad: true,
},
{
value: "110000",
label: "北京市",
disabled: true,
isLoad: true,
},
];
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);
const [valueAllPath, setValueAllPath] = useState<CascaderOption[]>([]);
const [value, setValue] = useState("");
const [num, setNum] = useState(0);
const [valueItem, setValueItem] = useState<CascaderOption | null>(null);
const cascaderRef = useRef<CascaderRefProps>(null);
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
const handleChange = (
value: CascaderOption | null,
valueAll: CascaderOption[]
) => {
console.log(value, valueAll);
setValueItem(value);
// setValue(value ? value.value : "");
setValueAllPath(valueAll);
};
// 模拟接口返回数据
const getServiceData = (item: CascaderOption) => {
return new Promise<CascaderOption[]>((resolve) => {
setTimeout(() => {
const count = num + 1;
setNum(count);
resolve([
{
label: `${item.label}-1 `,
value: item.value + 1,
isLoad: count >= 2 ? false : true,
},
{
label: `${item.label}-2 `,
value: item.value + 222,
isLoad: count >= 2 ? false : true,
},
]);
}, 1000);
});
};
const loadData = async (item: CascaderOption) => {
const data = await getServiceData(item);
return data;
};
const open = Boolean(anchorEl);
return (
<>
<div style={{ width: "500px" }}>
<h3>动态加载 </h3>
<h6>value:{value}</h6>
{valueItem ? (
<h6>
valueItem:{valueItem.value}/{valueItem.label}
</h6>
) : (
<></>
)}
{valueAllPath.length ? (
<h6>全路径:{valueAllPath.map((e) => e.label).join(" - ")}</h6>
) : (
<></>
)}
<div className="cascader">
<div className="cascader_input_box" onClick={handleClick}>
{valueAllPath.length ? (
<div className="cascader_input">
{valueAllPath.map((e) => e.label).join(" - ")}
</div>
) : (
<div className="placeholder">请选择</div>
)}
</div>
</div>
</div>
<Cascader
search
ref={cascaderRef}
value={value}
open={open}
anchorEl={anchorEl}
options={options}
onClose={() => setAnchorEl(null)}
onChange={handleChange}
loadData={loadData}
/>
</>
);
}
export default Default;
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
value | string | 选中的值 | |
options | CascaderOption[] | [] | 数据 |
open | boolean | false | 是否弹出选择器 |
anchorEl | HTMLDivElement | null | null | HTMLDivElement元素 用于展示窗口的位置 |
multiple | boolean | false | 是否开启多选 |
search | boolean | false | 是否开启搜索 |
searchEmptyText | string | 暂无数据 | 搜索为空提示 |
searchPlaceholder | string | 请输入关键词 | 搜索框提示语 |
loadData | (value: CascaderOption) => Promise<CascaderOption[]> | 动态加载数据 options中要存在isLoad 配合 async await 使用 | |
onChange | (value: CascaderOption | null, valueAll: CascaderOption[]) => void | 点击后的事件 | |
onClose | () => void | 隐藏选择器事件 | |
ref | CascaderRefProps |
setValue: (value: string[]) => void;
clearValue: () => void;
用于多选时使用
|
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
label | string | 展示的文字 | |
value | string | 对应的value | |
disabled | boolean | false | 禁用 |
isLoad | boolean | false | true=有下级数据 |
children | Array | children |
1.0.6 更新项目
1.0.7 多选时展开列表默认展示第一个数据
1.1.0 增加输入框筛选 修复 onChange 触发问题
1.1.4 增加在多选搜索的时候可以选择多个
1.1.5 增加 loadData 动态加载数据逻辑, options 中加入禁用