当前位置: 首页 > news >正文

夺宝网站制作/市场营销策划案例经典大全

夺宝网站制作,市场营销策划案例经典大全,怎么做网站的教程,工作总结开头和结束语作为一名前端工程师,我时常需要在项目中处理复杂的选择场景,比如组织架构选择、权限分配等。普通的下拉框已经无法满足需求,而 Ant Design 的 TreeSelect 组件虽然强大,但如何让它支持动态加载数据、树形结构选择,还能…

作为一名前端工程师,我时常需要在项目中处理复杂的选择场景,比如组织架构选择、权限分配等。普通的下拉框已经无法满足需求,而 Ant Design 的 TreeSelect 组件虽然强大,但如何让它支持动态加载数据、树形结构选择,还能与穿梭框的效果结合起来?这篇文章将带你基于 React、TypeScript 和 Antd,打造一个功能强大且易用的 TransferComSelect 组件,解决这些痛点。

为什么需要这个组件?

在实际业务中,我们经常会遇到以下需求:

  • 树形数据展示: 需要展示层级结构,比如公司部门树。
  • 动态加载: 数据量大时,按需加载子节点以提升性能。
  • 多选与穿梭: 支持多选,并清晰展示已选内容。
  • 灵活性: 可切换“只选本级”或“包含子级”的选择模式。

基于这些需求,我们将实现一个结合 TreeSelect 的树形选择组件,支持动态加载和自定义交互。

核心代码实现

以下是 TransferComSelect 组件的核心代码,我会逐步拆解它的实现逻辑:

.switch {display: flex;background-color: #fff;padding: 5px 10px;width: 100%;margin-bottom: 5px;>span {margin-right: 5px;}
}.tree {height: 300px;overflow-y: auto;scrollbar-width: none;/* Firefox */-ms-overflow-style: none;
}.tree::-webkit-scrollbar {display: none;
}
import React, { useState, useEffect, useCallback } from 'react';
import { TreeSelect, Switch, Spin, Empty } from 'antd';
import {debounce} from 'lodash'; // 引入 lodash 的防抖函数
import  './index.less';interface TreeDataNode {key: string;value: string;title: string;children?: TreeDataNode[];isLeaf?: boolean;
}interface TransferComSelectProps {loadDataFetch: (params: { parentId: string }) => Promise<any>;treeData?: TreeDataNode[];type?: number;selectedData?: {id:string}[];handleChange?: (data: { selectedIds: string[]; type: number }) => void;className?: string;style?: React.CSSProperties;placeholder?: string; // 新增:自定义 placeholderswitchText?: { onlyThisLevel: string; on: string; off: string }; // 新增:开关文案emptyText?: string; // 新增:空状态文案
}const TransferComSelect: React.FC<TransferComSelectProps> = (props) => {const {loadDataFetch,treeData = [],type = 0,selectedData = [],handleChange,className,style,placeholder = '请输入', // 默认值switchText = { onlyThisLevel: '只选本级', on: '开', off: '关' }, // 默认文案emptyText = '暂无数据', // 默认空状态文案} = props;const [sch, setSch] = useState(true);const [targetKeys, setTargetKeys] = useState<string[]>([]);const [treeDataSource, setTreeDataSource] = useState<TreeDataNode[]>(treeData);const [loading, setLoading] = useState(false);// 更新树数据源const updateTreeDataSource = (data: TreeDataNode[], key: string, children: TreeDataNode[]) => {return data.forEach((node) => {if (node.key === key) {node.children = children;} else if (node.children) {updateTreeDataSource(node.children, key, children);}});};// 动态加载子节点数据const loadData = (treeNode: any) => {return new Promise((resolve) => {setLoading(true);loadDataFetch({ parentId: treeNode.id }).then((children: any) => {const newChildren = children.map((i: any) => ({...i,isLeaf: i?.leaf,key: i?.id,value: i?.id,}));updateTreeDataSource(treeDataSource, treeNode.props.eventKey, newChildren);setTreeDataSource([...treeDataSource]);setLoading(false);resolve();}).catch(() => setLoading(false));});};// 处理选择变化const onChange = (newValue: any[]) => {setTargetKeys(newValue.map((i) => (i?.value||i)));};// 同步外部传入的已选数据useEffect(() => {if (selectedData?.length > 0) {setTargetKeys(selectedData.map((i) => i?.id));}}, [selectedData]);// 通知父组件选择结果useEffect(() => {if (handleChange) {handleChange({selectedIds: targetKeys,type,});}}, [targetKeys, handleChange, type]);// 新增:防抖搜索函数const filterTreeNode = useCallback(debounce((inputValue: string, treeNode: any) => {return treeNode.title.toLowerCase().includes(inputValue.toLowerCase());}, 300), // 300ms 防抖[]);const { SHOW_ALL } = TreeSelect;const tProps = {treeData: treeDataSource,value: targetKeys,onChange,treeCheckStrictly: sch,treeCheckable: true,showCheckedStrategy: SHOW_ALL,placeholder,loadData,showSearch: true,filterTreeNode,dropdownRender: (node: any) => (<><div className='switch'><span>{switchText.onlyThisLevel}</span><SwitchcheckedChildren={switchText.on}unCheckedChildren={switchText.off}checked={sch}onChange={setSch}/></div><Spin spinning={loading}>{treeDataSource.length === 0 && !loading ? (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={emptyText} />) : (node)}</Spin></>),className,style: { width: '100%', ...style },};return <TreeSelect {...tProps} />;
};export default TransferComSelect;

如何使用这个组件?

该组件已集成到 react-nexlif 开源库中。 具体文档可参考使用文档。你可以通过以下方式引入并使用:

pnpm add react-nexlif


import React from 'react';
import {TransferComSelect} from 'react-nexlif';const App: React.FC = () => {const initialTreeData = [{ key: '1', value: '1', title: 'Department A',id:'1' },{ key: '2', value: '2', title: 'Department B',id:'2' },];const fetchData = ({ parentId }: { parentId: string }) => {return new Promise((resolve) => {setTimeout(() => {resolve([{ id: `${parentId}-1`, title: `Sub ${parentId}-1`, leaf: true },{ id: `${parentId}-2`, title: `Sub ${parentId}-2`, leaf: true },]);}, 1000);});};const handleChange = (data: { list: { orgId: string }[]; type: number }) => {console.log('Selected:', data);};return (<div><h1>TransferComSelect   预览</h1><TransferComSelecttreeData={initialTreeData}loadDataFetch={fetchData}type={0}selectedData={[{ id: '1' }]}handleChange={handleChange}classtitle="custom-tree-select"style={{ border: '1px solid #1890ff', borderRadius: 4 }}placeholder="Please input" // 自定义 placeholderswitchText={{ onlyThisLevel: 'Only this level', on: 'On', off: 'Off' }} // 英文文案emptyText="No data available" // 自定义空状态文案/></div>);
};export default App;
代码亮点解析
  1. 动态加载数据: 通过 loadData 函数实现按需加载子节点,结合 loadDataFetch 接口请求数据,优化性能。
  2. 类型安全: 使用 TypeScript 定义 TreeDataNode 和 TransferComSelectProps,确保传入参数和数据结构清晰可控。
  3. 灵活选择模式: 通过 treeCheckStrictly 和 Switch 组件实现“只选本级”与“包含子级”的切换。
  4. 自定义下拉: 使用 dropdownRender 在下拉菜单中添加开关,增强交互体验。
  5. 状态同步: 通过 useEffect 将选择结果同步给父组件,保持数据一致性。
  6. 加载状态提示
    • 新增 loading 状态,在 loadData 中通过 setLoading 控制。
    • 使用 Antd 的 Spin 组件包裹下拉内容,数据加载时显示旋转动画,直观反馈用户。
  7. 搜索功能
    • 添加 showSearch: true 启用 TreeSelect 的搜索功能。
    • 实现 filterTreeNode 函数,支持对节点标题的模糊匹配,用户输入时快速定位。
  8. 样式定制
    • 新增 className 和 style 属性,允许调用者通过 CSS 类或内联样式调整组件外观。
    • 默认宽度保持 100%,通过 ...style 合并用户传入的样式,确保灵活性。
  • 搜索防抖
    • 使用 lodash/debounce 包装 filterTreeNode,设置 300ms 延迟。
    • 通过 useCallback 确保函数引用稳定,避免不必要的重新渲染。
    • 用户快速输入时,只在停止输入 300ms 后触发搜索,显著减少性能开销。
  • 空状态提示
    • 在 dropdownRender 中检查 treeDataSource.length === 0 且 !loading。
    • 使用 Antd 的 Empty 组件显示空状态,文案通过 emptyText 自定义。
    • 当数据为空时,用户会看到清晰的“暂无数据”提示,而不是空白。
  • 多语言支持
    • 新增 placeholder、switchText 和 emptyText 属性,将所有文案提取为 props。
    • 默认提供中文文案,调用者可传入英文或其他语言,轻松实现国际化。
    • 比如,switchText 支持开关的标签和状态文案自定义。
总结

通过 React、TypeScript 和 Antd 的 TreeSelect,我们实现了一个支持动态加载、多选切换的树形穿梭选择组件。它不仅满足了复杂业务场景的需求,还保持了代码的可读性和扩展性。

如果你在项目中也有类似需求,不妨试试这个组件!复制代码,稍作调整就能跑起来。有什么优化建议或使用心得,欢迎留言交流~

http://www.whsansanxincailiao.cn/news/32060010.html

相关文章:

  • 网站建设主要流程/上海网站优化公司
  • 自己做的网站如何让qq登录/宁波seo优化定制
  • 有了域名和空间怎么做网站/深圳最新疫情
  • 公众号做视频网站会封吗/网络营销师报名官网
  • 深圳龙华昨天死人新闻/seo技巧课程
  • wordpress外贸站/最新热点新闻事件素材
  • 做赚钱的网站/长春seo按天计费
  • 网站建设 模板/国内能用的搜索引擎
  • 怎么收录网站/如何做一个自己的网站
  • 外贸企业做网站/网站推广在线推广
  • 网站建设维护的相关基础知识/获客
  • 知名的环保行业网站开发/bt磁力搜索
  • 网站建设配置/成都专业网站推广公司
  • 域名邮箱和域名网站/网站是怎么做出来的
  • 做网站需要会什么编程/宁德市区哪里好玩
  • 网站怎么做图片按按钮跳转/优化设计六年级上册数学答案
  • 三河做网站/武汉网站设计公司
  • 网站运营专员是干嘛的/北京网站优化企业
  • 交友网站如何做/晚上看b站
  • 网站分页样式/关键词优化搜索引擎
  • 装修房子的效果图 三室二厅二卫/南宁seo外包服务商
  • 网站的ppt方案怎么做/电子商务专业就业方向
  • 昆明网站建设锐网/淘宝推广软件
  • 国际旅游网站设计报告/济南疫情最新消息
  • 网站开发线上销售技巧/百度的首页
  • b赣州网站建设/搜索引擎调词工具哪个好
  • 益阳网站建设方案/seo中文意思是
  • 公司网站推广计划书怎么做/百度招聘网最新招聘信息
  • 做网站怎么接业务/百度打广告怎么收费
  • 做网站注册会员加入实名认证功能/做销售怎样去寻找客户