Vue3實現(xiàn)折疊面板組件的示例代碼
更新時間:2024年01月08日 15:25:54 作者:前端老K
折疊面板大家都不陌生,很多時候需要實現(xiàn)一些復雜的交互,就會用到它,簡潔直觀還美觀,下面就跟隨小編一起學習一下如果使用Vue3實現(xiàn)折疊面板組件吧
背景
折疊面板大家都不陌生,很多時候需要實現(xiàn)一些復雜的交互,就會用到它,簡潔直觀還美觀,通常我們直接用第三方組件庫就行了,不過只會用還不行,還要會寫才行,下面我們一起手寫一個折疊面板組件。
最終效果
實現(xiàn)功能
- 手風琴模式
- 自定義標題
- 自定義內容
- 數(shù)據(jù)綁定,支持string | array
實現(xiàn)邏輯
首先創(chuàng)建組件目錄,如下:
index.vue 實現(xiàn)代碼:
<template> <div class="collapse-panel"> <slot></slot> </div> </template> <script setup lang="ts"> import { useSlots, ref, onMounted, provide } from 'vue' const slots = useSlots() const props = defineProps({ modelValue: { type: [String, Array, Number] }, // 數(shù)據(jù)綁定 accordion: { type: Boolean } // 是否開啟手風琴模式,默認不開啟 }) const emits = defineEmits(['update:modelValue', 'change']) const activeNames = ref([]) onMounted(() => { setValueLists() }) // 初始化設置激活項 const setValueLists = () => { if (!Array.isArray(props.modelValue)) { activeNames['value'] = [props.modelValue] } else { activeNames['value'] = props.modelValue } } // 點擊每項處理函數(shù) const toggle = (name) => { if (activeNames['value'].includes(name)) { // 收起時 activeNames['value'] = activeNames['value'].filter((item) => item != name) } else { // 展開時 if (props.accordion) { activeNames['value'] = [name] } else { activeNames['value'].push(name) } } emits('update:modelValue', activeNames['value']) emits('change', activeNames['value']) } // 提供父組件指定方法 provide('toggle', toggle) provide('activeNames', activeNames) </script> <style lang="less" scoped></style>
CollapseItem.vue 實現(xiàn)代碼
<template> <div class="collapse-item"> <div class="collapse-head"> <el-icon class="caret-down" :class="{ 'caret-open': isCollapse }" @click.stop="handlePanelItemClick"> <CaretRight /> </el-icon> <div class="collapse-head-right"> <span v-if="!slots.title" class="collapse-title">{{ attrs.title }}</span> <slot name="title"></slot> </div> </div> <CollapseTransition> <div v-show="isCollapse" class="collapse-content"> <slot name="content"></slot> </div> </CollapseTransition> </div> </template> <script setup lang="ts"> import { ref, useSlots, useAttrs, inject, computed } from 'vue' import CollapseTransition from './CollapseTransition.vue' const slots = useSlots() const attrs = useAttrs() const activeNames = inject('activeNames') const handleToggle = inject('toggle') const status = ref(false) // 開展狀態(tài) const isCollapse = computed(() => { return activeNames['value'].includes(attrs.name) }) const handlePanelItemClick = () => { handleToggle(attrs.name) } </script> <style scoped lang="less"> .collapse-item { display: flex; flex-flow: column; .collapse-head { display: flex; flex-flow: row nowrap; align-items: center; height: 42px; background: #d9d9d9; padding: 0 14px; border: 1px solid #cccccc; border-bottom: none; border-radius: 4px 4px 0px 0px; overflow: hidden; .caret-down { font-size: 20px; color: #1b1b1b; margin-right: 6px; cursor: pointer; transition: transform 0.3s; transform-origin: center center; &.caret-open { transform: rotate(90deg); } } .collapse-head-right { flex: 1; width: 0; .collapse-title { font-size: 14px; color: #1b1b1b; } } } .collapse-content { } } </style>
CollapseTransition.vue 展開收起動畫組件
<template> <transition @before-enter="beforeEnter" @enter="enter" @leave="leave" @after-leave="afterLeave"> <slot></slot> </transition> </template> <script setup lang="ts"> const beforeEnter = (el) => { el.classList.add('collapse-transition') el.dataset.oldPaddingTop = el.style.paddingTop el.dataset.oldPaddingBottom = el.style.paddingBottom el.dataset.oldOverflow = el.style.overflow el.style.overflow = 'hidden' el.style.height = '0' el.style.paddingTop = 0 el.style.paddingBottom = 0 } const enter = (el) => { el.style.height = el.scrollHeight + 'px' el.style.paddingTop = el.dataset.oldPaddingTop el.style.paddingBottom = el.dataset.oldPaddingBottom } const afterEnter = (el) => { el.classList.remove('collapse-transition') el.style.height = '' el.style.overflow = el.dataset.oldOverflow } const beforeLeave = (el) => { el.dataset.oldPaddingTop = el.style.paddingTop el.dataset.oldPaddingBottom = el.style.paddingBottom el.dataset.oldOverflow = el.style.overflow el.style.height = el.scrollHeight + 'px' el.style.overflow = 'hidden' } const leave = (el) => { el.classList.add('collapse-transition') el.style.height = 0 el.style.paddingTop = 0 el.style.paddingBottom = 0 } const afterLeave = (el) => { el.classList.remove('collapse-transition') el.style.height = '' el.style.overflow = el.dataset.oldOverflow el.style.paddingTop = el.dataset.oldPaddingTop el.style.paddingBottom = el.dataset.oldPaddingBottom } </script> <style scoped lang="less"> .collapse-transition { transition: all 0.3s ease-in-out; } </style>
組件的使用
// template <CollapsePanel v-model="activeName" @change="change" :accordion="accordion"> <collapse-item :name="1"> <template #title> <!-- 自定義title --> </template> <template #content> <!-- 自定義內容 --> </template> </collapse-item> <collapse-item :name="2"> <template #title> <!-- 自定義title --> </template> <template #content> <!-- 自定義內容 --> </template> </collapse-item> </CollapsePanel> //script const activeName = ref([2]) const accordion ref(true) // 是否開啟手風琴模式 // 點擊觸發(fā) const change = (value) => { console.log(value) }
以上就是Vue3實現(xiàn)折疊面板組件的示例代碼的詳細內容,更多關于Vue3折疊面板組件的資料請關注腳本之家其它相關文章!
相關文章
使用element組件table表格實現(xiàn)某條件下復選框無法勾選
這篇文章主要介紹了使用element組件table表格實現(xiàn)某條件下復選框無法勾選問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03vue+px2rem實現(xiàn)pc端大屏自適應的實例代碼(rem適配)
不管是移動端的適配,還是大屏需求,都離不開不一個單位rem,rem是相對于根元素的字體大小的單位,下面這篇文章主要給大家介紹了關于vue+px2rem實現(xiàn)pc端大屏自適應的相關資料,需要的朋友可以參考下2021-08-08vue路由$router.push()使用query傳參的實際開發(fā)使用
在vue項目中我們用函數(shù)式編程this.$router.push跳轉,用query傳遞一個對象時要把這個對象先轉化為字符串,然后在接收的時候要轉化為對象,下面這篇文章主要給大家介紹了關于vue路由$router.push()使用query傳參的實際開發(fā)使用,需要的朋友可以參考下2022-11-11