sgSearch源码
<template> <div :class="$options.name" :expand="expandSearch" :showCollapseBtn="showCollapseBtn" @keyup.enter="(expandSearch = true), $emit(`keyupEnter`, {})" > <!-- v-clickoutside="(d) => (expandSearch = false)" --> <ul class="search-list"> <slot name="searchFilter"></slot> <ul class="sg-search-btns"> <slot name="searchBtns"></slot> </ul> <ul class="sg-operate-btns"> <slot name="operateBtns"></slot> </ul> </ul> <!-- 折叠按钮 --> <sgCollapseBtn v-model="expandSearch" :placement="`bottom`" /> </div> </template> <script> import clickoutside from "element-ui/src/utils/clickoutside"; import sgCollapseBtn from "@/vue/components/admin/sgCollapseBtn"; export default { name: "sgSearch", directives: { clickoutside }, components: { sgCollapseBtn, }, data() { return { expandSearch: false, showCollapseBtn: false, defaultHeight: 50, //组件默认高度 }; }, props: [ "value", //是否显示 "disabled", //是否禁用 "collapse", "data", "showCollapseButton", //显示折叠按钮 ], computed: {}, watch: { collapse: { handler(newValue, oldValue) { this.expandSearch = !newValue; }, deep: true, //深度监听 immediate: true, //立即执行 }, expandSearch: { handler(newValue, oldValue) { this.$emit(`update:collapse`, !newValue); this.$nextTick(() => { this.getHeight(); // this.getTop(); }); }, deep: true, //深度监听 // immediate: true, //立即执行 }, showCollapseButton: { handler(newValue, oldValue) { this.$nextTick(() => { this.getShowCollapseBtn(); }); }, deep: true, //深度监听 // immediate: true, //立即执行 }, }, created() {}, mounted() { this.$el.style.setProperty("--defaultHeight", `${this.defaultHeight}px`); //js往css传递局部参数 this.addEvents(); }, methods: { addEvents(d) { this.removeEvents(); addEventListener("resize", this.resize); this.resize(); }, removeEvents(d) { removeEventListener("resize", this.resize); }, resize() { this.getShowCollapseBtn(); this.$nextTick(() => { this.getHeight(); }); }, getHeight() { let height = this.$el ? this.$el.getBoundingClientRect().height : 0; this.$emit(`getHeight`, height); }, getShowCollapseBtn(d) { if (this.showCollapseButton === "" || this.showCollapseButton) { this.showCollapseBtn = true; } else if (this.showCollapseButton === false) { this.showCollapseBtn = false; } else { let len_search_list = this.$el.querySelectorAll(`.search-list>li`).length; /*let len_search_btns = this.$el.querySelectorAll(`.sg-search-btns>*`).length; let len_operate_btns = this.$el.querySelectorAll(`.sg-operate-btns>*`).length; let len = len_search_list + len_search_btns + len_operate_btns; this.showCollapseBtn = len > 5; */ let searchList = this.$el.querySelector(`.search-list`); this.showCollapseBtn = len_search_list > 3 || searchList.offsetHeight > this.defaultHeight; } }, }, destroyed() { this.removeEvents(); }, }; </script> <style lang="scss" scoped> .sgSearch { position: relative; $defaultHeight: var(--defaultHeight); //默认高度 $collapseHeight: 75px; //折叠高度 $expandHeight: max-content; //展开高度 $colCount: 4; //每行数量 $itemGap: 10px; //每一项间距 $itemLabelGap: 5px; //每一项标签间距 width: 100%; flex-grow: 1; height: $defaultHeight; box-sizing: border-box; .sgCollapseBtn { display: none; } &[showCollapseBtn] { padding-bottom: 30px; height: $collapseHeight; .sgCollapseBtn { display: block; } } & > .search-list { width: 100%; flex-grow: 1; display: flex; flex-wrap: wrap; & > * { flex-shrink: 0; } & > li { width: calc((100% - #{$itemGap} * (#{$colCount} - 1)) / #{$colCount}); flex-wrap: nowrap; align-items: baseline; box-sizing: border-box; margin-right: $itemGap; margin-bottom: $itemGap; display: none; // 折叠的状态只显示前两个搜索项和搜索、重置按钮 &:nth-child(1), &:nth-child(2), &:nth-child(3) { display: flex; } label { flex-shrink: 0; margin-right: $itemLabelGap; text-align: right; } &:nth-child(#{$colCount}n) { margin-right: 0; } } .sg-search-btns { display: flex; flex-wrap: nowrap; align-items: baseline; & > * { margin-left: $itemGap; &:first-child { margin-left: 0; } } } .sg-operate-btns { display: flex; justify-content: flex-end; align-items: baseline; flex-wrap: nowrap; margin-left: auto; & > * { margin-left: $itemGap; } } } &[expand] { height: $expandHeight; & > .search-list { & > li, .sg-operate-btns { display: flex; } } } } </style>
应用
<template> <div :class="$options.name"> <sgSearch :collapse.sync="collapseSearch" @keyupEnter="(currentPage = 1), initList()" @getHeight="(d) => (sgSearchHeight = d)" > <template slot="searchFilter"> <li> <label>搜索</label> <el-input clearable placeholder="请输入关键词" v-model.trim="keyword" /> </li> <li style="width: 150px"> <label>状态</label> <el-select style="width: 100%" v-model="ZT" placeholder="请选择" clearable> <el-option v-for="(a, i) in ZTs" :key="i" :value="a.value" :label="a.label" ></el-option> </el-select> </li> <li> <label>创建时间</label> <el-date-picker v-model="GXSJ" ref="GXSJ" type="daterange" align="right" unlink-panels range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="$global.pickerOptions" clearable /> </li> <li> <label>更新时间</label> <el-date-picker v-model="GXSJ" ref="GXSJ" type="daterange" align="right" unlink-panels range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="$global.pickerOptions" clearable /> </li> </template> <template slot="searchBtns"> <el-button size="medium" type="primary" icon="el-icon-search" @click="(collapseSearch = true), (currentPage = 1), initList()" >搜索</el-button > <el-button size="medium" type="primary" @click="resetFilterData(), initList()" plain >重置</el-button > </template> <template slot="operateBtns"> <el-button size="medium" type="primary" @click="add">添加</el-button> <el-button :disabled="selection.length === 0" size="medium" type="danger" @click="delAny" >批量删除</el-button > </template> </sgSearch> <div class="sg-table" v-loading="loading" :full="fullscreenTable" @click="collapseSearch = true" > <el-table :data="tableData" ref="table" stripe border :header-cell-style="{ background: '#f5f7fa' }" :height="`calc(100vh - ${fullscreenTable ? 10 : 160 + sgSearchHeight}px - ${ total > 10 ? 40 : 0 }px)`" :show-header="true" style="width: 100%" @row-click="row_click" @selection-change="selection_change" :row-class-name="row_class_name" > <template slot="empty"> <el-empty v-show="!loading" :image="require('@/assets/404.png')"> <span slot="description">暂无数据</span> <el-button type="primary" icon="el-icon-s-promotion" plain @click="add" >去哪里添加数据</el-button > </el-empty> </template> <el-table-column type="selection" width="50" /> <el-table-column type="index" label="序号" width="60" /> <!-- <el-table-column prop="字段" label="列名" minWidth="200" /> --> <el-table-column :resizable="false" prop="ID" label="身份证号" minWidth="200"> <template v-slot:header="scope"> <span> 身份证号 <fullscreenTable v-model="fullscreenTable" /> </span> </template> <template slot-scope="scope"> <span>【索引{{ scope.$index }}】{{ scope.row.ID }}</span> </template> </el-table-column> <el-table-column label="用户名" show-overflow-tooltip minWidth="100"> <template slot-scope="scope"> <span>{{ scope.row.username }}</span> </template> </el-table-column> <el-table-column label="姓名" show-overflow-tooltip minWidth="80"> <template slot-scope="scope"> <span>{{ scope.row.name }}</span> </template> </el-table-column> <el-table-column label="权限角色" show-overflow-tooltip minWidth="100"> <template slot-scope="scope"> <span>{{ scope.row.role || `未分配` }}</span> </template> </el-table-column> <el-table-column label="操作" width="175"> <template slot-scope="scope"> <el-button size="mini" type="primary" @click.stop="edit(scope.row)" @dblclick.native.stop >修改</el-button > <el-button size="mini" type="danger" @click.stop="del(scope.row)" @dblclick.native.stop >删除</el-button > </template> </el-table-column> </el-table> <el-pagination style="width: 100%; text-align: center; margin-top: 10px" background :hidden="total <= 10" :layout="`total, sizes, prev, pager, next, jumper`" :page-sizes="[10, 20, 50, 100]" :pager-count="7" :current-page.sync="currentPage" :page-size.sync="pageSize" :total="total" @size-change="initList" @current-change="initList" /> </div> </div> </template> <script> import sgSearch from "@/vue/components/admin/sgSearch"; export default { name: "sgBody", components: { sgSearch }, data() { return { ZT: 1, //当前状态 ZTs: [ { value: 1, label: "显示文本1" }, { value: 2, label: "显示文本2" }, { value: 3, label: "显示文本3" }, { value: 4, label: "显示文本4" }, { value: 5, label: "显示文本5" }, ], fullscreenTable: false, //全屏表格 collapseSearch: false, //折叠搜索栏 sgSearchHeight: 0, //搜索栏的高度 tableData: [ { ID: "330110198704103091", username: "username1", name: "姓名1", role: "role1" }, { ID: "330110198704103092", username: "username2", name: "姓名2", role: "role2" }, { ID: "330110198704103093", username: "username3", name: "姓名3", role: "role3" }, { ID: "330110198704103094", username: "username4", name: "姓名4", role: "role4" }, { ID: "330110198704103095", username: "username5", name: "姓名5", role: "role5" }, ], //表格数据 selection: [], //表格选中项数组 currentPage: 1, pageSize: 10, // total: 0, total: 999, }; }, methods: { row_click(row, column, event) { this.$refs.table.toggleRowSelection(row); }, selection_change(selection) { this.selection = selection; }, row_class_name({ row, rowIndex }) { return this.selection.some((v) => v.ID === row.ID) ? "selected" : ""; }, }, }; </script>
依赖的折叠按钮组件