vue2.0 自定义 折叠列表(Accordion)组件
1.自定义 折叠列表
Accordion.vue
(1)sass 版本
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 115 116 117 118 | <!-- 折叠列表 组件 --> <template> <nav : class = "$style.accWrapper" > <div : class = "$style.accTitle" @click= "toggleList" > <span>{{ title.area }}</span> <span>当前人数:{{ title.num }}人</span> <span>总人数:{{ title.sum }}人</span> <img src= "../assets/img/arrow_right.png" alt= "chevron" : class = "[{ [$style.open_menu]: isDisplay, [$style.close_menu]: !isDisplay }, $style.accChevron]" /> </div> <ul : class = "[{ [$style.maxHeight]: isDisplay }, $style.accList]" > <li : class = "$style.accListItem" v- for = "item in list" > <span>{{ item.area }}</span> <span>当前人数:{{ item.num }}人</span> <span>总人数:{{ item.sum }}人</span> </li> </ul> </nav> </template> <script> export default { data () { return { isDisplay: false } }, props: { title: { type: Object, default (){ return {} } }, list: { type: Array, required: true } }, methods: { toggleList () { this .isDisplay = ! this .isDisplay } } } </script> <style lang= "scss" module> .accWrapper { display:flex; flex-direction: column; } .accTitle { display: flex; justify-content: space-between; align-items: baseline; height: 50px; line-height: 50px; font-size: 16px; background: #eee; text-indent: 1em; cursor: pointer; } .accChevron { width: 20px; margin-right: 15px; } .accList{ list-style: none; padding: 0; margin: 0; font-size: 16px; overflow: hidden; max-height: 0; transition: max-height .5s ease-out; } .accList.maxHeight { max-height: 500px; transition: max-height .5s ease- in ; } .accListItem { background-image: url(../assets/img/arrow_right.png); background-repeat: no-repeat; background-size: 20px 20px; background-position: 95% 50%; display: flex; // justify-content: space-between; align-items: baseline; height: 50px; line-height: 50px; font-size: 16px; text-indent: 1em; cursor: pointer; } /* chevron animation */ @keyframes open-menu { to { transform: rotate(90deg); } } @keyframes close-menu { from { transform: rotate(90deg); } to { transform: rotate(0deg); } } .open_menu { animation: open-menu 0.4s ease-out forwards; } .close_menu { animation: close-menu 0.4s ease-out forwards; } </style> |
(2)less 版本
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 115 116 117 118 | <!-- 折叠列表 组件 --> <template> <nav class = "accWrapper" > <div class = "accTitle" @click= "toggleList" > <span>{{ title.area }}</span> <span>当前人数:{{ title.num }}人</span> <span>总人数:{{ title.sum }}人</span> <img src= "../assets/img/arrow_right.png" alt= "chevron" : class = "['accChevron', { 'open_menu': isDisplay, 'close_menu': !isDisplay }]" /> </div> <ul : class = "['accList', { 'maxHeight': isDisplay }]" > <li class = "accListItem" v- for = "item in list" > <span>{{ item.area }}</span> <span>当前人数:{{ item.num }}人</span> <span>总人数:{{ item.sum }}人</span> </li> </ul> </nav> </template> <script> export default { data () { return { isDisplay: false } }, props: { title: { type: Object, default (){ return {} } }, list: { type: Array, required: true } }, methods: { toggleList () { this .isDisplay = ! this .isDisplay } } } </script> <style lang= "less" scoped> .accWrapper { display:flex; flex-direction: column; } .accTitle { display: flex; justify-content: space-between; align-items: baseline; height: 50px; line-height: 50px; font-size: 16px; background: #eee; text-indent: 1em; cursor: pointer; } .accChevron { width: 20px; margin-right: 15px; } .accList{ list-style: none; padding: 0; margin: 0; font-size: 16px; overflow: hidden; max-height: 0; transition: max-height .5s ease-out; } .accList.maxHeight { max-height: 500px; transition: max-height .5s ease- in ; } .accListItem { background-image: url(../assets/img/arrow_right.png); background-repeat: no-repeat; background-size: 20px 20px; background-position: 95% 50%; display: flex; // justify-content: space-between; align-items: baseline; height: 50px; line-height: 50px; font-size: 16px; text-indent: 1em; cursor: pointer; } /* chevron animation */ @keyframes open-menu { to { transform: rotate(90deg); } } @keyframes close-menu { from { transform: rotate(90deg); } to { transform: rotate(0deg); } } .open_menu { animation: open-menu 0.4s ease-out forwards; } .close_menu { animation: close-menu 0.4s ease-out forwards; } </style> |
2.页面调用
Fold.vue
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 | <!-- 折叠列表 --> <template> <div> <!-- 标题栏 --> <mt-header title= "折叠列表" > <router-link to= "/" slot= "left" > <mt-button icon= "back" >返回</mt-button> </router-link> </mt-header> <!-- 列表 --> <accordion v- for = "(item,index) in dataList" :key= "item.id" :title= "item" :list= "item.child" > </accordion> </div> </template> <script> import Accordion from '../components/Accordion' export default { name: 'Fold' , components: { Accordion, }, data(){ return { dataList:[ { "area" : "深圳" , "num" : "10" , "sum" : "30" , "child" :[ { "area" : "罗湖" , "num" : "20" , "sum" : "20" }, { "area" : "福田" , "num" : "20" , "sum" : "20" }, { "area" : "南山" , "num" : "20" , "sum" : "20" } ]}, { "area" : "广州" , "num" : "10" , "sum" : "30" , "child" :[ { "area" : "白云" , "num" : "20" , "sum" : "20" }, { "area" : "福田" , "num" : "20" , "sum" : "20" }, { "area" : "南山" , "num" : "20" , "sum" : "20" } ]} ] } } } </script> <style lang= "scss" scoped> // </style> |
3.效果图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY