后臺管理系統(tǒng)中大多數(shù)都有列表的搜索,那么用戶的需求又需要必要時收縮搜索區(qū)域,需要時再展開。

而且怪的是他還需要一些部分不可收縮,不需要的地方才收縮。使用v-if來解決吧又不咋美觀,我們還需要一個簡單的動畫效果。我們先寫一個組件,直接上代碼。
```javascript
<template>
? ? <div
? ? ? ? class="collapse-el">
? ? ? ? <div
? ? ? ? ? ? ref="CollapseElRef"
? ? ? ? ? ? class="collapse-el-container">
? ? ? ? ? ? <div class="collapse-el-container-container">
? ? ? ? ? ? ? ? <slot></slot>
? ? ? ? ? ? </div>
? ? ? ? </div>
? ? ? ? <div
? ? ? ? ? ? v-if="showBt"
? ? ? ? ? ? class="collapse-el-show-container">
? ? ? ? ? ? <div
? ? ? ? ? ? ? ? @click="handleClick"
? ? ? ? ? ? ? ? class="container">
? ? ? ? ? ? ? ? <div
? ? ? ? ? ? ? ? ? ? :class="{
? ? ? ? ? ? ? ? ? ? ? ? 'bt':true,
? ? ? ? ? ? ? ? ? ? ? ? 'show':show,
? ? ? ? ? ? ? ? ? ? }">
? ? ? ? ? ? ? ? ? ? <SvgIcon
? ? ? ? ? ? ? ? ? ? ? ? :style="'width:15px;height:15px;'"
? ? ? ? ? ? ? ? ? ? ? ? name="sort-down"></SvgIcon>
? ? ? ? ? ? ? ? </div>
? ? ? ? ? ? ? ? {{show?'收縮':'展開'}}
? ? ? ? ? ? </div>
? ? ? ? </div>
? ? </div>
</template>
<script>
/**
* 折疊組件
*/
import {
? ? defineComponent,ref,toRef,
? ? onMounted,
? ? watch,onBeforeUnmount,
} from 'vue';
import SvgIcon from "@/components/svgIcon/index.vue";
export default defineComponent({
? ? name:'Collapse',
? ? components: {
? ? ? ? SvgIcon,
? ? },
? ? props:{
? ? ? ? show:{? //是否顯示
? ? ? ? ? ? type:Boolean,
? ? ? ? ? ? default:true,
? ? ? ? },
? ? ? ? showBt:{? //是否顯示展開按鈕
? ? ? ? ? ? type:Boolean,
? ? ? ? ? ? default:false,
? ? ? ? },
? ? ? ? anchorPointSignName:{? //錨點標識(可用querySelector查詢出來的標識)
? ? ? ? ? ? type:String,
? ? ? ? ? ? default:'.anchor-point-target',
? ? ? ? },
? ? },
? ? emits:['onClick'],
? ? setup(props,{emit}){
? ? ? ? const CollapseElRef = ref(null);
? ? ? ? const show = toRef(props,'show');
? ? ? ? const showBt = toRef(props,'showBt');
? ? ? ? const anchorPointSignName = toRef(props,'anchorPointSignName');
? ? ? ? onMounted(() => {
? ? ? ? ? ? const childEl = CollapseElRef.value.firstChild;
? ? ? ? ? ? const resizeObserver = new ResizeObserver((entries) => {
? ? ? ? ? ? ? ? computHeight();
? ? ? ? ? ? });
? ? ? ? ? ? resizeObserver.observe(childEl);
? ? ? ? });
? ? ? ? let timer = null;
? ? ? ? watch(show,(newValue)=>{
? ? ? ? ? ? computHeight();
? ? ? ? },{
? ? ? ? ? ? immediate:false,
? ? ? ? });
? ? ? ? /** 表示是顯示的 */
? ? ? ? function isActive(){
? ? ? ? ? ? if(!CollapseElRef.value) return false;
? ? ? ? ? ? const elRect = CollapseElRef.value.getBoundingClientRect();
? ? ? ? ? ? if(elRect.top==0 && elRect.bottom==0 && elRect.left==0 && elRect.right==0) return false;
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? /** 設置顯示高度 */
? ? ? ? function computHeight(){
? ? ? ? ? ? clearTimeout(timer);
? ? ? ? ? ? timer = setTimeout(()=>{
? ? ? ? ? ? ? ? if (!isActive()) return;
? ? ? ? ? ? ? ? if(show.value){
? ? ? ? ? ? ? ? ? ? const childHight = CollapseElRef.value.firstChild.getBoundingClientRect().height;
? ? ? ? ? ? ? ? ? ? CollapseElRef.value.style.height = childHight + 'px';
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? //如果是隱藏的話找出錨點元素
? ? ? ? ? ? ? ? ? ? const anchorPointEl = CollapseElRef.value.querySelector(anchorPointSignName.value);
? ? ? ? ? ? ? ? ? ? if(!anchorPointEl){
? ? ? ? ? ? ? ? ? ? ? ? CollapseElRef.value.style.height = 0 + 'px';
? ? ? ? ? ? ? ? ? ? }else{? //表示只隱藏到錨點元素
? ? ? ? ? ? ? ? ? ? ? ? const parentRect = CollapseElRef.value.getBoundingClientRect();
? ? ? ? ? ? ? ? ? ? ? ? const anchorPointElRect = anchorPointEl.getBoundingClientRect();
? ? ? ? ? ? ? ? ? ? ? ? const height = anchorPointElRect.y - parentRect.y + anchorPointElRect.height;
? ? ? ? ? ? ? ? ? ? ? ? CollapseElRef.value.style.height = height + 'px';
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }, 26);
? ? ? ? }
? ? ? ? onBeforeUnmount(()=>{
? ? ? ? ? ? clearTimeout(timer);
? ? ? ? });
? ? ? ? /** 收縮組件點擊事件,向外部拋出 */
? ? ? ? function handleClick(){
? ? ? ? ? ? emit('onClick');
? ? ? ? }
? ? ? ? return {
? ? ? ? ? ? CollapseElRef,
? ? ? ? ? ? show,
? ? ? ? ? ? showBt,
? ? ? ? ? ? handleClick,
? ? ? ? };
? ? },
});
</script>
<style lang='scss' scoped>
.collapse-el{
? ? position: relative;
? ? width: 100%;
? ? height: auto;
? ? >.collapse-el-container{
? ? ? ? position: relative;
? ? ? ? width: 100%;
? ? ? ? overflow: hidden;
? ? ? ? transition: all 0.2s;
? ? ? ? height: 0;
? ? ? ? >.collapse-el-container-container{
? ? ? ? ? ? position: absolute;
? ? ? ? ? ? top: 0;
? ? ? ? ? ? left: 0;
? ? ? ? ? ? width: 100%;
? ? ? ? ? ? height: fit-content;
? ? ? ? }
? ? }
? ? >.collapse-el-show-container{
? ? ? ? display: flex;
? ? ? ? justify-content: center;
? ? ? ? align-items: center;
? ? ? ? position: absolute;
? ? ? ? bottom: -7.5px;
? ? ? ? left: 0;
? ? ? ? width: 100%;
? ? ? ? pointer-events: none;
? ? ? ? >.container{
? ? ? ? ? ? width: fit-content;
? ? ? ? ? ? height: fit-content;
? ? ? ? ? ? cursor: pointer;
? ? ? ? ? ? display: flex;
? ? ? ? ? ? align-items: center;
? ? ? ? ? ? font-size: 12px;
? ? ? ? ? ? opacity: 0.5;
? ? ? ? ? ? pointer-events: initial;
? ? ? ? ? ? line-height: 1;
? ? ? ? ? ? >.bt{
? ? ? ? ? ? ? ? width: 15px;
? ? ? ? ? ? ? ? height: 15px;
? ? ? ? ? ? ? ? display: flex;
? ? ? ? ? ? ? ? justify-content: center;
? ? ? ? ? ? ? ? align-items: center;
? ? ? ? ? ? ? ? transition: all 0.2s;
? ? ? ? ? ? ? ? transform: rotate(0deg);
? ? ? ? ? ? ? ? &.show{
? ? ? ? ? ? ? ? ? ? transform: rotate(180deg);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
</style>
```
這樣我們就有了一個可伸縮的容器組件,只需要把相應元素放在這個組件中就行了
```javascript
? ? ? ? ? <DifinCollapse
? ? ? ? ? ? ? ? :show="dataContainer.showSearch"
? ? ? ? ? ? ? ? :showBt="true"
? ? ? ? ? ? ? ? @onClick="dataContainer.showSearch=!dataContainer.showSearch">
? ? ? ? ? ? ? ? <el-col :span="24" :xs="24">
? ? ? ? ? ? ? ? ? ? <el-form
? ? ? ? ? ? ? ? ? ? ? ? :model="dataContainer.form"
? ? ? ? ? ? ? ? ? ? ? ? ref="QueryFormRef"
? ? ? ? ? ? ? ? ? ? ? ? :inline="true"
? ? ? ? ? ? ? ? ? ? ? ? label-width="110px">
? ? ? ? ? ? ? ? ? ? ? ? <el-row :gutter="0">
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class="anchor-point-target"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="用戶名稱" prop="userName">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.userName"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請輸入"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @keyup.enter="handleQuery"/>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="昵稱" prop="nickName">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.nickName"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請輸入"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @keyup.enter="handleQuery"/>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="數(shù)據(jù)編號" prop="id">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.id"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請輸入"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @keyup.enter="handleQuery"/>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="手機號碼" prop="phone">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.phone"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請輸入"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @keyup.enter="handleQuery"/>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="可選擇" prop="disabled">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-select
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? style="width:100%;"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.disabled"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請選擇"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @change="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? >
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-option
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-for="item in dataContainer.optionList"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :key="item.id"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :label="item.label"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :value="item.value"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ></el-option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-select>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="6" :xs="6">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label="郵箱" prop="email">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v-model="dataContainer.form.email"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? placeholder="請輸入"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clearable
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @clear="handleQuery"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @keyup.enter="handleQuery"/>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-col :span="12" :xs="12">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-form-item label=" ">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-button
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? type="primary"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @click="handleQuery">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <SvgIcon
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :style="'width:15px;height:15px;margin-right:5px;'"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name="search-bt"></SvgIcon>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 查詢
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-button>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <el-button
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @click="resetQuery">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <SvgIcon
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :style="'width:15px;height:15px;margin-right:5px;'"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name="redo"></SvgIcon>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 重置
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-button>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-form-item>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? ? ? ? ? ? ? </el-row>
? ? ? ? ? ? ? ? ? ? </el-form>
? ? ? ? ? ? ? ? </el-col>
? ? ? ? ? ? </DifinCollapse>
```
是不是非常簡單呢,我們可以指定一個元素使收縮的時候只能收縮到相應位置就行了,完美解決需求。[DEMO](https://admin.dumogu.top/main/show-list)。