【react+taro做一个商品分类的组件】版本1(我愿称之为最简版本)
UI设计图:
组件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | import Taro from '@tarojs/taro' ; import { View, Button } from '@tarojs/components' ; import classNames from 'classnames' ; import IconFont from "@/components/iconfont" ; import './index.scss' ; class TreeSelect extends Taro.PureComponent { constructor(props) { super (props); this .onDialogConfirm = this .onDialogConfirm.bind( this ); } state = { isActive: 0, rightList: [], selectedList: [] } static defaultProps = { list: [], confirmText: '保存' , showConfirm: true , // 是否显示确定按钮 } componentDidMount() { const { list } = this .props; this .setState({ rightList: list[0].children }); } // 确认事件 onDialogConfirm() { const { onConfirm } = this .props; const { selectedList } = this .state; if ( typeof onConfirm === 'function' ) { onConfirm(selectedList); } } selectLeft(index) { const { list } = this .props; this .setState({ rightList: list[index].children, isActive: index }); } addSelected(id) { const { selectedList } = this .state; const newList = Array.from( new Set([...selectedList, id])); this .setState({ selectedList: newList }); } render() { const { list, confirmText, showConfirm, styles } = this .props; const { isActive, rightList, selectedList } = this .state; return ( <View style={{...styles}}> <View className= 'treeSelect' > { /* left-father */ } <View className= 'treeSelect-left' > {list && list.map((item, index) => ( <View key={item.id} className={classNames( 'leftBtn' , { active: isActive === index }, { activeA: isActive === (index + 1) }, { activeB: isActive === (index - 1) }) } onClick={() => { this .selectLeft(index); }} > {item.title} </View> ) )} </View> { /* right-children */ } <View className= 'treeSelect-right' > {rightList && rightList.map((item) => ( <View key={item.id} className={classNames( 'rightBtn' , { active: selectedList.includes(item.id) })} onClick={() => { this .addSelected(item.id);}} > <View>{item.title}</View> <View style={{ display: selectedList.includes(item.id) ? 'flex' : 'none' }} className= 'checkIcon' > <IconFont name= 'common_icon_dagou' size={32} color= 'rgb(58,110,244)' /> </View> </View> ) )} </View> </View> {showConfirm && <View className= 'btns' > <Button FormType= 'submit' className={classNames( 'btn' , { active: selectedList.length })} onClick={ this .onDialogConfirm} >{confirmText}</Button> </View>} </View> ); } } export default TreeSelect; |
组件样式表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | .treeSelect { width: 100%; background-color: #fff; display: flex; justify-content: flex-start; &-left { width: 40%; .leftBtn { position: relative; width: 100%; height: 88px; line-height: 88px; padding-left: 80px; color: #171717; box-sizing: border-box; background-color: #F7F7F9; &.active { color: #3A6EF4; background-color: #fff; } &.activeA{ border-bottom-right-radius: 20px; } &.activeB{ border-top-right-radius: 20px; } } } &-right { width: 60%; .rightBtn{ height: 88px; line-height: 88px; padding-left: 120px; color: #171717; box-sizing: border-box; &.active { color: #3A6EF4; display: flex; justify-content: space-between; align-items: center; .checkIcon{ margin-right: 50px; height: 100%; display: flex; justify-content: center; align-items: center; } } } } } .btns { position: absolute; left: 0; right: 0; bottom: 40px; text-align: center; padding: 0 24px; box-sizing: border-box; .btn { width: 100%; height: 80px; padding: 0; color: #fff; background-color: #A5A8AF; box-shadow: 0px 4px 12px #B9BCC5; font-weight: bold; border: none; border-radius: 12px; &.active { background-color: #3A6EF4; box-shadow: 0px 4px 12px #3A6EF4; } } } |
调用组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import TreeSelect from '@/components/TreeSelect' ; 。。。 const myList = [ { id: '1212121' , title: '日用品' , children: [ { id: '32232312' , title: '洗发水' }, { id: '3234232' , title: '洗发水1' }, { id: '32243132' , title: '洗发水2' }, { id: '2131212312' , title: '洗发水3' }, ] }, { id: '121212w2221' , title: '服务' , children: [ { id: '3223222222312' , title: '洗发水222' }, { id: '3234232342432' , title: '洗发水3331' }, { id: '32243342132' , title: '洗发水4442' }, { id: '123232113324524' , title: '洗发水3555' }, ] }, { id: '121212w2221' , title: '服务333' , children: [ { id: '322322222231332' , title: '洗发水233322' }, { id: '323423234243222' , title: '洗发水3333331' }, { id: '322433421322' , title: '洗发水3334442' }, { id: '1232321133224524' , title: '洗发水3533355' }, ] } ]; <TreeSelect list={myList} /> |
微信小程序预览效果:
TBC.
分类:
react从入门到放弃
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具